Repository navigation
Conversation
|
@llvm/pr-subscribers-backend-sparc Author: Brad Smith (brad0) ChangesOn 32-bit SPARC, a return value that does not fit in the return Check the lowered sret argument / SRetReturnReg instead of the IR Fixes #232963 Patch is 24.29 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/240041.diff 7 Files Affected:
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 7821adaefba93b..47ef77c8838efd 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -317,12 +317,11 @@ SparcTargetLowering::LowerReturn_32(SDValue Chain, CallingConv::ID CallConv,
}
unsigned RetAddrOffset = 8; // Call Inst + Delay Slot
- // If the function returns a struct, copy the SRetReturnReg to I0
- if (MF.getFunction().hasStructRetAttr()) {
- SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>();
- Register Reg = SFI->getSRetReturnReg();
- if (!Reg)
- llvm_unreachable("sret virtual register not created in the entry block");
+ // If the function returns a struct, copy the SRetReturnReg to I0. This
+ // covers both an explicit sret parameter and a return value that was
+ // demoted to sret because it does not fit in the return registers.
+ SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>();
+ if (Register Reg = SFI->getSRetReturnReg()) {
auto PtrVT = getPointerTy(DAG.getDataLayout());
SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, PtrVT);
Chain = DAG.getCopyToReg(Chain, DL, SP::I0, Val, Glue);
@@ -332,7 +331,9 @@ SparcTargetLowering::LowerReturn_32(SDValue Chain, CallingConv::ID CallConv,
// A zero-sized return value, e.g. an empty struct or union, is returned
// without an unimp instruction after the call, so there is nothing for the
// return to skip over.
- Type *RetType = MF.getFunction().getParamStructRetType(0);
+ const Function &F = MF.getFunction();
+ Type *RetType =
+ F.hasStructRetAttr() ? F.getParamStructRetType(0) : F.getReturnType();
if (!RetType->isEmptyTy())
RetAddrOffset = 12; // CallInst + Delay Slot + Unimp
}
@@ -591,7 +592,9 @@ SDValue SparcTargetLowering::LowerFormalArguments_32(
}
}
- if (MF.getFunction().hasStructRetAttr()) {
+ // Ins[0] is an sret argument both for an explicit sret parameter and for a
+ // return value that was demoted to sret.
+ if (!Ins.empty() && Ins[0].Flags.isSRet()) {
// Copy the SRet Argument to SRetReturnReg.
SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>();
Register Reg = SFI->getSRetReturnReg();
diff --git a/llvm/test/CodeGen/SPARC/fmuladd-soft-float.ll b/llvm/test/CodeGen/SPARC/fmuladd-soft-float.ll
index 54bd83f10586cd..f222afd5cfb1ea 100644
--- a/llvm/test/CodeGen/SPARC/fmuladd-soft-float.ll
+++ b/llvm/test/CodeGen/SPARC/fmuladd-soft-float.ll
@@ -250,7 +250,7 @@ define <4 x double> @fmuladd_contract_v4f64(<4 x double> %a, <4 x double> %b, <4
; SOFT-FLOAT-32-NEXT: .cfi_def_cfa_register %fp
; SOFT-FLOAT-32-NEXT: .cfi_window_save
; SOFT-FLOAT-32-NEXT: .cfi_register %o7, %i7
-; SOFT-FLOAT-32-NEXT: ld [%fp+64], %l6
+; SOFT-FLOAT-32-NEXT: ld [%fp+64], %l0
; SOFT-FLOAT-32-NEXT: ld [%fp+156], %g2
; SOFT-FLOAT-32-NEXT: st %g2, [%fp+-4] ! 4-byte Folded Spill
; SOFT-FLOAT-32-NEXT: ld [%fp+160], %g2
@@ -263,15 +263,15 @@ define <4 x double> @fmuladd_contract_v4f64(<4 x double> %a, <4 x double> %b, <4
; SOFT-FLOAT-32-NEXT: st %g2, [%fp+-20] ! 4-byte Folded Spill
; SOFT-FLOAT-32-NEXT: ld [%fp+144], %g2
; SOFT-FLOAT-32-NEXT: st %g2, [%fp+-24] ! 4-byte Folded Spill
-; SOFT-FLOAT-32-NEXT: ld [%fp+132], %g2
+; SOFT-FLOAT-32-NEXT: ld [%fp+132], %l7
+; SOFT-FLOAT-32-NEXT: ld [%fp+136], %g2
; SOFT-FLOAT-32-NEXT: st %g2, [%fp+-28] ! 4-byte Folded Spill
-; SOFT-FLOAT-32-NEXT: ld [%fp+136], %l7
-; SOFT-FLOAT-32-NEXT: ld [%fp+100], %l0
-; SOFT-FLOAT-32-NEXT: ld [%fp+104], %l1
-; SOFT-FLOAT-32-NEXT: ld [%fp+108], %l2
-; SOFT-FLOAT-32-NEXT: ld [%fp+112], %l3
-; SOFT-FLOAT-32-NEXT: ld [%fp+116], %l4
-; SOFT-FLOAT-32-NEXT: ld [%fp+120], %l5
+; SOFT-FLOAT-32-NEXT: ld [%fp+100], %l2
+; SOFT-FLOAT-32-NEXT: ld [%fp+104], %l3
+; SOFT-FLOAT-32-NEXT: ld [%fp+108], %l4
+; SOFT-FLOAT-32-NEXT: ld [%fp+112], %l5
+; SOFT-FLOAT-32-NEXT: ld [%fp+116], %l6
+; SOFT-FLOAT-32-NEXT: ld [%fp+120], %l1
; SOFT-FLOAT-32-NEXT: ld [%fp+92], %o0
; SOFT-FLOAT-32-NEXT: ld [%fp+96], %o1
; SOFT-FLOAT-32-NEXT: ld [%fp+124], %o2
@@ -281,26 +281,26 @@ define <4 x double> @fmuladd_contract_v4f64(<4 x double> %a, <4 x double> %b, <4
; SOFT-FLOAT-32-NEXT: st %o1, [%fp+-36] ! 4-byte Folded Spill
; SOFT-FLOAT-32-NEXT: mov %i4, %o0
; SOFT-FLOAT-32-NEXT: mov %i5, %o1
-; SOFT-FLOAT-32-NEXT: mov %l4, %o2
+; SOFT-FLOAT-32-NEXT: mov %l6, %o2
; SOFT-FLOAT-32-NEXT: call __muldf3
-; SOFT-FLOAT-32-NEXT: mov %l5, %o3
-; SOFT-FLOAT-32-NEXT: mov %o0, %l4
-; SOFT-FLOAT-32-NEXT: mov %o1, %l5
+; SOFT-FLOAT-32-NEXT: mov %l1, %o3
+; SOFT-FLOAT-32-NEXT: mov %o0, %l1
+; SOFT-FLOAT-32-NEXT: mov %o1, %l6
; SOFT-FLOAT-32-NEXT: mov %i2, %o0
; SOFT-FLOAT-32-NEXT: mov %i3, %o1
-; SOFT-FLOAT-32-NEXT: mov %l2, %o2
+; SOFT-FLOAT-32-NEXT: mov %l4, %o2
; SOFT-FLOAT-32-NEXT: call __muldf3
-; SOFT-FLOAT-32-NEXT: mov %l3, %o3
+; SOFT-FLOAT-32-NEXT: mov %l5, %o3
; SOFT-FLOAT-32-NEXT: mov %o0, %i4
; SOFT-FLOAT-32-NEXT: mov %o1, %i5
; SOFT-FLOAT-32-NEXT: mov %i0, %o0
; SOFT-FLOAT-32-NEXT: mov %i1, %o1
-; SOFT-FLOAT-32-NEXT: mov %l0, %o2
+; SOFT-FLOAT-32-NEXT: mov %l2, %o2
; SOFT-FLOAT-32-NEXT: call __muldf3
-; SOFT-FLOAT-32-NEXT: mov %l1, %o3
-; SOFT-FLOAT-32-NEXT: ld [%fp+-28], %o2 ! 4-byte Folded Reload
+; SOFT-FLOAT-32-NEXT: mov %l3, %o3
+; SOFT-FLOAT-32-NEXT: mov %l7, %o2
; SOFT-FLOAT-32-NEXT: call __adddf3
-; SOFT-FLOAT-32-NEXT: mov %l7, %o3
+; SOFT-FLOAT-32-NEXT: ld [%fp+-28], %o3
; SOFT-FLOAT-32-NEXT: mov %o0, %i2
; SOFT-FLOAT-32-NEXT: mov %o1, %i3
; SOFT-FLOAT-32-NEXT: mov %i4, %o0
@@ -310,8 +310,8 @@ define <4 x double> @fmuladd_contract_v4f64(<4 x double> %a, <4 x double> %b, <4
; SOFT-FLOAT-32-NEXT: ld [%fp+-24], %o3
; SOFT-FLOAT-32-NEXT: mov %o0, %i4
; SOFT-FLOAT-32-NEXT: mov %o1, %i5
-; SOFT-FLOAT-32-NEXT: mov %l4, %o0
-; SOFT-FLOAT-32-NEXT: mov %l5, %o1
+; SOFT-FLOAT-32-NEXT: mov %l1, %o0
+; SOFT-FLOAT-32-NEXT: mov %l6, %o1
; SOFT-FLOAT-32-NEXT: ld [%fp+-12], %o2 ! 4-byte Folded Reload
; SOFT-FLOAT-32-NEXT: call __adddf3
; SOFT-FLOAT-32-NEXT: ld [%fp+-16], %o3
@@ -324,12 +324,12 @@ define <4 x double> @fmuladd_contract_v4f64(<4 x double> %a, <4 x double> %b, <4
; SOFT-FLOAT-32-NEXT: ld [%fp+-8], %o3
; SOFT-FLOAT-32-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
; SOFT-FLOAT-32-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
-; SOFT-FLOAT-32-NEXT: std %o0, [%l6+24]
-; SOFT-FLOAT-32-NEXT: std %i0, [%l6+16]
-; SOFT-FLOAT-32-NEXT: std %i4, [%l6+8]
-; SOFT-FLOAT-32-NEXT: std %i2, [%l6]
-; SOFT-FLOAT-32-NEXT: ret
-; SOFT-FLOAT-32-NEXT: restore
+; SOFT-FLOAT-32-NEXT: std %o0, [%l0+24]
+; SOFT-FLOAT-32-NEXT: std %i0, [%l0+16]
+; SOFT-FLOAT-32-NEXT: std %i4, [%l0+8]
+; SOFT-FLOAT-32-NEXT: std %i2, [%l0]
+; SOFT-FLOAT-32-NEXT: jmp %i7+12
+; SOFT-FLOAT-32-NEXT: restore %g0, %l0, %o0
;
; SOFT-FLOAT-64-LABEL: fmuladd_contract_v4f64:
; SOFT-FLOAT-64: .cfi_startproc
diff --git a/llvm/test/CodeGen/SPARC/fp128-abi.ll b/llvm/test/CodeGen/SPARC/fp128-abi.ll
index c38892f4f6371f..eec75087e4827e 100644
--- a/llvm/test/CodeGen/SPARC/fp128-abi.ll
+++ b/llvm/test/CodeGen/SPARC/fp128-abi.ll
@@ -23,7 +23,7 @@ define fp128 @f128_direct(fp128 %num) nounwind {
; SPARC32-NEXT: ldd [%fp+-16], %f2
; SPARC32-NEXT: std %f0, [%i0+8]
; SPARC32-NEXT: std %f2, [%i0]
-; SPARC32-NEXT: ret
+; SPARC32-NEXT: jmp %i7+12
; SPARC32-NEXT: restore
;
; SPARC64-LABEL: f128_direct:
@@ -66,8 +66,8 @@ define fp128 @f128_direct_spill(i32 %o0, i32 %o1, i32 %o2, i32 %o3, i32 %o4, i32
; SPARC32-NEXT: ldd [%fp+-16], %f2
; SPARC32-NEXT: std %f0, [%l0+8]
; SPARC32-NEXT: std %f2, [%l0]
-; SPARC32-NEXT: ret
-; SPARC32-NEXT: restore
+; SPARC32-NEXT: jmp %i7+12
+; SPARC32-NEXT: restore %g0, %l0, %o0
;
; SPARC64-LABEL: f128_direct_spill:
; SPARC64: ! %bb.0:
diff --git a/llvm/test/CodeGen/SPARC/fp128-strict.ll b/llvm/test/CodeGen/SPARC/fp128-strict.ll
index b65a49675f4c31..a27f209e371516 100644
--- a/llvm/test/CodeGen/SPARC/fp128-strict.ll
+++ b/llvm/test/CodeGen/SPARC/fp128-strict.ll
@@ -31,7 +31,7 @@ define fp128 @fadd_f128(fp128 %a, fp128 %b) nounwind strictfp {
; SOFT32-NEXT: ldd [%fp+-16], %f2
; SOFT32-NEXT: std %f0, [%i0+8]
; SOFT32-NEXT: std %f2, [%i0]
-; SOFT32-NEXT: ret
+; SOFT32-NEXT: jmp %i7+12
; SOFT32-NEXT: restore
;
; SOFT64-LABEL: fadd_f128:
@@ -59,7 +59,7 @@ define fp128 @fadd_f128(fp128 %a, fp128 %b) nounwind strictfp {
; HARD32-NEXT: ld [%sp+64], %o0
; HARD32-NEXT: faddq %f4, %f0, %f0
; HARD32-NEXT: std %f2, [%o0+8]
-; HARD32-NEXT: retl
+; HARD32-NEXT: jmp %o7+12
; HARD32-NEXT: std %f0, [%o0]
;
; HARD-LABEL: fadd_f128:
@@ -93,7 +93,7 @@ define fp128 @fsub_f128(fp128 %a, fp128 %b) nounwind strictfp {
; SOFT32-NEXT: ldd [%fp+-16], %f2
; SOFT32-NEXT: std %f0, [%i0+8]
; SOFT32-NEXT: std %f2, [%i0]
-; SOFT32-NEXT: ret
+; SOFT32-NEXT: jmp %i7+12
; SOFT32-NEXT: restore
;
; SOFT64-LABEL: fsub_f128:
@@ -121,7 +121,7 @@ define fp128 @fsub_f128(fp128 %a, fp128 %b) nounwind strictfp {
; HARD32-NEXT: ld [%sp+64], %o0
; HARD32-NEXT: fsubq %f4, %f0, %f0
; HARD32-NEXT: std %f2, [%o0+8]
-; HARD32-NEXT: retl
+; HARD32-NEXT: jmp %o7+12
; HARD32-NEXT: std %f0, [%o0]
;
; HARD-LABEL: fsub_f128:
@@ -155,7 +155,7 @@ define fp128 @fmul_f128(fp128 %a, fp128 %b) nounwind strictfp {
; SOFT32-NEXT: ldd [%fp+-16], %f2
; SOFT32-NEXT: std %f0, [%i0+8]
; SOFT32-NEXT: std %f2, [%i0]
-; SOFT32-NEXT: ret
+; SOFT32-NEXT: jmp %i7+12
; SOFT32-NEXT: restore
;
; SOFT64-LABEL: fmul_f128:
@@ -183,7 +183,7 @@ define fp128 @fmul_f128(fp128 %a, fp128 %b) nounwind strictfp {
; HARD32-NEXT: ld [%sp+64], %o0
; HARD32-NEXT: fmulq %f4, %f0, %f0
; HARD32-NEXT: std %f2, [%o0+8]
-; HARD32-NEXT: retl
+; HARD32-NEXT: jmp %o7+12
; HARD32-NEXT: std %f0, [%o0]
;
; HARD-LABEL: fmul_f128:
@@ -217,7 +217,7 @@ define fp128 @fdiv_f128(fp128 %a, fp128 %b) nounwind strictfp {
; SOFT32-NEXT: ldd [%fp+-16], %f2
; SOFT32-NEXT: std %f0, [%i0+8]
; SOFT32-NEXT: std %f2, [%i0]
-; SOFT32-NEXT: ret
+; SOFT32-NEXT: jmp %i7+12
; SOFT32-NEXT: restore
;
; SOFT64-LABEL: fdiv_f128:
@@ -245,7 +245,7 @@ define fp128 @fdiv_f128(fp128 %a, fp128 %b) nounwind strictfp {
; HARD32-NEXT: ld [%sp+64], %o0
; HARD32-NEXT: fdivq %f4, %f0, %f0
; HARD32-NEXT: std %f2, [%o0+8]
-; HARD32-NEXT: retl
+; HARD32-NEXT: jmp %o7+12
; HARD32-NEXT: std %f0, [%o0]
;
; HARD-LABEL: fdiv_f128:
@@ -274,7 +274,7 @@ define fp128 @fsqrt_f128(fp128 %a) nounwind strictfp {
; SOFT32-NEXT: ldd [%fp+-16], %f2
; SOFT32-NEXT: std %f0, [%i0+8]
; SOFT32-NEXT: std %f2, [%i0]
-; SOFT32-NEXT: ret
+; SOFT32-NEXT: jmp %i7+12
; SOFT32-NEXT: restore
;
; SOFT64-LABEL: fsqrt_f128:
@@ -297,7 +297,7 @@ define fp128 @fsqrt_f128(fp128 %a) nounwind strictfp {
; HARD32-NEXT: ld [%sp+64], %o0
; HARD32-NEXT: fsqrtq %f0, %f0
; HARD32-NEXT: std %f2, [%o0+8]
-; HARD32-NEXT: retl
+; HARD32-NEXT: jmp %o7+12
; HARD32-NEXT: std %f0, [%o0]
;
; HARD-LABEL: fsqrt_f128:
@@ -327,7 +327,7 @@ define fp128 @fpext_f64_f128(double %a) nounwind strictfp {
; SOFT32-NEXT: ldd [%fp+-24], %f2
; SOFT32-NEXT: std %f0, [%i0+8]
; SOFT32-NEXT: std %f2, [%i0]
-; SOFT32-NEXT: ret
+; SOFT32-NEXT: jmp %i7+12
; SOFT32-NEXT: restore
;
; SOFT64-LABEL: fpext_f64_f128:
@@ -353,7 +353,7 @@ define fp128 @fpext_f64_f128(double %a) nounwind strictfp {
; HARD32-NEXT: fdtoq %f0, %f0
; HARD32-NEXT: std %f2, [%o0+8]
; HARD32-NEXT: std %f0, [%o0]
-; HARD32-NEXT: retl
+; HARD32-NEXT: jmp %o7+12
; HARD32-NEXT: add %sp, 104, %sp
;
; HARD-LABEL: fpext_f64_f128:
@@ -646,8 +646,8 @@ define fp128 @sitofp_i32_f128(i32 %a) nounwind strictfp {
; SOFT32-NEXT: ldd [%fp+-16], %f2
; SOFT32-NEXT: std %f0, [%i1+8]
; SOFT32-NEXT: std %f2, [%i1]
-; SOFT32-NEXT: ret
-; SOFT32-NEXT: restore
+; SOFT32-NEXT: jmp %i7+12
+; SOFT32-NEXT: restore %g0, %i1, %o0
;
; SOFT64-LABEL: sitofp_i32_f128:
; SOFT64: ! %bb.0:
@@ -669,7 +669,7 @@ define fp128 @sitofp_i32_f128(i32 %a) nounwind strictfp {
; HARD32-NEXT: fitoq %f0, %f0
; HARD32-NEXT: std %f2, [%o0+8]
; HARD32-NEXT: std %f0, [%o0]
-; HARD32-NEXT: retl
+; HARD32-NEXT: jmp %o7+12
; HARD32-NEXT: add %sp, 96, %sp
;
; HARD-LABEL: sitofp_i32_f128:
@@ -699,8 +699,8 @@ define fp128 @sitofp_i64_f128(i64 %a) nounwind strictfp {
; SOFT32-NEXT: ldd [%fp+-16], %f2
; SOFT32-NEXT: std %f0, [%i2+8]
; SOFT32-NEXT: std %f2, [%i2]
-; SOFT32-NEXT: ret
-; SOFT32-NEXT: restore
+; SOFT32-NEXT: jmp %i7+12
+; SOFT32-NEXT: restore %g0, %i2, %o0
;
; SOFT64-LABEL: sitofp_i64_f128:
; SOFT64: ! %bb.0:
@@ -727,8 +727,8 @@ define fp128 @sitofp_i64_f128(i64 %a) nounwind strictfp {
; HARD32-NEXT: ldd [%fp+-16], %f2
; HARD32-NEXT: std %f0, [%i2+8]
; HARD32-NEXT: std %f2, [%i2]
-; HARD32-NEXT: ret
-; HARD32-NEXT: restore
+; HARD32-NEXT: jmp %i7+12
+; HARD32-NEXT: restore %g0, %i2, %o0
;
; HARD-LABEL: sitofp_i64_f128:
; HARD: ! %bb.0:
@@ -756,8 +756,8 @@ define fp128 @uitofp_i32_f128(i32 %a) nounwind strictfp {
; SOFT32-NEXT: ldd [%fp+-16], %f2
; SOFT32-NEXT: std %f0, [%i1+8]
; SOFT32-NEXT: std %f2, [%i1]
-; SOFT32-NEXT: ret
-; SOFT32-NEXT: restore
+; SOFT32-NEXT: jmp %i7+12
+; SOFT32-NEXT: restore %g0, %i1, %o0
;
; SOFT64-LABEL: uitofp_i32_f128:
; SOFT64: ! %bb.0:
@@ -786,7 +786,7 @@ define fp128 @uitofp_i32_f128(i32 %a) nounwind strictfp {
; HARD32-NEXT: fdtoq %f0, %f0
; HARD32-NEXT: std %f2, [%o0+8]
; HARD32-NEXT: std %f0, [%o0]
-; HARD32-NEXT: retl
+; HARD32-NEXT: jmp %o7+12
; HARD32-NEXT: add %sp, 104, %sp
;
; HARD-LABEL: uitofp_i32_f128:
diff --git a/llvm/test/CodeGen/SPARC/half.ll b/llvm/test/CodeGen/SPARC/half.ll
index 3721c7456d02b7..f2449a16a4cfa4 100644
--- a/llvm/test/CodeGen/SPARC/half.ll
+++ b/llvm/test/CodeGen/SPARC/half.ll
@@ -387,8 +387,8 @@ define <4 x double> @test_extend64_vec4(ptr %p) nounwind {
; SPARC32-NEXT: std %f0, [%i1+8]
; SPARC32-NEXT: ldd [%fp+-24], %f0 ! 8-byte Folded Reload
; SPARC32-NEXT: std %f0, [%i1]
-; SPARC32-NEXT: ret
-; SPARC32-NEXT: restore
+; SPARC32-NEXT: jmp %i7+12
+; SPARC32-NEXT: restore %g0, %i1, %o0
;
; SPARC64-LABEL: test_extend64_vec4:
; SPARC64: ! %bb.0:
diff --git a/llvm/test/CodeGen/SPARC/llvm.sincos.ll b/llvm/test/CodeGen/SPARC/llvm.sincos.ll
index 42a89af184789d..664145c0d592bb 100644
--- a/llvm/test/CodeGen/SPARC/llvm.sincos.ll
+++ b/llvm/test/CodeGen/SPARC/llvm.sincos.ll
@@ -569,42 +569,42 @@ define { <3 x float>, <3 x float> } @test_sincos_v3f32(<3 x float> %a) #0 {
; SPARC32-NEXT: ld [%fp+-12], %f0
; SPARC32-NEXT: ld [%fp+-8], %f1
; SPARC32-NEXT: ld [%fp+-4], %f2
-; SPARC32-NEXT: ld [%fp+64], %i3
+; SPARC32-NEXT: ld [%fp+64], %i0
; SPARC32-NEXT: st %f0, [%fp+-24]
; SPARC32-NEXT: st %f1, [%fp+-20]
; SPARC32-NEXT: st %f2, [%fp+-16]
-; SPARC32-NEXT: ld [%fp+-24], %i0
+; SPARC32-NEXT: ld [%fp+-24], %i1
; SPARC32-NEXT: call sinf
-; SPARC32-NEXT: mov %i0, %o0
+; SPARC32-NEXT: mov %i1, %o0
; SPARC32-NEXT: st %f0, [%fp+-28] ! 4-byte Folded Spill
-; SPARC32-NEXT: ld [%fp+-20], %i1
+; SPARC32-NEXT: ld [%fp+-20], %i2
; SPARC32-NEXT: call sinf
-; SPARC32-NEXT: mov %i1, %o0
+; SPARC32-NEXT: mov %i2, %o0
; SPARC32-NEXT: st %f0, [%fp+-32] ! 4-byte Folded Spill
-; SPARC32-NEXT: ld [%fp+-16], %i2
+; SPARC32-NEXT: ld [%fp+-16], %i3
; SPARC32-NEXT: call sinf
-; SPARC32-NEXT: mov %i2, %o0
+; SPARC32-NEXT: mov %i3, %o0
; SPARC32-NEXT: st %f0, [%fp+-36] ! 4-byte Folded Spill
; SPARC32-NEXT: call cosf
-; SPARC32-NEXT: mov %i0, %o0
+; SPARC32-NEXT: mov %i1, %o0
; SPARC32-NEXT: st %f0, [%fp+-40] ! 4-byte Folded Spill
; SPARC32-NEXT: call cosf
-; SPARC32-NEXT: mov %i1, %o0
+; SPARC32-NEXT: mov %i2, %o0
; SPARC32-NEXT: st %f0, [%fp+-44] ! 4-byte Folded Spill
; SPARC32-NEXT: call cosf
-; SPARC32-NEXT: mov %i2, %o0
-; SPARC32-NEXT: st %f0, [%i3+24]
+; SPARC32-NEXT: mov %i3, %o0
+; SPARC32-NEXT: st %f0, [%i0+24]
; SPARC32-NEXT: ld [%fp+-44], %f0 ! 4-byte Folded Reload
-; SPARC32-NEXT: st %f0, [%i3+20]
+; SPARC32-NEXT: st %f0, [%i0+20]
; SPARC32-NEXT: ld [%fp+-40], %f0 ! 4-byte Folded Reload
-; SPARC32-NEXT: st %f0, [%i3+16]
+; SPARC32-NEXT: st %f0, [%i0+16]
; SPARC32-NEXT: ld [%fp+-36], %f0 ! 4-byte Folded Reload
-; SPARC32-NEXT: st %f0, [%i3+8]
+; SPARC32-NEXT: st %f0, [%i0+8]
; SPARC32-NEXT: ld [%fp+-32], %f0 ! 4-byte Folded Reload
-; SPARC32-NEXT: st %f0, [%i3+4]
+; SPARC32-NEXT: st %f0, [%i0+4]
; SPARC32-NEXT: ld [%fp+-28], %f0 ! 4-byte Folded Reload
-; SPARC32-NEXT: st %f0, [%i3]
-; SPARC32-NEXT: ret
+; SPARC32-NEXT: st %f0, [%i0]
+; SPARC32-NEXT: jmp %i7+12
; SPARC32-NEXT: restore
;
; SPARC64-LABEL: test_sincos_v3f32:
@@ -654,8 +654,8 @@ define { <3 x float>, <3 x float> } @test_sincos_v3f32(<3 x float> %a) #0 {
; GNU32-NEXT: mov %i0, %o0
; GNU32-NEXT: call sincosf
; GNU32-NEXT: mov %i3, %o1
-; GNU32-NEXT: ret
-; GNU32-NEXT: restore
+; GNU32-NEXT: jmp %i7+12
+; GNU32-NEXT: restore %g0, %i3, %o0
;
; GNU64-LABEL: test_sincos_v3f32:
; GNU64: ! %bb.0:
@@ -808,34 +808,34 @@ define { <2 x double>, <2 x double> } @test_sincos_v2f64(<2 x double> %a) #0 {
; SPARC32-NEXT: std %i0, [%fp+-8]
; SPARC32-NEXT: ldd [%fp+-8], %f0
; SPARC32-NEXT: ldd [%fp+-16], %f2
-; SPARC32-NEXT: ld [%fp+64], %i4
+; SPARC32-NEXT: ld [%fp+64], %i0
; SPARC32-NEXT: std %f0, [%fp+-32]
; SPARC32-NEXT: std %f2, [%fp+-24]
-; SPARC32-NEXT: ldd [%fp+-32], %i0
-; SPARC32-NEXT: mov %i0, %o0
-; SPARC32-NEXT: call sin
-; SPARC32-NEXT: mov %i1, %o1
-; SPARC32-NEXT: std %f0, [%fp+-40] ! 8-byte Folded Spill
-; SPARC32-NEXT: ldd [%fp+-24], %i2
+; SPARC32-NEXT: ldd [%fp+-32], %i2
; SPARC32-NEXT: mov %i2, %o0
; SPARC32-NEXT: call sin
; SPARC32-NEXT: mov %i3, %o1
+; SPARC32-NEXT: std %f0, [%fp+-40] ! 8-byte Folded Spill
+; SPARC32-NEXT: ldd [%fp+-24], %i4
+; SPARC32-NEXT: mov %i4, %o0
+; SPARC32-NEXT: call sin
+; SPARC32-NEXT: mov %i5, %o1
; SPARC32-NEXT: std %f0, [%fp+-48] ! 8-byte Folded Spill
-; SPARC32-NEXT: mov %i0, %o0
-; SPARC32-NEXT: call cos
-; SPARC32-NEXT: mov %i1, %o1
-; SPARC32-NEXT: std %f0, [%fp+-56] ! 8-byte Folded Spill
; SPARC32-NEXT: mov %i2, %o0
; SPARC32-NEXT: call cos
; SPARC32-NEXT: mov %i3, %o1
-; SPARC32-NEXT: std %f0, [%i4+24]
+; SPARC32-NEXT: std %f0, [%fp+-56] ! 8-byte Folded Spill
+; SPARC32-NEXT: mov %i4, %o0
+; SPARC32-NEXT: call cos
+; SPARC32-NEXT: mov %i5, %o1
+; SPARC32-NEXT: std %f0, [%i0+24]
; SPARC32-NEXT: ldd [%fp+-56], %f0 ! 8-byte Folded Reload
-; SPARC32-NEXT: std %f0, [%i4+16]
+; SPARC32-NEXT: std %f0, [%i0+16]
; SPARC32-NEXT: ldd [%fp+-48], %f0 ! 8-byte Folded Reload
-; SPARC32-NEXT: std %f0, [%i4+8]
+; SPARC32-NEXT: std %f0, [%i0+8]
; SPARC32-NEXT: ldd [%fp+-40], %f0 ! 8-byte Folded Reload
-; SPARC32-NEXT: std %f0, [%i4]
-; SPARC32-NEXT: ret
+; SPARC32-NEXT: std %f0, [%i0]
+; SPARC32-NEXT: jmp %i7+12
; SPARC32-NEXT: restore
;
; SPARC64-LABEL: test_sincos_v2f64:
@@ -884,7 +884,7 @@ define { <2 x double>, <2 x double> } @test_sincos_v2f64(<2 x double> %a) #0 {
; GNU32-NEXT: add %i0, 16, %o3
; GNU32-NEXT: call sincos
; GNU32-NEXT: mov %i0, %o2
-; GNU32-NEXT: ret
+; GNU32-NEXT: jmp %i7+12
; GNU32-NEXT: restore
;
; GNU64-LABEL: test_sincos_v2f64:
diff --git a/llvm/test/CodeGen/SPARC/sret-demoted.ll b/llvm/test/CodeGen/SPARC/sret-demoted.ll
new file mode 100644
index 00000000000000..93fb1fa939ef4e
--- /dev/null
+++ b/llvm/test/CodeGen/SPARC/sret-demoted.ll
@@ -0,0 +1,138 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=sparc | FileCheck %s --check-prefixes=CHECK,LEAF
+; RUN: llc < %s -mtriple=sparc -disable-sparc-leaf-proc | ...
[truncated]
|
|
Seems like |
On 32-bit SPARC, a return value that does not fit in the return registers (e.g. fp128, or a struct larger than six i32s) is demoted to a hidden sret argument by the generic call lowering. The caller side keys off the sret argument flags and correctly emits the struct-return sequence with an unimp after the call. The callee side, however, only checked hasStructRetAttr() on the IR function, which is false for a demoted return. As a result the callee neither copied the sret pointer to %i0 nor returned past the unimp, so control landed on the unimp in the caller and trapped. Check the lowered sret argument / SRetReturnReg instead of the IR attribute so demoted returns are handled the same way as an explicit sret parameter. IsEligibleForTailCallOptimization() had the same problem: a caller whose return value was demoted to sret has no sret attribute, and the check was skipped entirely when the callee has no arguments. In both cases a struct-returning function could tail call a non-sret function, which then returns to %o7+8 and lands on the unimp. Treat the caller as struct-returning if it has an SRetReturnReg, and compare against the callee even when it has no arguments. Fixes llvm#232963 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
300ecc8 to
22cd917
Compare
On 32-bit SPARC, a return value that does not fit in the return
registers (e.g. fp128, or a struct larger than six i32s) is demoted
to a hidden sret argument by the generic call lowering. The caller
side keys off the sret argument flags and correctly emits the
struct-return sequence with an unimp after the call. The callee side,
however, only checked hasStructRetAttr() on the IR function, which
is false for a demoted return. As a result the callee neither copied
the sret pointer to %i0 nor returned past the unimp, so control
landed on the unimp in the caller and trapped.
Check the lowered sret argument / SRetReturnReg instead of the IR
attribute so demoted returns are handled the same way as an
explicit sret parameter.
IsEligibleForTailCallOptimization() had the same problem: a caller
whose return value was demoted to sret has no sret attribute, and the
check was skipped entirely when the callee has no arguments. In both
cases a struct-returning function could tail call a non-sret function,
which then returns to %o7+8 and lands on the unimp. Treat the caller
as struct-returning if it has an SRetReturnReg, and compare against
the callee even when it has no arguments.
Fixes #232963