LLVM 20.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"
24#include "llvm/IR/DebugLoc.h"
25#include "llvm/MC/MCInstrDesc.h"
26#include <cassert>
27#include <new>
28
29using namespace llvm;
30
31#define DEBUG_TYPE "thumb2-it"
32#define PASS_NAME "Thumb IT blocks insertion pass"
33
34STATISTIC(NumITs, "Number of IT blocks inserted");
35STATISTIC(NumMovedInsts, "Number of predicated instructions moved");
36
38
39namespace {
40
41 class Thumb2ITBlock : public MachineFunctionPass {
42 public:
43 static char ID;
44
45 bool restrictIT;
46 const Thumb2InstrInfo *TII;
48 ARMFunctionInfo *AFI;
49
50 Thumb2ITBlock() : MachineFunctionPass(ID) {}
51
52 bool runOnMachineFunction(MachineFunction &Fn) override;
53
56 MachineFunctionProperties::Property::NoVRegs);
57 }
58
59 StringRef getPassName() const override {
60 return PASS_NAME;
61 }
62
63 private:
64 bool MoveCopyOutOfITBlock(MachineInstr *MI,
67 bool InsertITInstructions(MachineBasicBlock &Block);
68 };
69
70 char Thumb2ITBlock::ID = 0;
71
72} // end anonymous namespace
73
74INITIALIZE_PASS(Thumb2ITBlock, DEBUG_TYPE, PASS_NAME, false, false)
75
76/// TrackDefUses - Tracking what registers are being defined and used by
77/// instructions in the IT block. This also tracks "dependencies", i.e. uses
78/// in the IT block that are defined before the IT instruction.
81 using RegList = SmallVector<unsigned, 4>;
82 RegList LocalDefs;
83 RegList LocalUses;
84
85 for (auto &MO : MI->operands()) {
86 if (!MO.isReg())
87 continue;
88 Register Reg = MO.getReg();
89 if (!Reg || Reg == ARM::ITSTATE || Reg == ARM::SP)
90 continue;
91 if (MO.isUse())
92 LocalUses.push_back(Reg);
93 else
94 LocalDefs.push_back(Reg);
95 }
96
97 auto InsertUsesDefs = [&](RegList &Regs, RegisterSet &UsesDefs) {
98 for (unsigned Reg : Regs)
99 for (MCPhysReg Subreg : TRI->subregs_inclusive(Reg))
100 UsesDefs.insert(Subreg);
101 };
102
103 InsertUsesDefs(LocalDefs, Defs);
104 InsertUsesDefs(LocalUses, Uses);
105}
106
107/// Clear kill flags for any uses in the given set. This will likely
108/// conservatively remove more kill flags than are necessary, but removing them
109/// is safer than incorrect kill flags remaining on instructions.
111 for (MachineOperand &MO : MI->operands()) {
112 if (!MO.isReg() || MO.isDef() || !MO.isKill())
113 continue;
114 if (!Uses.count(MO.getReg()))
115 continue;
116 MO.setIsKill(false);
117 }
118}
119
120static bool isCopy(MachineInstr *MI) {
121 switch (MI->getOpcode()) {
122 default:
123 return false;
124 case ARM::MOVr:
125 case ARM::MOVr_TC:
126 case ARM::tMOVr:
127 case ARM::t2MOVr:
128 return true;
129 }
130}
131
132bool
133Thumb2ITBlock::MoveCopyOutOfITBlock(MachineInstr *MI,
135 RegisterSet &Defs, RegisterSet &Uses) {
136 if (!isCopy(MI))
137 return false;
138 // llvm models select's as two-address instructions. That means a copy
139 // is inserted before a t2MOVccr, etc. If the copy is scheduled in
140 // between selects we would end up creating multiple IT blocks.
141 assert(MI->getOperand(0).getSubReg() == 0 &&
142 MI->getOperand(1).getSubReg() == 0 &&
143 "Sub-register indices still around?");
144
145 Register DstReg = MI->getOperand(0).getReg();
146 Register SrcReg = MI->getOperand(1).getReg();
147
148 // First check if it's safe to move it.
149 if (Uses.count(DstReg) || Defs.count(SrcReg))
150 return false;
151
152 // If the CPSR is defined by this copy, then we don't want to move it. E.g.,
153 // if we have:
154 //
155 // movs r1, r1
156 // rsb r1, 0
157 // movs r2, r2
158 // rsb r2, 0
159 //
160 // we don't want this to be converted to:
161 //
162 // movs r1, r1
163 // movs r2, r2
164 // itt mi
165 // rsb r1, 0
166 // rsb r2, 0
167 //
168 const MCInstrDesc &MCID = MI->getDesc();
169 if (MI->hasOptionalDef() &&
170 MI->getOperand(MCID.getNumOperands() - 1).getReg() == ARM::CPSR)
171 return false;
172
173 // Then peek at the next instruction to see if it's predicated on CC or OCC.
174 // If not, then there is nothing to be gained by moving the copy.
176 ++I;
177 MachineBasicBlock::iterator E = MI->getParent()->end();
178
179 while (I != E && I->isDebugInstr())
180 ++I;
181
182 if (I != E) {
183 Register NPredReg;
184 ARMCC::CondCodes NCC = getITInstrPredicate(*I, NPredReg);
185 if (NCC == CC || NCC == OCC)
186 return true;
187 }
188 return false;
189}
190
191bool Thumb2ITBlock::InsertITInstructions(MachineBasicBlock &MBB) {
192 bool Modified = false;
193 RegisterSet Defs, Uses;
195
196 while (MBBI != E) {
197 MachineInstr *MI = &*MBBI;
198 DebugLoc dl = MI->getDebugLoc();
199 Register PredReg;
201 if (CC == ARMCC::AL) {
202 ++MBBI;
203 continue;
204 }
205
206 Defs.clear();
207 Uses.clear();
208 TrackDefUses(MI, Defs, Uses, TRI);
209
210 // Insert an IT instruction.
211 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT))
212 .addImm(CC);
213
214 // Add implicit use of ITSTATE to IT block instructions.
215 MI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/,
216 true/*isImp*/, false/*isKill*/));
217
218 MachineInstr *LastITMI = MI;
219 MachineBasicBlock::iterator InsertPos = MIB.getInstr();
220 ++MBBI;
221
222 // Form IT block.
224 unsigned Mask = 0, Pos = 3;
225
226 // IT blocks are limited to one conditional op if -arm-restrict-it
227 // is set: skip the loop
228 if (!restrictIT) {
229 LLVM_DEBUG(dbgs() << "Allowing complex IT block\n");
230 // Branches, including tricky ones like LDM_RET, need to end an IT
231 // block so check the instruction we just put in the block.
232 for (; MBBI != E && Pos &&
233 (!MI->isBranch() && !MI->isReturn()) ; ++MBBI) {
234 if (MBBI->isDebugInstr())
235 continue;
236
237 MachineInstr *NMI = &*MBBI;
238 MI = NMI;
239
240 Register NPredReg;
241 ARMCC::CondCodes NCC = getITInstrPredicate(*NMI, NPredReg);
242 if (NCC == CC || NCC == OCC) {
243 Mask |= ((NCC ^ CC) & 1) << Pos;
244 // Add implicit use of ITSTATE.
245 NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/,
246 true/*isImp*/, false/*isKill*/));
247 LastITMI = NMI;
248 } else {
249 if (NCC == ARMCC::AL &&
250 MoveCopyOutOfITBlock(NMI, CC, OCC, Defs, Uses)) {
251 --MBBI;
252 MBB.remove(NMI);
253 MBB.insert(InsertPos, NMI);
255 ++NumMovedInsts;
256 continue;
257 }
258 break;
259 }
260 TrackDefUses(NMI, Defs, Uses, TRI);
261 --Pos;
262 }
263 }
264
265 // Finalize IT mask.
266 Mask |= (1 << Pos);
267 MIB.addImm(Mask);
268
269 // Last instruction in IT block kills ITSTATE.
270 LastITMI->findRegisterUseOperand(ARM::ITSTATE, /*TRI=*/nullptr)
271 ->setIsKill();
272
273 // Finalize the bundle.
275 ++LastITMI->getIterator());
276
277 Modified = true;
278 ++NumITs;
279 }
280
281 return Modified;
282}
283
284bool Thumb2ITBlock::runOnMachineFunction(MachineFunction &Fn) {
285 const ARMSubtarget &STI = Fn.getSubtarget<ARMSubtarget>();
286 if (!STI.isThumb2())
287 return false;
288 AFI = Fn.getInfo<ARMFunctionInfo>();
289 TII = static_cast<const Thumb2InstrInfo *>(STI.getInstrInfo());
290 TRI = STI.getRegisterInfo();
291 restrictIT = STI.restrictIT();
292
293 if (!AFI->isThumbFunction())
294 return false;
295
296 bool Modified = false;
297 for (auto &MBB : Fn )
298 Modified |= InsertITInstructions(MBB);
299
300 if (Modified)
301 AFI->setHasITBlocks(true);
302
303 return Modified;
304}
305
306/// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks
307/// insertion pass.
308FunctionPass *llvm::createThumb2ITBlockPass() { return new Thumb2ITBlock(); }
aarch64 promote const
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator MBBI
#define LLVM_DEBUG(...)
Definition: Debug.h:106
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
Remove Loads Into Fake Uses
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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:166
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.
#define PASS_NAME
#define DEBUG_TYPE
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
Definition: ARMSubtarget.h:238
bool isThumb2() const
Definition: ARMSubtarget.h:404
const ARMBaseRegisterInfo * getRegisterInfo() const override
Definition: ARMSubtarget.h:250
bool restrictIT() const
Definition: ARMSubtarget.h:431
A debug info location.
Definition: DebugLoc.h:33
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:237
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.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
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.
Definition: MachineInstr.h:69
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)
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:132
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
self_iterator getIterator()
Definition: ilist_node.h:132
static CondCodes getOppositeCondition(CondCodes CC)
Definition: ARMBaseInfo.h:48
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.
Definition: BitmaskEnum.h:125
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.
Definition: AddressRanges.h:18
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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
FunctionPass * createThumb2ITBlockPass()
createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks insertion pass.