summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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