//===-- RISCVISelDAGToDAG.cpp - A dag to dag inst selector for RISCV ------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines an instruction selector for the RISCV target. // //===----------------------------------------------------------------------===// #include "RISCV.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" #include "RISCVTargetMachine.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; #define DEBUG_TYPE "riscv-isel" // RISCV-specific code to select RISCV machine instructions for // SelectionDAG operations. namespace { class RISCVDAGToDAGISel final : public SelectionDAGISel { const RISCVSubtarget *Subtarget; public: explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine) : SelectionDAGISel(TargetMachine) {} StringRef getPassName() const override { return "RISCV DAG->DAG Pattern Instruction Selection"; } bool runOnMachineFunction(MachineFunction &MF) override { Subtarget = &MF.getSubtarget(); return SelectionDAGISel::runOnMachineFunction(MF); } void Select(SDNode *Node) override; bool SelectAddrFI(SDValue Addr, SDValue &Base); // Include the pieces autogenerated from the target description. #include "RISCVGenDAGISel.inc" }; } void RISCVDAGToDAGISel::Select(SDNode *Node) { unsigned Opcode = Node->getOpcode(); MVT XLenVT = Subtarget->getXLenVT(); // Dump information about the Node being selected. DEBUG(dbgs() << "Selecting: "; Node->dump(CurDAG); dbgs() << "\n"); // If we have a custom node, we have already selected if (Node->isMachineOpcode()) { DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n"); Node->setNodeId(-1); return; } // Instruction Selection not handled by the auto-generated tablegen selection // should be handled here. EVT VT = Node->getValueType(0); if (Opcode == ISD::Constant && VT == XLenVT) { auto *ConstNode = cast(Node); // Materialize zero constants as copies from X0. This allows the coalescer // to propagate these into other instructions. if (ConstNode->isNullValue()) { SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), SDLoc(Node), RISCV::X0, XLenVT); ReplaceNode(Node, New.getNode()); return; } } if (Opcode == ISD::FrameIndex) { SDLoc DL(Node); SDValue Imm = CurDAG->getTargetConstant(0, DL, XLenVT); int FI = dyn_cast(Node)->getIndex(); EVT VT = Node->getValueType(0); SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm)); return; } // Select the default instruction. SelectCode(Node); } bool RISCVDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) { if (auto FIN = dyn_cast(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT()); return true; } return false; } // This pass converts a legalized DAG into a RISCV-specific DAG, ready // for instruction scheduling. FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) { return new RISCVDAGToDAGISel(TM); }