aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Bradbury <asb@lowrisc.org>2017-10-19 21:37:38 +0000
committerAlex Bradbury <asb@lowrisc.org>2017-10-19 21:37:38 +0000
commit5a3d179fab70138a1cb63a8d7c4a407dbb7dba6e (patch)
treee50f04a5ea2113534abebbd84e3300b3c5dc5982
parentab16d0abcd68c515720e0da86db48e36db562d3f (diff)
[RISCV] Initial codegen support for ALU operations
This adds the minimum necessary to support codegen for simple ALU operations on RV32. Prolog and epilog insertion, support for memory operations etc etc follow in future patches. Leave guessInstructionProperties=1 until https://reviews.llvm.org/D37065 is reviewed and lands. Differential Revision: https://reviews.llvm.org/D29933 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@316188 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/RISCV/CMakeLists.txt11
-rw-r--r--lib/Target/RISCV/LLVMBuild.txt3
-rw-r--r--lib/Target/RISCV/RISCV.h31
-rw-r--r--lib/Target/RISCV/RISCV.td7
-rw-r--r--lib/Target/RISCV/RISCVAsmPrinter.cpp67
-rw-r--r--lib/Target/RISCV/RISCVCallingConv.td29
-rw-r--r--lib/Target/RISCV/RISCVFrameLowering.cpp29
-rw-r--r--lib/Target/RISCV/RISCVFrameLowering.h35
-rw-r--r--lib/Target/RISCV/RISCVISelDAGToDAG.cpp63
-rw-r--r--lib/Target/RISCV/RISCVISelLowering.cpp170
-rw-r--r--lib/Target/RISCV/RISCVISelLowering.h62
-rw-r--r--lib/Target/RISCV/RISCVInstrInfo.cpp31
-rw-r--r--lib/Target/RISCV/RISCVInstrInfo.h32
-rw-r--r--lib/Target/RISCV/RISCVInstrInfo.td60
-rw-r--r--lib/Target/RISCV/RISCVMCInstLower.cpp50
-rw-r--r--lib/Target/RISCV/RISCVRegisterInfo.cpp61
-rw-r--r--lib/Target/RISCV/RISCVRegisterInfo.h40
-rw-r--r--lib/Target/RISCV/RISCVRegisterInfo.td13
-rw-r--r--lib/Target/RISCV/RISCVSubtarget.cpp48
-rw-r--r--lib/Target/RISCV/RISCVSubtarget.h75
-rw-r--r--lib/Target/RISCV/RISCVTargetMachine.cpp26
-rw-r--r--lib/Target/RISCV/RISCVTargetMachine.h6
-rw-r--r--test/CodeGen/RISCV/alu32.ll163
-rw-r--r--test/CodeGen/RISCV/lit.local.cfg2
24 files changed, 1103 insertions, 11 deletions
diff --git a/lib/Target/RISCV/CMakeLists.txt b/lib/Target/RISCV/CMakeLists.txt
index b9f3fc110c7..bac4d4c353d 100644
--- a/lib/Target/RISCV/CMakeLists.txt
+++ b/lib/Target/RISCV/CMakeLists.txt
@@ -3,14 +3,25 @@ set(LLVM_TARGET_DEFINITIONS RISCV.td)
tablegen(LLVM RISCVGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM RISCVGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM RISCVGenMCCodeEmitter.inc -gen-emitter)
+tablegen(LLVM RISCVGenMCPseudoLowering.inc -gen-pseudo-lowering)
tablegen(LLVM RISCVGenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM RISCVGenAsmWriter.inc -gen-asm-writer)
+tablegen(LLVM RISCVGenCallingConv.inc -gen-callingconv)
+tablegen(LLVM RISCVGenDAGISel.inc -gen-dag-isel)
tablegen(LLVM RISCVGenSubtargetInfo.inc -gen-subtarget)
tablegen(LLVM RISCVGenDisassemblerTables.inc -gen-disassembler)
add_public_tablegen_target(RISCVCommonTableGen)
add_llvm_target(RISCVCodeGen
+ RISCVAsmPrinter.cpp
+ RISCVFrameLowering.cpp
+ RISCVInstrInfo.cpp
+ RISCVISelDAGToDAG.cpp
+ RISCVISelLowering.cpp
+ RISCVMCInstLower.cpp
+ RISCVRegisterInfo.cpp
+ RISCVSubtarget.cpp
RISCVTargetMachine.cpp
)
diff --git a/lib/Target/RISCV/LLVMBuild.txt b/lib/Target/RISCV/LLVMBuild.txt
index e15963b5bd7..ab21565b0c2 100644
--- a/lib/Target/RISCV/LLVMBuild.txt
+++ b/lib/Target/RISCV/LLVMBuild.txt
@@ -30,5 +30,6 @@ has_disassembler = 1
type = Library
name = RISCVCodeGen
parent = RISCV
-required_libraries = AsmPrinter Core CodeGen MC RISCVAsmPrinter RISCVDesc RISCVInfo Support Target
+required_libraries = AsmPrinter Core CodeGen MC RISCVAsmPrinter RISCVDesc
+ RISCVInfo SelectionDAG Support Target
add_to_library_groups = RISCV
diff --git a/lib/Target/RISCV/RISCV.h b/lib/Target/RISCV/RISCV.h
new file mode 100644
index 00000000000..1b6140203c8
--- /dev/null
+++ b/lib/Target/RISCV/RISCV.h
@@ -0,0 +1,31 @@
+//===-- RISCV.h - Top-level interface for RISCV -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the entry points for global functions defined in the LLVM
+// RISC-V back-end.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_RISCV_RISCV_H
+#define LLVM_LIB_TARGET_RISCV_RISCV_H
+
+#include "MCTargetDesc/RISCVMCTargetDesc.h"
+#include "llvm/Target/TargetMachine.h"
+
+namespace llvm {
+class RISCVTargetMachine;
+class MCInst;
+class MachineInstr;
+
+void LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI);
+
+FunctionPass *createRISCVISelDag(RISCVTargetMachine &TM);
+}
+
+#endif
diff --git a/lib/Target/RISCV/RISCV.td b/lib/Target/RISCV/RISCV.td
index 7b61901915f..da919acad36 100644
--- a/lib/Target/RISCV/RISCV.td
+++ b/lib/Target/RISCV/RISCV.td
@@ -20,10 +20,11 @@ def RV64 : HwMode<"+64bit">;
def RV32 : HwMode<"-64bit">;
//===----------------------------------------------------------------------===//
-// Register file, instruction descriptions.
+// Registers, calling conventions, instruction descriptions.
//===----------------------------------------------------------------------===//
include "RISCVRegisterInfo.td"
+include "RISCVCallingConv.td"
include "RISCVInstrInfo.td"
//===----------------------------------------------------------------------===//
@@ -38,7 +39,9 @@ def : ProcessorModel<"generic-rv64", NoSchedModel, [Feature64Bit]>;
// Define the RISC-V target.
//===----------------------------------------------------------------------===//
-def RISCVInstrInfo : InstrInfo;
+def RISCVInstrInfo : InstrInfo {
+ let guessInstructionProperties = 0;
+}
def RISCVAsmParser : AsmParser {
let ShouldEmitMatchRegisterAltName = 1;
diff --git a/lib/Target/RISCV/RISCVAsmPrinter.cpp b/lib/Target/RISCV/RISCVAsmPrinter.cpp
new file mode 100644
index 00000000000..1c213b6c7e9
--- /dev/null
+++ b/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -0,0 +1,67 @@
+//===-- RISCVAsmPrinter.cpp - RISCV LLVM assembly writer ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a printer that converts from our internal representation
+// of machine-dependent LLVM code to the RISCV assembly language.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCV.h"
+#include "InstPrinter/RISCVInstPrinter.h"
+#include "RISCVTargetMachine.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "asm-printer"
+
+namespace {
+class RISCVAsmPrinter : public AsmPrinter {
+public:
+ explicit RISCVAsmPrinter(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> Streamer)
+ : AsmPrinter(TM, std::move(Streamer)) {}
+
+ StringRef getPassName() const override { return "RISCV Assembly Printer"; }
+
+ void EmitInstruction(const MachineInstr *MI) override;
+
+ bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
+ const MachineInstr *MI);
+};
+}
+
+// Simple pseudo-instructions have their lowering (with expansion to real
+// instructions) auto-generated.
+#include "RISCVGenMCPseudoLowering.inc"
+
+void RISCVAsmPrinter::EmitInstruction(const MachineInstr *MI) {
+ // Do any auto-generated pseudo lowerings.
+ if (emitPseudoExpansionLowering(*OutStreamer, MI))
+ return;
+
+ MCInst TmpInst;
+ LowerRISCVMachineInstrToMCInst(MI, TmpInst);
+ EmitToStreamer(*OutStreamer, TmpInst);
+}
+
+// Force static initialization.
+extern "C" void LLVMInitializeRISCVAsmPrinter() {
+ RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());
+ RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target());
+}
diff --git a/lib/Target/RISCV/RISCVCallingConv.td b/lib/Target/RISCV/RISCVCallingConv.td
new file mode 100644
index 00000000000..e0c25e32e01
--- /dev/null
+++ b/lib/Target/RISCV/RISCVCallingConv.td
@@ -0,0 +1,29 @@
+//===-- RISCVCallingConv.td - Calling Conventions RISCV ----*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This describes the calling conventions for the RISCV architecture.
+//
+//===----------------------------------------------------------------------===//
+
+// RISCV 32-bit C return-value convention.
+def RetCC_RISCV32 : CallingConv<[CCIfType<[i32], CCAssignToReg<[X10, X11]>>]>;
+
+// RISCV 32-bit C Calling convention.
+def CC_RISCV32 : CallingConv<[
+ // Promote i8/i16 args to i32
+ CCIfType<[ i8, i16 ], CCPromoteToType<i32>>,
+
+ // All arguments get passed in integer registers if there is space.
+ CCIfType<[i32], CCAssignToReg<[ X10, X11, X12, X13, X14, X15, X16, X17]>>,
+
+ // Could be assigned to the stack in 8-byte aligned units, but unsupported
+ CCAssignToStack<8, 8>
+]>;
+
+def CSR : CalleeSavedRegs<(add X1, X3, X4, X8, X9, (sequence "X%u", 18, 27))>;
diff --git a/lib/Target/RISCV/RISCVFrameLowering.cpp b/lib/Target/RISCV/RISCVFrameLowering.cpp
new file mode 100644
index 00000000000..fd3b258e26c
--- /dev/null
+++ b/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -0,0 +1,29 @@
+//===-- RISCVFrameLowering.cpp - RISCV Frame Information ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the RISCV implementation of TargetFrameLowering class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCVFrameLowering.h"
+#include "RISCVSubtarget.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+
+using namespace llvm;
+
+bool RISCVFrameLowering::hasFP(const MachineFunction &MF) const { return true; }
+
+void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
+ MachineBasicBlock &MBB) const {}
+
+void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
+ MachineBasicBlock &MBB) const {}
diff --git a/lib/Target/RISCV/RISCVFrameLowering.h b/lib/Target/RISCV/RISCVFrameLowering.h
new file mode 100644
index 00000000000..14772ddac4a
--- /dev/null
+++ b/lib/Target/RISCV/RISCVFrameLowering.h
@@ -0,0 +1,35 @@
+//===-- RISCVFrameLowering.h - Define frame lowering for RISCV -*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements RISCV-specific bits of TargetFrameLowering class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_RISCV_RISCVFRAMELOWERING_H
+#define LLVM_LIB_TARGET_RISCV_RISCVFRAMELOWERING_H
+
+#include "llvm/Target/TargetFrameLowering.h"
+
+namespace llvm {
+class RISCVSubtarget;
+
+class RISCVFrameLowering : public TargetFrameLowering {
+public:
+ explicit RISCVFrameLowering(const RISCVSubtarget &STI)
+ : TargetFrameLowering(StackGrowsDown,
+ /*StackAlignment=*/16,
+ /*LocalAreaOffset=*/0) {}
+
+ void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
+ void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
+
+ bool hasFP(const MachineFunction &MF) const override;
+};
+}
+#endif
diff --git a/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
new file mode 100644
index 00000000000..78f61fa4184
--- /dev/null
+++ b/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -0,0 +1,63 @@
+//===-- 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/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 {
+public:
+ explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine)
+ : SelectionDAGISel(TargetMachine) {}
+
+ StringRef getPassName() const override {
+ return "RISCV DAG->DAG Pattern Instruction Selection";
+ }
+
+ void Select(SDNode *Node) override;
+
+// Include the pieces autogenerated from the target description.
+#include "RISCVGenDAGISel.inc"
+};
+}
+
+void RISCVDAGToDAGISel::Select(SDNode *Node) {
+ // 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;
+ }
+
+ // Select the default instruction.
+ SelectCode(Node);
+}
+
+// This pass converts a legalized DAG into a RISCV-specific DAG, ready
+// for instruction scheduling.
+FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) {
+ return new RISCVDAGToDAGISel(TM);
+}
diff --git a/lib/Target/RISCV/RISCVISelLowering.cpp b/lib/Target/RISCV/RISCVISelLowering.cpp
new file mode 100644
index 00000000000..d76170b7b78
--- /dev/null
+++ b/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -0,0 +1,170 @@
+//===-- RISCVISelLowering.cpp - RISCV DAG Lowering Implementation --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interfaces that RISCV uses to lower LLVM code into a
+// selection DAG.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCVISelLowering.h"
+#include "RISCV.h"
+#include "RISCVRegisterInfo.h"
+#include "RISCVSubtarget.h"
+#include "RISCVTargetMachine.h"
+#include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
+#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "riscv-lower"
+
+RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
+ const RISCVSubtarget &STI)
+ : TargetLowering(TM), Subtarget(STI) {
+
+ MVT XLenVT = Subtarget.getXLenVT();
+
+ // Set up the register classes.
+ addRegisterClass(XLenVT, &RISCV::GPRRegClass);
+
+ // Compute derived properties from the register classes.
+ computeRegisterProperties(STI.getRegisterInfo());
+
+ setStackPointerRegisterToSaveRestore(RISCV::X2);
+
+ // TODO: add all necessary setOperationAction calls.
+
+ setBooleanContents(ZeroOrOneBooleanContent);
+
+ // Function alignments (log2).
+ setMinFunctionAlignment(3);
+ setPrefFunctionAlignment(3);
+}
+
+SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
+ SelectionDAG &DAG) const {
+ switch (Op.getOpcode()) {
+ default:
+ report_fatal_error("unimplemented operand");
+ }
+}
+
+// Calling Convention Implementation.
+#include "RISCVGenCallingConv.inc"
+
+// Transform physical registers into virtual registers.
+SDValue RISCVTargetLowering::LowerFormalArguments(
+ SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
+ SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+
+ switch (CallConv) {
+ default:
+ report_fatal_error("Unsupported calling convention");
+ case CallingConv::C:
+ break;
+ }
+
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineRegisterInfo &RegInfo = MF.getRegInfo();
+ MVT XLenVT = Subtarget.getXLenVT();
+
+ if (IsVarArg)
+ report_fatal_error("VarArg not supported");
+
+ // Assign locations to all of the incoming arguments.
+ SmallVector<CCValAssign, 16> ArgLocs;
+ CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
+ CCInfo.AnalyzeFormalArguments(Ins, CC_RISCV32);
+
+ for (auto &VA : ArgLocs) {
+ if (!VA.isRegLoc())
+ report_fatal_error("Defined with too many args");
+
+ // Arguments passed in registers.
+ EVT RegVT = VA.getLocVT();
+ if (RegVT != XLenVT) {
+ DEBUG(dbgs() << "LowerFormalArguments Unhandled argument type: "
+ << RegVT.getEVTString() << "\n");
+ report_fatal_error("unhandled argument type");
+ }
+ const unsigned VReg =
+ RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
+ RegInfo.addLiveIn(VA.getLocReg(), VReg);
+ SDValue ArgIn = DAG.getCopyFromReg(Chain, DL, VReg, RegVT);
+
+ InVals.push_back(ArgIn);
+ }
+ return Chain;
+}
+
+SDValue
+RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+ bool IsVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<SDValue> &OutVals,
+ const SDLoc &DL, SelectionDAG &DAG) const {
+ if (IsVarArg) {
+ report_fatal_error("VarArg not supported");
+ }
+
+ // Stores the assignment of the return value to a location.
+ SmallVector<CCValAssign, 16> RVLocs;
+
+ // Info about the registers and stack slot.
+ CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
+ *DAG.getContext());
+
+ CCInfo.AnalyzeReturn(Outs, RetCC_RISCV32);
+
+ SDValue Flag;
+ SmallVector<SDValue, 4> RetOps(1, Chain);
+
+ // Copy the result values into the output registers.
+ for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) {
+ CCValAssign &VA = RVLocs[i];
+ assert(VA.isRegLoc() && "Can only return in registers!");
+
+ Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Flag);
+
+ // Guarantee that all emitted copies are stuck together.
+ Flag = Chain.getValue(1);
+ RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
+ }
+
+ RetOps[0] = Chain; // Update chain.
+
+ // Add the flag if we have it.
+ if (Flag.getNode()) {
+ RetOps.push_back(Flag);
+ }
+
+ return DAG.getNode(RISCVISD::RET_FLAG, DL, MVT::Other, RetOps);
+}
+
+const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
+ switch ((RISCVISD::NodeType)Opcode) {
+ case RISCVISD::FIRST_NUMBER:
+ break;
+ case RISCVISD::RET_FLAG:
+ return "RISCVISD::RET_FLAG";
+ }
+ return nullptr;
+}
diff --git a/lib/Target/RISCV/RISCVISelLowering.h b/lib/Target/RISCV/RISCVISelLowering.h
new file mode 100644
index 00000000000..9fed48fc04e
--- /dev/null
+++ b/lib/Target/RISCV/RISCVISelLowering.h
@@ -0,0 +1,62 @@
+//===-- RISCVISelLowering.h - RISCV DAG Lowering Interface ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interfaces that RISCV uses to lower LLVM code into a
+// selection DAG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_RISCV_RISCVISELLOWERING_H
+#define LLVM_LIB_TARGET_RISCV_RISCVISELLOWERING_H
+
+#include "RISCV.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/Target/TargetLowering.h"
+
+namespace llvm {
+class RISCVSubtarget;
+namespace RISCVISD {
+enum NodeType : unsigned {
+ FIRST_NUMBER = ISD::BUILTIN_OP_END,
+ RET_FLAG
+};
+}
+
+class RISCVTargetLowering : public TargetLowering {
+ const RISCVSubtarget &Subtarget;
+
+public:
+ explicit RISCVTargetLowering(const TargetMachine &TM,
+ const RISCVSubtarget &STI);
+
+ // Provide custom lowering hooks for some operations.
+ SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
+
+ // This method returns the name of a target specific DAG node.
+ const char *getTargetNodeName(unsigned Opcode) const override;
+
+private:
+ // Lower incoming arguments, copy physregs into vregs
+ SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
+ bool IsVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ const SDLoc &DL, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const override;
+ SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
+ SelectionDAG &DAG) const override;
+ bool shouldConvertConstantLoadToIntImm(const APInt &Imm,
+ Type *Ty) const override {
+ return true;
+ }
+};
+}
+
+#endif
diff --git a/lib/Target/RISCV/RISCVInstrInfo.cpp b/lib/Target/RISCV/RISCVInstrInfo.cpp
new file mode 100644
index 00000000000..92db5358ce4
--- /dev/null
+++ b/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -0,0 +1,31 @@
+//===-- RISCVInstrInfo.cpp - RISCV Instruction Information ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the RISCV implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCVInstrInfo.h"
+#include "RISCV.h"
+#include "RISCVSubtarget.h"
+#include "RISCVTargetMachine.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
+
+#define GET_INSTRINFO_CTOR_DTOR
+#include "RISCVGenInstrInfo.inc"
+
+using namespace llvm;
+
+RISCVInstrInfo::RISCVInstrInfo() : RISCVGenInstrInfo() {}
diff --git a/lib/Target/RISCV/RISCVInstrInfo.h b/lib/Target/RISCV/RISCVInstrInfo.h
new file mode 100644
index 00000000000..50404d5554d
--- /dev/null
+++ b/lib/Target/RISCV/RISCVInstrInfo.h
@@ -0,0 +1,32 @@
+//===-- RISCVInstrInfo.h - RISCV Instruction Information --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the RISCV implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_RISCV_RISCVINSTRINFO_H
+#define LLVM_LIB_TARGET_RISCV_RISCVINSTRINFO_H
+
+#include "RISCVRegisterInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
+
+#define GET_INSTRINFO_HEADER
+#include "RISCVGenInstrInfo.inc"
+
+namespace llvm {
+
+class RISCVInstrInfo : public RISCVGenInstrInfo {
+
+public:
+ RISCVInstrInfo();
+};
+}
+
+#endif
diff --git a/lib/Target/RISCV/RISCVInstrInfo.td b/lib/Target/RISCV/RISCVInstrInfo.td
index 213ef63f5f9..23adf1eda9d 100644
--- a/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/lib/Target/RISCV/RISCVInstrInfo.td
@@ -14,6 +14,13 @@
include "RISCVInstrFormats.td"
//===----------------------------------------------------------------------===//
+// RISC-V specific DAG Nodes.
+//===----------------------------------------------------------------------===//
+
+def RetFlag : SDNode<"RISCVISD::RET_FLAG", SDTNone,
+ [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
+
+//===----------------------------------------------------------------------===//
// Operand and SDNode transformation definitions.
//===----------------------------------------------------------------------===//
@@ -43,12 +50,12 @@ def fencearg : Operand<XLenVT> {
let DecoderMethod = "decodeUImmOperand<4>";
}
-def uimm5 : Operand<XLenVT> {
+def uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<5>;
let DecoderMethod = "decodeUImmOperand<5>";
}
-def simm12 : Operand<XLenVT> {
+def simm12 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isInt<12>(Imm);}]> {
let ParserMatchClass = SImmAsmOperand<12>;
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeSImmOperand<12>";
@@ -231,3 +238,52 @@ def CSRRC : CSR_ir<0b011, "csrrc">;
def CSRRWI : CSR_ii<0b101, "csrrwi">;
def CSRRSI : CSR_ii<0b110, "csrrsi">;
def CSRRCI : CSR_ii<0b111, "csrrci">;
+
+//===----------------------------------------------------------------------===//
+// Pseudo-instructions and codegen patterns
+//
+// Naming convention: For 'generic' pattern classes, we use the naming
+// convention PatTy1Ty2. For pattern classes which offer a more complex
+// expension, prefix the class name, e.g. BccPat.
+//===----------------------------------------------------------------------===//
+
+/// Generic pattern classes
+
+class PatGprGpr<SDPatternOperator OpNode, RVInstR Inst>
+ : Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>;
+class PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst>
+ : Pat<(OpNode GPR:$rs1, simm12:$imm12), (Inst GPR:$rs1, simm12:$imm12)>;
+class PatGprUimm5<SDPatternOperator OpNode, RVInstIShift Inst>
+ : Pat<(OpNode GPR:$rs1, uimm5:$shamt),
+ (Inst GPR:$rs1, uimm5:$shamt)>;
+
+/// Simple arithmetic operations
+
+def : PatGprGpr<add, ADD>;
+def : PatGprSimm12<add, ADDI>;
+def : PatGprGpr<sub, SUB>;
+def : PatGprGpr<or, OR>;
+def : PatGprSimm12<or, ORI>;
+def : PatGprGpr<and, AND>;
+def : PatGprSimm12<and, ANDI>;
+def : PatGprGpr<xor, XOR>;
+def : PatGprSimm12<xor, XORI>;
+def : PatGprGpr<shl, SLL>;
+def : PatGprUimm5<shl, SLLI>;
+def : PatGprGpr<srl, SRL>;
+def : PatGprUimm5<srl, SRLI>;
+def : PatGprGpr<sra, SRA>;
+def : PatGprUimm5<sra, SRAI>;
+
+/// Setcc
+
+def : PatGprGpr<setlt, SLT>;
+def : PatGprSimm12<setlt, SLTI>;
+def : PatGprGpr<setult, SLTU>;
+def : PatGprSimm12<setult, SLTIU>;
+
+/// Branches and jumps
+
+let isBarrier = 1, isReturn = 1, isTerminator = 1 in
+def PseudoRET : Pseudo<(outs), (ins), [(RetFlag)]>,
+ PseudoInstExpansion<(JALR X0, X1, 0)>;
diff --git a/lib/Target/RISCV/RISCVMCInstLower.cpp b/lib/Target/RISCV/RISCVMCInstLower.cpp
new file mode 100644
index 00000000000..1ac8d982ff9
--- /dev/null
+++ b/lib/Target/RISCV/RISCVMCInstLower.cpp
@@ -0,0 +1,50 @@
+//===-- RISCVMCInstLower.cpp - Convert RISCV MachineInstr to an MCInst ------=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code to lower RISCV MachineInstrs to their corresponding
+// MCInst records.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCV.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+void llvm::LowerRISCVMachineInstrToMCInst(const MachineInstr *MI,
+ MCInst &OutMI) {
+ OutMI.setOpcode(MI->getOpcode());
+
+ for (const MachineOperand &MO : MI->operands()) {
+ MCOperand MCOp;
+ switch (MO.getType()) {
+ default:
+ report_fatal_error(
+ "LowerRISCVMachineInstrToMCInst: unknown operand type");
+ case MachineOperand::MO_Register:
+ // Ignore all implicit register operands.
+ if (MO.isImplicit())
+ continue;
+ MCOp = MCOperand::createReg(MO.getReg());
+ break;
+ case MachineOperand::MO_Immediate:
+ MCOp = MCOperand::createImm(MO.getImm());
+ break;
+ }
+
+ OutMI.addOperand(MCOp);
+ }
+}
diff --git a/lib/Target/RISCV/RISCVRegisterInfo.cpp b/lib/Target/RISCV/RISCVRegisterInfo.cpp
new file mode 100644
index 00000000000..4f6c528061c
--- /dev/null
+++ b/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -0,0 +1,61 @@
+//===-- RISCVRegisterInfo.cpp - RISCV Register Information ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the RISCV implementation of the TargetRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCVRegisterInfo.h"
+#include "RISCV.h"
+#include "RISCVSubtarget.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/Target/TargetInstrInfo.h"
+
+#define GET_REGINFO_TARGET_DESC
+#include "RISCVGenRegisterInfo.inc"
+
+using namespace llvm;
+
+RISCVRegisterInfo::RISCVRegisterInfo(unsigned HwMode)
+ : RISCVGenRegisterInfo(RISCV::X1, /*DwarfFlavour*/0, /*EHFlavor*/0,
+ /*PC*/0, HwMode) {}
+
+const MCPhysReg *
+RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
+ return CSR_SaveList;
+}
+
+BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
+ BitVector Reserved(getNumRegs());
+
+ // Use markSuperRegs to ensure any register aliases are also reserved
+ markSuperRegs(Reserved, RISCV::X0); // zero
+ markSuperRegs(Reserved, RISCV::X1); // ra
+ markSuperRegs(Reserved, RISCV::X2); // sp
+ markSuperRegs(Reserved, RISCV::X3); // gp
+ markSuperRegs(Reserved, RISCV::X4); // tp
+ markSuperRegs(Reserved, RISCV::X8); // fp
+ assert(checkAllSuperRegsMarked(Reserved));
+ return Reserved;
+}
+
+void RISCVRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
+ int SPAdj, unsigned FIOperandNum,
+ RegScavenger *RS) const {
+ report_fatal_error("Subroutines not supported yet");
+}
+
+unsigned RISCVRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
+ return RISCV::X8;
+}
diff --git a/lib/Target/RISCV/RISCVRegisterInfo.h b/lib/Target/RISCV/RISCVRegisterInfo.h
new file mode 100644
index 00000000000..94af9f44ecd
--- /dev/null
+++ b/lib/Target/RISCV/RISCVRegisterInfo.h
@@ -0,0 +1,40 @@
+//===-- RISCVRegisterInfo.h - RISCV Register Information Impl ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the RISCV implementation of the TargetRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_RISCV_RISCVREGISTERINFO_H
+#define LLVM_LIB_TARGET_RISCV_RISCVREGISTERINFO_H
+
+#include "llvm/Target/TargetRegisterInfo.h"
+
+#define GET_REGINFO_HEADER
+#include "RISCVGenRegisterInfo.inc"
+
+namespace llvm {
+
+struct RISCVRegisterInfo : public RISCVGenRegisterInfo {
+
+ RISCVRegisterInfo(unsigned HwMode);
+
+ const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
+
+ BitVector getReservedRegs(const MachineFunction &MF) const override;
+
+ void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
+ unsigned FIOperandNum,
+ RegScavenger *RS = nullptr) const override;
+
+ unsigned getFrameRegister(const MachineFunction &MF) const override;
+};
+}
+
+#endif
diff --git a/lib/Target/RISCV/RISCVRegisterInfo.td b/lib/Target/RISCV/RISCVRegisterInfo.td
index a5484130dfc..78c036a37b9 100644
--- a/lib/Target/RISCV/RISCVRegisterInfo.td
+++ b/lib/Target/RISCV/RISCVRegisterInfo.td
@@ -58,10 +58,15 @@ let RegAltNameIndices = [ABIRegAltName] in {
def XLenVT : ValueTypeByHwMode<[RV32, RV64, DefaultMode],
[i32, i64, i32]>;
-// TODO: once codegen is implemented, registers should be listed in an order
-// reflecting the preferred register allocation sequence.
-def GPR : RegisterClass< "RISCV", [XLenVT], 32, (add
- (sequence "X%u", 0, 31)
+// The order of registers represents the preferred allocation sequence.
+// Registers are listed in the order caller-save, callee-save, specials.
+def GPR : RegisterClass<"RISCV", [XLenVT], 32, (add
+ (sequence "X%u", 10, 17),
+ (sequence "X%u", 5, 7),
+ (sequence "X%u", 28, 31),
+ (sequence "X%u", 8, 9),
+ (sequence "X%u", 18, 27),
+ (sequence "X%u", 0, 4)
)> {
let RegInfos = RegInfoByHwMode<
[RV32, RV64, DefaultMode],
diff --git a/lib/Target/RISCV/RISCVSubtarget.cpp b/lib/Target/RISCV/RISCVSubtarget.cpp
new file mode 100644
index 00000000000..b221ea84a33
--- /dev/null
+++ b/lib/Target/RISCV/RISCVSubtarget.cpp
@@ -0,0 +1,48 @@
+//===-- RISCVSubtarget.cpp - RISCV Subtarget Information ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the RISCV specific subclass of TargetSubtargetInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCVSubtarget.h"
+#include "RISCV.h"
+#include "RISCVFrameLowering.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "riscv-subtarget"
+
+#define GET_SUBTARGETINFO_TARGET_DESC
+#define GET_SUBTARGETINFO_CTOR
+#include "RISCVGenSubtargetInfo.inc"
+
+void RISCVSubtarget::anchor() {}
+
+RISCVSubtarget &RISCVSubtarget::initializeSubtargetDependencies(StringRef CPU,
+ StringRef FS,
+ bool Is64Bit) {
+ // Determine default and user-specified characteristics
+ std::string CPUName = CPU;
+ if (CPUName.empty())
+ CPUName = Is64Bit ? "generic-rv64" : "generic-rv32";
+ ParseSubtargetFeatures(CPUName, FS);
+ if (Is64Bit) {
+ XLenVT = MVT::i64;
+ XLen = 64;
+ }
+ return *this;
+}
+
+RISCVSubtarget::RISCVSubtarget(const Triple &TT, const std::string &CPU,
+ const std::string &FS, const TargetMachine &TM)
+ : RISCVGenSubtargetInfo(TT, CPU, FS),
+ FrameLowering(initializeSubtargetDependencies(CPU, FS, TT.isArch64Bit())),
+ InstrInfo(), RegInfo(getHwMode()), TLInfo(TM, *this) {}
diff --git a/lib/Target/RISCV/RISCVSubtarget.h b/lib/Target/RISCV/RISCVSubtarget.h
new file mode 100644
index 00000000000..657b0e65620
--- /dev/null
+++ b/lib/Target/RISCV/RISCVSubtarget.h
@@ -0,0 +1,75 @@
+//===-- RISCVSubtarget.h - Define Subtarget for the RISCV -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the RISCV specific subclass of TargetSubtargetInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_RISCV_RISCVSUBTARGET_H
+#define LLVM_LIB_TARGET_RISCV_RISCVSUBTARGET_H
+
+#include "RISCVFrameLowering.h"
+#include "RISCVISelLowering.h"
+#include "RISCVInstrInfo.h"
+#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+
+#define GET_SUBTARGETINFO_HEADER
+#include "RISCVGenSubtargetInfo.inc"
+
+namespace llvm {
+class StringRef;
+
+class RISCVSubtarget : public RISCVGenSubtargetInfo {
+ virtual void anchor();
+ bool HasRV64 = false;
+ unsigned XLen = 32;
+ MVT XLenVT = MVT::i32;
+ RISCVFrameLowering FrameLowering;
+ RISCVInstrInfo InstrInfo;
+ RISCVRegisterInfo RegInfo;
+ RISCVTargetLowering TLInfo;
+ SelectionDAGTargetInfo TSInfo;
+
+ /// Initializes using the passed in CPU and feature strings so that we can
+ /// use initializer lists for subtarget initialization.
+ RISCVSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS,
+ bool Is64Bit);
+
+public:
+ // Initializes the data members to match that of the specified triple.
+ RISCVSubtarget(const Triple &TT, const std::string &CPU,
+ const std::string &FS, const TargetMachine &TM);
+
+ // Parses features string setting specified subtarget options. The
+ // definition of this function is auto-generated by tblgen.
+ void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
+
+ const RISCVFrameLowering *getFrameLowering() const override {
+ return &FrameLowering;
+ }
+ const RISCVInstrInfo *getInstrInfo() const override { return &InstrInfo; }
+ const RISCVRegisterInfo *getRegisterInfo() const override {
+ return &RegInfo;
+ }
+ const RISCVTargetLowering *getTargetLowering() const override {
+ return &TLInfo;
+ }
+ const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
+ return &TSInfo;
+ }
+ bool is64Bit() const { return HasRV64; }
+ MVT getXLenVT() const { return XLenVT; }
+ unsigned getXLen() const { return XLen; }
+};
+} // End llvm namespace
+
+#endif
diff --git a/lib/Target/RISCV/RISCVTargetMachine.cpp b/lib/Target/RISCV/RISCVTargetMachine.cpp
index 78d9cf53b5d..34da6de504d 100644
--- a/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "RISCV.h"
#include "RISCVTargetMachine.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/Passes.h"
@@ -58,10 +59,31 @@ RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
: LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
getEffectiveRelocModel(TT, RM),
getEffectiveCodeModel(CM), OL),
- TLOF(make_unique<TargetLoweringObjectFileELF>()) {
+ TLOF(make_unique<TargetLoweringObjectFileELF>()),
+ Subtarget(TT, CPU, FS, *this) {
initAsmInfo();
}
+namespace {
+class RISCVPassConfig : public TargetPassConfig {
+public:
+ RISCVPassConfig(RISCVTargetMachine &TM, PassManagerBase &PM)
+ : TargetPassConfig(TM, PM) {}
+
+ RISCVTargetMachine &getRISCVTargetMachine() const {
+ return getTM<RISCVTargetMachine>();
+ }
+
+ bool addInstSelector() override;
+};
+}
+
TargetPassConfig *RISCVTargetMachine::createPassConfig(PassManagerBase &PM) {
- return new TargetPassConfig(*this, PM);
+ return new RISCVPassConfig(*this, PM);
+}
+
+bool RISCVPassConfig::addInstSelector() {
+ addPass(createRISCVISelDag(getRISCVTargetMachine()));
+
+ return false;
}
diff --git a/lib/Target/RISCV/RISCVTargetMachine.h b/lib/Target/RISCV/RISCVTargetMachine.h
index 5c2ec956ee2..02361dddebf 100644
--- a/lib/Target/RISCV/RISCVTargetMachine.h
+++ b/lib/Target/RISCV/RISCVTargetMachine.h
@@ -15,6 +15,7 @@
#define LLVM_LIB_TARGET_RISCV_RISCVTARGETMACHINE_H
#include "MCTargetDesc/RISCVMCTargetDesc.h"
+#include "RISCVSubtarget.h"
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Target/TargetMachine.h"
@@ -22,6 +23,7 @@
namespace llvm {
class RISCVTargetMachine : public LLVMTargetMachine {
std::unique_ptr<TargetLoweringObjectFile> TLOF;
+ RISCVSubtarget Subtarget;
public:
RISCVTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
@@ -29,6 +31,10 @@ public:
Optional<Reloc::Model> RM, Optional<CodeModel::Model> CM,
CodeGenOpt::Level OL, bool JIT);
+ const RISCVSubtarget *getSubtargetImpl(const Function &) const override {
+ return &Subtarget;
+ }
+
TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
TargetLoweringObjectFile *getObjFileLowering() const override {
diff --git a/test/CodeGen/RISCV/alu32.ll b/test/CodeGen/RISCV/alu32.ll
new file mode 100644
index 00000000000..32242d2e40d
--- /dev/null
+++ b/test/CodeGen/RISCV/alu32.ll
@@ -0,0 +1,163 @@
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN: | FileCheck %s -check-prefix=RV32I
+
+; Register-immediate instructions
+
+define i32 @addi(i32 %a) nounwind {
+; RV32I-LABEL: addi:
+; RV32I: addi a0, a0, 1
+; RV32I: jalr zero, ra, 0
+; TODO: check support for materialising larger constants
+ %1 = add i32 %a, 1
+ ret i32 %1
+}
+
+define i32 @slti(i32 %a) nounwind {
+; RV32I-LABEL: slti:
+; RV32I: slti a0, a0, 2
+; RV32I: jalr zero, ra, 0
+ %1 = icmp slt i32 %a, 2
+ %2 = zext i1 %1 to i32
+ ret i32 %2
+}
+
+define i32 @sltiu(i32 %a) nounwind {
+; RV32I-LABEL: sltiu:
+; RV32I: sltiu a0, a0, 3
+; RV32I: jalr zero, ra, 0
+ %1 = icmp ult i32 %a, 3
+ %2 = zext i1 %1 to i32
+ ret i32 %2
+}
+
+define i32 @xori(i32 %a) nounwind {
+; RV32I-LABEL: xori:
+; RV32I: xori a0, a0, 4
+; RV32I: jalr zero, ra, 0
+ %1 = xor i32 %a, 4
+ ret i32 %1
+}
+
+define i32 @ori(i32 %a) nounwind {
+; RV32I-LABEL: ori:
+; RV32I: ori a0, a0, 5
+; RV32I: jalr zero, ra, 0
+ %1 = or i32 %a, 5
+ ret i32 %1
+}
+
+define i32 @andi(i32 %a) nounwind {
+; RV32I-LABEL: andi:
+; RV32I: andi a0, a0, 6
+; RV32I: jalr zero, ra, 0
+ %1 = and i32 %a, 6
+ ret i32 %1
+}
+
+define i32 @slli(i32 %a) nounwind {
+; RV32I-LABEL: slli:
+; RV32I: slli a0, a0, 7
+; RV32I: jalr zero, ra, 0
+ %1 = shl i32 %a, 7
+ ret i32 %1
+}
+
+define i32 @srli(i32 %a) nounwind {
+; RV32I-LABEL: srli:
+; RV32I: srli a0, a0, 8
+; RV32I: jalr zero, ra, 0
+ %1 = lshr i32 %a, 8
+ ret i32 %1
+}
+
+define i32 @srai(i32 %a) nounwind {
+; RV32I-LABEL: srai:
+; RV32I: srai a0, a0, 9
+; RV32I: jalr zero, ra, 0
+ %1 = ashr i32 %a, 9
+ ret i32 %1
+}
+
+; Register-register instructions
+
+define i32 @add(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: add:
+; RV32I: add a0, a0, a1
+; RV32I: jalr zero, ra, 0
+ %1 = add i32 %a, %b
+ ret i32 %1
+}
+
+define i32 @sub(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: sub:
+; RV32I: sub a0, a0, a1
+; RV32I: jalr zero, ra, 0
+ %1 = sub i32 %a, %b
+ ret i32 %1
+}
+
+define i32 @sll(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: sll:
+; RV32I: sll a0, a0, a1
+; RV32I: jalr zero, ra, 0
+ %1 = shl i32 %a, %b
+ ret i32 %1
+}
+
+define i32 @slt(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: slt:
+; RV32I: slt a0, a0, a1
+; RV32I: jalr zero, ra, 0
+ %1 = icmp slt i32 %a, %b
+ %2 = zext i1 %1 to i32
+ ret i32 %2
+}
+
+define i32 @sltu(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: sltu:
+; RV32I: sltu a0, a0, a1
+; RV32I: jalr zero, ra, 0
+ %1 = icmp ult i32 %a, %b
+ %2 = zext i1 %1 to i32
+ ret i32 %2
+}
+
+define i32 @xor(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: xor:
+; RV32I: xor a0, a0, a1
+; RV32I: jalr zero, ra, 0
+ %1 = xor i32 %a, %b
+ ret i32 %1
+}
+
+define i32 @srl(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: srl:
+; RV32I: srl a0, a0, a1
+; RV32I: jalr zero, ra, 0
+ %1 = lshr i32 %a, %b
+ ret i32 %1
+}
+
+define i32 @sra(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: sra:
+; RV32I: sra a0, a0, a1
+; RV32I: jalr zero, ra, 0
+ %1 = ashr i32 %a, %b
+ ret i32 %1
+}
+
+define i32 @or(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: or:
+; RV32I: or a0, a0, a1
+; RV32I: jalr zero, ra, 0
+ %1 = or i32 %a, %b
+ ret i32 %1
+}
+
+define i32 @and(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: and:
+; RV32I: and a0, a0, a1
+; RV32I: jalr zero, ra, 0
+ %1 = and i32 %a, %b
+ ret i32 %1
+}
diff --git a/test/CodeGen/RISCV/lit.local.cfg b/test/CodeGen/RISCV/lit.local.cfg
new file mode 100644
index 00000000000..c63820126f8
--- /dev/null
+++ b/test/CodeGen/RISCV/lit.local.cfg
@@ -0,0 +1,2 @@
+if not 'RISCV' in config.root.targets:
+ config.unsupported = True