An IR instruction in DAG needs to be lowered to a target-specific instruction. The SDAG node contains IR, which needs to be mapped on machine-specific DAG nodes. The outcome of the selection phase is ready for scheduling.
TOYDAGToDAGISel
, needs to be defined. To compile the file containing this class definition, add the filename to the CMakeLists.txt
file in the TOY
folder:$ vi CMakeLists .txt add_llvm_target(... ... TOYISelDAGToDAG.cpp ... )
TOYTargetMachine.h
and TOYTargetMachine.cpp
files:$ vi TOYTargetMachine.h const TOYInstrInfo *getInstrInfo() const override { return getSubtargetImpl()->getInstrInfo(); }
TOYTargetMachine.cpp
will create a pass in the instruction selection stage:class TOYPassConfig : public TargetPassConfig { public: ... virtual bool addInstSelector(); }; ... bool TOYPassConfig::addInstSelector() { addPass(createTOYISelDag(getTOYTargetMachine())); return false; }
To define an instruction selection function, proceed with the following steps:
TOYISelDAGToDAG.cpp
:$ vi TOYISelDAGToDAG.cpp
#include "TOY.h" #include "TOYTargetMachine.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "TOYInstrInfo.h"
TOYDAGToDAGISel
as follows, which will inherit from the SelectionDAGISel
class:class TOYDAGToDAGISel : public SelectionDAGISel { const TOYSubtarget &Subtarget; public: explicit TOYDAGToDAGISel(TOYTargetMachine &TM, CodeGenOpt::Level OptLevel) : SelectionDAGISel(TM, OptLevel), Subtarget(*TM.getSubtargetImpl()) {} };
Select()
, which will return an SDNode
object specific to the machine instruction:Declare it in the class:
SDNode *Select(SDNode *N);
Define it further as follows:
SDNode *TOYDAGToDAGISel::Select(SDNode *N) { return SelectCode(N); }
Declare it as shown here:
bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
Define it further, like this:
bool TOYDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), getTargetLowering()- >getPointerTy()); Offset = CurDAG->getTargetConstant(0, MVT::i32); return true; } if (Addr.getOpcode() == ISD::TargetExternalSymbol || Addr.getOpcode() == ISD::TargetGlobalAddress || Addr.getOpcode() == ISD::TargetGlobalTLSAddress) { return false; // direct calls. } Base = Addr; Offset = CurDAG->getTargetConstant(0, MVT::i32); return true; }
createTOYISelDag
pass converts a legalized DAG into a toy-specific DAG, ready for instruction scheduling in the same file:FunctionPass *llvm::createTOYISelDag(TOYTargetMachine &TM, CodeGenOpt::Level OptLevel) { return new TOYDAGToDAGISel(TM, OptLevel); }
The TOYDAGToDAGISel::Select()
function of TOYISelDAGToDAG.cpp
is used for the selection of the OP code DAG node, while TOYDAGToDAGISel::SelectAddr()
is used for the selection of the DATA DAG node with the addr
type. Note that if the address is global or external, we return false for the address, since its address is calculated in the global context.
18.119.159.178