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 // If we have a custom node, we have already selected 62 if (Node->isMachineOpcode()) { 63 DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n"); 64 Node->setNodeId(-1); 65 return; 66 } 67 68 // Instruction Selection not handled by the auto-generated tablegen selection 69 // should be handled here. 70 EVT VT = Node->getValueType(0); 71 if (Opcode == ISD::Constant && VT == XLenVT) { 72 auto *ConstNode = cast<ConstantSDNode>(Node); 73 // Materialize zero constants as copies from X0. This allows the coalescer 74 // to propagate these into other instructions. 75 if (ConstNode->isNullValue()) { 76 SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(Node), 77 RISCV::X0, XLenVT); 78 ReplaceNode(Node, New.getNode()); 79 return; 80 } 81 } 82 if (Opcode == ISD::FrameIndex) { 83 SDLoc DL(Node); 84 SDValue Imm = CurDAG->getTargetConstant(0, DL, XLenVT); 85 int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex(); 86 EVT VT = Node->getValueType(0); 87 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); 88 ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm)); 89 return; 90 } 91 92 // Select the default instruction. 93 SelectCode(Node); 94 } 95 96 bool RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand( 97 const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) { 98 switch (ConstraintID) { 99 case InlineAsm::Constraint_i: 100 case InlineAsm::Constraint_m: 101 // We just support simple memory operands that have a single address 102 // operand and need no special handling. 103 OutOps.push_back(Op); 104 return false; 105 default: 106 break; 107 } 108 109 return true; 110 } 111 112 bool RISCVDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) { 113 if (auto FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 114 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT()); 115 return true; 116 } 117 return false; 118 } 119 120 // This pass converts a legalized DAG into a RISCV-specific DAG, ready 121 // for instruction scheduling. 122 FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) { 123 return new RISCVDAGToDAGISel(TM); 124 } 125