• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- Thumb2ITBlockPass.cpp - Insert Thumb-2 IT blocks ------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #define DEBUG_TYPE "thumb2-it"
11 #include "ARM.h"
12 #include "ARMMachineFunctionInfo.h"
13 #include "Thumb2InstrInfo.h"
14 #include "llvm/CodeGen/MachineInstr.h"
15 #include "llvm/CodeGen/MachineInstrBuilder.h"
16 #include "llvm/CodeGen/MachineInstrBundle.h"
17 #include "llvm/CodeGen/MachineFunctionPass.h"
18 #include "llvm/ADT/SmallSet.h"
19 #include "llvm/ADT/Statistic.h"
20 using namespace llvm;
21 
22 STATISTIC(NumITs,        "Number of IT blocks inserted");
23 STATISTIC(NumMovedInsts, "Number of predicated instructions moved");
24 
25 namespace {
26   class Thumb2ITBlockPass : public MachineFunctionPass {
27     bool PreRegAlloc;
28 
29   public:
30     static char ID;
Thumb2ITBlockPass()31     Thumb2ITBlockPass() : MachineFunctionPass(ID) {}
32 
33     const Thumb2InstrInfo *TII;
34     const TargetRegisterInfo *TRI;
35     ARMFunctionInfo *AFI;
36 
37     virtual bool runOnMachineFunction(MachineFunction &Fn);
38 
getPassName() const39     virtual const char *getPassName() const {
40       return "Thumb IT blocks insertion pass";
41     }
42 
43   private:
44     bool MoveCopyOutOfITBlock(MachineInstr *MI,
45                               ARMCC::CondCodes CC, ARMCC::CondCodes OCC,
46                               SmallSet<unsigned, 4> &Defs,
47                               SmallSet<unsigned, 4> &Uses);
48     bool InsertITInstructions(MachineBasicBlock &MBB);
49   };
50   char Thumb2ITBlockPass::ID = 0;
51 }
52 
53 /// TrackDefUses - Tracking what registers are being defined and used by
54 /// instructions in the IT block. This also tracks "dependencies", i.e. uses
55 /// in the IT block that are defined before the IT instruction.
TrackDefUses(MachineInstr * MI,SmallSet<unsigned,4> & Defs,SmallSet<unsigned,4> & Uses,const TargetRegisterInfo * TRI)56 static void TrackDefUses(MachineInstr *MI,
57                          SmallSet<unsigned, 4> &Defs,
58                          SmallSet<unsigned, 4> &Uses,
59                          const TargetRegisterInfo *TRI) {
60   SmallVector<unsigned, 4> LocalDefs;
61   SmallVector<unsigned, 4> LocalUses;
62 
63   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
64     MachineOperand &MO = MI->getOperand(i);
65     if (!MO.isReg())
66       continue;
67     unsigned Reg = MO.getReg();
68     if (!Reg || Reg == ARM::ITSTATE || Reg == ARM::SP)
69       continue;
70     if (MO.isUse())
71       LocalUses.push_back(Reg);
72     else
73       LocalDefs.push_back(Reg);
74   }
75 
76   for (unsigned i = 0, e = LocalUses.size(); i != e; ++i) {
77     unsigned Reg = LocalUses[i];
78     Uses.insert(Reg);
79     for (const uint16_t *Subreg = TRI->getSubRegisters(Reg);
80          *Subreg; ++Subreg)
81       Uses.insert(*Subreg);
82   }
83 
84   for (unsigned i = 0, e = LocalDefs.size(); i != e; ++i) {
85     unsigned Reg = LocalDefs[i];
86     Defs.insert(Reg);
87     for (const uint16_t *Subreg = TRI->getSubRegisters(Reg);
88          *Subreg; ++Subreg)
89       Defs.insert(*Subreg);
90     if (Reg == ARM::CPSR)
91       continue;
92   }
93 }
94 
isCopy(MachineInstr * MI)95 static bool isCopy(MachineInstr *MI) {
96   switch (MI->getOpcode()) {
97   default:
98     return false;
99   case ARM::MOVr:
100   case ARM::MOVr_TC:
101   case ARM::tMOVr:
102   case ARM::t2MOVr:
103     return true;
104   }
105 }
106 
107 bool
MoveCopyOutOfITBlock(MachineInstr * MI,ARMCC::CondCodes CC,ARMCC::CondCodes OCC,SmallSet<unsigned,4> & Defs,SmallSet<unsigned,4> & Uses)108 Thumb2ITBlockPass::MoveCopyOutOfITBlock(MachineInstr *MI,
109                                       ARMCC::CondCodes CC, ARMCC::CondCodes OCC,
110                                         SmallSet<unsigned, 4> &Defs,
111                                         SmallSet<unsigned, 4> &Uses) {
112   if (!isCopy(MI))
113     return false;
114   // llvm models select's as two-address instructions. That means a copy
115   // is inserted before a t2MOVccr, etc. If the copy is scheduled in
116   // between selects we would end up creating multiple IT blocks.
117   assert(MI->getOperand(0).getSubReg() == 0 &&
118          MI->getOperand(1).getSubReg() == 0 &&
119          "Sub-register indices still around?");
120 
121   unsigned DstReg = MI->getOperand(0).getReg();
122   unsigned SrcReg = MI->getOperand(1).getReg();
123 
124   // First check if it's safe to move it.
125   if (Uses.count(DstReg) || Defs.count(SrcReg))
126     return false;
127 
128   // If the CPSR is defined by this copy, then we don't want to move it. E.g.,
129   // if we have:
130   //
131   //   movs  r1, r1
132   //   rsb   r1, 0
133   //   movs  r2, r2
134   //   rsb   r2, 0
135   //
136   // we don't want this to be converted to:
137   //
138   //   movs  r1, r1
139   //   movs  r2, r2
140   //   itt   mi
141   //   rsb   r1, 0
142   //   rsb   r2, 0
143   //
144   const MCInstrDesc &MCID = MI->getDesc();
145   if (MI->hasOptionalDef() &&
146       MI->getOperand(MCID.getNumOperands() - 1).getReg() == ARM::CPSR)
147     return false;
148 
149   // Then peek at the next instruction to see if it's predicated on CC or OCC.
150   // If not, then there is nothing to be gained by moving the copy.
151   MachineBasicBlock::iterator I = MI; ++I;
152   MachineBasicBlock::iterator E = MI->getParent()->end();
153   while (I != E && I->isDebugValue())
154     ++I;
155   if (I != E) {
156     unsigned NPredReg = 0;
157     ARMCC::CondCodes NCC = getITInstrPredicate(I, NPredReg);
158     if (NCC == CC || NCC == OCC)
159       return true;
160   }
161   return false;
162 }
163 
InsertITInstructions(MachineBasicBlock & MBB)164 bool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) {
165   bool Modified = false;
166 
167   SmallSet<unsigned, 4> Defs;
168   SmallSet<unsigned, 4> Uses;
169   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
170   while (MBBI != E) {
171     MachineInstr *MI = &*MBBI;
172     DebugLoc dl = MI->getDebugLoc();
173     unsigned PredReg = 0;
174     ARMCC::CondCodes CC = getITInstrPredicate(MI, PredReg);
175     if (CC == ARMCC::AL) {
176       ++MBBI;
177       continue;
178     }
179 
180     Defs.clear();
181     Uses.clear();
182     TrackDefUses(MI, Defs, Uses, TRI);
183 
184     // Insert an IT instruction.
185     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT))
186       .addImm(CC);
187 
188     // Add implicit use of ITSTATE to IT block instructions.
189     MI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/,
190                                              true/*isImp*/, false/*isKill*/));
191 
192     MachineInstr *LastITMI = MI;
193     MachineBasicBlock::iterator InsertPos = MIB;
194     ++MBBI;
195 
196     // Form IT block.
197     ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC);
198     unsigned Mask = 0, Pos = 3;
199     // Branches, including tricky ones like LDM_RET, need to end an IT
200     // block so check the instruction we just put in the block.
201     for (; MBBI != E && Pos &&
202            (!MI->isBranch() && !MI->isReturn()) ; ++MBBI) {
203       if (MBBI->isDebugValue())
204         continue;
205 
206       MachineInstr *NMI = &*MBBI;
207       MI = NMI;
208 
209       unsigned NPredReg = 0;
210       ARMCC::CondCodes NCC = getITInstrPredicate(NMI, NPredReg);
211       if (NCC == CC || NCC == OCC) {
212         Mask |= (NCC & 1) << Pos;
213         // Add implicit use of ITSTATE.
214         NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/,
215                                                true/*isImp*/, false/*isKill*/));
216         LastITMI = NMI;
217       } else {
218         if (NCC == ARMCC::AL &&
219             MoveCopyOutOfITBlock(NMI, CC, OCC, Defs, Uses)) {
220           --MBBI;
221           MBB.remove(NMI);
222           MBB.insert(InsertPos, NMI);
223           ++NumMovedInsts;
224           continue;
225         }
226         break;
227       }
228       TrackDefUses(NMI, Defs, Uses, TRI);
229       --Pos;
230     }
231 
232     // Finalize IT mask.
233     Mask |= (1 << Pos);
234     // Tag along (firstcond[0] << 4) with the mask.
235     Mask |= (CC & 1) << 4;
236     MIB.addImm(Mask);
237 
238     // Last instruction in IT block kills ITSTATE.
239     LastITMI->findRegisterUseOperand(ARM::ITSTATE)->setIsKill();
240 
241     // Finalize the bundle.
242     MachineBasicBlock::instr_iterator LI = LastITMI;
243     finalizeBundle(MBB, InsertPos.getInstrIterator(), llvm::next(LI));
244 
245     Modified = true;
246     ++NumITs;
247   }
248 
249   return Modified;
250 }
251 
runOnMachineFunction(MachineFunction & Fn)252 bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) {
253   const TargetMachine &TM = Fn.getTarget();
254   AFI = Fn.getInfo<ARMFunctionInfo>();
255   TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo());
256   TRI = TM.getRegisterInfo();
257 
258   if (!AFI->isThumbFunction())
259     return false;
260 
261   bool Modified = false;
262   for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; ) {
263     MachineBasicBlock &MBB = *MFI;
264     ++MFI;
265     Modified |= InsertITInstructions(MBB);
266   }
267 
268   if (Modified)
269     AFI->setHasITBlocks(true);
270 
271   return Modified;
272 }
273 
274 /// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks
275 /// insertion pass.
createThumb2ITBlockPass()276 FunctionPass *llvm::createThumb2ITBlockPass() {
277   return new Thumb2ITBlockPass();
278 }
279