]>
git.proxmox.com Git - rustc.git/blob - src/llvm/lib/Target/ARM/Thumb2ITBlockPass.cpp
1 //===-- Thumb2ITBlockPass.cpp - Insert Thumb-2 IT blocks ------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 #include "ARMMachineFunctionInfo.h"
12 #include "Thumb2InstrInfo.h"
13 #include "llvm/ADT/SmallSet.h"
14 #include "llvm/ADT/Statistic.h"
15 #include "llvm/CodeGen/MachineFunctionPass.h"
16 #include "llvm/CodeGen/MachineInstr.h"
17 #include "llvm/CodeGen/MachineInstrBuilder.h"
18 #include "llvm/CodeGen/MachineInstrBundle.h"
21 #define DEBUG_TYPE "thumb2-it"
23 STATISTIC(NumITs
, "Number of IT blocks inserted");
24 STATISTIC(NumMovedInsts
, "Number of predicated instructions moved");
27 class Thumb2ITBlockPass
: public MachineFunctionPass
{
30 Thumb2ITBlockPass() : MachineFunctionPass(ID
) {}
33 const Thumb2InstrInfo
*TII
;
34 const TargetRegisterInfo
*TRI
;
37 bool runOnMachineFunction(MachineFunction
&Fn
) override
;
39 const char *getPassName() const override
{
40 return "Thumb IT blocks insertion pass";
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
);
50 char Thumb2ITBlockPass::ID
= 0;
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
;
63 for (unsigned i
= 0, e
= MI
->getNumOperands(); i
!= e
; ++i
) {
64 MachineOperand
&MO
= MI
->getOperand(i
);
67 unsigned Reg
= MO
.getReg();
68 if (!Reg
|| Reg
== ARM::ITSTATE
|| Reg
== ARM::SP
)
71 LocalUses
.push_back(Reg
);
73 LocalDefs
.push_back(Reg
);
76 for (unsigned i
= 0, e
= LocalUses
.size(); i
!= e
; ++i
) {
77 unsigned Reg
= LocalUses
[i
];
78 for (MCSubRegIterator
Subreg(Reg
, TRI
, /*IncludeSelf=*/true);
79 Subreg
.isValid(); ++Subreg
)
83 for (unsigned i
= 0, e
= LocalDefs
.size(); i
!= e
; ++i
) {
84 unsigned Reg
= LocalDefs
[i
];
85 for (MCSubRegIterator
Subreg(Reg
, TRI
, /*IncludeSelf=*/true);
86 Subreg
.isValid(); ++Subreg
)
93 static bool isCopy(MachineInstr
*MI
) {
94 switch (MI
->getOpcode()) {
106 Thumb2ITBlockPass::MoveCopyOutOfITBlock(MachineInstr
*MI
,
107 ARMCC::CondCodes CC
, ARMCC::CondCodes OCC
,
108 SmallSet
<unsigned, 4> &Defs
,
109 SmallSet
<unsigned, 4> &Uses
) {
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?");
119 unsigned DstReg
= MI
->getOperand(0).getReg();
120 unsigned SrcReg
= MI
->getOperand(1).getReg();
122 // First check if it's safe to move it.
123 if (Uses
.count(DstReg
) || Defs
.count(SrcReg
))
126 // If the CPSR is defined by this copy, then we don't want to move it. E.g.,
134 // we don't want this to be converted to:
142 const MCInstrDesc
&MCID
= MI
->getDesc();
143 if (MI
->hasOptionalDef() &&
144 MI
->getOperand(MCID
.getNumOperands() - 1).getReg() == ARM::CPSR
)
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())
154 unsigned NPredReg
= 0;
155 ARMCC::CondCodes NCC
= getITInstrPredicate(I
, NPredReg
);
156 if (NCC
== CC
|| NCC
== OCC
)
162 bool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock
&MBB
) {
163 bool Modified
= false;
165 SmallSet
<unsigned, 4> Defs
;
166 SmallSet
<unsigned, 4> Uses
;
167 MachineBasicBlock::iterator MBBI
= MBB
.begin(), E
= MBB
.end();
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
) {
180 TrackDefUses(MI
, Defs
, Uses
, TRI
);
182 // Insert an IT instruction.
183 MachineInstrBuilder MIB
= BuildMI(MBB
, MBBI
, dl
, TII
->get(ARM::t2IT
))
186 // Add implicit use of ITSTATE to IT block instructions.
187 MI
->addOperand(MachineOperand::CreateReg(ARM::ITSTATE
, false/*ifDef*/,
188 true/*isImp*/, false/*isKill*/));
190 MachineInstr
*LastITMI
= MI
;
191 MachineBasicBlock::iterator InsertPos
= MIB
.getInstr();
195 ARMCC::CondCodes OCC
= ARMCC::getOppositeCondition(CC
);
196 unsigned Mask
= 0, Pos
= 3;
198 // v8 IT blocks are limited to one conditional op unless -arm-no-restrict-it
199 // is set: skip the loop
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())
208 MachineInstr
*NMI
= &*MBBI
;
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*/));
220 if (NCC
== ARMCC::AL
&&
221 MoveCopyOutOfITBlock(NMI
, CC
, OCC
, Defs
, Uses
)) {
224 MBB
.insert(InsertPos
, NMI
);
230 TrackDefUses(NMI
, Defs
, Uses
, TRI
);
237 // Tag along (firstcond[0] << 4) with the mask.
238 Mask
|= (CC
& 1) << 4;
241 // Last instruction in IT block kills ITSTATE.
242 LastITMI
->findRegisterUseOperand(ARM::ITSTATE
)->setIsKill();
244 // Finalize the bundle.
245 MachineBasicBlock::instr_iterator LI
= LastITMI
;
246 finalizeBundle(MBB
, InsertPos
.getInstrIterator(), std::next(LI
));
255 bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction
&Fn
) {
256 const TargetMachine
&TM
= Fn
.getTarget();
257 AFI
= Fn
.getInfo
<ARMFunctionInfo
>();
258 TII
= static_cast<const Thumb2InstrInfo
*>(
259 TM
.getSubtargetImpl()->getInstrInfo());
260 TRI
= TM
.getSubtargetImpl()->getRegisterInfo();
261 restrictIT
= TM
.getSubtarget
<ARMSubtarget
>().restrictIT();
263 if (!AFI
->isThumbFunction())
266 bool Modified
= false;
267 for (MachineFunction::iterator MFI
= Fn
.begin(), E
= Fn
.end(); MFI
!= E
; ) {
268 MachineBasicBlock
&MBB
= *MFI
;
270 Modified
|= InsertITInstructions(MBB
);
274 AFI
->setHasITBlocks(true);
279 /// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks
281 FunctionPass
*llvm::createThumb2ITBlockPass() {
282 return new Thumb2ITBlockPass();