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