]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
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 | ||
223e47cc LB |
10 | #include "ARM.h" |
11 | #include "ARMMachineFunctionInfo.h" | |
12 | #include "Thumb2InstrInfo.h" | |
970d7e83 LB |
13 | #include "llvm/ADT/SmallSet.h" |
14 | #include "llvm/ADT/Statistic.h" | |
15 | #include "llvm/CodeGen/MachineFunctionPass.h" | |
223e47cc LB |
16 | #include "llvm/CodeGen/MachineInstr.h" |
17 | #include "llvm/CodeGen/MachineInstrBuilder.h" | |
18 | #include "llvm/CodeGen/MachineInstrBundle.h" | |
223e47cc LB |
19 | using namespace llvm; |
20 | ||
1a4d82fc JJ |
21 | #define DEBUG_TYPE "thumb2-it" |
22 | ||
223e47cc LB |
23 | STATISTIC(NumITs, "Number of IT blocks inserted"); |
24 | STATISTIC(NumMovedInsts, "Number of predicated instructions moved"); | |
25 | ||
26 | namespace { | |
27 | class Thumb2ITBlockPass : public MachineFunctionPass { | |
28 | public: | |
29 | static char ID; | |
30 | Thumb2ITBlockPass() : MachineFunctionPass(ID) {} | |
31 | ||
1a4d82fc | 32 | bool restrictIT; |
223e47cc LB |
33 | const Thumb2InstrInfo *TII; |
34 | const TargetRegisterInfo *TRI; | |
35 | ARMFunctionInfo *AFI; | |
36 | ||
1a4d82fc | 37 | bool runOnMachineFunction(MachineFunction &Fn) override; |
223e47cc | 38 | |
1a4d82fc | 39 | const char *getPassName() const override { |
223e47cc LB |
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. | |
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]; | |
1a4d82fc JJ |
78 | for (MCSubRegIterator Subreg(Reg, TRI, /*IncludeSelf=*/true); |
79 | Subreg.isValid(); ++Subreg) | |
223e47cc LB |
80 | Uses.insert(*Subreg); |
81 | } | |
82 | ||
83 | for (unsigned i = 0, e = LocalDefs.size(); i != e; ++i) { | |
84 | unsigned Reg = LocalDefs[i]; | |
1a4d82fc JJ |
85 | for (MCSubRegIterator Subreg(Reg, TRI, /*IncludeSelf=*/true); |
86 | Subreg.isValid(); ++Subreg) | |
223e47cc LB |
87 | Defs.insert(*Subreg); |
88 | if (Reg == ARM::CPSR) | |
89 | continue; | |
90 | } | |
91 | } | |
92 | ||
93 | static bool isCopy(MachineInstr *MI) { | |
94 | switch (MI->getOpcode()) { | |
95 | default: | |
96 | return false; | |
97 | case ARM::MOVr: | |
98 | case ARM::MOVr_TC: | |
99 | case ARM::tMOVr: | |
100 | case ARM::t2MOVr: | |
101 | return true; | |
102 | } | |
103 | } | |
104 | ||
105 | bool | |
106 | Thumb2ITBlockPass::MoveCopyOutOfITBlock(MachineInstr *MI, | |
107 | ARMCC::CondCodes CC, ARMCC::CondCodes OCC, | |
108 | SmallSet<unsigned, 4> &Defs, | |
109 | SmallSet<unsigned, 4> &Uses) { | |
110 | if (!isCopy(MI)) | |
111 | return false; | |
112 | // llvm models select's as two-address instructions. That means a copy | |
113 | // is inserted before a t2MOVccr, etc. If the copy is scheduled in | |
114 | // between selects we would end up creating multiple IT blocks. | |
115 | assert(MI->getOperand(0).getSubReg() == 0 && | |
116 | MI->getOperand(1).getSubReg() == 0 && | |
117 | "Sub-register indices still around?"); | |
118 | ||
119 | unsigned DstReg = MI->getOperand(0).getReg(); | |
120 | unsigned SrcReg = MI->getOperand(1).getReg(); | |
121 | ||
122 | // First check if it's safe to move it. | |
123 | if (Uses.count(DstReg) || Defs.count(SrcReg)) | |
124 | return false; | |
125 | ||
126 | // If the CPSR is defined by this copy, then we don't want to move it. E.g., | |
127 | // if we have: | |
128 | // | |
129 | // movs r1, r1 | |
130 | // rsb r1, 0 | |
131 | // movs r2, r2 | |
132 | // rsb r2, 0 | |
133 | // | |
134 | // we don't want this to be converted to: | |
135 | // | |
136 | // movs r1, r1 | |
137 | // movs r2, r2 | |
138 | // itt mi | |
139 | // rsb r1, 0 | |
140 | // rsb r2, 0 | |
141 | // | |
142 | const MCInstrDesc &MCID = MI->getDesc(); | |
143 | if (MI->hasOptionalDef() && | |
144 | MI->getOperand(MCID.getNumOperands() - 1).getReg() == ARM::CPSR) | |
145 | return false; | |
146 | ||
147 | // Then peek at the next instruction to see if it's predicated on CC or OCC. | |
148 | // If not, then there is nothing to be gained by moving the copy. | |
149 | MachineBasicBlock::iterator I = MI; ++I; | |
150 | MachineBasicBlock::iterator E = MI->getParent()->end(); | |
151 | while (I != E && I->isDebugValue()) | |
152 | ++I; | |
153 | if (I != E) { | |
154 | unsigned NPredReg = 0; | |
155 | ARMCC::CondCodes NCC = getITInstrPredicate(I, NPredReg); | |
156 | if (NCC == CC || NCC == OCC) | |
157 | return true; | |
158 | } | |
159 | return false; | |
160 | } | |
161 | ||
162 | bool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) { | |
163 | bool Modified = false; | |
164 | ||
165 | SmallSet<unsigned, 4> Defs; | |
166 | SmallSet<unsigned, 4> Uses; | |
167 | MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); | |
168 | while (MBBI != E) { | |
169 | MachineInstr *MI = &*MBBI; | |
170 | DebugLoc dl = MI->getDebugLoc(); | |
171 | unsigned PredReg = 0; | |
172 | ARMCC::CondCodes CC = getITInstrPredicate(MI, PredReg); | |
173 | if (CC == ARMCC::AL) { | |
174 | ++MBBI; | |
175 | continue; | |
176 | } | |
177 | ||
178 | Defs.clear(); | |
179 | Uses.clear(); | |
180 | TrackDefUses(MI, Defs, Uses, TRI); | |
181 | ||
182 | // Insert an IT instruction. | |
183 | MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT)) | |
184 | .addImm(CC); | |
185 | ||
186 | // Add implicit use of ITSTATE to IT block instructions. | |
187 | MI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/, | |
188 | true/*isImp*/, false/*isKill*/)); | |
189 | ||
190 | MachineInstr *LastITMI = MI; | |
191 | MachineBasicBlock::iterator InsertPos = MIB; | |
192 | ++MBBI; | |
193 | ||
194 | // Form IT block. | |
195 | ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC); | |
196 | unsigned Mask = 0, Pos = 3; | |
1a4d82fc JJ |
197 | |
198 | // v8 IT blocks are limited to one conditional op unless -arm-no-restrict-it | |
199 | // is set: skip the loop | |
200 | if (!restrictIT) { | |
201 | // Branches, including tricky ones like LDM_RET, need to end an IT | |
202 | // block so check the instruction we just put in the block. | |
203 | for (; MBBI != E && Pos && | |
204 | (!MI->isBranch() && !MI->isReturn()) ; ++MBBI) { | |
205 | if (MBBI->isDebugValue()) | |
223e47cc | 206 | continue; |
1a4d82fc JJ |
207 | |
208 | MachineInstr *NMI = &*MBBI; | |
209 | MI = NMI; | |
210 | ||
211 | unsigned NPredReg = 0; | |
212 | ARMCC::CondCodes NCC = getITInstrPredicate(NMI, NPredReg); | |
213 | if (NCC == CC || NCC == OCC) { | |
214 | Mask |= (NCC & 1) << Pos; | |
215 | // Add implicit use of ITSTATE. | |
216 | NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/, | |
217 | true/*isImp*/, false/*isKill*/)); | |
218 | LastITMI = NMI; | |
219 | } else { | |
220 | if (NCC == ARMCC::AL && | |
221 | MoveCopyOutOfITBlock(NMI, CC, OCC, Defs, Uses)) { | |
222 | --MBBI; | |
223 | MBB.remove(NMI); | |
224 | MBB.insert(InsertPos, NMI); | |
225 | ++NumMovedInsts; | |
226 | continue; | |
227 | } | |
228 | break; | |
223e47cc | 229 | } |
1a4d82fc JJ |
230 | TrackDefUses(NMI, Defs, Uses, TRI); |
231 | --Pos; | |
223e47cc | 232 | } |
223e47cc LB |
233 | } |
234 | ||
235 | // Finalize IT mask. | |
236 | Mask |= (1 << Pos); | |
237 | // Tag along (firstcond[0] << 4) with the mask. | |
238 | Mask |= (CC & 1) << 4; | |
239 | MIB.addImm(Mask); | |
240 | ||
241 | // Last instruction in IT block kills ITSTATE. | |
242 | LastITMI->findRegisterUseOperand(ARM::ITSTATE)->setIsKill(); | |
243 | ||
244 | // Finalize the bundle. | |
245 | MachineBasicBlock::instr_iterator LI = LastITMI; | |
1a4d82fc | 246 | finalizeBundle(MBB, InsertPos.getInstrIterator(), std::next(LI)); |
223e47cc LB |
247 | |
248 | Modified = true; | |
249 | ++NumITs; | |
250 | } | |
251 | ||
252 | return Modified; | |
253 | } | |
254 | ||
255 | bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) { | |
256 | const TargetMachine &TM = Fn.getTarget(); | |
257 | AFI = Fn.getInfo<ARMFunctionInfo>(); | |
1a4d82fc JJ |
258 | TII = static_cast<const Thumb2InstrInfo *>( |
259 | TM.getSubtargetImpl()->getInstrInfo()); | |
260 | TRI = TM.getSubtargetImpl()->getRegisterInfo(); | |
261 | restrictIT = TM.getSubtarget<ARMSubtarget>().restrictIT(); | |
223e47cc LB |
262 | |
263 | if (!AFI->isThumbFunction()) | |
264 | return false; | |
265 | ||
266 | bool Modified = false; | |
267 | for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; ) { | |
268 | MachineBasicBlock &MBB = *MFI; | |
269 | ++MFI; | |
270 | Modified |= InsertITInstructions(MBB); | |
271 | } | |
272 | ||
273 | if (Modified) | |
274 | AFI->setHasITBlocks(true); | |
275 | ||
276 | return Modified; | |
277 | } | |
278 | ||
279 | /// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks | |
280 | /// insertion pass. | |
281 | FunctionPass *llvm::createThumb2ITBlockPass() { | |
282 | return new Thumb2ITBlockPass(); | |
283 | } |