Index: include/llvm/CodeGen/SelectionDAGISel.h =================================================================== --- include/llvm/CodeGen/SelectionDAGISel.h +++ include/llvm/CodeGen/SelectionDAGISel.h @@ -276,6 +276,8 @@ return false; } + bool isOrEquivalentToAdd(const SDNode *N) const; + private: // Calls to these functions are generated by tblgen. Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -3761,6 +3761,25 @@ } } +bool SelectionDAGISel::isOrEquivalentToAdd(const SDNode *N) const { + assert(N->getOpcode() == ISD::OR && "Unexpected opcode"); + auto *C = dyn_cast(N->getOperand(1)); + if (!C) + return false; + + // Detect when "or" is used to add an offset to a stack object. + if (auto *FN = dyn_cast(N->getOperand(0))) { + MachineFrameInfo &MFI = MF->getFrameInfo(); + unsigned A = MFI.getObjectAlignment(FN->getIndex()); + assert(isPowerOf2_32(A) && "Unexpected alignment"); + int32_t Off = C->getSExtValue(); + // If the alleged offset fits in the zero bits guaranteed by + // the alignment, then this or is really an add. + return (Off >= 0) && (((A - 1) & Off) == unsigned(Off)); + } + return false; +} + void SelectionDAGISel::CannotYetSelect(SDNode *N) { std::string msg; raw_string_ostream Msg(msg); Index: lib/Target/Hexagon/HexagonISelDAGToDAG.h =================================================================== --- lib/Target/Hexagon/HexagonISelDAGToDAG.h +++ lib/Target/Hexagon/HexagonISelDAGToDAG.h @@ -121,7 +121,6 @@ void SelectHvxRor(SDNode *N); bool keepsLowBits(const SDValue &Val, unsigned NumBits, SDValue &Src); - bool isOrEquivalentToAdd(const SDNode *N) const; bool isAlignedMemNode(const MemSDNode *N) const; bool isSmallStackStore(const StoreSDNode *N) const; bool isPositiveHalfWord(const SDNode *N) const; Index: lib/Target/Hexagon/HexagonISelDAGToDAG.cpp =================================================================== --- lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -1421,26 +1421,6 @@ return false; } - -bool HexagonDAGToDAGISel::isOrEquivalentToAdd(const SDNode *N) const { - assert(N->getOpcode() == ISD::OR); - auto *C = dyn_cast(N->getOperand(1)); - if (!C) - return false; - - // Detect when "or" is used to add an offset to a stack object. - if (auto *FN = dyn_cast(N->getOperand(0))) { - MachineFrameInfo &MFI = MF->getFrameInfo(); - unsigned A = MFI.getObjectAlignment(FN->getIndex()); - assert(isPowerOf2_32(A)); - int32_t Off = C->getSExtValue(); - // If the alleged offset fits in the zero bits guaranteed by - // the alignment, then this or is really an add. - return (Off >= 0) && (((A-1) & Off) == unsigned(Off)); - } - return false; -} - bool HexagonDAGToDAGISel::isAlignedMemNode(const MemSDNode *N) const { return N->getAlignment() >= N->getMemoryVT().getStoreSize(); } Index: lib/Target/RISCV/RISCVFrameLowering.h =================================================================== --- lib/Target/RISCV/RISCVFrameLowering.h +++ lib/Target/RISCV/RISCVFrameLowering.h @@ -29,6 +29,9 @@ void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + int getFrameIndexReference(const MachineFunction &MF, int FI, + unsigned &FrameReg) const override; + bool hasFP(const MachineFunction &MF) const override; MachineBasicBlock::iterator Index: lib/Target/RISCV/RISCVFrameLowering.cpp =================================================================== --- lib/Target/RISCV/RISCVFrameLowering.cpp +++ lib/Target/RISCV/RISCVFrameLowering.cpp @@ -27,3 +27,32 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {} + +int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF, + int FI, + unsigned &FrameReg) const { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo(); + + // Callee-saved registers should be referenced relative to the stack + // pointer (positive offset), otherwise use the frame pointer (negative + // offset). + const std::vector &CSI = MFI.getCalleeSavedInfo(); + int MinCSFI = 0; + int MaxCSFI = -1; + + int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea() + + MFI.getOffsetAdjustment(); + + if (CSI.size()) { + MinCSFI = CSI[0].getFrameIdx(); + MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); + } + + FrameReg = RI->getFrameRegister(MF); + if (FI >= MinCSFI && FI <= MaxCSFI) { + FrameReg = RISCV::X2; + Offset += MF.getFrameInfo().getStackSize(); + } + return Offset; +} Index: lib/Target/RISCV/RISCVISelDAGToDAG.cpp =================================================================== --- lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -14,6 +14,7 @@ #include "RISCV.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" #include "RISCVTargetMachine.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" @@ -43,6 +44,8 @@ void Select(SDNode *Node) override; + bool SelectAddrFI(SDValue Addr, SDValue &Base); + // Include the pieces autogenerated from the target description. #include "RISCVGenDAGISel.inc" }; @@ -76,11 +79,28 @@ return; } } + if (Opcode == ISD::FrameIndex) { + SDLoc DL(Node); + SDValue Imm = CurDAG->getTargetConstant(0, DL, XLenVT); + int FI = dyn_cast(Node)->getIndex(); + EVT VT = Node->getValueType(0); + SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); + ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm)); + return; + } // Select the default instruction. SelectCode(Node); } +bool RISCVDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) { + if (auto FIN = dyn_cast(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT()); + return true; + } + return false; +} + // This pass converts a legalized DAG into a RISCV-specific DAG, ready // for instruction scheduling. FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) { Index: lib/Target/RISCV/RISCVInstrInfo.td =================================================================== --- lib/Target/RISCV/RISCVInstrInfo.td +++ lib/Target/RISCV/RISCVInstrInfo.td @@ -111,6 +111,10 @@ // Standalone (codegen-only) immleaf patterns. def simm32 : ImmLeaf(Imm);}]>; +// Addressing modes. +// Necessary because a frameindex can't be matched directly in a pattern. +def AddrFI : ComplexPattern; + // Extract least significant 12 bits from an immediate value and sign extend // them. def LO12Sext : SDNodeXForm; +/// Predicates + +def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{ + return isOrEquivalentToAdd(N); +}]>; + /// Immediates def : Pat<(simm12:$imm), (ADDI X0, simm12:$imm)>; @@ -321,6 +331,13 @@ def : PatGprGpr; def : PatGprUimm5; +/// FrameIndex calculations + +def : Pat<(add (i32 AddrFI:$Rs), simm12:$imm12), + (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>; +def : Pat<(IsOrAdd (i32 AddrFI:$Rs), simm12:$imm12), + (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>; + /// Setcc def : PatGprGpr; @@ -401,8 +418,13 @@ multiclass LdPat { def : Pat<(LoadOp GPR:$rs1), (Inst GPR:$rs1, 0)>; + def : Pat<(LoadOp AddrFI:$rs1), (Inst AddrFI:$rs1, 0)>; def : Pat<(LoadOp (add GPR:$rs1, simm12:$imm12)), (Inst GPR:$rs1, simm12:$imm12)>; + def : Pat<(LoadOp (add AddrFI:$rs1, simm12:$imm12)), + (Inst AddrFI:$rs1, simm12:$imm12)>; + def : Pat<(LoadOp (IsOrAdd AddrFI:$rs1, simm12:$imm12)), + (Inst AddrFI:$rs1, simm12:$imm12)>; } defm : LdPat; @@ -417,8 +439,13 @@ multiclass StPat { def : Pat<(StoreOp GPR:$rs2, GPR:$rs1), (Inst GPR:$rs2, GPR:$rs1, 0)>; + def : Pat<(StoreOp GPR:$rs2, AddrFI:$rs1), (Inst GPR:$rs2, AddrFI:$rs1, 0)>; def : Pat<(StoreOp GPR:$rs2, (add GPR:$rs1, simm12:$imm12)), (Inst GPR:$rs2, GPR:$rs1, simm12:$imm12)>; + def : Pat<(StoreOp GPR:$rs2, (add AddrFI:$rs1, simm12:$imm12)), + (Inst GPR:$rs2, AddrFI:$rs1, simm12:$imm12)>; + def : Pat<(StoreOp GPR:$rs2, (IsOrAdd AddrFI:$rs1, simm12:$imm12)), + (Inst GPR:$rs2, AddrFI:$rs1, simm12:$imm12)>; } defm : StPat; Index: lib/Target/RISCV/RISCVRegisterInfo.cpp =================================================================== --- lib/Target/RISCV/RISCVRegisterInfo.cpp +++ lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -57,22 +57,20 @@ void RISCVRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS) const { - // TODO: this implementation is a temporary placeholder which does just - // enough to allow other aspects of code generation to be tested - assert(SPAdj == 0 && "Unexpected non-zero SPAdj value"); MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); - const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); DebugLoc DL = MI.getDebugLoc(); - unsigned FrameReg = getFrameRegister(MF); int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); - int Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg); - Offset += MI.getOperand(FIOperandNum + 1).getImm(); + unsigned FrameReg; + int Offset = + getFrameLowering(MF)->getFrameIndexReference(MF, FrameIndex, FrameReg) + + MI.getOperand(FIOperandNum + 1).getImm(); - assert(TFI->hasFP(MF) && "eliminateFrameIndex currently requires hasFP"); + assert(MF.getSubtarget().getFrameLowering()->hasFP(MF) && + "eliminateFrameIndex currently requires hasFP"); // Offsets must be directly encoded in a 12-bit immediate field if (!isInt<12>(Offset)) { Index: test/CodeGen/RISCV/blockaddress.ll =================================================================== --- test/CodeGen/RISCV/blockaddress.ll +++ test/CodeGen/RISCV/blockaddress.ll @@ -7,7 +7,7 @@ define void @test_blockaddress() nounwind { ; RV32I-LABEL: test_blockaddress: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 0(s0) +; RV32I-NEXT: sw ra, 0(sp) ; RV32I-NEXT: lui a0, %hi(addr) ; RV32I-NEXT: addi a0, a0, %lo(addr) ; RV32I-NEXT: lui a1, %hi(.Ltmp0) @@ -17,7 +17,7 @@ ; RV32I-NEXT: jalr zero, a0, 0 ; RV32I-NEXT: .Ltmp0: # Block address taken ; RV32I-NEXT: .LBB0_1: # %block -; RV32I-NEXT: lw ra, 0(s0) +; RV32I-NEXT: lw ra, 0(sp) ; RV32I-NEXT: jalr zero, ra, 0 store volatile i8* blockaddress(@test_blockaddress, %block), i8** @addr %val = load volatile i8*, i8** @addr Index: test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll =================================================================== --- test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll +++ test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll @@ -82,7 +82,7 @@ define i8 @test_cttz_i8(i8 %a) nounwind { ; RV32I-LABEL: test_cttz_i8: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: addi a1, a0, 0 ; RV32I-NEXT: addi a0, zero, 8 ; RV32I-NEXT: andi a2, a1, 255 @@ -115,7 +115,7 @@ ; RV32I-NEXT: jalr ra, a2, 0 ; RV32I-NEXT: srli a0, a0, 24 ; RV32I-NEXT: .LBB3_2: # %cond.end -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %tmp = call i8 @llvm.cttz.i8(i8 %a, i1 false) ret i8 %tmp @@ -124,7 +124,7 @@ define i16 @test_cttz_i16(i16 %a) nounwind { ; RV32I-LABEL: test_cttz_i16: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: addi a1, a0, 0 ; RV32I-NEXT: addi a0, zero, 16 ; RV32I-NEXT: lui a2, 16 @@ -159,7 +159,7 @@ ; RV32I-NEXT: jalr ra, a2, 0 ; RV32I-NEXT: srli a0, a0, 24 ; RV32I-NEXT: .LBB4_2: # %cond.end -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %tmp = call i16 @llvm.cttz.i16(i16 %a, i1 false) ret i16 %tmp @@ -168,7 +168,7 @@ define i32 @test_cttz_i32(i32 %a) nounwind { ; RV32I-LABEL: test_cttz_i32: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: addi a1, a0, 0 ; RV32I-NEXT: addi a0, zero, 32 ; RV32I-NEXT: beq a1, zero, .LBB5_2 @@ -200,7 +200,7 @@ ; RV32I-NEXT: jalr ra, a2, 0 ; RV32I-NEXT: srli a0, a0, 24 ; RV32I-NEXT: .LBB5_2: # %cond.end -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %tmp = call i32 @llvm.cttz.i32(i32 %a, i1 false) ret i32 %tmp @@ -209,7 +209,7 @@ define i32 @test_ctlz_i32(i32 %a) nounwind { ; RV32I-LABEL: test_ctlz_i32: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: addi a1, a0, 0 ; RV32I-NEXT: addi a0, zero, 32 ; RV32I-NEXT: beq a1, zero, .LBB6_2 @@ -249,7 +249,7 @@ ; RV32I-NEXT: jalr ra, a2, 0 ; RV32I-NEXT: srli a0, a0, 24 ; RV32I-NEXT: .LBB6_2: # %cond.end -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %tmp = call i32 @llvm.ctlz.i32(i32 %a, i1 false) ret i32 %tmp @@ -258,14 +258,14 @@ define i64 @test_cttz_i64(i64 %a) nounwind { ; RV32I-LABEL: test_cttz_i64: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 28(s0) -; RV32I-NEXT: sw s1, 24(s0) -; RV32I-NEXT: sw s2, 20(s0) -; RV32I-NEXT: sw s3, 16(s0) -; RV32I-NEXT: sw s4, 12(s0) -; RV32I-NEXT: sw s5, 8(s0) -; RV32I-NEXT: sw s6, 4(s0) -; RV32I-NEXT: sw s7, 0(s0) +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: sw s6, 4(sp) +; RV32I-NEXT: sw s7, 0(sp) ; RV32I-NEXT: addi s1, a1, 0 ; RV32I-NEXT: addi s2, a0, 0 ; RV32I-NEXT: addi a0, s2, -1 @@ -317,14 +317,14 @@ ; RV32I-NEXT: .LBB7_2: ; RV32I-NEXT: addi a0, s1, 0 ; RV32I-NEXT: addi a1, zero, 0 -; RV32I-NEXT: lw s7, 0(s0) -; RV32I-NEXT: lw s6, 4(s0) -; RV32I-NEXT: lw s5, 8(s0) -; RV32I-NEXT: lw s4, 12(s0) -; RV32I-NEXT: lw s3, 16(s0) -; RV32I-NEXT: lw s2, 20(s0) -; RV32I-NEXT: lw s1, 24(s0) -; RV32I-NEXT: lw ra, 28(s0) +; RV32I-NEXT: lw s7, 0(sp) +; RV32I-NEXT: lw s6, 4(sp) +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) ; RV32I-NEXT: jalr zero, ra, 0 %tmp = call i64 @llvm.cttz.i64(i64 %a, i1 false) ret i64 %tmp @@ -333,7 +333,7 @@ define i8 @test_cttz_i8_zero_undef(i8 %a) nounwind { ; RV32I-LABEL: test_cttz_i8_zero_undef: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: addi a1, a0, -1 ; RV32I-NEXT: xori a0, a0, -1 ; RV32I-NEXT: and a0, a0, a1 @@ -359,7 +359,7 @@ ; RV32I-NEXT: addi a2, a2, %lo(__mulsi3) ; RV32I-NEXT: jalr ra, a2, 0 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %tmp = call i8 @llvm.cttz.i8(i8 %a, i1 true) ret i8 %tmp @@ -368,7 +368,7 @@ define i16 @test_cttz_i16_zero_undef(i16 %a) nounwind { ; RV32I-LABEL: test_cttz_i16_zero_undef: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: addi a1, a0, -1 ; RV32I-NEXT: xori a0, a0, -1 ; RV32I-NEXT: and a0, a0, a1 @@ -394,7 +394,7 @@ ; RV32I-NEXT: addi a2, a2, %lo(__mulsi3) ; RV32I-NEXT: jalr ra, a2, 0 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %tmp = call i16 @llvm.cttz.i16(i16 %a, i1 true) ret i16 %tmp @@ -403,7 +403,7 @@ define i32 @test_cttz_i32_zero_undef(i32 %a) nounwind { ; RV32I-LABEL: test_cttz_i32_zero_undef: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: addi a1, a0, -1 ; RV32I-NEXT: xori a0, a0, -1 ; RV32I-NEXT: and a0, a0, a1 @@ -429,7 +429,7 @@ ; RV32I-NEXT: addi a2, a2, %lo(__mulsi3) ; RV32I-NEXT: jalr ra, a2, 0 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %tmp = call i32 @llvm.cttz.i32(i32 %a, i1 true) ret i32 %tmp @@ -438,14 +438,14 @@ define i64 @test_cttz_i64_zero_undef(i64 %a) nounwind { ; RV32I-LABEL: test_cttz_i64_zero_undef: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 28(s0) -; RV32I-NEXT: sw s1, 24(s0) -; RV32I-NEXT: sw s2, 20(s0) -; RV32I-NEXT: sw s3, 16(s0) -; RV32I-NEXT: sw s4, 12(s0) -; RV32I-NEXT: sw s5, 8(s0) -; RV32I-NEXT: sw s6, 4(s0) -; RV32I-NEXT: sw s7, 0(s0) +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw s1, 24(sp) +; RV32I-NEXT: sw s2, 20(sp) +; RV32I-NEXT: sw s3, 16(sp) +; RV32I-NEXT: sw s4, 12(sp) +; RV32I-NEXT: sw s5, 8(sp) +; RV32I-NEXT: sw s6, 4(sp) +; RV32I-NEXT: sw s7, 0(sp) ; RV32I-NEXT: addi s1, a1, 0 ; RV32I-NEXT: addi s2, a0, 0 ; RV32I-NEXT: addi a0, s2, -1 @@ -497,14 +497,14 @@ ; RV32I-NEXT: .LBB11_2: ; RV32I-NEXT: addi a0, s1, 0 ; RV32I-NEXT: addi a1, zero, 0 -; RV32I-NEXT: lw s7, 0(s0) -; RV32I-NEXT: lw s6, 4(s0) -; RV32I-NEXT: lw s5, 8(s0) -; RV32I-NEXT: lw s4, 12(s0) -; RV32I-NEXT: lw s3, 16(s0) -; RV32I-NEXT: lw s2, 20(s0) -; RV32I-NEXT: lw s1, 24(s0) -; RV32I-NEXT: lw ra, 28(s0) +; RV32I-NEXT: lw s7, 0(sp) +; RV32I-NEXT: lw s6, 4(sp) +; RV32I-NEXT: lw s5, 8(sp) +; RV32I-NEXT: lw s4, 12(sp) +; RV32I-NEXT: lw s3, 16(sp) +; RV32I-NEXT: lw s2, 20(sp) +; RV32I-NEXT: lw s1, 24(sp) +; RV32I-NEXT: lw ra, 28(sp) ; RV32I-NEXT: jalr zero, ra, 0 %tmp = call i64 @llvm.cttz.i64(i64 %a, i1 true) ret i64 %tmp @@ -513,7 +513,7 @@ define i32 @test_ctpop_i32(i32 %a) nounwind { ; RV32I-LABEL: test_ctpop_i32: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a1, 349525 ; RV32I-NEXT: addi a1, a1, 1365 ; RV32I-NEXT: srli a2, a0, 1 @@ -536,7 +536,7 @@ ; RV32I-NEXT: addi a2, a2, %lo(__mulsi3) ; RV32I-NEXT: jalr ra, a2, 0 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = call i32 @llvm.ctpop.i32(i32 %a) ret i32 %1 Index: test/CodeGen/RISCV/calls.ll =================================================================== --- test/CodeGen/RISCV/calls.ll +++ test/CodeGen/RISCV/calls.ll @@ -7,11 +7,11 @@ define i32 @test_call_external(i32 %a) nounwind { ; RV32I-LABEL: test_call_external: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a1, %hi(external_function) ; RV32I-NEXT: addi a1, a1, %lo(external_function) ; RV32I-NEXT: jalr ra, a1, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = call i32 @external_function(i32 %a) ret i32 %1 @@ -29,11 +29,11 @@ define i32 @test_call_defined(i32 %a) nounwind { ; RV32I-LABEL: test_call_defined: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a1, %hi(defined_function) ; RV32I-NEXT: addi a1, a1, %lo(defined_function) ; RV32I-NEXT: jalr ra, a1, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = call i32 @defined_function(i32 %a) nounwind ret i32 %1 @@ -42,11 +42,11 @@ define i32 @test_call_indirect(i32 (i32)* %a, i32 %b) nounwind { ; RV32I-LABEL: test_call_indirect: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: addi a2, a0, 0 ; RV32I-NEXT: addi a0, a1, 0 ; RV32I-NEXT: jalr ra, a2, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = call i32 %a(i32 %b) ret i32 %1 @@ -67,16 +67,16 @@ define i32 @test_call_fastcc(i32 %a, i32 %b) nounwind { ; RV32I-LABEL: test_call_fastcc: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) -; RV32I-NEXT: sw s1, 8(s0) +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: sw s1, 8(sp) ; RV32I-NEXT: addi s1, a0, 0 ; RV32I-NEXT: lui a0, %hi(fastcc_function) ; RV32I-NEXT: addi a2, a0, %lo(fastcc_function) ; RV32I-NEXT: addi a0, s1, 0 ; RV32I-NEXT: jalr ra, a2, 0 ; RV32I-NEXT: addi a0, s1, 0 -; RV32I-NEXT: lw s1, 8(s0) -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw s1, 8(sp) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = call fastcc i32 @fastcc_function(i32 %a, i32 %b) ret i32 %a Index: test/CodeGen/RISCV/div.ll =================================================================== --- test/CodeGen/RISCV/div.ll +++ test/CodeGen/RISCV/div.ll @@ -5,11 +5,11 @@ define i32 @udiv(i32 %a, i32 %b) { ; RV32I-LABEL: udiv: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a2, %hi(__udivsi3) ; RV32I-NEXT: addi a2, a2, %lo(__udivsi3) ; RV32I-NEXT: jalr ra, a2, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = udiv i32 %a, %b ret i32 %1 @@ -18,12 +18,12 @@ define i32 @udiv_constant(i32 %a) { ; RV32I-LABEL: udiv_constant: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a1, %hi(__udivsi3) ; RV32I-NEXT: addi a2, a1, %lo(__udivsi3) ; RV32I-NEXT: addi a1, zero, 5 ; RV32I-NEXT: jalr ra, a2, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = udiv i32 %a, 5 ret i32 %1 @@ -41,11 +41,11 @@ define i64 @udiv64(i64 %a, i64 %b) { ; RV32I-LABEL: udiv64: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a4, %hi(__udivdi3) ; RV32I-NEXT: addi a4, a4, %lo(__udivdi3) ; RV32I-NEXT: jalr ra, a4, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = udiv i64 %a, %b ret i64 %1 @@ -54,13 +54,13 @@ define i64 @udiv64_constant(i64 %a) { ; RV32I-LABEL: udiv64_constant: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a2, %hi(__udivdi3) ; RV32I-NEXT: addi a4, a2, %lo(__udivdi3) ; RV32I-NEXT: addi a2, zero, 5 ; RV32I-NEXT: addi a3, zero, 0 ; RV32I-NEXT: jalr ra, a4, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = udiv i64 %a, 5 ret i64 %1 @@ -69,11 +69,11 @@ define i32 @sdiv(i32 %a, i32 %b) { ; RV32I-LABEL: sdiv: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a2, %hi(__divsi3) ; RV32I-NEXT: addi a2, a2, %lo(__divsi3) ; RV32I-NEXT: jalr ra, a2, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = sdiv i32 %a, %b ret i32 %1 @@ -82,12 +82,12 @@ define i32 @sdiv_constant(i32 %a) { ; RV32I-LABEL: sdiv_constant: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a1, %hi(__divsi3) ; RV32I-NEXT: addi a2, a1, %lo(__divsi3) ; RV32I-NEXT: addi a1, zero, 5 ; RV32I-NEXT: jalr ra, a2, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = sdiv i32 %a, 5 ret i32 %1 @@ -108,11 +108,11 @@ define i64 @sdiv64(i64 %a, i64 %b) { ; RV32I-LABEL: sdiv64: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a4, %hi(__divdi3) ; RV32I-NEXT: addi a4, a4, %lo(__divdi3) ; RV32I-NEXT: jalr ra, a4, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = sdiv i64 %a, %b ret i64 %1 @@ -121,13 +121,13 @@ define i64 @sdiv64_constant(i64 %a) { ; RV32I-LABEL: sdiv64_constant: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a2, %hi(__divdi3) ; RV32I-NEXT: addi a4, a2, %lo(__divdi3) ; RV32I-NEXT: addi a2, zero, 5 ; RV32I-NEXT: addi a3, zero, 0 ; RV32I-NEXT: jalr ra, a4, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = sdiv i64 %a, 5 ret i64 %1 Index: test/CodeGen/RISCV/frame.ll =================================================================== --- /dev/null +++ test/CodeGen/RISCV/frame.ll @@ -0,0 +1,36 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32I %s + +%struct.key_t = type { i32, [16 x i8] } + +; FIXME: prologue and epilogue insertion must be implemented to complete this +; test + +define i32 @test() nounwind { +; RV32I-LABEL: test: +; RV32I: # %bb.0: +; RV32I-NEXT: sw ra, 28(sp) +; RV32I-NEXT: sw zero, -8(s0) +; RV32I-NEXT: sw zero, -12(s0) +; RV32I-NEXT: sw zero, -16(s0) +; RV32I-NEXT: sw zero, -20(s0) +; RV32I-NEXT: sw zero, -24(s0) +; RV32I-NEXT: lui a0, %hi(test1) +; RV32I-NEXT: addi a1, a0, %lo(test1) +; RV32I-NEXT: addi a0, s0, -20 +; RV32I-NEXT: jalr ra, a1, 0 +; RV32I-NEXT: addi a0, zero, 0 +; RV32I-NEXT: lw ra, 28(sp) +; RV32I-NEXT: jalr zero, ra, 0 + %key = alloca %struct.key_t, align 4 + %1 = bitcast %struct.key_t* %key to i8* + call void @llvm.memset.p0i8.i64(i8* %1, i8 0, i64 20, i32 4, i1 false) + %2 = getelementptr inbounds %struct.key_t, %struct.key_t* %key, i64 0, i32 1, i64 0 + call void @test1(i8* %2) #3 + ret i32 0 +} + +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) + +declare void @test1(i8*) Index: test/CodeGen/RISCV/indirectbr.ll =================================================================== --- test/CodeGen/RISCV/indirectbr.ll +++ test/CodeGen/RISCV/indirectbr.ll @@ -5,11 +5,11 @@ define i32 @indirectbr(i8* %target) nounwind { ; RV32I-LABEL: indirectbr: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 0(s0) +; RV32I-NEXT: sw ra, 0(sp) ; RV32I-NEXT: jalr zero, a0, 0 ; RV32I-NEXT: .LBB0_1: # %ret ; RV32I-NEXT: addi a0, zero, 0 -; RV32I-NEXT: lw ra, 0(s0) +; RV32I-NEXT: lw ra, 0(sp) ; RV32I-NEXT: jalr zero, ra, 0 indirectbr i8* %target, [label %test_label] test_label: @@ -21,11 +21,11 @@ define i32 @indirectbr_with_offset(i8* %a) nounwind { ; RV32I-LABEL: indirectbr_with_offset: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 0(s0) +; RV32I-NEXT: sw ra, 0(sp) ; RV32I-NEXT: jalr zero, a0, 1380 ; RV32I-NEXT: .LBB1_1: # %ret ; RV32I-NEXT: addi a0, zero, 0 -; RV32I-NEXT: lw ra, 0(s0) +; RV32I-NEXT: lw ra, 0(sp) ; RV32I-NEXT: jalr zero, ra, 0 %target = getelementptr inbounds i8, i8* %a, i32 1380 indirectbr i8* %target, [label %test_label] Index: test/CodeGen/RISCV/mul.ll =================================================================== --- test/CodeGen/RISCV/mul.ll +++ test/CodeGen/RISCV/mul.ll @@ -5,12 +5,12 @@ define i32 @square(i32 %a) { ; RV32I-LABEL: square: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a1, %hi(__mulsi3) ; RV32I-NEXT: addi a2, a1, %lo(__mulsi3) ; RV32I-NEXT: addi a1, a0, 0 ; RV32I-NEXT: jalr ra, a2, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = mul i32 %a, %a ret i32 %1 @@ -19,11 +19,11 @@ define i32 @mul(i32 %a, i32 %b) { ; RV32I-LABEL: mul: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a2, %hi(__mulsi3) ; RV32I-NEXT: addi a2, a2, %lo(__mulsi3) ; RV32I-NEXT: jalr ra, a2, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = mul i32 %a, %b ret i32 %1 @@ -32,12 +32,12 @@ define i32 @mul_constant(i32 %a) { ; RV32I-LABEL: mul_constant: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a1, %hi(__mulsi3) ; RV32I-NEXT: addi a2, a1, %lo(__mulsi3) ; RV32I-NEXT: addi a1, zero, 5 ; RV32I-NEXT: jalr ra, a2, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = mul i32 %a, 5 ret i32 %1 @@ -55,11 +55,11 @@ define i64 @mul64(i64 %a, i64 %b) { ; RV32I-LABEL: mul64: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a4, %hi(__muldi3) ; RV32I-NEXT: addi a4, a4, %lo(__muldi3) ; RV32I-NEXT: jalr ra, a4, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = mul i64 %a, %b ret i64 %1 @@ -68,13 +68,13 @@ define i64 @mul64_constant(i64 %a) { ; RV32I-LABEL: mul64_constant: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a2, %hi(__muldi3) ; RV32I-NEXT: addi a4, a2, %lo(__muldi3) ; RV32I-NEXT: addi a2, zero, 5 ; RV32I-NEXT: addi a3, zero, 0 ; RV32I-NEXT: jalr ra, a4, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = mul i64 %a, 5 ret i64 %1 Index: test/CodeGen/RISCV/rem.ll =================================================================== --- test/CodeGen/RISCV/rem.ll +++ test/CodeGen/RISCV/rem.ll @@ -5,11 +5,11 @@ define i32 @urem(i32 %a, i32 %b) nounwind { ; RV32I-LABEL: urem: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a2, %hi(__umodsi3) ; RV32I-NEXT: addi a2, a2, %lo(__umodsi3) ; RV32I-NEXT: jalr ra, a2, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = urem i32 %a, %b ret i32 %1 @@ -18,11 +18,11 @@ define i32 @srem(i32 %a, i32 %b) nounwind { ; RV32I-LABEL: srem: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a2, %hi(__modsi3) ; RV32I-NEXT: addi a2, a2, %lo(__modsi3) ; RV32I-NEXT: jalr ra, a2, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = srem i32 %a, %b ret i32 %1 Index: test/CodeGen/RISCV/shifts.ll =================================================================== --- test/CodeGen/RISCV/shifts.ll +++ test/CodeGen/RISCV/shifts.ll @@ -8,11 +8,11 @@ define i64 @lshr64(i64 %a, i64 %b) nounwind { ; RV32I-LABEL: lshr64: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a3, %hi(__lshrdi3) ; RV32I-NEXT: addi a3, a3, %lo(__lshrdi3) ; RV32I-NEXT: jalr ra, a3, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = lshr i64 %a, %b ret i64 %1 @@ -21,11 +21,11 @@ define i64 @ashr64(i64 %a, i64 %b) nounwind { ; RV32I-LABEL: ashr64: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a3, %hi(__ashrdi3) ; RV32I-NEXT: addi a3, a3, %lo(__ashrdi3) ; RV32I-NEXT: jalr ra, a3, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = ashr i64 %a, %b ret i64 %1 @@ -34,11 +34,11 @@ define i64 @shl64(i64 %a, i64 %b) nounwind { ; RV32I-LABEL: shl64: ; RV32I: # %bb.0: -; RV32I-NEXT: sw ra, 12(s0) +; RV32I-NEXT: sw ra, 12(sp) ; RV32I-NEXT: lui a3, %hi(__ashldi3) ; RV32I-NEXT: addi a3, a3, %lo(__ashldi3) ; RV32I-NEXT: jalr ra, a3, 0 -; RV32I-NEXT: lw ra, 12(s0) +; RV32I-NEXT: lw ra, 12(sp) ; RV32I-NEXT: jalr zero, ra, 0 %1 = shl i64 %a, %b ret i64 %1