Index: lib/Target/RISCV/RISCVFrameLowering.cpp =================================================================== --- lib/Target/RISCV/RISCVFrameLowering.cpp +++ lib/Target/RISCV/RISCVFrameLowering.cpp @@ -74,7 +74,7 @@ .addReg(SrcReg) .addImm(Val) .setMIFlag(Flag); - } else if (isInt<32>(Val)) { + } else { unsigned Opc = RISCV::ADD; bool isSub = Val < 0; if (isSub) { @@ -83,13 +83,15 @@ } Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); - TII->movImm32(MBB, MBBI, DL, ScratchReg, Val, Flag); + if (isInt<32>(Val)) { + TII->movImm32(MBB, MBBI, DL, ScratchReg, Val, Flag); + } else { + TII->movImm64(MBB, MBBI, DL, ScratchReg, Val, Flag); + } BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg) .addReg(SrcReg) .addReg(ScratchReg, RegState::Kill) .setMIFlag(Flag); - } else { - report_fatal_error("adjustReg cannot yet handle adjustments >32 bits"); } } Index: lib/Target/RISCV/RISCVInstrInfo.h =================================================================== --- lib/Target/RISCV/RISCVInstrInfo.h +++ lib/Target/RISCV/RISCVInstrInfo.h @@ -51,6 +51,11 @@ const DebugLoc &DL, Register DstReg, uint64_t Val, MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const; + // Materializes the given int64 Val into DstReg. + void movImm64(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, unsigned DstReg, uint64_t Val, + MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const; + unsigned getInstSizeInBytes(const MachineInstr &MI) const override; bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, Index: lib/Target/RISCV/RISCVInstrInfo.cpp =================================================================== --- lib/Target/RISCV/RISCVInstrInfo.cpp +++ lib/Target/RISCV/RISCVInstrInfo.cpp @@ -14,6 +14,7 @@ #include "RISCV.h" #include "RISCVSubtarget.h" #include "RISCVTargetMachine.h" +#include "Utils/RISCVMatInt.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -176,6 +177,59 @@ .setMIFlag(Flag); } +static unsigned getTempReg(MachineFunction *MF, MachineInstr::MIFlag Flag) { + MachineRegisterInfo &MRI = MF->getRegInfo(); + unsigned TempReg; + + // We can use T1 as temp register if the instruction is FrameSetup or + // FrameDestroy. + if ((Flag == MachineInstr::FrameSetup) || + (Flag == MachineInstr::FrameDestroy)) { + TempReg = RISCV::X6; + } else { + TempReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); + } + + return TempReg; +} + +void RISCVInstrInfo::movImm64(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, unsigned DstReg, uint64_t Val, + MachineInstr::MIFlag Flag) const { + MachineFunction *MF = MBB.getParent(); + bool IsRV64 = MF->getSubtarget().is64Bit(); + unsigned SrcReg = RISCV::X0; + unsigned Num = 0; + unsigned Result; + + RISCVMatInt::InstSeq Seq; + RISCVMatInt::generateInstSeq(Val, IsRV64, Seq); + assert(Seq.size() > 0); + + for (RISCVMatInt::Inst &Inst : Seq) { + // Write the final result to DstReg if it's the last instruction in the Seq. + // Otherwise, write the result to the temp register. + if (++Num == Seq.size()) + Result = DstReg; + else + Result = getTempReg(MF, Flag); + + if (Inst.Opc == RISCV::LUI) { + BuildMI(MBB, MBBI, DL, get(RISCV::LUI), Result) + .addImm(Inst.Imm) + .setMIFlag(Flag); + } else { + BuildMI(MBB, MBBI, DL, get(Inst.Opc), Result) + .addReg(SrcReg, RegState::Kill) + .addImm(Inst.Imm) + .setMIFlag(Flag); + } + // Only the first instruction has X0 as its source. + SrcReg = Result; + } +} + // The contents of values added to Cond are not examined outside of // RISCVInstrInfo, giving us flexibility in what to push to it. For RISCV, we // push BranchOpcode, Reg1, Reg2. Index: test/CodeGen/RISCV/rv64-large-stack.ll =================================================================== --- /dev/null +++ test/CodeGen/RISCV/rv64-large-stack.ll @@ -0,0 +1,63 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s | FileCheck %s +; +; The test case check that RV64 could handle the stack adjustment offset exceed +; 32-bit. + +@v = common dso_local global i32 0, align 4 + +define void @foo() nounwind { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lui t1, 95 +; CHECK-NEXT: addiw t1, t1, 1505 +; CHECK-NEXT: slli t1, t1, 13 +; CHECK-NEXT: addi a0, t1, 32 +; CHECK-NEXT: sub sp, sp, a0 +; CHECK-NEXT: lui a0, 781250 +; CHECK-NEXT: addi a0, a0, 24 +; CHECK-NEXT: add a0, sp, a0 +; CHECK-NEXT: sd ra, 0(a0) +; CHECK-NEXT: lui a0, %hi(v) +; CHECK-NEXT: lw a0, %lo(v)(a0) +; CHECK-NEXT: call __floatsitf +; CHECK-NEXT: addi a2, zero, 511 +; CHECK-NEXT: slli a3, a2, 53 +; CHECK-NEXT: mv a2, zero +; CHECK-NEXT: call __multf3 +; CHECK-NEXT: call bar +; CHECK-NEXT: addi a0, sp, 16 +; CHECK-NEXT: call baz +; CHECK-NEXT: lui a0, 781250 +; CHECK-NEXT: addi a0, a0, 24 +; CHECK-NEXT: add a0, sp, a0 +; CHECK-NEXT: ld ra, 0(a0) +; CHECK-NEXT: lui t1, 95 +; CHECK-NEXT: addiw t1, t1, 1505 +; CHECK-NEXT: slli t1, t1, 13 +; CHECK-NEXT: addi a0, t1, 32 +; CHECK-NEXT: add sp, sp, a0 +; CHECK-NEXT: ret +entry: + %w = alloca [100000000 x { fp128, fp128 }], align 16 + %0 = bitcast [100000000 x { fp128, fp128 }]* %w to i8* + call void @llvm.lifetime.start.p0i8(i64 3200000000, i8* nonnull %0) + %1 = load volatile i32, i32* @v, align 4 + %conv = sitofp i32 %1 to fp128 + %div = fmul fp128 %conv, 0xL00000000000000003FE0000000000000 + tail call void @bar(fp128 %div) #3 + %arraydecay = getelementptr inbounds [100000000 x { fp128, fp128 }], [100000000 x { fp128, fp128 }]* %w, i64 0, i64 0 + call void @baz({ fp128, fp128 }* nonnull %arraydecay) + call void @llvm.lifetime.end.p0i8(i64 3200000000, i8* nonnull %0) + ret void +} + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) + +declare void @bar(fp128) + +declare void @baz({ fp128, fp128 }*) + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)