diff options
Diffstat (limited to 'contrib/llvm/patches/patch-r262261-llvm-r199028-sparc.diff')
-rw-r--r-- | contrib/llvm/patches/patch-r262261-llvm-r199028-sparc.diff | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/contrib/llvm/patches/patch-r262261-llvm-r199028-sparc.diff b/contrib/llvm/patches/patch-r262261-llvm-r199028-sparc.diff new file mode 100644 index 0000000..78bcc61 --- /dev/null +++ b/contrib/llvm/patches/patch-r262261-llvm-r199028-sparc.diff @@ -0,0 +1,147 @@ +Pull in r199028 from upstream llvm trunk (by Jakob Stoklund Olesen): + + The SPARCv9 ABI returns a float in %f0. + + This is different from the argument passing convention which puts the + first float argument in %f1. + + With this patch, all returned floats are treated as if the 'inreg' flag + were set. This means multiple float return values get packed in %f0, + %f1, %f2, ... + + Note that when returning a struct in registers, clang will set the + 'inreg' flag on the return value, so that behavior is unchanged. This + also happens when returning a float _Complex. + +Introduced here: http://svn.freebsd.org/changeset/base/262261 + +Index: test/CodeGen/SPARC/64abi.ll +=================================================================== +--- test/CodeGen/SPARC/64abi.ll ++++ test/CodeGen/SPARC/64abi.ll +@@ -180,7 +180,7 @@ define void @call_inreg_fi(i32* %p, i32 %i1, float + } + + ; CHECK: inreg_ff +-; CHECK: fsubs %f0, %f1, %f1 ++; CHECK: fsubs %f0, %f1, %f0 + define float @inreg_ff(float inreg %a0, ; %f0 + float inreg %a1) { ; %f1 + %rv = fsub float %a0, %a1 +@@ -262,10 +262,10 @@ define void @call_ret_i64_pair(i64* %i0) { + ret void + } + +-; This is not a C struct, each member uses 8 bytes. ++; This is not a C struct, the i32 member uses 8 bytes, but the float only 4. + ; CHECK: ret_i32_float_pair + ; CHECK: ld [%i2], %i0 +-; CHECK: ld [%i3], %f3 ++; CHECK: ld [%i3], %f2 + define { i32, float } @ret_i32_float_pair(i32 %a0, i32 %a1, + i32* %p, float* %q) { + %r1 = load i32* %p +@@ -279,7 +279,7 @@ define { i32, float } @ret_i32_float_pair(i32 %a0, + ; CHECK: call_ret_i32_float_pair + ; CHECK: call ret_i32_float_pair + ; CHECK: st %o0, [%i0] +-; CHECK: st %f3, [%i1] ++; CHECK: st %f2, [%i1] + define void @call_ret_i32_float_pair(i32* %i0, float* %i1) { + %rv = call { i32, float } @ret_i32_float_pair(i32 undef, i32 undef, + i32* undef, float* undef) +Index: test/CodeGen/SPARC/constpool.ll +=================================================================== +--- test/CodeGen/SPARC/constpool.ll ++++ test/CodeGen/SPARC/constpool.ll +@@ -21,7 +21,7 @@ entry: + ; abs44: add %[[R1]], %m44(.LCPI0_0), %[[R2:[gilo][0-7]]] + ; abs44: sllx %[[R2]], 12, %[[R3:[gilo][0-7]]] + ; abs44: retl +-; abs44: ld [%[[R3]]+%l44(.LCPI0_0)], %f1 ++; abs44: ld [%[[R3]]+%l44(.LCPI0_0)], %f0 + + + ; abs64: floatCP +@@ -31,7 +31,7 @@ entry: + ; abs64: add %[[R3]], %hm(.LCPI0_0), %[[R4:[gilo][0-7]]] + ; abs64: sllx %[[R4]], 32, %[[R5:[gilo][0-7]]] + ; abs64: retl +-; abs64: ld [%[[R5]]+%[[R2]]], %f1 ++; abs64: ld [%[[R5]]+%[[R2]]], %f0 + + + ; v8pic32: floatCP +@@ -50,7 +50,7 @@ entry: + ; v9pic32: sethi %hi(.LCPI0_0), %[[R1:[gilo][0-7]]] + ; v9pic32: add %[[R1]], %lo(.LCPI0_0), %[[Goffs:[gilo][0-7]]] + ; v9pic32: ldx [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]] +-; v9pic32: ld [%[[Gaddr]]], %f1 ++; v9pic32: ld [%[[Gaddr]]], %f0 + ; v9pic32: ret + ; v9pic32: restore + +Index: test/CodeGen/SPARC/64cond.ll +=================================================================== +--- test/CodeGen/SPARC/64cond.ll ++++ test/CodeGen/SPARC/64cond.ll +@@ -80,7 +80,7 @@ entry: + ; CHECK: selectf32_xcc + ; CHECK: cmp %i0, %i1 + ; CHECK: fmovsg %xcc, %f5, %f7 +-; CHECK: fmovs %f7, %f1 ++; CHECK: fmovs %f7, %f0 + define float @selectf32_xcc(i64 %x, i64 %y, float %a, float %b) { + entry: + %tobool = icmp sgt i64 %x, %y +Index: lib/Target/Sparc/SparcISelLowering.cpp +=================================================================== +--- lib/Target/Sparc/SparcISelLowering.cpp ++++ lib/Target/Sparc/SparcISelLowering.cpp +@@ -254,7 +254,7 @@ SparcTargetLowering::LowerReturn_64(SDValue Chain, + DAG.getTarget(), RVLocs, *DAG.getContext()); + + // Analyze return values. +- CCInfo.AnalyzeReturn(Outs, CC_Sparc64); ++ CCInfo.AnalyzeReturn(Outs, RetCC_Sparc64); + + SDValue Flag; + SmallVector<SDValue, 4> RetOps(1, Chain); +@@ -1258,7 +1258,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering:: + if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && CLI.CS == 0) + CLI.Ins[0].Flags.setInReg(); + +- RVInfo.AnalyzeCallResult(CLI.Ins, CC_Sparc64); ++ RVInfo.AnalyzeCallResult(CLI.Ins, RetCC_Sparc64); + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { +Index: lib/Target/Sparc/SparcCallingConv.td +=================================================================== +--- lib/Target/Sparc/SparcCallingConv.td ++++ lib/Target/Sparc/SparcCallingConv.td +@@ -103,7 +103,7 @@ def RetCC_Sparc32 : CallingConv<[ + // Function return values are passed exactly like function arguments, except a + // struct up to 32 bytes in size can be returned in registers. + +-// Function arguments AND return values. ++// Function arguments AND most return values. + def CC_Sparc64 : CallingConv<[ + // The frontend uses the inreg flag to indicate i32 and float arguments from + // structs. These arguments are not promoted to 64 bits, but they can still +@@ -118,6 +118,15 @@ def CC_Sparc64 : CallingConv<[ + CCCustom<"CC_Sparc64_Full"> + ]>; + ++def RetCC_Sparc64 : CallingConv<[ ++ // A single f32 return value always goes in %f0. The ABI doesn't specify what ++ // happens to multiple f32 return values outside a struct. ++ CCIfType<[f32], CCCustom<"CC_Sparc64_Half">>, ++ ++ // Otherwise, return values are passed exactly like arguments. ++ CCDelegateTo<CC_Sparc64> ++]>; ++ + // Callee-saved registers are handled by the register window mechanism. + def CSR : CalleeSavedRegs<(add)> { + let OtherPreserved = (add (sequence "I%u", 0, 7), |