References:
TargetPassConfig::addCoreISelPasses()
will create the core passes needed for instruction selection in LLVM.
It will
FastISel
, SelectionDAG
, or GlobalISel
) for the compilation, whichever is available or meets the configuration options.addPass(&FinalizeISelID);
printAndVerify("After Instruction Selection");
.```C++
bool TargetPassConfig::addCoreISelPasses() { // Enable FastISel with -fast-isel, but allow that to be overridden. TM->setO0WantsFastISel(EnableFastISelOption != cl::BOU_FALSE);
// Determine an instruction selector. enum class SelectorType { SelectionDAG, FastISel, GlobalISel }; SelectorType Selector;
if (EnableFastISelOption == cl::BOU_TRUE) Selector = SelectorType::FastISel; else if (EnableGlobalISelOption == cl::BOU_TRUE || (TM->Options.EnableGlobalISel && EnableGlobalISelOption != cl::BOU_FALSE)) Selector = SelectorType::GlobalISel; else if (TM->getOptLevel() == CodeGenOpt::None && TM->getO0WantsFastISel()) Selector = SelectorType::FastISel; else Selector = SelectorType::SelectionDAG;
// Set consistently TM->Options.EnableFastISel and EnableGlobalISel.
if (Selector == SelectorType::FastISel) {
errs() << “Lele: use FastISel, will have no IRTranslator….\n”;
TM->setFastISel(true);
TM->setGlobalISel(false);
} else if (Selector == SelectorType::GlobalISel) {
errs() << “Lele: use GlobalISel, will add IRTranslator….\n”;
TM->setFastISel(false);
TM->setGlobalISel(true);
} else {
errs() << “Lele: use SelectionDAG, will have no IRTranslator….\n”;
}
// Add instruction selector passes.
if (Selector == SelectorType::GlobalISel) {
SaveAndRestore
addPreLegalizeMachineIR();
if (addLegalizeMachineIR())
return true;
// Before running the register bank selector, ask the target if it
// wants to run some passes.
addPreRegBankSelect();
if (addRegBankSelect())
return true;
addPreGlobalInstructionSelect();
if (addGlobalInstructionSelect())
return true;
// Pass to reset the MachineFunction if the ISel failed.
addPass(createResetMachineFunctionPass(
reportDiagnosticWhenGlobalISelFallback(), isGlobalISelAbortEnabled()));
// Provide a fallback path when we do not want to abort on
// not-yet-supported input.
if (!isGlobalISelAbortEnabled() && addInstSelector())
return true;
} else { errs() << “Lele: Not GlobalISel, no IRTranslator, creating target dependent” << “passes…\n”; if (addInstSelector()) return true; }
// Expand pseudo-instructions emitted by ISel. Don’t run the verifier before // FinalizeISel. addPass(&FinalizeISelID);
// Print the instruction selected machine code… printAndVerify(“After Instruction Selection”);
return false; }
```
addInstSelector()
is target specific. For example, see MIPS ISel
References: llvm/include/llvm/CodeGen/CallingConvLower.h llvm/lib/CodeGen/CallingConvLower.cpp class CCState. Holds information needed while lowering arguments and return values. It captures which registers are already assigned and which stack slots are used. It provides accessors to allocate these values.
References llvm/include/llvm/CodeGen/SelectionDAGNodes.h: class SDLoc Two points where the debug location info is passed from IR to MIR: When an SDNode is created from the DAGBuilder, the DebugLoc is extracted from the original Instruction, and IROrder is the ordinal position of the instruction. When an SDNode is created after the DAG is being built, both DebugLoc and the IROrder are propagated from the original SDNode.
References: llvm/include/llvm/CodeGen/SelectionDAGISel.h llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp LLVM Selection DAG Introduction Pass registration // llvm/lib/Target/Mips/MipsTargetMachine.cpp // Install an instruction selector pass using // the ISelDag to gen Mips code. bool MipsPassConfig::addInstSelector() { DebugLL("adding MipsModuleISelDagPass\n"); addPass(createMipsModuleISelDagPass()); DebugLL("adding Mips16ISelDag\n"); addPass(createMips16ISelDag(getMipsTargetMachine(), getOptLevel())); DebugLL("adding MipsSEISelDag\n"); addPass(createMipsSEISelDag(getMipsTargetMachine(), getOptLevel())); DebugLL("done adding MipsSEISelDag\n"); return false; } SelectionDAGISel::runOnMachineFunction() SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) SelectionDAGISel::runOnMachineFunction() bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { DebugLL("SelectionDAGISel pass on MF: "<< mf.getName() << "\n"); CurDAG->init(*MF, *ORE, this, LibInfo, getAnalysisIfAvailable<LegacyDivergenceAnalysis>()); SDB->init(GFI, AA, LibInfo); // SDB: SelectionDAGBuilder MachineBasicBlock *EntryMBB = &MF->front(); /////////////////////////////////////////// // Do selection for all basic blocks.
References: llvm/lib/Target/Mips/MipsTargetMachine.cpp 3 Passes for Mips ISel MipsModuleDAGToDAGISel, a pass used to change the subtarget for the Mips Instruction selector. Mips16DAGToDAGISel, Subclass of MipsDAGToDAGISel specialized for mips16. MipsSEDAGToDAGISel, Subclass of MipsDAGToDAGISel specialized for mips32/64. The core passes are Mips16DAGToDAGISel for 16-bit mips and MipsSEDAGToDAGISel for 32⁄64 bit mips. Both of them finally calls the parent pass entry (SelectionDAGISel::runOnMachineFunction) in their implementation. See more impl details on SelectionDAGISel.
Reference: LLVM in progress: Global Instruction Selection Instruction Selection Reference LLVM Core Pipeline LLVM Core Pipleline – InstructionSelect InstructionSelect pass transforms generic machine instructions into equivalent target-specifc instructions. It traverses the MachineFunction bottom-up, selecting uses before definitions, enabling trivial dead code elimination. The target implements InstructionSelector class, containing target-specific selection logic. InstructionSelector::select virtual bool select(MachineInstr &MI) This method is responsible for mutating (or replacing) a possibly-generic MI into a fully target-specific equivalent.
If you could revise
the fundmental principles of
computer system design
to improve security...
... what would you change?