blob: 23a0382d4427e9c6f4e3ddb62656cbc9c1262345 [file] [log] [blame]
Alex Bradbury89718422017-10-19 21:37:38 +00001//===-- 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"
Alex Bradbury660bcce2017-12-11 11:53:54 +000017#include "llvm/CodeGen/MachineFrameInfo.h"
Alex Bradbury89718422017-10-19 21:37:38 +000018#include "llvm/CodeGen/SelectionDAGISel.h"
19#include "llvm/Support/Debug.h"
20#include "llvm/Support/MathExtras.h"
21#include "llvm/Support/raw_ostream.h"
22using namespace llvm;
23
24#define DEBUG_TYPE "riscv-isel"
25
26// RISCV-specific code to select RISCV machine instructions for
27// SelectionDAG operations.
28namespace {
29class RISCVDAGToDAGISel final : public SelectionDAGISel {
Alex Bradbury0c7b3642017-11-21 08:23:08 +000030 const RISCVSubtarget *Subtarget;
31
Alex Bradbury89718422017-10-19 21:37:38 +000032public:
33 explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine)
34 : SelectionDAGISel(TargetMachine) {}
35
36 StringRef getPassName() const override {
37 return "RISCV DAG->DAG Pattern Instruction Selection";
38 }
39
Alex Bradbury0c7b3642017-11-21 08:23:08 +000040 bool runOnMachineFunction(MachineFunction &MF) override {
41 Subtarget = &MF.getSubtarget<RISCVSubtarget>();
42 return SelectionDAGISel::runOnMachineFunction(MF);
43 }
44
Alex Bradbury89718422017-10-19 21:37:38 +000045 void Select(SDNode *Node) override;
46
Alex Bradbury9330e642018-01-10 20:05:09 +000047 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
48 std::vector<SDValue> &OutOps) override;
49
Alex Bradbury660bcce2017-12-11 11:53:54 +000050 bool SelectAddrFI(SDValue Addr, SDValue &Base);
51
Alex Bradbury89718422017-10-19 21:37:38 +000052// Include the pieces autogenerated from the target description.
53#include "RISCVGenDAGISel.inc"
54};
55}
56
57void RISCVDAGToDAGISel::Select(SDNode *Node) {
Alex Bradbury0c7b3642017-11-21 08:23:08 +000058 unsigned Opcode = Node->getOpcode();
59 MVT XLenVT = Subtarget->getXLenVT();
60
Alex Bradbury89718422017-10-19 21:37:38 +000061 // 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
Alex Bradbury0c7b3642017-11-21 08:23:08 +000071 // Instruction Selection not handled by the auto-generated tablegen selection
72 // should be handled here.
73 EVT VT = Node->getValueType(0);
Alex Bradbury9caefe32017-11-21 12:00:19 +000074 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;
Alex Bradbury0c7b3642017-11-21 08:23:08 +000083 }
Alex Bradbury0c7b3642017-11-21 08:23:08 +000084 }
Alex Bradbury660bcce2017-12-11 11:53:54 +000085 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 }
Alex Bradbury0c7b3642017-11-21 08:23:08 +000094
Alex Bradbury89718422017-10-19 21:37:38 +000095 // Select the default instruction.
96 SelectCode(Node);
97}
98
Alex Bradbury9330e642018-01-10 20:05:09 +000099bool 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
Alex Bradbury660bcce2017-12-11 11:53:54 +0000115bool 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
Alex Bradbury89718422017-10-19 21:37:38 +0000123// This pass converts a legalized DAG into a RISCV-specific DAG, ready
124// for instruction scheduling.
125FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) {
126 return new RISCVDAGToDAGISel(TM);
127}