xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- llvm/CodeGen/GlobalISel/InstructionSelect.cpp - InstructionSelect ---==//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric /// \file
9*0b57cec5SDimitry Andric /// This file implements the InstructionSelect class.
10*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
11*0b57cec5SDimitry Andric 
12*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
13*0b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
14*0b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
15*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
16*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
17*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/Utils.h"
18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
19*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
20*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
21*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
22*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
23*0b57cec5SDimitry Andric #include "llvm/Config/config.h"
24*0b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
25*0b57cec5SDimitry Andric #include "llvm/IR/Function.h"
26*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
27*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
28*0b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h"
29*0b57cec5SDimitry Andric 
30*0b57cec5SDimitry Andric #define DEBUG_TYPE "instruction-select"
31*0b57cec5SDimitry Andric 
32*0b57cec5SDimitry Andric using namespace llvm;
33*0b57cec5SDimitry Andric 
34*0b57cec5SDimitry Andric #ifdef LLVM_GISEL_COV_PREFIX
35*0b57cec5SDimitry Andric static cl::opt<std::string>
36*0b57cec5SDimitry Andric     CoveragePrefix("gisel-coverage-prefix", cl::init(LLVM_GISEL_COV_PREFIX),
37*0b57cec5SDimitry Andric                    cl::desc("Record GlobalISel rule coverage files of this "
38*0b57cec5SDimitry Andric                             "prefix if instrumentation was generated"));
39*0b57cec5SDimitry Andric #else
40*0b57cec5SDimitry Andric static const std::string CoveragePrefix = "";
41*0b57cec5SDimitry Andric #endif
42*0b57cec5SDimitry Andric 
43*0b57cec5SDimitry Andric char InstructionSelect::ID = 0;
44*0b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(InstructionSelect, DEBUG_TYPE,
45*0b57cec5SDimitry Andric                       "Select target instructions out of generic instructions",
46*0b57cec5SDimitry Andric                       false, false)
47*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
48*0b57cec5SDimitry Andric INITIALIZE_PASS_END(InstructionSelect, DEBUG_TYPE,
49*0b57cec5SDimitry Andric                     "Select target instructions out of generic instructions",
50*0b57cec5SDimitry Andric                     false, false)
51*0b57cec5SDimitry Andric 
52*0b57cec5SDimitry Andric InstructionSelect::InstructionSelect() : MachineFunctionPass(ID) { }
53*0b57cec5SDimitry Andric 
54*0b57cec5SDimitry Andric void InstructionSelect::getAnalysisUsage(AnalysisUsage &AU) const {
55*0b57cec5SDimitry Andric   AU.addRequired<TargetPassConfig>();
56*0b57cec5SDimitry Andric   getSelectionDAGFallbackAnalysisUsage(AU);
57*0b57cec5SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
58*0b57cec5SDimitry Andric }
59*0b57cec5SDimitry Andric 
60*0b57cec5SDimitry Andric bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
61*0b57cec5SDimitry Andric   // If the ISel pipeline failed, do not bother running that pass.
62*0b57cec5SDimitry Andric   if (MF.getProperties().hasProperty(
63*0b57cec5SDimitry Andric           MachineFunctionProperties::Property::FailedISel))
64*0b57cec5SDimitry Andric     return false;
65*0b57cec5SDimitry Andric 
66*0b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Selecting function: " << MF.getName() << '\n');
67*0b57cec5SDimitry Andric 
68*0b57cec5SDimitry Andric   const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
69*0b57cec5SDimitry Andric   const InstructionSelector *ISel = MF.getSubtarget().getInstructionSelector();
70*0b57cec5SDimitry Andric   CodeGenCoverage CoverageInfo;
71*0b57cec5SDimitry Andric   assert(ISel && "Cannot work without InstructionSelector");
72*0b57cec5SDimitry Andric 
73*0b57cec5SDimitry Andric   // An optimization remark emitter. Used to report failures.
74*0b57cec5SDimitry Andric   MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
75*0b57cec5SDimitry Andric 
76*0b57cec5SDimitry Andric   // FIXME: There are many other MF/MFI fields we need to initialize.
77*0b57cec5SDimitry Andric 
78*0b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
79*0b57cec5SDimitry Andric #ifndef NDEBUG
80*0b57cec5SDimitry Andric   // Check that our input is fully legal: we require the function to have the
81*0b57cec5SDimitry Andric   // Legalized property, so it should be.
82*0b57cec5SDimitry Andric   // FIXME: This should be in the MachineVerifier, as the RegBankSelected
83*0b57cec5SDimitry Andric   // property check already is.
84*0b57cec5SDimitry Andric   if (!DisableGISelLegalityCheck)
85*0b57cec5SDimitry Andric     if (const MachineInstr *MI = machineFunctionIsIllegal(MF)) {
86*0b57cec5SDimitry Andric       reportGISelFailure(MF, TPC, MORE, "gisel-select",
87*0b57cec5SDimitry Andric                          "instruction is not legal", *MI);
88*0b57cec5SDimitry Andric       return false;
89*0b57cec5SDimitry Andric     }
90*0b57cec5SDimitry Andric   // FIXME: We could introduce new blocks and will need to fix the outer loop.
91*0b57cec5SDimitry Andric   // Until then, keep track of the number of blocks to assert that we don't.
92*0b57cec5SDimitry Andric   const size_t NumBlocks = MF.size();
93*0b57cec5SDimitry Andric #endif
94*0b57cec5SDimitry Andric 
95*0b57cec5SDimitry Andric   for (MachineBasicBlock *MBB : post_order(&MF)) {
96*0b57cec5SDimitry Andric     if (MBB->empty())
97*0b57cec5SDimitry Andric       continue;
98*0b57cec5SDimitry Andric 
99*0b57cec5SDimitry Andric     // Select instructions in reverse block order. We permit erasing so have
100*0b57cec5SDimitry Andric     // to resort to manually iterating and recognizing the begin (rend) case.
101*0b57cec5SDimitry Andric     bool ReachedBegin = false;
102*0b57cec5SDimitry Andric     for (auto MII = std::prev(MBB->end()), Begin = MBB->begin();
103*0b57cec5SDimitry Andric          !ReachedBegin;) {
104*0b57cec5SDimitry Andric #ifndef NDEBUG
105*0b57cec5SDimitry Andric       // Keep track of the insertion range for debug printing.
106*0b57cec5SDimitry Andric       const auto AfterIt = std::next(MII);
107*0b57cec5SDimitry Andric #endif
108*0b57cec5SDimitry Andric       // Select this instruction.
109*0b57cec5SDimitry Andric       MachineInstr &MI = *MII;
110*0b57cec5SDimitry Andric 
111*0b57cec5SDimitry Andric       // And have our iterator point to the next instruction, if there is one.
112*0b57cec5SDimitry Andric       if (MII == Begin)
113*0b57cec5SDimitry Andric         ReachedBegin = true;
114*0b57cec5SDimitry Andric       else
115*0b57cec5SDimitry Andric         --MII;
116*0b57cec5SDimitry Andric 
117*0b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Selecting: \n  " << MI);
118*0b57cec5SDimitry Andric 
119*0b57cec5SDimitry Andric       // We could have folded this instruction away already, making it dead.
120*0b57cec5SDimitry Andric       // If so, erase it.
121*0b57cec5SDimitry Andric       if (isTriviallyDead(MI, MRI)) {
122*0b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Is dead; erasing.\n");
123*0b57cec5SDimitry Andric         MI.eraseFromParentAndMarkDBGValuesForRemoval();
124*0b57cec5SDimitry Andric         continue;
125*0b57cec5SDimitry Andric       }
126*0b57cec5SDimitry Andric 
127*0b57cec5SDimitry Andric       if (!ISel->select(MI, CoverageInfo)) {
128*0b57cec5SDimitry Andric         // FIXME: It would be nice to dump all inserted instructions.  It's
129*0b57cec5SDimitry Andric         // not obvious how, esp. considering select() can insert after MI.
130*0b57cec5SDimitry Andric         reportGISelFailure(MF, TPC, MORE, "gisel-select", "cannot select", MI);
131*0b57cec5SDimitry Andric         return false;
132*0b57cec5SDimitry Andric       }
133*0b57cec5SDimitry Andric 
134*0b57cec5SDimitry Andric       // Dump the range of instructions that MI expanded into.
135*0b57cec5SDimitry Andric       LLVM_DEBUG({
136*0b57cec5SDimitry Andric         auto InsertedBegin = ReachedBegin ? MBB->begin() : std::next(MII);
137*0b57cec5SDimitry Andric         dbgs() << "Into:\n";
138*0b57cec5SDimitry Andric         for (auto &InsertedMI : make_range(InsertedBegin, AfterIt))
139*0b57cec5SDimitry Andric           dbgs() << "  " << InsertedMI;
140*0b57cec5SDimitry Andric         dbgs() << '\n';
141*0b57cec5SDimitry Andric       });
142*0b57cec5SDimitry Andric     }
143*0b57cec5SDimitry Andric   }
144*0b57cec5SDimitry Andric 
145*0b57cec5SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
146*0b57cec5SDimitry Andric     if (MBB.empty())
147*0b57cec5SDimitry Andric       continue;
148*0b57cec5SDimitry Andric 
149*0b57cec5SDimitry Andric     // Try to find redundant copies b/w vregs of the same register class.
150*0b57cec5SDimitry Andric     bool ReachedBegin = false;
151*0b57cec5SDimitry Andric     for (auto MII = std::prev(MBB.end()), Begin = MBB.begin(); !ReachedBegin;) {
152*0b57cec5SDimitry Andric       // Select this instruction.
153*0b57cec5SDimitry Andric       MachineInstr &MI = *MII;
154*0b57cec5SDimitry Andric 
155*0b57cec5SDimitry Andric       // And have our iterator point to the next instruction, if there is one.
156*0b57cec5SDimitry Andric       if (MII == Begin)
157*0b57cec5SDimitry Andric         ReachedBegin = true;
158*0b57cec5SDimitry Andric       else
159*0b57cec5SDimitry Andric         --MII;
160*0b57cec5SDimitry Andric       if (MI.getOpcode() != TargetOpcode::COPY)
161*0b57cec5SDimitry Andric         continue;
162*0b57cec5SDimitry Andric       unsigned SrcReg = MI.getOperand(1).getReg();
163*0b57cec5SDimitry Andric       unsigned DstReg = MI.getOperand(0).getReg();
164*0b57cec5SDimitry Andric       if (TargetRegisterInfo::isVirtualRegister(SrcReg) &&
165*0b57cec5SDimitry Andric           TargetRegisterInfo::isVirtualRegister(DstReg)) {
166*0b57cec5SDimitry Andric         auto SrcRC = MRI.getRegClass(SrcReg);
167*0b57cec5SDimitry Andric         auto DstRC = MRI.getRegClass(DstReg);
168*0b57cec5SDimitry Andric         if (SrcRC == DstRC) {
169*0b57cec5SDimitry Andric           MRI.replaceRegWith(DstReg, SrcReg);
170*0b57cec5SDimitry Andric           MI.eraseFromParentAndMarkDBGValuesForRemoval();
171*0b57cec5SDimitry Andric         }
172*0b57cec5SDimitry Andric       }
173*0b57cec5SDimitry Andric     }
174*0b57cec5SDimitry Andric   }
175*0b57cec5SDimitry Andric 
176*0b57cec5SDimitry Andric #ifndef NDEBUG
177*0b57cec5SDimitry Andric   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
178*0b57cec5SDimitry Andric   // Now that selection is complete, there are no more generic vregs.  Verify
179*0b57cec5SDimitry Andric   // that the size of the now-constrained vreg is unchanged and that it has a
180*0b57cec5SDimitry Andric   // register class.
181*0b57cec5SDimitry Andric   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
182*0b57cec5SDimitry Andric     unsigned VReg = TargetRegisterInfo::index2VirtReg(I);
183*0b57cec5SDimitry Andric 
184*0b57cec5SDimitry Andric     MachineInstr *MI = nullptr;
185*0b57cec5SDimitry Andric     if (!MRI.def_empty(VReg))
186*0b57cec5SDimitry Andric       MI = &*MRI.def_instr_begin(VReg);
187*0b57cec5SDimitry Andric     else if (!MRI.use_empty(VReg))
188*0b57cec5SDimitry Andric       MI = &*MRI.use_instr_begin(VReg);
189*0b57cec5SDimitry Andric     if (!MI)
190*0b57cec5SDimitry Andric       continue;
191*0b57cec5SDimitry Andric 
192*0b57cec5SDimitry Andric     const TargetRegisterClass *RC = MRI.getRegClassOrNull(VReg);
193*0b57cec5SDimitry Andric     if (!RC) {
194*0b57cec5SDimitry Andric       reportGISelFailure(MF, TPC, MORE, "gisel-select",
195*0b57cec5SDimitry Andric                          "VReg has no regclass after selection", *MI);
196*0b57cec5SDimitry Andric       return false;
197*0b57cec5SDimitry Andric     }
198*0b57cec5SDimitry Andric 
199*0b57cec5SDimitry Andric     const LLT Ty = MRI.getType(VReg);
200*0b57cec5SDimitry Andric     if (Ty.isValid() && Ty.getSizeInBits() > TRI.getRegSizeInBits(*RC)) {
201*0b57cec5SDimitry Andric       reportGISelFailure(
202*0b57cec5SDimitry Andric           MF, TPC, MORE, "gisel-select",
203*0b57cec5SDimitry Andric           "VReg's low-level type and register class have different sizes", *MI);
204*0b57cec5SDimitry Andric       return false;
205*0b57cec5SDimitry Andric     }
206*0b57cec5SDimitry Andric   }
207*0b57cec5SDimitry Andric 
208*0b57cec5SDimitry Andric   if (MF.size() != NumBlocks) {
209*0b57cec5SDimitry Andric     MachineOptimizationRemarkMissed R("gisel-select", "GISelFailure",
210*0b57cec5SDimitry Andric                                       MF.getFunction().getSubprogram(),
211*0b57cec5SDimitry Andric                                       /*MBB=*/nullptr);
212*0b57cec5SDimitry Andric     R << "inserting blocks is not supported yet";
213*0b57cec5SDimitry Andric     reportGISelFailure(MF, TPC, MORE, R);
214*0b57cec5SDimitry Andric     return false;
215*0b57cec5SDimitry Andric   }
216*0b57cec5SDimitry Andric #endif
217*0b57cec5SDimitry Andric   auto &TLI = *MF.getSubtarget().getTargetLowering();
218*0b57cec5SDimitry Andric   TLI.finalizeLowering(MF);
219*0b57cec5SDimitry Andric 
220*0b57cec5SDimitry Andric   LLVM_DEBUG({
221*0b57cec5SDimitry Andric     dbgs() << "Rules covered by selecting function: " << MF.getName() << ":";
222*0b57cec5SDimitry Andric     for (auto RuleID : CoverageInfo.covered())
223*0b57cec5SDimitry Andric       dbgs() << " id" << RuleID;
224*0b57cec5SDimitry Andric     dbgs() << "\n\n";
225*0b57cec5SDimitry Andric   });
226*0b57cec5SDimitry Andric   CoverageInfo.emit(CoveragePrefix,
227*0b57cec5SDimitry Andric                     MF.getSubtarget()
228*0b57cec5SDimitry Andric                         .getTargetLowering()
229*0b57cec5SDimitry Andric                         ->getTargetMachine()
230*0b57cec5SDimitry Andric                         .getTarget()
231*0b57cec5SDimitry Andric                         .getBackendName());
232*0b57cec5SDimitry Andric 
233*0b57cec5SDimitry Andric   // If we successfully selected the function nothing is going to use the vreg
234*0b57cec5SDimitry Andric   // types after us (otherwise MIRPrinter would need them). Make sure the types
235*0b57cec5SDimitry Andric   // disappear.
236*0b57cec5SDimitry Andric   MRI.clearVirtRegTypes();
237*0b57cec5SDimitry Andric 
238*0b57cec5SDimitry Andric   // FIXME: Should we accurately track changes?
239*0b57cec5SDimitry Andric   return true;
240*0b57cec5SDimitry Andric }
241