Index: lib/Target/RISCV/CMakeLists.txt =================================================================== --- lib/Target/RISCV/CMakeLists.txt +++ lib/Target/RISCV/CMakeLists.txt @@ -3,14 +3,25 @@ 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: lib/Target/RISCV/LLVMBuild.txt =================================================================== --- lib/Target/RISCV/LLVMBuild.txt +++ lib/Target/RISCV/LLVMBuild.txt @@ -30,5 +30,6 @@ 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 Index: lib/Target/RISCV/RISCV.h =================================================================== --- /dev/null +++ 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 Index: lib/Target/RISCV/RISCV.td =================================================================== --- lib/Target/RISCV/RISCV.td +++ lib/Target/RISCV/RISCV.td @@ -10,10 +10,13 @@ include "llvm/Target/Target.td" include "RISCVRegisterInfo.td" +include "RISCVCallingConv.td" include "RISCVInstrInfo.td" -def RISCVInstrInfo : InstrInfo; +def RISCVInstrInfo : InstrInfo { + let guessInstructionProperties = 0; +} def Feature64Bit : SubtargetFeature<"64bit", "HasRV64", "true", "Implements RV64">; Index: lib/Target/RISCV/RISCVAsmPrinter.cpp =================================================================== --- /dev/null +++ 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 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 X(getTheRISCV32Target()); + RegisterAsmPrinter Y(getTheRISCV64Target()); +} Index: lib/Target/RISCV/RISCVCallingConv.td =================================================================== --- /dev/null +++ lib/Target/RISCV/RISCVCallingConv.td @@ -0,0 +1,31 @@ +//===-- 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_32, X11_32]>>]>; + +// RISCV 32-bit C Calling convention. +def CC_RISCV32 : CallingConv<[ + // Promote i8/i16 args to i32 + CCIfType<[ i8, i16 ], CCPromoteToType>, + + // All arguments get passed in integer registers if there is space. + CCIfType<[i32], CCAssignToReg<[ X10_32, X11_32, X12_32, X13_32, X14_32, + X15_32, X16_32, X17_32 ]>>, + + // Could be assigned to the stack in 8-byte aligned units, but unsupported + CCAssignToStack<8, 8> +]>; + +def CSR : CalleeSavedRegs<(add X1_32, X3_32, X4_32, X8_32, X9_32, + (sequence "X%u_32", 18, 27))>; Index: lib/Target/RISCV/RISCVFrameLowering.h =================================================================== --- /dev/null +++ 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 Index: lib/Target/RISCV/RISCVFrameLowering.cpp =================================================================== --- /dev/null +++ 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 {} Index: lib/Target/RISCV/RISCVISelDAGToDAG.cpp =================================================================== --- /dev/null +++ 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); +} Index: lib/Target/RISCV/RISCVISelLowering.h =================================================================== --- /dev/null +++ lib/Target/RISCV/RISCVISelLowering.h @@ -0,0 +1,60 @@ +//===-- 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 { +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 &Ins, + const SDLoc &DL, SelectionDAG &DAG, + SmallVectorImpl &InVals) const override; + SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, const SDLoc &DL, + SelectionDAG &DAG) const override; + bool shouldConvertConstantLoadToIntImm(const APInt &Imm, + Type *Ty) const override { + return true; + } +}; +} + +#endif Index: lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- /dev/null +++ lib/Target/RISCV/RISCVISelLowering.cpp @@ -0,0 +1,172 @@ +//===-- 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) { + + // Set up the register classes. + addRegisterClass(MVT::i32, &RISCV::GPRRegClass); + + // Compute derived properties from the register classes. + computeRegisterProperties(STI.getRegisterInfo()); + + setStackPointerRegisterToSaveRestore(RISCV::X2_32); + + // 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 &Ins, const SDLoc &DL, + SelectionDAG &DAG, SmallVectorImpl &InVals) const { + + switch (CallConv) { + default: + report_fatal_error("Unsupported calling convention"); + case CallingConv::C: + break; + } + + MachineFunction &MF = DAG.getMachineFunction(); + MachineRegisterInfo &RegInfo = MF.getRegInfo(); + + if (IsVarArg) + report_fatal_error("VarArg not supported"); + + // Assign locations to all of the incoming arguments. + SmallVector ArgLocs; + CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); + CCInfo.AnalyzeFormalArguments(Ins, CC_RISCV32); + + for (auto &VA : ArgLocs) { + if (VA.isRegLoc()) { + // Arguments passed in registers. + EVT RegVT = VA.getLocVT(); + switch (RegVT.getSimpleVT().SimpleTy) { + case MVT::i32: { + const unsigned VReg = + RegInfo.createVirtualRegister(&RISCV::GPRRegClass); + RegInfo.addLiveIn(VA.getLocReg(), VReg); + SDValue ArgIn = DAG.getCopyFromReg(Chain, DL, VReg, RegVT); + + InVals.push_back(ArgIn); + break; + } + default: + DEBUG(dbgs() << "LowerFormalArguments Unhandled argument type: " + << RegVT.getEVTString() << "\n"); + report_fatal_error("unhandled argument type"); + } + } else { + report_fatal_error("Defined with too many args"); + } + } + return Chain; +} + +SDValue +RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &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 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 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; +} Index: lib/Target/RISCV/RISCVInstrInfo.h =================================================================== --- /dev/null +++ lib/Target/RISCV/RISCVInstrInfo.h @@ -0,0 +1,35 @@ +//===-- 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 { + const RISCVRegisterInfo RI; + +public: + RISCVInstrInfo(); + + const RISCVRegisterInfo &getRegisterInfo() const { return RI; } +}; +} + +#endif Index: lib/Target/RISCV/RISCVInstrInfo.cpp =================================================================== --- /dev/null +++ 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() {} Index: lib/Target/RISCV/RISCVInstrInfo.td =================================================================== --- lib/Target/RISCV/RISCVInstrInfo.td +++ lib/Target/RISCV/RISCVInstrInfo.td @@ -13,6 +13,11 @@ include "RISCVInstrFormats.td" +// Target-independent nodes +def RetFlag : SDNode<"RISCVISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; + +// Operands class ImmAsmOperand : AsmOperandClass { let Name = prefix # "Imm" # width # suffix; let RenderMethod = "addImmOperands"; @@ -39,12 +44,12 @@ let DecoderMethod = "decodeUImmOperand<4>"; } -def uimm5 : Operand { +def uimm5 : Operand, ImmLeaf(Imm);}]> { let ParserMatchClass = UImmAsmOperand<5>; let DecoderMethod = "decodeUImmOperand<5>"; } -def simm12 : Operand { +def simm12 : Operand, ImmLeaf(Imm);}]> { let ParserMatchClass = SImmAsmOperand<12>; let EncoderMethod = "getImmOpValue"; let DecoderMethod = "decodeSImmOperand<12>"; @@ -83,6 +88,7 @@ // like // is adopted. +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { def LUI : FU<0b0110111, (outs GPR:$rd), (ins uimm20:$imm20), "lui\t$rd, $imm20", []>; @@ -94,11 +100,12 @@ def JALR : FI<0b000, 0b1100111, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), "jalr\t$rd, $rs1, $imm12", []>; +} +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class Bcc funct3, string OpcodeStr> : FSB { -} + OpcodeStr#"\t$rs1, $rs2, $imm12", []>; def BEQ : Bcc<0b000, "beq">; def BNE : Bcc<0b001, "bne">; @@ -107,11 +114,10 @@ def BLTU : Bcc<0b110, "bltu">; def BGEU : Bcc<0b111, "bgeu">; +let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in class LD_ri funct3, string OpcodeStr> : FI { - let mayLoad = 1; -} + OpcodeStr#"\t$rd, ${imm12}(${rs1})", []>; def LB : LD_ri<0b000, "lb">; def LH : LD_ri<0b001, "lh">; @@ -119,21 +125,19 @@ def LBU : LD_ri<0b100, "lbu">; def LHU : LD_ri<0b101, "lhu">; +let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in class ST_ri funct3, string OpcodeStr> : FS { - let mayStore = 1; -} + OpcodeStr#"\t$rs2, ${imm12}(${rs1})", []>; def SB : ST_ri<0b000, "sb">; def SH : ST_ri<0b001, "sh">; def SW : ST_ri<0b010, "sw">; +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class ALU_ri funct3, string OpcodeStr> : FI -{ -} + OpcodeStr#"\t$rd, $rs1, $imm12", []>; def ADDI : ALU_ri<0b000, "addi">; def SLTI : ALU_ri<0b010, "slti">; @@ -142,21 +146,19 @@ def ORI : ALU_ri<0b110, "ori">; def ANDI : ALU_ri<0b111, "andi">; +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class SHIFT32_ri funct3, string OpcodeStr> : FI32Shift -{ -} + OpcodeStr#"\t$rd, $rs1, $shamt", []>; def SLLI : SHIFT32_ri<0, 0b001, "slli">; def SRLI : SHIFT32_ri<0, 0b101, "srli">; def SRAI : SHIFT32_ri<1, 0b101, "srai">; +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class ALU_rr funct7, bits<3> funct3, string OpcodeStr> : FR -{ -} + OpcodeStr#"\t$rd, $rs1, $rs2", []>; def ADD : ALU_rr<0b0000000, 0b000, "add">; def SUB : ALU_rr<0b0100000, 0b000, "sub">; @@ -169,6 +171,7 @@ def OR : ALU_rr<0b0000000, 0b110, "or">; def AND : ALU_rr<0b0000000, 0b111, "and">; +let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { def FENCE : FI<0b000, 0b0001111, (outs), (ins fencearg:$pred, fencearg:$succ), "fence\t$pred, $succ", []> { bits<4> pred; @@ -185,31 +188,77 @@ let imm12 = 0; } -let rs1=0, rd=0 in { +let rs1 = 0, rd = 0 in { def ECALL : FI<0b000, 0b1110011, (outs), (ins), "ecall", []> { - let imm12=0; + let imm12 = 0; } def EBREAK : FI<0b000, 0b1110011, (outs), (ins), "ebreak", []> { - let imm12=1; + let imm12 = 1; } } +} +let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in class CSR_rr funct3, string OpcodeStr> : FI -{ -} + OpcodeStr#"\t$rd, $imm12, $rs1", []>; def CSRRW : CSR_rr<0b001, "csrrw">; def CSRRS : CSR_rr<0b010, "csrrs">; def CSRRC : CSR_rr<0b011, "csrrc">; +let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in class CSR_ri funct3, string OpcodeStr> : FI -{ -} + OpcodeStr#"\t$rd, $imm12, $rs1", []>; def CSRRWI : CSR_ri<0b101, "csrrwi">; def CSRRSI : CSR_ri<0b110, "csrrsi">; def CSRRCI : CSR_ri<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 : + Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>; +class PatGprSimm12 : + Pat<(OpNode GPR:$rs1, simm12:$imm12), (Inst GPR:$rs1, simm12:$imm12)>; +class PatGprUimm5 : + Pat<(OpNode GPR:$rs1, uimm5:$shamt), (Inst GPR:$rs1, uimm5:$shamt)>; + +/// Simple arithmetic operations + +def : PatGprGpr; +def : PatGprSimm12; +def : PatGprGpr; +def : PatGprGpr; +def : PatGprSimm12; +def : PatGprGpr; +def : PatGprSimm12; +def : PatGprGpr; +def : PatGprSimm12; +def : PatGprGpr; +def : PatGprUimm5; +def : PatGprGpr; +def : PatGprUimm5; +def : PatGprGpr; +def : PatGprUimm5; + +/// Setcc + +def : PatGprGpr; +def : PatGprSimm12; +def : PatGprGpr; +def : PatGprSimm12; + +/// Branches and jumps + +let isBarrier = 1, isReturn = 1, isTerminator = 1 in +def PseudoRET : Pseudo<(outs), (ins), [(RetFlag)]>, + PseudoInstExpansion<(JALR X0_32, X1_32, 0)>; Index: lib/Target/RISCV/RISCVMCInstLower.cpp =================================================================== --- /dev/null +++ lib/Target/RISCV/RISCVMCInstLower.cpp @@ -0,0 +1,52 @@ +//===-- 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 (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + + 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); + } +} Index: lib/Target/RISCV/RISCVRegisterInfo.h =================================================================== --- /dev/null +++ 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(); + + 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: lib/Target/RISCV/RISCVRegisterInfo.cpp =================================================================== --- /dev/null +++ lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -0,0 +1,65 @@ +//===-- 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() : RISCVGenRegisterInfo(RISCV::X1_32) {} + +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_64); // zero + markSuperRegs(Reserved, RISCV::X0_32); // zero + markSuperRegs(Reserved, RISCV::X1_64); // ra + markSuperRegs(Reserved, RISCV::X1_32); // ra + markSuperRegs(Reserved, RISCV::X2_64); // sp + markSuperRegs(Reserved, RISCV::X2_32); // sp + markSuperRegs(Reserved, RISCV::X3_64); // gp + markSuperRegs(Reserved, RISCV::X3_32); // gp + markSuperRegs(Reserved, RISCV::X4_64); // tp + markSuperRegs(Reserved, RISCV::X4_32); // tp + markSuperRegs(Reserved, RISCV::X8_64); // fp + markSuperRegs(Reserved, RISCV::X8_32); // 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_32; +} Index: lib/Target/RISCV/RISCVRegisterInfo.td =================================================================== --- lib/Target/RISCV/RISCVRegisterInfo.td +++ lib/Target/RISCV/RISCVRegisterInfo.td @@ -79,12 +79,22 @@ // similar are implemented, we can just use one 'GPR' class for most // instruction definitions. -// TODO: once codegen is implemented, registers should be listed in an order -// reflecting the preferred register allocation sequence. +// The order of registers represents the preferred allocation sequence. +// Registers are listed in the order caller-save, callee-save, specials. def GPR : RegisterClass<"RISCV", [i32], 32, (add - (sequence "X%u_32", 0, 31) + (sequence "X%u_32", 10, 17), + (sequence "X%u_32", 5, 7), + (sequence "X%u_32", 28, 31), + (sequence "X%u_32", 8, 9), + (sequence "X%u_32", 18, 27), + (sequence "X%u_32", 0, 4) )>; def GPR64 : RegisterClass<"RISCV", [i64], 64, (add - (sequence "X%u_64", 0, 31) + (sequence "X%u_64", 10, 17), + (sequence "X%u_64", 5, 7), + (sequence "X%u_64", 28, 31), + (sequence "X%u_64", 8, 9), + (sequence "X%u_64", 18, 27), + (sequence "X%u_64", 0, 4) )>; Index: lib/Target/RISCV/RISCVSubtarget.h =================================================================== --- /dev/null +++ lib/Target/RISCV/RISCVSubtarget.h @@ -0,0 +1,64 @@ +//===-- 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(); + RISCVInstrInfo InstrInfo; + RISCVFrameLowering FrameLowering; + RISCVTargetLowering TLInfo; + SelectionDAGTargetInfo TSInfo; + bool HasRV64; + +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 TargetRegisterInfo *getRegisterInfo() const override { + return &InstrInfo.getRegisterInfo(); + } + const RISCVTargetLowering *getTargetLowering() const override { + return &TLInfo; + } + const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { + return &TSInfo; + } +}; +} // End llvm namespace + +#endif Index: lib/Target/RISCV/RISCVSubtarget.cpp =================================================================== --- /dev/null +++ lib/Target/RISCV/RISCVSubtarget.cpp @@ -0,0 +1,32 @@ +//===-- 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(const Triple &TT, const std::string &CPU, + const std::string &FS, const TargetMachine &TM) + : RISCVGenSubtargetInfo(TT, CPU, FS), InstrInfo(), FrameLowering(*this), + TLInfo(TM, *this), HasRV64(false) {} Index: lib/Target/RISCV/RISCVTargetMachine.h =================================================================== --- lib/Target/RISCV/RISCVTargetMachine.h +++ 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 TLOF; + RISCVSubtarget Subtarget; public: RISCVTargetMachine(const Target &T, const Triple &TT, StringRef CPU, @@ -29,6 +31,10 @@ Optional RM, Optional CM, CodeGenOpt::Level OL, bool JIT); + const RISCVSubtarget *getSubtargetImpl(const Function &) const override { + return &Subtarget; + } + TargetPassConfig *createPassConfig(PassManagerBase &PM) override; TargetLoweringObjectFile *getObjFileLowering() const override { Index: lib/Target/RISCV/RISCVTargetMachine.cpp =================================================================== --- lib/Target/RISCV/RISCVTargetMachine.cpp +++ 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 @@ : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, getEffectiveRelocModel(TT, RM), getEffectiveCodeModel(CM), OL), - TLOF(make_unique()) { + TLOF(make_unique()), + 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(); + } + + 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: test/CodeGen/RISCV/alu.ll =================================================================== --- /dev/null +++ test/CodeGen/RISCV/alu.ll @@ -0,0 +1,162 @@ +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s | FileCheck %s + +; Register-immediate instructions + +define i32 @addi(i32 %a) nounwind { +; CHECK-LABEL: addi: +; CHECK: addi a0, a0, 1 +; CHECK: 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 { +; CHECK-LABEL: slti: +; CHECK: slti a0, a0, 2 +; CHECK: 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 { +; CHECK-LABEL: sltiu: +; CHECK: sltiu a0, a0, 3 +; CHECK: 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 { +; CHECK-LABEL: xori: +; CHECK: xori a0, a0, 4 +; CHECK: jalr zero, ra, 0 + %1 = xor i32 %a, 4 + ret i32 %1 +} + +define i32 @ori(i32 %a) nounwind { +; CHECK-LABEL: ori: +; CHECK: ori a0, a0, 5 +; CHECK: jalr zero, ra, 0 + %1 = or i32 %a, 5 + ret i32 %1 +} + +define i32 @andi(i32 %a) nounwind { +; CHECK-LABEL: andi: +; CHECK: andi a0, a0, 6 +; CHECK: jalr zero, ra, 0 + %1 = and i32 %a, 6 + ret i32 %1 +} + +define i32 @slli(i32 %a) nounwind { +; CHECK-LABEL: slli: +; CHECK: slli a0, a0, 7 +; CHECK: jalr zero, ra, 0 + %1 = shl i32 %a, 7 + ret i32 %1 +} + +define i32 @srli(i32 %a) nounwind { +; CHECK-LABEL: srli: +; CHECK: srli a0, a0, 8 +; CHECK: jalr zero, ra, 0 + %1 = lshr i32 %a, 8 + ret i32 %1 +} + +define i32 @srai(i32 %a) nounwind { +; CHECK-LABEL: srai: +; CHECK: srai a0, a0, 9 +; CHECK: jalr zero, ra, 0 + %1 = ashr i32 %a, 9 + ret i32 %1 +} + +; Register-register instructions + +define i32 @add(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: add: +; CHECK: add a0, a0, a1 +; CHECK: jalr zero, ra, 0 + %1 = add i32 %a, %b + ret i32 %1 +} + +define i32 @sub(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: sub: +; CHECK: sub a0, a0, a1 +; CHECK: jalr zero, ra, 0 + %1 = sub i32 %a, %b + ret i32 %1 +} + +define i32 @sll(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: sll: +; CHECK: sll a0, a0, a1 +; CHECK: jalr zero, ra, 0 + %1 = shl i32 %a, %b + ret i32 %1 +} + +define i32 @slt(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: slt: +; CHECK: slt a0, a0, a1 +; CHECK: 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 { +; CHECK-LABEL: sltu: +; CHECK: sltu a0, a0, a1 +; CHECK: 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 { +; CHECK-LABEL: xor: +; CHECK: xor a0, a0, a1 +; CHECK: jalr zero, ra, 0 + %1 = xor i32 %a, %b + ret i32 %1 +} + +define i32 @srl(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: srl: +; CHECK: srl a0, a0, a1 +; CHECK: jalr zero, ra, 0 + %1 = lshr i32 %a, %b + ret i32 %1 +} + +define i32 @sra(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: sra: +; CHECK: sra a0, a0, a1 +; CHECK: jalr zero, ra, 0 + %1 = ashr i32 %a, %b + ret i32 %1 +} + +define i32 @or(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: or: +; CHECK: or a0, a0, a1 +; CHECK: jalr zero, ra, 0 + %1 = or i32 %a, %b + ret i32 %1 +} + +define i32 @and(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: and: +; CHECK: and a0, a0, a1 +; CHECK: jalr zero, ra, 0 + %1 = and i32 %a, %b + ret i32 %1 +} Index: test/CodeGen/RISCV/lit.local.cfg =================================================================== --- /dev/null +++ test/CodeGen/RISCV/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'RISCV' in config.root.targets: + config.unsupported = True