xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonTfrCleanup.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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;
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   }
59*0fca6ea1SDimitry Andric   StringRef getPassName() const override { return "Hexagon TFR Cleanup"; }
60*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 
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.
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.
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.
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.
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.
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 
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 
322*0fca6ea1SDimitry Andric FunctionPass *llvm::createHexagonTfrCleanup() {
323*0fca6ea1SDimitry Andric   return new HexagonTfrCleanup();
324*0fca6ea1SDimitry Andric }
325