diff options
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 |