LLVM 24.0.0git
Thumb2ITBlockPass.cpp
Go to the documentation of this file.
1//===-- Thumb2ITBlockPass.cpp - Insert Thumb-2 IT blocks ------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "ARM.h"
11#include "ARMSubtarget.h"
12#include "Thumb2InstrInfo.h"
13#include "llvm/ADT/SmallSet.h"
15#include "llvm/ADT/Statistic.h"
16#include "llvm/ADT/StringRef.h"
25#include "llvm/IR/DebugLoc.h"
26#include "llvm/MC/MCInstrDesc.h"
27#include <cassert>
28#include <new>
29
30using namespace llvm;
31
32#define DEBUG_TYPE "thumb2-it"
33#define PASS_NAME "Thumb IT blocks insertion pass"
34
35STATISTIC(NumITs, "Number of IT blocks inserted");
36STATISTIC(NumMovedInsts, "Number of predicated instructions moved");
37
38using RegisterSet = SmallSet<unsigned, 4>;
39
40namespace {
41
42 class Thumb2ITBlock : public MachineFunctionPass {
43 public:
44 static char ID;
45
46 bool restrictIT;
47 const Thumb2InstrInfo *TII;
49 ARMFunctionInfo *AFI;
50
51 Thumb2ITBlock() : MachineFunctionPass(ID) {}
52
53 bool runOnMachineFunction(MachineFunction &Fn) override;
54
55 MachineFunctionProperties getRequiredProperties() const override {
56 return MachineFunctionProperties().setNoVRegs();
57 }
58
59 StringRef getPassName() const override {
60 return PASS_NAME;
61 }
62
63 void getAnalysisUsage(AnalysisUsage &AU) const override {
66 }
67
68 private:
69 bool MoveCopyOutOfITBlock(MachineInstr *MI,
71 RegisterSet &Defs, RegisterSet &Uses);
72 bool InsertITInstructions(MachineBasicBlock &Block);
73 };
74
75 char Thumb2ITBlock::ID = 0;
76
77} // end anonymous namespace
78
79INITIALIZE_PASS(Thumb2ITBlock, DEBUG_TYPE, PASS_NAME, false, false)
80
81/// TrackDefUses - Tracking what registers are being defined and used by
82/// instructions in the IT block. This also tracks "dependencies", i.e. uses
83/// in the IT block that are defined before the IT instruction.
84static void TrackDefUses(MachineInstr *MI, RegisterSet &Defs, RegisterSet &Uses,
86 using RegList = SmallVector<unsigned, 4>;
87 RegList LocalDefs;
88 RegList LocalUses;
89
90 for (auto &MO : MI->operands()) {
91 if (!MO.isReg())
92 continue;
93 Register Reg = MO.getReg();
94 if (!Reg || Reg == ARM::ITSTATE || Reg == ARM::SP)
95 continue;
96 if (MO.isUse())
97 LocalUses.push_back(Reg);
98 else
99 LocalDefs.push_back(Reg);
100 }
101
102 auto InsertUsesDefs = [&](RegList &Regs, RegisterSet &UsesDefs) {
103 for (unsigned Reg : Regs)
104 UsesDefs.insert_range(TRI->subregs_inclusive(Reg));
105 };
106
107 InsertUsesDefs(LocalDefs, Defs);
108 InsertUsesDefs(LocalUses, Uses);
109}
110
111/// Clear kill flags for any uses in the given set. This will likely
112/// conservatively remove more kill flags than are necessary, but removing them
113/// is safer than incorrect kill flags remaining on instructions.
114static void ClearKillFlags(MachineInstr *MI, RegisterSet &Uses) {
115 for (MachineOperand &MO : MI->operands()) {
116 if (!MO.isReg() || MO.isDef() || !MO.isKill())
117 continue;
118 if (!Uses.count(MO.getReg()))
119 continue;
120 MO.setIsKill(false);
121 }
122}
123
124static bool isCopy(MachineInstr *MI) {
125 switch (MI->getOpcode()) {
126 default:
127 return false;
128 case ARM::MOVr:
129 case ARM::MOVr_TC:
130 case ARM::tMOVr:
131 case ARM::t2MOVr:
132 return true;
133 }
134}
135
136bool
137Thumb2ITBlock::MoveCopyOutOfITBlock(MachineInstr *MI,
139 RegisterSet &Defs, RegisterSet &Uses) {
140 if (!isCopy(MI))
141 return false;
142 // llvm models select's as two-address instructions. That means a copy
143 // is inserted before a t2MOVccr, etc. If the copy is scheduled in
144 // between selects we would end up creating multiple IT blocks.
145 assert(MI->getOperand(0).getSubReg() == 0 &&
146 MI->getOperand(1).getSubReg() == 0 &&
147 "Sub-register indices still around?");
148
149 Register DstReg = MI->getOperand(0).getReg();
150 Register SrcReg = MI->getOperand(1).getReg();
151
152 // First check if it's safe to move it.
153 if (Uses.count(DstReg) || Defs.count(SrcReg))
154 return false;
155
156 // If the CPSR is defined by this copy, then we don't want to move it. E.g.,
157 // if we have:
158 //
159 // movs r1, r1
160 // rsb r1, 0
161 // movs r2, r2
162 // rsb r2, 0
163 //
164 // we don't want this to be converted to:
165 //
166 // movs r1, r1
167 // movs r2, r2
168 // itt mi
169 // rsb r1, 0
170 // rsb r2, 0
171 //
172 const MCInstrDesc &MCID = MI->getDesc();
173 if (MI->hasOptionalDef() &&
174 MI->getOperand(MCID.getNumOperands() - 1).getReg() == ARM::CPSR)
175 return false;
176
177 // Then peek at the next instruction to see if it's predicated on CC or OCC.
178 // If not, then there is nothing to be gained by moving the copy.
180 ++I;
181 MachineBasicBlock::iterator E = MI->getParent()->end();
182
183 while (I != E && I->isDebugInstr())
184 ++I;
185
186 if (I != E) {
187 Register NPredReg;
188 ARMCC::CondCodes NCC = getITInstrPredicate(*I, NPredReg);
189 if (NCC == CC || NCC == OCC)
190 return true;
191 }
192 return false;
193}
194
195bool Thumb2ITBlock::InsertITInstructions(MachineBasicBlock &MBB) {
196 bool Modified = false;
197 RegisterSet Defs, Uses;
199
200 while (MBBI != E) {
201 MachineInstr *MI = &*MBBI;
202 DebugLoc dl = MI->getDebugLoc();
203 Register PredReg;
205 if (CC == ARMCC::AL) {
206 ++MBBI;
207 continue;
208 }
209
210 Defs.clear();
211 Uses.clear();
212 TrackDefUses(MI, Defs, Uses, TRI);
213
214 // Insert an IT instruction.
215 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT))
216 .addImm(CC);
217
218 // Add implicit use of ITSTATE to IT block instructions.
219 MI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/,
220 true/*isImp*/, false/*isKill*/));
221
222 MachineInstr *LastITMI = MI;
223 MachineBasicBlock::iterator InsertPos = MIB.getInstr();
224 ++MBBI;
225
226 // Form IT block.
228 unsigned Mask = 0, Pos = 3;
229
230 // IT blocks are limited to one conditional op if -arm-restrict-it
231 // is set: skip the loop
232 if (!restrictIT) {
233 LLVM_DEBUG(dbgs() << "Allowing complex IT block\n");
234 // Branches, including tricky ones like LDM_RET, need to end an IT
235 // block so check the instruction we just put in the block.
236 for (; MBBI != E && Pos &&
237 (!MI->isBranch() && !MI->isReturn()) ; ++MBBI) {
238 if (MBBI->isDebugInstr())
239 continue;
240
241 MachineInstr *NMI = &*MBBI;
242 MI = NMI;
243
244 Register NPredReg;
245 ARMCC::CondCodes NCC = getITInstrPredicate(*NMI, NPredReg);
246 if (NCC == CC || NCC == OCC) {
247 Mask |= ((NCC ^ CC) & 1) << Pos;
248 // Add implicit use of ITSTATE.
249 NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/,
250 true/*isImp*/, false/*isKill*/));
251 LastITMI = NMI;
252 } else {
253 if (NCC == ARMCC::AL &&
254 MoveCopyOutOfITBlock(NMI, CC, OCC, Defs, Uses)) {
255 --MBBI;
256 MBB.remove(NMI);
257 MBB.insert(InsertPos, NMI);
259 ++NumMovedInsts;
260 continue;
261 }
262 break;
263 }
264 TrackDefUses(NMI, Defs, Uses, TRI);
265 --Pos;
266 }
267 }
268
269 // Finalize IT mask.
270 Mask |= (1 << Pos);
271 MIB.addImm(Mask);
272
273 // Last instruction in IT block kills ITSTATE.
274 LastITMI->findRegisterUseOperand(ARM::ITSTATE, /*TRI=*/nullptr)
275 ->setIsKill();
276
277 // Finalize the bundle.
279 ++LastITMI->getIterator());
280
281 Modified = true;
282 ++NumITs;
283 }
284
285 return Modified;
286}
287
288bool Thumb2ITBlock::runOnMachineFunction(MachineFunction &Fn) {
289 const ARMSubtarget &STI = Fn.getSubtarget<ARMSubtarget>();
290 if (!STI.isThumb2())
291 return false;
292 AFI = Fn.getInfo<ARMFunctionInfo>();
293 TII = static_cast<const Thumb2InstrInfo *>(STI.getInstrInfo());
294 TRI = STI.getRegisterInfo();
295 restrictIT = STI.restrictIT();
296
297 if (!AFI->isThumbFunction())
298 return false;
299
300 bool Modified = false;
301 for (auto &MBB : Fn )
302 Modified |= InsertITInstructions(MBB);
303
304 if (Modified)
305 AFI->setHasITBlocks(true);
306
307 return Modified;
308}
309
310/// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks
311/// insertion pass.
312FunctionPass *llvm::createThumb2ITBlockPass() { return new Thumb2ITBlock(); }
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
Remove Loads Into Fake Uses
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
SmallSet< unsigned, 4 > RegisterSet
static bool isCopy(MachineInstr *MI)
static void ClearKillFlags(MachineInstr *MI, RegisterSet &Uses)
Clear kill flags for any uses in the given set.
static void TrackDefUses(MachineInstr *MI, RegisterSet &Defs, RegisterSet &Uses, const TargetRegisterInfo *TRI)
TrackDefUses - Tracking what registers are being defined and used by instructions in the IT block.
#define PASS_NAME
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb2() const
const ARMBaseRegisterInfo * getRegisterInfo() const override
bool restrictIT() const
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
MachineInstr * remove(MachineInstr *I)
Remove the unbundled instruction from the instruction list without deleting it.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Properties which a MachineFunction may have at a given point in time.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
MachineOperand * findRegisterUseOperand(Register Reg, const TargetRegisterInfo *TRI, bool isKill=false)
Wrapper for findRegisterUseOperandIdx, it returns a pointer to the MachineOperand rather than an inde...
MachineOperand class - Representation of each machine instruction operand.
void setIsKill(bool Val=true)
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:134
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
self_iterator getIterator()
Definition ilist_node.h:123
static CondCodes getOppositeCondition(CondCodes CC)
Definition ARMBaseInfo.h:49
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
ARMCC::CondCodes getITInstrPredicate(const MachineInstr &MI, Register &PredReg)
getITInstrPredicate - Valid only in Thumb2 mode.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
FunctionPass * createThumb2ITBlockPass()
createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks insertion pass.