]> granicus.if.org Git - llvm/commitdiff
[RISCV] Initial codegen support for ALU operations
authorAlex Bradbury <asb@lowrisc.org>
Thu, 19 Oct 2017 21:37:38 +0000 (21:37 +0000)
committerAlex Bradbury <asb@lowrisc.org>
Thu, 19 Oct 2017 21:37:38 +0000 (21:37 +0000)
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

24 files changed:
lib/Target/RISCV/CMakeLists.txt
lib/Target/RISCV/LLVMBuild.txt
lib/Target/RISCV/RISCV.h [new file with mode: 0644]
lib/Target/RISCV/RISCV.td
lib/Target/RISCV/RISCVAsmPrinter.cpp [new file with mode: 0644]
lib/Target/RISCV/RISCVCallingConv.td [new file with mode: 0644]
lib/Target/RISCV/RISCVFrameLowering.cpp [new file with mode: 0644]
lib/Target/RISCV/RISCVFrameLowering.h [new file with mode: 0644]
lib/Target/RISCV/RISCVISelDAGToDAG.cpp [new file with mode: 0644]
lib/Target/RISCV/RISCVISelLowering.cpp [new file with mode: 0644]
lib/Target/RISCV/RISCVISelLowering.h [new file with mode: 0644]
lib/Target/RISCV/RISCVInstrInfo.cpp [new file with mode: 0644]
lib/Target/RISCV/RISCVInstrInfo.h [new file with mode: 0644]
lib/Target/RISCV/RISCVInstrInfo.td
lib/Target/RISCV/RISCVMCInstLower.cpp [new file with mode: 0644]
lib/Target/RISCV/RISCVRegisterInfo.cpp [new file with mode: 0644]
lib/Target/RISCV/RISCVRegisterInfo.h [new file with mode: 0644]
lib/Target/RISCV/RISCVRegisterInfo.td
lib/Target/RISCV/RISCVSubtarget.cpp [new file with mode: 0644]
lib/Target/RISCV/RISCVSubtarget.h [new file with mode: 0644]
lib/Target/RISCV/RISCVTargetMachine.cpp
lib/Target/RISCV/RISCVTargetMachine.h
test/CodeGen/RISCV/alu32.ll [new file with mode: 0644]
test/CodeGen/RISCV/lit.local.cfg [new file with mode: 0644]

index b9f3fc110c7468a960873d19935573dcd44aaf22..bac4d4c353d26c7a6e945b8edfc651df656437db 100644 (file)
@@ -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
   )
 
index e15963b5bd7b4925c5dd50c2e2e131ffd2ace05f..ab21565b0c2e9381aea4f9aa684137ba0294dab2 100644 (file)
@@ -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 (file)
index 0000000..1b61402
--- /dev/null
@@ -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
index 7b61901915fd67a116962e696684740217dd067c..da919acad3689a421d748317b161acb9b240491a 100644 (file)
@@ -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 (file)
index 0000000..1c213b6
--- /dev/null
@@ -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 (file)
index 0000000..e0c25e3
--- /dev/null
@@ -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 (file)
index 0000000..fd3b258
--- /dev/null
@@ -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 (file)
index 0000000..14772dd
--- /dev/null
@@ -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 (file)
index 0000000..78f61fa
--- /dev/null
@@ -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 (file)
index 0000000..d76170b
--- /dev/null
@@ -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 (file)
index 0000000..9fed48f
--- /dev/null
@@ -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 (file)
index 0000000..92db535
--- /dev/null
@@ -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 (file)
index 0000000..50404d5
--- /dev/null
@@ -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
index 213ef63f5f9fae92bd22fdd203c1e643888c2526..23adf1eda9d09323da3e0668f6883ef51db46e0f 100644 (file)
 
 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 (file)
index 0000000..1ac8d98
--- /dev/null
@@ -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 (file)
index 0000000..4f6c528
--- /dev/null
@@ -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 (file)
index 0000000..94af9f4
--- /dev/null
@@ -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
index a5484130dfcf6ec33237690a67f863205422f458..78c036a37b904049382cc35e04f9c4be64b2db00 100644 (file)
@@ -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 (file)
index 0000000..b221ea8
--- /dev/null
@@ -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 (file)
index 0000000..657b0e6
--- /dev/null
@@ -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
index 78d9cf53b5d6ee422cfbc401bffe0468cee569b7..34da6de504df0ae046e467b715a9239a6dc206b4 100644 (file)
@@ -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;
 }
index 5c2ec956ee29b043ad9d509842df597c5bb2c09f..02361dddebf7b462fd685f141836dae74ac2bb62 100644 (file)
@@ -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 (file)
index 0000000..32242d2
--- /dev/null
@@ -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 (file)
index 0000000..c638201
--- /dev/null
@@ -0,0 +1,2 @@
+if not 'RISCV' in config.root.targets:
+    config.unsupported = True