diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -1046,7 +1046,8 @@ // Insert the spill to the stack frame. Register Reg = CS.getReg(); const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.storeRegToStackSlot(MBB, MI, Reg, true, CS.getFrameIdx(), RC, TRI); + TII.storeRegToStackSlot(MBB, MI, Reg, !MBB.isLiveIn(Reg), CS.getFrameIdx(), + RC, TRI); } return true; diff --git a/llvm/test/CodeGen/RISCV/live-sp.mir b/llvm/test/CodeGen/RISCV/live-sp.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/live-sp.mir @@ -0,0 +1,94 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=riscv64 -run-pass=prologepilog -simplify-mir -o - %s | FileCheck %s +# verify live-on-entry registers are not marked killed by spills +--- | + + declare void @vararg(i32 signext, ...) + + define void @test1() { + entry: + %a = alloca i32, align 4 + %0 = call i8* @llvm.returnaddress(i32 0) + %1 = ptrtoint i8* %0 to i64 + %conv = trunc i64 %1 to i32 + store i32 %conv, i32* %a, align 4 + %2 = load i32, i32* %a, align 4 + call void (i32, ...) @vararg(i32 signext 0, i32 signext %2) + ret void + } + + ; Function Attrs: nofree nosync nounwind readnone willreturn + declare i8* @llvm.returnaddress(i32 immarg) #0 + + attributes #0 = { nofree nosync nounwind readnone willreturn } + +... +--- +name: test1 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: [] +liveins: + - { reg: '$x1', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: true + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 4 + adjustsStack: false + hasCalls: true + stackProtector: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: a, type: default, offset: 0, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0.entry: + liveins: $x1 + + ; CHECK-LABEL: name: test1 + ; CHECK: liveins: $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x2 = frame-setup ADDI $x2, -16 + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16 + ; CHECK-NEXT: SD $x1, $x2, 8 :: (store (s64) into %stack.1) + ; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $x1, -8 + ; CHECK-NEXT: SW renamable $x1, $x2, 4 :: (store (s32) into %ir.a) + ; CHECK-NEXT: renamable $x11 = ADDIW killed renamable $x1, 0 + ; CHECK-NEXT: $x10 = COPY $x0 + ; CHECK-NEXT: PseudoCALL target-flags(riscv-plt) @vararg, csr_ilp32_lp64, implicit-def dead $x1, implicit killed $x10, implicit $x11, implicit-def $x2 + ; CHECK-NEXT: $x1 = LD $x2, 8 :: (load (s64) from %stack.1) + ; CHECK-NEXT: $x2 = frame-destroy ADDI $x2, 16 + ; CHECK-NEXT: PseudoRET + SW renamable $x1, %stack.0.a, 0 :: (store (s32) into %ir.a) + renamable $x11 = ADDIW killed renamable $x1, 0 + ADJCALLSTACKDOWN 0, 0, implicit-def dead $x2, implicit $x2 + $x10 = COPY $x0 + PseudoCALL target-flags(riscv-plt) @vararg, csr_ilp32_lp64, implicit-def dead $x1, implicit killed $x10, implicit $x11, implicit-def $x2 + ADJCALLSTACKUP 0, 0, implicit-def dead $x2, implicit $x2 + PseudoRET + +...