1*0fca6ea1SDimitry Andric //===------- HexagonTfrCleanup.cpp - Hexagon Transfer Cleanup Pass -------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric // This pass is to address a situation that appears after register allocaion
9*0fca6ea1SDimitry Andric // evey now and then, namely a register copy from a source that was defined
10*0fca6ea1SDimitry Andric // as an immediate value in the same block (usually just before the copy).
11*0fca6ea1SDimitry Andric //
12*0fca6ea1SDimitry Andric // Here is an example of actual code emitted that shows this problem:
13*0fca6ea1SDimitry Andric //
14*0fca6ea1SDimitry Andric // .LBB0_5:
15*0fca6ea1SDimitry Andric // {
16*0fca6ea1SDimitry Andric // r5 = zxtb(r8)
17*0fca6ea1SDimitry Andric // r6 = or(r6, ##12345)
18*0fca6ea1SDimitry Andric // }
19*0fca6ea1SDimitry Andric // {
20*0fca6ea1SDimitry Andric // r3 = xor(r1, r2)
21*0fca6ea1SDimitry Andric // r1 = #0 <-- r1 set to #0
22*0fca6ea1SDimitry Andric // }
23*0fca6ea1SDimitry Andric // {
24*0fca6ea1SDimitry Andric // r7 = r1 <-- r7 set to r1
25*0fca6ea1SDimitry Andric // r0 = zxtb(r3)
26*0fca6ea1SDimitry Andric // }
27*0fca6ea1SDimitry Andric
28*0fca6ea1SDimitry Andric #define DEBUG_TYPE "tfr-cleanup"
29*0fca6ea1SDimitry Andric #include "HexagonTargetMachine.h"
30*0fca6ea1SDimitry Andric
31*0fca6ea1SDimitry Andric #include "llvm/CodeGen/LiveInterval.h"
32*0fca6ea1SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
33*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
34*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
35*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
36*0fca6ea1SDimitry Andric #include "llvm/CodeGen/Passes.h"
37*0fca6ea1SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
38*0fca6ea1SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
39*0fca6ea1SDimitry Andric #include "llvm/Support/CommandLine.h"
40*0fca6ea1SDimitry Andric #include "llvm/Support/Debug.h"
41*0fca6ea1SDimitry Andric #include "llvm/Support/raw_ostream.h"
42*0fca6ea1SDimitry Andric #include "llvm/Target/TargetMachine.h"
43*0fca6ea1SDimitry Andric
44*0fca6ea1SDimitry Andric using namespace llvm;
45*0fca6ea1SDimitry Andric
46*0fca6ea1SDimitry Andric namespace llvm {
47*0fca6ea1SDimitry Andric FunctionPass *createHexagonTfrCleanup();
48*0fca6ea1SDimitry Andric void initializeHexagonTfrCleanupPass(PassRegistry &);
49*0fca6ea1SDimitry Andric } // namespace llvm
50*0fca6ea1SDimitry Andric
51*0fca6ea1SDimitry Andric namespace {
52*0fca6ea1SDimitry Andric class HexagonTfrCleanup : public MachineFunctionPass {
53*0fca6ea1SDimitry Andric public:
54*0fca6ea1SDimitry Andric static char ID;
HexagonTfrCleanup()55*0fca6ea1SDimitry Andric HexagonTfrCleanup() : MachineFunctionPass(ID), HII(0), TRI(0) {
56*0fca6ea1SDimitry Andric PassRegistry &R = *PassRegistry::getPassRegistry();
57*0fca6ea1SDimitry Andric initializeHexagonTfrCleanupPass(R);
58*0fca6ea1SDimitry Andric }
getPassName() const59*0fca6ea1SDimitry Andric StringRef getPassName() const override { return "Hexagon TFR Cleanup"; }
getAnalysisUsage(AnalysisUsage & AU) const60*0fca6ea1SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
61*0fca6ea1SDimitry Andric AU.setPreservesAll();
62*0fca6ea1SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
63*0fca6ea1SDimitry Andric }
64*0fca6ea1SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
65*0fca6ea1SDimitry Andric
66*0fca6ea1SDimitry Andric private:
67*0fca6ea1SDimitry Andric const HexagonInstrInfo *HII;
68*0fca6ea1SDimitry Andric const TargetRegisterInfo *TRI;
69*0fca6ea1SDimitry Andric
70*0fca6ea1SDimitry Andric typedef DenseMap<unsigned, uint64_t> ImmediateMap;
71*0fca6ea1SDimitry Andric
72*0fca6ea1SDimitry Andric bool isIntReg(unsigned Reg, bool &Is32);
73*0fca6ea1SDimitry Andric void setReg(unsigned R32, uint32_t V32, ImmediateMap &IMap);
74*0fca6ea1SDimitry Andric bool getReg(unsigned Reg, uint64_t &Val, ImmediateMap &IMap);
75*0fca6ea1SDimitry Andric bool updateImmMap(MachineInstr *MI, ImmediateMap &IMap);
76*0fca6ea1SDimitry Andric bool rewriteIfImm(MachineInstr *MI, ImmediateMap &IMap, SlotIndexes *Indexes);
77*0fca6ea1SDimitry Andric bool eraseIfRedundant(MachineInstr *MI, SlotIndexes *Indexes);
78*0fca6ea1SDimitry Andric };
79*0fca6ea1SDimitry Andric } // namespace
80*0fca6ea1SDimitry Andric
81*0fca6ea1SDimitry Andric char HexagonTfrCleanup::ID = 0;
82*0fca6ea1SDimitry Andric
83*0fca6ea1SDimitry Andric namespace llvm {
84*0fca6ea1SDimitry Andric char &HexagonTfrCleanupID = HexagonTfrCleanup::ID;
85*0fca6ea1SDimitry Andric }
86*0fca6ea1SDimitry Andric
isIntReg(unsigned Reg,bool & Is32)87*0fca6ea1SDimitry Andric bool HexagonTfrCleanup::isIntReg(unsigned Reg, bool &Is32) {
88*0fca6ea1SDimitry Andric Is32 = Hexagon::IntRegsRegClass.contains(Reg);
89*0fca6ea1SDimitry Andric return Is32 || Hexagon::DoubleRegsRegClass.contains(Reg);
90*0fca6ea1SDimitry Andric }
91*0fca6ea1SDimitry Andric
92*0fca6ea1SDimitry Andric // Assign given value V32 to the specified the register R32 in the map. Only
93*0fca6ea1SDimitry Andric // 32-bit registers are valid arguments.
setReg(unsigned R32,uint32_t V32,ImmediateMap & IMap)94*0fca6ea1SDimitry Andric void HexagonTfrCleanup::setReg(unsigned R32, uint32_t V32, ImmediateMap &IMap) {
95*0fca6ea1SDimitry Andric ImmediateMap::iterator F = IMap.find(R32);
96*0fca6ea1SDimitry Andric if (F == IMap.end())
97*0fca6ea1SDimitry Andric IMap.insert(std::make_pair(R32, V32));
98*0fca6ea1SDimitry Andric else
99*0fca6ea1SDimitry Andric F->second = V32;
100*0fca6ea1SDimitry Andric }
101*0fca6ea1SDimitry Andric
102*0fca6ea1SDimitry Andric // Retrieve a value of the provided register Reg and store it into Val.
103*0fca6ea1SDimitry Andric // Return "true" if a value was found, "false" otherwise.
getReg(unsigned Reg,uint64_t & Val,ImmediateMap & IMap)104*0fca6ea1SDimitry Andric bool HexagonTfrCleanup::getReg(unsigned Reg, uint64_t &Val,
105*0fca6ea1SDimitry Andric ImmediateMap &IMap) {
106*0fca6ea1SDimitry Andric bool Is32;
107*0fca6ea1SDimitry Andric if (!isIntReg(Reg, Is32))
108*0fca6ea1SDimitry Andric return false;
109*0fca6ea1SDimitry Andric
110*0fca6ea1SDimitry Andric if (Is32) {
111*0fca6ea1SDimitry Andric ImmediateMap::iterator F = IMap.find(Reg);
112*0fca6ea1SDimitry Andric if (F == IMap.end())
113*0fca6ea1SDimitry Andric return false;
114*0fca6ea1SDimitry Andric Val = F->second;
115*0fca6ea1SDimitry Andric return true;
116*0fca6ea1SDimitry Andric }
117*0fca6ea1SDimitry Andric
118*0fca6ea1SDimitry Andric // For 64-bit registers, compose the value from the values of its
119*0fca6ea1SDimitry Andric // subregisters.
120*0fca6ea1SDimitry Andric unsigned SubL = TRI->getSubReg(Reg, Hexagon::isub_lo);
121*0fca6ea1SDimitry Andric unsigned SubH = TRI->getSubReg(Reg, Hexagon::isub_hi);
122*0fca6ea1SDimitry Andric ImmediateMap::iterator FL = IMap.find(SubL), FH = IMap.find(SubH);
123*0fca6ea1SDimitry Andric if (FL == IMap.end() || FH == IMap.end())
124*0fca6ea1SDimitry Andric return false;
125*0fca6ea1SDimitry Andric Val = (FH->second << 32) | FL->second;
126*0fca6ea1SDimitry Andric return true;
127*0fca6ea1SDimitry Andric }
128*0fca6ea1SDimitry Andric
129*0fca6ea1SDimitry Andric // Process an instruction and record the relevant information in the imme-
130*0fca6ea1SDimitry Andric // diate map.
updateImmMap(MachineInstr * MI,ImmediateMap & IMap)131*0fca6ea1SDimitry Andric bool HexagonTfrCleanup::updateImmMap(MachineInstr *MI, ImmediateMap &IMap) {
132*0fca6ea1SDimitry Andric using namespace Hexagon;
133*0fca6ea1SDimitry Andric
134*0fca6ea1SDimitry Andric if (MI->isCall()) {
135*0fca6ea1SDimitry Andric IMap.clear();
136*0fca6ea1SDimitry Andric return true;
137*0fca6ea1SDimitry Andric }
138*0fca6ea1SDimitry Andric
139*0fca6ea1SDimitry Andric // If this is an instruction that loads a constant into a register,
140*0fca6ea1SDimitry Andric // record this information in IMap.
141*0fca6ea1SDimitry Andric unsigned Opc = MI->getOpcode();
142*0fca6ea1SDimitry Andric if (Opc == A2_tfrsi || Opc == A2_tfrpi) {
143*0fca6ea1SDimitry Andric unsigned DefR = MI->getOperand(0).getReg();
144*0fca6ea1SDimitry Andric bool Is32;
145*0fca6ea1SDimitry Andric if (!isIntReg(DefR, Is32))
146*0fca6ea1SDimitry Andric return false;
147*0fca6ea1SDimitry Andric if (!MI->getOperand(1).isImm()) {
148*0fca6ea1SDimitry Andric if (!Is32) {
149*0fca6ea1SDimitry Andric IMap.erase(TRI->getSubReg(DefR, isub_lo));
150*0fca6ea1SDimitry Andric IMap.erase(TRI->getSubReg(DefR, isub_hi));
151*0fca6ea1SDimitry Andric } else {
152*0fca6ea1SDimitry Andric IMap.erase(DefR);
153*0fca6ea1SDimitry Andric }
154*0fca6ea1SDimitry Andric return false;
155*0fca6ea1SDimitry Andric }
156*0fca6ea1SDimitry Andric uint64_t Val = MI->getOperand(1).getImm();
157*0fca6ea1SDimitry Andric // If it's a 64-bit register, break it up into subregisters.
158*0fca6ea1SDimitry Andric if (!Is32) {
159*0fca6ea1SDimitry Andric uint32_t VH = (Val >> 32), VL = (Val & 0xFFFFFFFFU);
160*0fca6ea1SDimitry Andric setReg(TRI->getSubReg(DefR, isub_lo), VL, IMap);
161*0fca6ea1SDimitry Andric setReg(TRI->getSubReg(DefR, isub_hi), VH, IMap);
162*0fca6ea1SDimitry Andric } else {
163*0fca6ea1SDimitry Andric setReg(DefR, Val, IMap);
164*0fca6ea1SDimitry Andric }
165*0fca6ea1SDimitry Andric return true;
166*0fca6ea1SDimitry Andric }
167*0fca6ea1SDimitry Andric
168*0fca6ea1SDimitry Andric // Not a A2_tfr[sp]i. Invalidate all modified registers in IMap.
169*0fca6ea1SDimitry Andric for (MachineInstr::mop_iterator Mo = MI->operands_begin(),
170*0fca6ea1SDimitry Andric E = MI->operands_end();
171*0fca6ea1SDimitry Andric Mo != E; ++Mo) {
172*0fca6ea1SDimitry Andric if (Mo->isRegMask()) {
173*0fca6ea1SDimitry Andric IMap.clear();
174*0fca6ea1SDimitry Andric return true;
175*0fca6ea1SDimitry Andric }
176*0fca6ea1SDimitry Andric if (!Mo->isReg() || !Mo->isDef())
177*0fca6ea1SDimitry Andric continue;
178*0fca6ea1SDimitry Andric unsigned R = Mo->getReg();
179*0fca6ea1SDimitry Andric for (MCRegAliasIterator AR(R, TRI, true); AR.isValid(); ++AR) {
180*0fca6ea1SDimitry Andric ImmediateMap::iterator F = IMap.find(*AR);
181*0fca6ea1SDimitry Andric if (F != IMap.end())
182*0fca6ea1SDimitry Andric IMap.erase(F);
183*0fca6ea1SDimitry Andric }
184*0fca6ea1SDimitry Andric }
185*0fca6ea1SDimitry Andric return true;
186*0fca6ea1SDimitry Andric }
187*0fca6ea1SDimitry Andric
188*0fca6ea1SDimitry Andric // Rewrite the instruction as A2_tfrsi/A2_tfrpi, it is a copy of a source that
189*0fca6ea1SDimitry Andric // has a known constant value.
rewriteIfImm(MachineInstr * MI,ImmediateMap & IMap,SlotIndexes * Indexes)190*0fca6ea1SDimitry Andric bool HexagonTfrCleanup::rewriteIfImm(MachineInstr *MI, ImmediateMap &IMap,
191*0fca6ea1SDimitry Andric SlotIndexes *Indexes) {
192*0fca6ea1SDimitry Andric using namespace Hexagon;
193*0fca6ea1SDimitry Andric unsigned Opc = MI->getOpcode();
194*0fca6ea1SDimitry Andric switch (Opc) {
195*0fca6ea1SDimitry Andric case A2_tfr:
196*0fca6ea1SDimitry Andric case A2_tfrp:
197*0fca6ea1SDimitry Andric case COPY:
198*0fca6ea1SDimitry Andric break;
199*0fca6ea1SDimitry Andric default:
200*0fca6ea1SDimitry Andric return false;
201*0fca6ea1SDimitry Andric }
202*0fca6ea1SDimitry Andric
203*0fca6ea1SDimitry Andric unsigned DstR = MI->getOperand(0).getReg();
204*0fca6ea1SDimitry Andric unsigned SrcR = MI->getOperand(1).getReg();
205*0fca6ea1SDimitry Andric bool Tmp, Is32;
206*0fca6ea1SDimitry Andric if (!isIntReg(DstR, Is32) || !isIntReg(SrcR, Tmp))
207*0fca6ea1SDimitry Andric return false;
208*0fca6ea1SDimitry Andric assert(Tmp == Is32 && "Register size mismatch");
209*0fca6ea1SDimitry Andric uint64_t Val;
210*0fca6ea1SDimitry Andric bool Found = getReg(SrcR, Val, IMap);
211*0fca6ea1SDimitry Andric if (!Found)
212*0fca6ea1SDimitry Andric return false;
213*0fca6ea1SDimitry Andric
214*0fca6ea1SDimitry Andric MachineBasicBlock &B = *MI->getParent();
215*0fca6ea1SDimitry Andric DebugLoc DL = MI->getDebugLoc();
216*0fca6ea1SDimitry Andric int64_t SVal = Is32 ? int32_t(Val) : Val;
217*0fca6ea1SDimitry Andric auto &HST = B.getParent()->getSubtarget<HexagonSubtarget>();
218*0fca6ea1SDimitry Andric MachineInstr *NewMI;
219*0fca6ea1SDimitry Andric if (Is32)
220*0fca6ea1SDimitry Andric NewMI = BuildMI(B, MI, DL, HII->get(A2_tfrsi), DstR).addImm(SVal);
221*0fca6ea1SDimitry Andric else if (isInt<8>(SVal))
222*0fca6ea1SDimitry Andric NewMI = BuildMI(B, MI, DL, HII->get(A2_tfrpi), DstR).addImm(SVal);
223*0fca6ea1SDimitry Andric else if (isInt<8>(SVal >> 32) && isInt<8>(int32_t(Val & 0xFFFFFFFFLL)))
224*0fca6ea1SDimitry Andric NewMI = BuildMI(B, MI, DL, HII->get(A2_combineii), DstR)
225*0fca6ea1SDimitry Andric .addImm(int32_t(SVal >> 32))
226*0fca6ea1SDimitry Andric .addImm(int32_t(Val & 0xFFFFFFFFLL));
227*0fca6ea1SDimitry Andric else if (HST.isTinyCore())
228*0fca6ea1SDimitry Andric // Disable generating CONST64 since it requires load resource.
229*0fca6ea1SDimitry Andric return false;
230*0fca6ea1SDimitry Andric else
231*0fca6ea1SDimitry Andric NewMI = BuildMI(B, MI, DL, HII->get(CONST64), DstR).addImm(Val);
232*0fca6ea1SDimitry Andric
233*0fca6ea1SDimitry Andric // Replace the MI to reuse the same slot index
234*0fca6ea1SDimitry Andric if (Indexes)
235*0fca6ea1SDimitry Andric Indexes->replaceMachineInstrInMaps(*MI, *NewMI);
236*0fca6ea1SDimitry Andric MI->eraseFromParent();
237*0fca6ea1SDimitry Andric return true;
238*0fca6ea1SDimitry Andric }
239*0fca6ea1SDimitry Andric
240*0fca6ea1SDimitry Andric // Remove the instruction if it is a self-assignment.
eraseIfRedundant(MachineInstr * MI,SlotIndexes * Indexes)241*0fca6ea1SDimitry Andric bool HexagonTfrCleanup::eraseIfRedundant(MachineInstr *MI,
242*0fca6ea1SDimitry Andric SlotIndexes *Indexes) {
243*0fca6ea1SDimitry Andric unsigned Opc = MI->getOpcode();
244*0fca6ea1SDimitry Andric unsigned DefR, SrcR;
245*0fca6ea1SDimitry Andric bool IsUndef = false;
246*0fca6ea1SDimitry Andric switch (Opc) {
247*0fca6ea1SDimitry Andric case Hexagon::A2_tfr:
248*0fca6ea1SDimitry Andric // Rd = Rd
249*0fca6ea1SDimitry Andric DefR = MI->getOperand(0).getReg();
250*0fca6ea1SDimitry Andric SrcR = MI->getOperand(1).getReg();
251*0fca6ea1SDimitry Andric IsUndef = MI->getOperand(1).isUndef();
252*0fca6ea1SDimitry Andric break;
253*0fca6ea1SDimitry Andric case Hexagon::A2_tfrt:
254*0fca6ea1SDimitry Andric case Hexagon::A2_tfrf:
255*0fca6ea1SDimitry Andric // if ([!]Pu) Rd = Rd
256*0fca6ea1SDimitry Andric DefR = MI->getOperand(0).getReg();
257*0fca6ea1SDimitry Andric SrcR = MI->getOperand(2).getReg();
258*0fca6ea1SDimitry Andric IsUndef = MI->getOperand(2).isUndef();
259*0fca6ea1SDimitry Andric break;
260*0fca6ea1SDimitry Andric default:
261*0fca6ea1SDimitry Andric return false;
262*0fca6ea1SDimitry Andric }
263*0fca6ea1SDimitry Andric if (DefR != SrcR)
264*0fca6ea1SDimitry Andric return false;
265*0fca6ea1SDimitry Andric if (IsUndef) {
266*0fca6ea1SDimitry Andric MachineBasicBlock &B = *MI->getParent();
267*0fca6ea1SDimitry Andric DebugLoc DL = MI->getDebugLoc();
268*0fca6ea1SDimitry Andric auto DefI = BuildMI(B, MI, DL, HII->get(TargetOpcode::IMPLICIT_DEF), DefR);
269*0fca6ea1SDimitry Andric for (auto &Op : MI->operands())
270*0fca6ea1SDimitry Andric if (Op.isReg() && Op.isDef() && Op.isImplicit())
271*0fca6ea1SDimitry Andric DefI->addOperand(Op);
272*0fca6ea1SDimitry Andric }
273*0fca6ea1SDimitry Andric
274*0fca6ea1SDimitry Andric if (Indexes)
275*0fca6ea1SDimitry Andric Indexes->removeMachineInstrFromMaps(*MI);
276*0fca6ea1SDimitry Andric MI->eraseFromParent();
277*0fca6ea1SDimitry Andric return true;
278*0fca6ea1SDimitry Andric }
279*0fca6ea1SDimitry Andric
runOnMachineFunction(MachineFunction & MF)280*0fca6ea1SDimitry Andric bool HexagonTfrCleanup::runOnMachineFunction(MachineFunction &MF) {
281*0fca6ea1SDimitry Andric bool Changed = false;
282*0fca6ea1SDimitry Andric // Map: 32-bit register -> immediate value.
283*0fca6ea1SDimitry Andric // 64-bit registers are stored through their subregisters.
284*0fca6ea1SDimitry Andric ImmediateMap IMap;
285*0fca6ea1SDimitry Andric auto *SIWrapper = getAnalysisIfAvailable<SlotIndexesWrapperPass>();
286*0fca6ea1SDimitry Andric SlotIndexes *Indexes = SIWrapper ? &SIWrapper->getSI() : nullptr;
287*0fca6ea1SDimitry Andric
288*0fca6ea1SDimitry Andric auto &HST = MF.getSubtarget<HexagonSubtarget>();
289*0fca6ea1SDimitry Andric HII = HST.getInstrInfo();
290*0fca6ea1SDimitry Andric TRI = HST.getRegisterInfo();
291*0fca6ea1SDimitry Andric
292*0fca6ea1SDimitry Andric for (MachineBasicBlock &B : MF) {
293*0fca6ea1SDimitry Andric MachineBasicBlock::iterator J, F, NextJ;
294*0fca6ea1SDimitry Andric IMap.clear();
295*0fca6ea1SDimitry Andric bool Inserted = false, Erased = false;
296*0fca6ea1SDimitry Andric for (J = B.begin(), F = B.end(); J != F; J = NextJ) {
297*0fca6ea1SDimitry Andric NextJ = std::next(J);
298*0fca6ea1SDimitry Andric MachineInstr *MI = &*J;
299*0fca6ea1SDimitry Andric bool E = eraseIfRedundant(MI, Indexes);
300*0fca6ea1SDimitry Andric Erased |= E;
301*0fca6ea1SDimitry Andric if (E)
302*0fca6ea1SDimitry Andric continue;
303*0fca6ea1SDimitry Andric Inserted |= rewriteIfImm(MI, IMap, Indexes);
304*0fca6ea1SDimitry Andric MachineBasicBlock::iterator NewJ = std::prev(NextJ);
305*0fca6ea1SDimitry Andric updateImmMap(&*NewJ, IMap);
306*0fca6ea1SDimitry Andric }
307*0fca6ea1SDimitry Andric bool BlockC = Inserted | Erased;
308*0fca6ea1SDimitry Andric Changed |= BlockC;
309*0fca6ea1SDimitry Andric if (BlockC && Indexes)
310*0fca6ea1SDimitry Andric Indexes->repairIndexesInRange(&B, B.begin(), B.end());
311*0fca6ea1SDimitry Andric }
312*0fca6ea1SDimitry Andric
313*0fca6ea1SDimitry Andric return Changed;
314*0fca6ea1SDimitry Andric }
315*0fca6ea1SDimitry Andric
316*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
317*0fca6ea1SDimitry Andric // Public Constructor Functions
318*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
319*0fca6ea1SDimitry Andric INITIALIZE_PASS(HexagonTfrCleanup, "tfr-cleanup", "Hexagon TFR Cleanup", false,
320*0fca6ea1SDimitry Andric false)
321*0fca6ea1SDimitry Andric
createHexagonTfrCleanup()322*0fca6ea1SDimitry Andric FunctionPass *llvm::createHexagonTfrCleanup() {
323*0fca6ea1SDimitry Andric return new HexagonTfrCleanup();
324*0fca6ea1SDimitry Andric }
325