1 //===-- RISCVISelDAGToDAG.cpp - A dag to dag inst selector for RISCV ------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines an instruction selector for the RISCV target. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "RISCV.h" 15 #include "MCTargetDesc/RISCVMCTargetDesc.h" 16 #include "RISCVTargetMachine.h" 17 #include "llvm/CodeGen/MachineFrameInfo.h" 18 #include "llvm/CodeGen/SelectionDAGISel.h" 19 #include "llvm/Support/Debug.h" 20 #include "llvm/Support/MathExtras.h" 21 #include "llvm/Support/raw_ostream.h" 22 using namespace llvm; 23 24 #define DEBUG_TYPE "riscv-isel" 25 26 // RISCV-specific code to select RISCV machine instructions for 27 // SelectionDAG operations. 28 namespace { 29 class RISCVDAGToDAGISel final : public SelectionDAGISel { 30 const RISCVSubtarget *Subtarget; 31 32 public: 33 explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine) 34 : SelectionDAGISel(TargetMachine) {} 35 36 StringRef getPassName() const override { 37 return "RISCV DAG->DAG Pattern Instruction Selection"; 38 } 39 40 bool runOnMachineFunction(MachineFunction &MF) override { 41 Subtarget = &MF.getSubtarget<RISCVSubtarget>(); 42 return SelectionDAGISel::runOnMachineFunction(MF); 43 } 44 45 void Select(SDNode *Node) override; 46 47 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, 48 std::vector<SDValue> &OutOps) override; 49 50 bool SelectAddrFI(SDValue Addr, SDValue &Base); 51 52 // Include the pieces autogenerated from the target description. 53 #include "RISCVGenDAGISel.inc" 54 }; 55 } 56 57 void RISCVDAGToDAGISel::Select(SDNode *Node) { 58 unsigned Opcode = Node->getOpcode(); 59 MVT XLenVT = Subtarget->getXLenVT(); 60 61 // Dump information about the Node being selected. 62 DEBUG(dbgs() << "Selecting: "; Node->dump(CurDAG); dbgs() << "\n"); 63 64 // If we have a custom node, we have already selected 65 if (Node->isMachineOpcode()) { 66 DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n"); 67 Node->setNodeId(-1); 68 return; 69 } 70 71 // Instruction Selection not handled by the auto-generated tablegen selection 72 // should be handled here. 73 EVT VT = Node->getValueType(0); 74 if (Opcode == ISD::Constant && VT == XLenVT) { 75 auto *ConstNode = cast<ConstantSDNode>(Node); 76 // Materialize zero constants as copies from X0. This allows the coalescer 77 // to propagate these into other instructions. 78 if (ConstNode->isNullValue()) { 79 SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(Node), 80 RISCV::X0, XLenVT); 81 ReplaceNode(Node, New.getNode()); 82 return; 83 } 84 } 85 if (Opcode == ISD::FrameIndex) { 86 SDLoc DL(Node); 87 SDValue Imm = CurDAG->getTargetConstant(0, DL, XLenVT); 88 int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex(); 89 EVT VT = Node->getValueType(0); 90 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); 91 ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm)); 92 return; 93 } 94 95 // Select the default instruction. 96 SelectCode(Node); 97 } 98 99 bool RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand( 100 const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) { 101 switch (ConstraintID) { 102 case InlineAsm::Constraint_i: 103 case InlineAsm::Constraint_m: 104 // We just support simple memory operands that have a single address 105 // operand and need no special handling. 106 OutOps.push_back(Op); 107 return false; 108 default: 109 break; 110 } 111 112 return true; 113 } 114 115 bool RISCVDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) { 116 if (auto FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 117 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT()); 118 return true; 119 } 120 return false; 121 } 122 123 // This pass converts a legalized DAG into a RISCV-specific DAG, ready 124 // for instruction scheduling. 125 FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) { 126 return new RISCVDAGToDAGISel(TM); 127 } 128