xref: /aosp_15_r20/external/llvm/lib/Target/Lanai/LanaiDelaySlotFiller.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- LanaiDelaySlotFiller.cpp - Lanai delay slot filler ----------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // Simple pass to fills delay slots with useful instructions.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "Lanai.h"
15*9880d681SAndroid Build Coastguard Worker #include "LanaiTargetMachine.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallSet.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h"
22*9880d681SAndroid Build Coastguard Worker 
23*9880d681SAndroid Build Coastguard Worker using namespace llvm;
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "delay-slot-filler"
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker STATISTIC(FilledSlots, "Number of delay slots filled");
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
30*9880d681SAndroid Build Coastguard Worker     NopDelaySlotFiller("lanai-nop-delay-filler", cl::init(false),
31*9880d681SAndroid Build Coastguard Worker                        cl::desc("Fill Lanai delay slots with NOPs."),
32*9880d681SAndroid Build Coastguard Worker                        cl::Hidden);
33*9880d681SAndroid Build Coastguard Worker 
34*9880d681SAndroid Build Coastguard Worker namespace {
35*9880d681SAndroid Build Coastguard Worker struct Filler : public MachineFunctionPass {
36*9880d681SAndroid Build Coastguard Worker   // Target machine description which we query for reg. names, data
37*9880d681SAndroid Build Coastguard Worker   // layout, etc.
38*9880d681SAndroid Build Coastguard Worker   const TargetInstrInfo *TII;
39*9880d681SAndroid Build Coastguard Worker   const TargetRegisterInfo *TRI;
40*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::instr_iterator LastFiller;
41*9880d681SAndroid Build Coastguard Worker 
42*9880d681SAndroid Build Coastguard Worker   static char ID;
Filler__anone088df060111::Filler43*9880d681SAndroid Build Coastguard Worker   explicit Filler() : MachineFunctionPass(ID) {}
44*9880d681SAndroid Build Coastguard Worker 
getPassName__anone088df060111::Filler45*9880d681SAndroid Build Coastguard Worker   const char *getPassName() const override { return "Lanai Delay Slot Filler"; }
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker   bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
48*9880d681SAndroid Build Coastguard Worker 
runOnMachineFunction__anone088df060111::Filler49*9880d681SAndroid Build Coastguard Worker   bool runOnMachineFunction(MachineFunction &MF) override {
50*9880d681SAndroid Build Coastguard Worker     const LanaiSubtarget &Subtarget = MF.getSubtarget<LanaiSubtarget>();
51*9880d681SAndroid Build Coastguard Worker     TII = Subtarget.getInstrInfo();
52*9880d681SAndroid Build Coastguard Worker     TRI = Subtarget.getRegisterInfo();
53*9880d681SAndroid Build Coastguard Worker 
54*9880d681SAndroid Build Coastguard Worker     bool Changed = false;
55*9880d681SAndroid Build Coastguard Worker     for (MachineFunction::iterator FI = MF.begin(), FE = MF.end(); FI != FE;
56*9880d681SAndroid Build Coastguard Worker          ++FI)
57*9880d681SAndroid Build Coastguard Worker       Changed |= runOnMachineBasicBlock(*FI);
58*9880d681SAndroid Build Coastguard Worker     return Changed;
59*9880d681SAndroid Build Coastguard Worker   }
60*9880d681SAndroid Build Coastguard Worker 
getRequiredProperties__anone088df060111::Filler61*9880d681SAndroid Build Coastguard Worker   MachineFunctionProperties getRequiredProperties() const override {
62*9880d681SAndroid Build Coastguard Worker     return MachineFunctionProperties().set(
63*9880d681SAndroid Build Coastguard Worker         MachineFunctionProperties::Property::AllVRegsAllocated);
64*9880d681SAndroid Build Coastguard Worker   }
65*9880d681SAndroid Build Coastguard Worker 
66*9880d681SAndroid Build Coastguard Worker   void insertDefsUses(MachineBasicBlock::instr_iterator MI,
67*9880d681SAndroid Build Coastguard Worker                       SmallSet<unsigned, 32> &RegDefs,
68*9880d681SAndroid Build Coastguard Worker                       SmallSet<unsigned, 32> &RegUses);
69*9880d681SAndroid Build Coastguard Worker 
70*9880d681SAndroid Build Coastguard Worker   bool isRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg);
71*9880d681SAndroid Build Coastguard Worker 
72*9880d681SAndroid Build Coastguard Worker   bool delayHasHazard(MachineBasicBlock::instr_iterator MI, bool &SawLoad,
73*9880d681SAndroid Build Coastguard Worker                       bool &SawStore, SmallSet<unsigned, 32> &RegDefs,
74*9880d681SAndroid Build Coastguard Worker                       SmallSet<unsigned, 32> &RegUses);
75*9880d681SAndroid Build Coastguard Worker 
76*9880d681SAndroid Build Coastguard Worker   bool findDelayInstr(MachineBasicBlock &MBB,
77*9880d681SAndroid Build Coastguard Worker                       MachineBasicBlock::instr_iterator Slot,
78*9880d681SAndroid Build Coastguard Worker                       MachineBasicBlock::instr_iterator &Filler);
79*9880d681SAndroid Build Coastguard Worker };
80*9880d681SAndroid Build Coastguard Worker char Filler::ID = 0;
81*9880d681SAndroid Build Coastguard Worker } // end of anonymous namespace
82*9880d681SAndroid Build Coastguard Worker 
83*9880d681SAndroid Build Coastguard Worker // createLanaiDelaySlotFillerPass - Returns a pass that fills in delay
84*9880d681SAndroid Build Coastguard Worker // slots in Lanai MachineFunctions
85*9880d681SAndroid Build Coastguard Worker FunctionPass *
createLanaiDelaySlotFillerPass(const LanaiTargetMachine & tm)86*9880d681SAndroid Build Coastguard Worker llvm::createLanaiDelaySlotFillerPass(const LanaiTargetMachine &tm) {
87*9880d681SAndroid Build Coastguard Worker   return new Filler();
88*9880d681SAndroid Build Coastguard Worker }
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker // runOnMachineBasicBlock - Fill in delay slots for the given basic block.
91*9880d681SAndroid Build Coastguard Worker // There is one or two delay slot per delayed instruction.
runOnMachineBasicBlock(MachineBasicBlock & MBB)92*9880d681SAndroid Build Coastguard Worker bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
93*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
94*9880d681SAndroid Build Coastguard Worker   LastFiller = MBB.instr_end();
95*9880d681SAndroid Build Coastguard Worker 
96*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock::instr_iterator I = MBB.instr_begin();
97*9880d681SAndroid Build Coastguard Worker        I != MBB.instr_end(); ++I) {
98*9880d681SAndroid Build Coastguard Worker     if (I->getDesc().hasDelaySlot()) {
99*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock::instr_iterator InstrWithSlot = I;
100*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock::instr_iterator J = I;
101*9880d681SAndroid Build Coastguard Worker 
102*9880d681SAndroid Build Coastguard Worker       // Treat RET specially as it is only instruction with 2 delay slots
103*9880d681SAndroid Build Coastguard Worker       // generated while all others generated have 1 delay slot.
104*9880d681SAndroid Build Coastguard Worker       if (I->getOpcode() == Lanai::RET) {
105*9880d681SAndroid Build Coastguard Worker         // RET is generated as part of epilogue generation and hence we know
106*9880d681SAndroid Build Coastguard Worker         // what the two instructions preceding it are and that it is safe to
107*9880d681SAndroid Build Coastguard Worker         // insert RET above them.
108*9880d681SAndroid Build Coastguard Worker         MachineBasicBlock::reverse_instr_iterator RI(I);
109*9880d681SAndroid Build Coastguard Worker         assert(RI->getOpcode() == Lanai::LDW_RI && RI->getOperand(0).isReg() &&
110*9880d681SAndroid Build Coastguard Worker                RI->getOperand(0).getReg() == Lanai::FP &&
111*9880d681SAndroid Build Coastguard Worker                RI->getOperand(1).isReg() &&
112*9880d681SAndroid Build Coastguard Worker                RI->getOperand(1).getReg() == Lanai::FP &&
113*9880d681SAndroid Build Coastguard Worker                RI->getOperand(2).isImm() && RI->getOperand(2).getImm() == -8);
114*9880d681SAndroid Build Coastguard Worker         ++RI;
115*9880d681SAndroid Build Coastguard Worker         assert(RI->getOpcode() == Lanai::ADD_I_LO &&
116*9880d681SAndroid Build Coastguard Worker                RI->getOperand(0).isReg() &&
117*9880d681SAndroid Build Coastguard Worker                RI->getOperand(0).getReg() == Lanai::SP &&
118*9880d681SAndroid Build Coastguard Worker                RI->getOperand(1).isReg() &&
119*9880d681SAndroid Build Coastguard Worker                RI->getOperand(1).getReg() == Lanai::FP);
120*9880d681SAndroid Build Coastguard Worker         ++RI;
121*9880d681SAndroid Build Coastguard Worker         MachineBasicBlock::instr_iterator FI(RI.base());
122*9880d681SAndroid Build Coastguard Worker         MBB.splice(std::next(I), &MBB, FI, I);
123*9880d681SAndroid Build Coastguard Worker         FilledSlots += 2;
124*9880d681SAndroid Build Coastguard Worker       } else {
125*9880d681SAndroid Build Coastguard Worker         if (!NopDelaySlotFiller && findDelayInstr(MBB, I, J)) {
126*9880d681SAndroid Build Coastguard Worker           MBB.splice(std::next(I), &MBB, J);
127*9880d681SAndroid Build Coastguard Worker         } else {
128*9880d681SAndroid Build Coastguard Worker           BuildMI(MBB, std::next(I), DebugLoc(), TII->get(Lanai::NOP));
129*9880d681SAndroid Build Coastguard Worker         }
130*9880d681SAndroid Build Coastguard Worker         ++FilledSlots;
131*9880d681SAndroid Build Coastguard Worker       }
132*9880d681SAndroid Build Coastguard Worker 
133*9880d681SAndroid Build Coastguard Worker       Changed = true;
134*9880d681SAndroid Build Coastguard Worker       // Record the filler instruction that filled the delay slot.
135*9880d681SAndroid Build Coastguard Worker       // The instruction after it will be visited in the next iteration.
136*9880d681SAndroid Build Coastguard Worker       LastFiller = ++I;
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker       // Bundle the delay slot filler to InstrWithSlot so that the machine
139*9880d681SAndroid Build Coastguard Worker       // verifier doesn't expect this instruction to be a terminator.
140*9880d681SAndroid Build Coastguard Worker       MIBundleBuilder(MBB, InstrWithSlot, std::next(LastFiller));
141*9880d681SAndroid Build Coastguard Worker     }
142*9880d681SAndroid Build Coastguard Worker   }
143*9880d681SAndroid Build Coastguard Worker   return Changed;
144*9880d681SAndroid Build Coastguard Worker }
145*9880d681SAndroid Build Coastguard Worker 
findDelayInstr(MachineBasicBlock & MBB,MachineBasicBlock::instr_iterator Slot,MachineBasicBlock::instr_iterator & Filler)146*9880d681SAndroid Build Coastguard Worker bool Filler::findDelayInstr(MachineBasicBlock &MBB,
147*9880d681SAndroid Build Coastguard Worker                             MachineBasicBlock::instr_iterator Slot,
148*9880d681SAndroid Build Coastguard Worker                             MachineBasicBlock::instr_iterator &Filler) {
149*9880d681SAndroid Build Coastguard Worker   SmallSet<unsigned, 32> RegDefs;
150*9880d681SAndroid Build Coastguard Worker   SmallSet<unsigned, 32> RegUses;
151*9880d681SAndroid Build Coastguard Worker 
152*9880d681SAndroid Build Coastguard Worker   insertDefsUses(Slot, RegDefs, RegUses);
153*9880d681SAndroid Build Coastguard Worker 
154*9880d681SAndroid Build Coastguard Worker   bool SawLoad = false;
155*9880d681SAndroid Build Coastguard Worker   bool SawStore = false;
156*9880d681SAndroid Build Coastguard Worker 
157*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock::reverse_instr_iterator I(Slot); I != MBB.instr_rend();
158*9880d681SAndroid Build Coastguard Worker        ++I) {
159*9880d681SAndroid Build Coastguard Worker     // skip debug value
160*9880d681SAndroid Build Coastguard Worker     if (I->isDebugValue())
161*9880d681SAndroid Build Coastguard Worker       continue;
162*9880d681SAndroid Build Coastguard Worker 
163*9880d681SAndroid Build Coastguard Worker     // Convert to forward iterator.
164*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::instr_iterator FI(std::next(I).base());
165*9880d681SAndroid Build Coastguard Worker 
166*9880d681SAndroid Build Coastguard Worker     if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isLabel() ||
167*9880d681SAndroid Build Coastguard Worker         FI == LastFiller || I->isPseudo())
168*9880d681SAndroid Build Coastguard Worker       break;
169*9880d681SAndroid Build Coastguard Worker 
170*9880d681SAndroid Build Coastguard Worker     if (delayHasHazard(FI, SawLoad, SawStore, RegDefs, RegUses)) {
171*9880d681SAndroid Build Coastguard Worker       insertDefsUses(FI, RegDefs, RegUses);
172*9880d681SAndroid Build Coastguard Worker       continue;
173*9880d681SAndroid Build Coastguard Worker     }
174*9880d681SAndroid Build Coastguard Worker     Filler = FI;
175*9880d681SAndroid Build Coastguard Worker     return true;
176*9880d681SAndroid Build Coastguard Worker   }
177*9880d681SAndroid Build Coastguard Worker   return false;
178*9880d681SAndroid Build Coastguard Worker }
179*9880d681SAndroid Build Coastguard Worker 
delayHasHazard(MachineBasicBlock::instr_iterator MI,bool & SawLoad,bool & SawStore,SmallSet<unsigned,32> & RegDefs,SmallSet<unsigned,32> & RegUses)180*9880d681SAndroid Build Coastguard Worker bool Filler::delayHasHazard(MachineBasicBlock::instr_iterator MI, bool &SawLoad,
181*9880d681SAndroid Build Coastguard Worker                             bool &SawStore, SmallSet<unsigned, 32> &RegDefs,
182*9880d681SAndroid Build Coastguard Worker                             SmallSet<unsigned, 32> &RegUses) {
183*9880d681SAndroid Build Coastguard Worker   if (MI->isImplicitDef() || MI->isKill())
184*9880d681SAndroid Build Coastguard Worker     return true;
185*9880d681SAndroid Build Coastguard Worker 
186*9880d681SAndroid Build Coastguard Worker   // Loads or stores cannot be moved past a store to the delay slot
187*9880d681SAndroid Build Coastguard Worker   // and stores cannot be moved past a load.
188*9880d681SAndroid Build Coastguard Worker   if (MI->mayLoad()) {
189*9880d681SAndroid Build Coastguard Worker     if (SawStore)
190*9880d681SAndroid Build Coastguard Worker       return true;
191*9880d681SAndroid Build Coastguard Worker     SawLoad = true;
192*9880d681SAndroid Build Coastguard Worker   }
193*9880d681SAndroid Build Coastguard Worker 
194*9880d681SAndroid Build Coastguard Worker   if (MI->mayStore()) {
195*9880d681SAndroid Build Coastguard Worker     if (SawStore)
196*9880d681SAndroid Build Coastguard Worker       return true;
197*9880d681SAndroid Build Coastguard Worker     SawStore = true;
198*9880d681SAndroid Build Coastguard Worker     if (SawLoad)
199*9880d681SAndroid Build Coastguard Worker       return true;
200*9880d681SAndroid Build Coastguard Worker   }
201*9880d681SAndroid Build Coastguard Worker 
202*9880d681SAndroid Build Coastguard Worker   assert((!MI->isCall() && !MI->isReturn()) &&
203*9880d681SAndroid Build Coastguard Worker          "Cannot put calls or returns in delay slot.");
204*9880d681SAndroid Build Coastguard Worker 
205*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
206*9880d681SAndroid Build Coastguard Worker     const MachineOperand &MO = MI->getOperand(I);
207*9880d681SAndroid Build Coastguard Worker     unsigned Reg;
208*9880d681SAndroid Build Coastguard Worker 
209*9880d681SAndroid Build Coastguard Worker     if (!MO.isReg() || !(Reg = MO.getReg()))
210*9880d681SAndroid Build Coastguard Worker       continue; // skip
211*9880d681SAndroid Build Coastguard Worker 
212*9880d681SAndroid Build Coastguard Worker     if (MO.isDef()) {
213*9880d681SAndroid Build Coastguard Worker       // check whether Reg is defined or used before delay slot.
214*9880d681SAndroid Build Coastguard Worker       if (isRegInSet(RegDefs, Reg) || isRegInSet(RegUses, Reg))
215*9880d681SAndroid Build Coastguard Worker         return true;
216*9880d681SAndroid Build Coastguard Worker     }
217*9880d681SAndroid Build Coastguard Worker     if (MO.isUse()) {
218*9880d681SAndroid Build Coastguard Worker       // check whether Reg is defined before delay slot.
219*9880d681SAndroid Build Coastguard Worker       if (isRegInSet(RegDefs, Reg))
220*9880d681SAndroid Build Coastguard Worker         return true;
221*9880d681SAndroid Build Coastguard Worker     }
222*9880d681SAndroid Build Coastguard Worker   }
223*9880d681SAndroid Build Coastguard Worker   return false;
224*9880d681SAndroid Build Coastguard Worker }
225*9880d681SAndroid Build Coastguard Worker 
226*9880d681SAndroid Build Coastguard Worker // Insert Defs and Uses of MI into the sets RegDefs and RegUses.
insertDefsUses(MachineBasicBlock::instr_iterator MI,SmallSet<unsigned,32> & RegDefs,SmallSet<unsigned,32> & RegUses)227*9880d681SAndroid Build Coastguard Worker void Filler::insertDefsUses(MachineBasicBlock::instr_iterator MI,
228*9880d681SAndroid Build Coastguard Worker                             SmallSet<unsigned, 32> &RegDefs,
229*9880d681SAndroid Build Coastguard Worker                             SmallSet<unsigned, 32> &RegUses) {
230*9880d681SAndroid Build Coastguard Worker   // If MI is a call or return, just examine the explicit non-variadic operands.
231*9880d681SAndroid Build Coastguard Worker   MCInstrDesc MCID = MI->getDesc();
232*9880d681SAndroid Build Coastguard Worker   unsigned E = MI->isCall() || MI->isReturn() ? MCID.getNumOperands()
233*9880d681SAndroid Build Coastguard Worker                                               : MI->getNumOperands();
234*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0; I != E; ++I) {
235*9880d681SAndroid Build Coastguard Worker     const MachineOperand &MO = MI->getOperand(I);
236*9880d681SAndroid Build Coastguard Worker     unsigned Reg;
237*9880d681SAndroid Build Coastguard Worker 
238*9880d681SAndroid Build Coastguard Worker     if (!MO.isReg() || !(Reg = MO.getReg()))
239*9880d681SAndroid Build Coastguard Worker       continue;
240*9880d681SAndroid Build Coastguard Worker 
241*9880d681SAndroid Build Coastguard Worker     if (MO.isDef())
242*9880d681SAndroid Build Coastguard Worker       RegDefs.insert(Reg);
243*9880d681SAndroid Build Coastguard Worker     else if (MO.isUse())
244*9880d681SAndroid Build Coastguard Worker       RegUses.insert(Reg);
245*9880d681SAndroid Build Coastguard Worker   }
246*9880d681SAndroid Build Coastguard Worker 
247*9880d681SAndroid Build Coastguard Worker   // Call & return instructions defines SP implicitly. Implicit defines are not
248*9880d681SAndroid Build Coastguard Worker   // included in the RegDefs set of calls but instructions modifying SP cannot
249*9880d681SAndroid Build Coastguard Worker   // be inserted in the delay slot of a call/return as these instructions are
250*9880d681SAndroid Build Coastguard Worker   // expanded to multiple instructions with SP modified before the branch that
251*9880d681SAndroid Build Coastguard Worker   // has the delay slot.
252*9880d681SAndroid Build Coastguard Worker   if (MI->isCall() || MI->isReturn())
253*9880d681SAndroid Build Coastguard Worker     RegDefs.insert(Lanai::SP);
254*9880d681SAndroid Build Coastguard Worker }
255*9880d681SAndroid Build Coastguard Worker 
256*9880d681SAndroid Build Coastguard Worker // Returns true if the Reg or its alias is in the RegSet.
isRegInSet(SmallSet<unsigned,32> & RegSet,unsigned Reg)257*9880d681SAndroid Build Coastguard Worker bool Filler::isRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg) {
258*9880d681SAndroid Build Coastguard Worker   // Check Reg and all aliased Registers.
259*9880d681SAndroid Build Coastguard Worker   for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
260*9880d681SAndroid Build Coastguard Worker     if (RegSet.count(*AI))
261*9880d681SAndroid Build Coastguard Worker       return true;
262*9880d681SAndroid Build Coastguard Worker   return false;
263*9880d681SAndroid Build Coastguard Worker }
264