1 Pull in r198145 from upstream llvm trunk (by Venkatraman Govindaraju):
3 [SparcV9]: Implement lowering of long double (fp128) arguments in Sparc64 ABI.
4 Also, pass fp128 arguments to varargs through integer registers if necessary.
6 Introduced here: http://svn.freebsd.org/changeset/base/262261
8 Index: test/CodeGen/SPARC/64abi.ll
9 ===================================================================
10 --- test/CodeGen/SPARC/64abi.ll
11 +++ test/CodeGen/SPARC/64abi.ll
12 @@ -411,3 +411,33 @@ entry:
15 declare i32 @use_buf(i32, i8*)
17 +; CHECK-LABEL: test_fp128_args
18 +; CHECK-DAG: std %f0, [%fp+{{.+}}]
19 +; CHECK-DAG: std %f2, [%fp+{{.+}}]
20 +; CHECK-DAG: std %f6, [%fp+{{.+}}]
21 +; CHECK-DAG: std %f4, [%fp+{{.+}}]
22 +; CHECK: add %fp, [[Offset:[0-9]+]], %o0
23 +; CHECK: call _Qp_add
24 +; CHECK: ldd [%fp+[[Offset]]], %f0
25 +define fp128 @test_fp128_args(fp128 %a, fp128 %b) {
27 + %0 = fadd fp128 %a, %b
31 +declare i64 @receive_fp128(i64 %a, ...)
33 +; CHECK-LABEL: test_fp128_variable_args
34 +; CHECK-DAG: std %f4, [%sp+[[Offset0:[0-9]+]]]
35 +; CHECK-DAG: std %f6, [%sp+[[Offset1:[0-9]+]]]
36 +; CHECK-DAG: ldx [%sp+[[Offset0]]], %o2
37 +; CHECK-DAG: ldx [%sp+[[Offset1]]], %o3
38 +; CHECK: call receive_fp128
39 +define i64 @test_fp128_variable_args(i64 %a, fp128 %b) {
41 + %0 = call i64 (i64, ...)* @receive_fp128(i64 %a, fp128 %b)
46 Index: lib/Target/Sparc/SparcISelLowering.cpp
47 ===================================================================
48 --- lib/Target/Sparc/SparcISelLowering.cpp
49 +++ lib/Target/Sparc/SparcISelLowering.cpp
50 @@ -80,11 +80,14 @@ static bool CC_Sparc_Assign_f64(unsigned &ValNo, M
51 static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT,
52 MVT &LocVT, CCValAssign::LocInfo &LocInfo,
53 ISD::ArgFlagsTy &ArgFlags, CCState &State) {
54 - assert((LocVT == MVT::f32 || LocVT.getSizeInBits() == 64) &&
55 + assert((LocVT == MVT::f32 || LocVT == MVT::f128
56 + || LocVT.getSizeInBits() == 64) &&
57 "Can't handle non-64 bits locations");
59 // Stack space is allocated for all arguments starting from [%fp+BIAS+128].
60 - unsigned Offset = State.AllocateStack(8, 8);
61 + unsigned size = (LocVT == MVT::f128) ? 16 : 8;
62 + unsigned alignment = (LocVT == MVT::f128) ? 16 : 8;
63 + unsigned Offset = State.AllocateStack(size, alignment);
66 if (LocVT == MVT::i64 && Offset < 6*8)
67 @@ -96,6 +99,9 @@ static bool CC_Sparc64_Full(unsigned &ValNo, MVT &
68 else if (LocVT == MVT::f32 && Offset < 16*8)
69 // Promote floats to %f1, %f3, ...
70 Reg = SP::F1 + Offset/4;
71 + else if (LocVT == MVT::f128 && Offset < 16*8)
72 + // Promote long doubles to %q0-%q28. (Which LLVM calls Q0-Q7).
73 + Reg = SP::Q0 + Offset/16;
75 // Promote to register when possible, otherwise use the stack slot.
77 @@ -998,9 +1004,10 @@ static void fixupVariableFloatArgs(SmallVectorImpl
78 ArrayRef<ISD::OutputArg> Outs) {
79 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
80 const CCValAssign &VA = ArgLocs[i];
81 + MVT ValTy = VA.getLocVT();
82 // FIXME: What about f32 arguments? C promotes them to f64 when calling
84 - if (!VA.isRegLoc() || VA.getLocVT() != MVT::f64)
85 + if (!VA.isRegLoc() || (ValTy != MVT::f64 && ValTy != MVT::f128))
87 // The fixed arguments to a varargs function still go in FP registers.
88 if (Outs[VA.getValNo()].IsFixed)
89 @@ -1010,15 +1017,25 @@ static void fixupVariableFloatArgs(SmallVectorImpl
92 // Determine the offset into the argument array.
93 - unsigned Offset = 8 * (VA.getLocReg() - SP::D0);
94 + unsigned firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0;
95 + unsigned argSize = (ValTy == MVT::f64) ? 8 : 16;
96 + unsigned Offset = argSize * (VA.getLocReg() - firstReg);
97 assert(Offset < 16*8 && "Offset out of range, bad register enum?");
100 // This argument should go in %i0-%i5.
101 unsigned IReg = SP::I0 + Offset/8;
102 - // Full register, just bitconvert into i64.
103 - NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(),
104 - IReg, MVT::i64, CCValAssign::BCvt);
105 + if (ValTy == MVT::f64)
106 + // Full register, just bitconvert into i64.
107 + NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(),
108 + IReg, MVT::i64, CCValAssign::BCvt);
110 + assert(ValTy == MVT::f128 && "Unexpected type!");
111 + // Full register, just bitconvert into i128 -- We will lower this into
112 + // two i64s in LowerCall_64.
113 + NewVA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(),
114 + IReg, MVT::i128, CCValAssign::BCvt);
117 // This needs to go to memory, we're out of integer registers.
118 NewVA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(),
119 @@ -1094,11 +1111,46 @@ SparcTargetLowering::LowerCall_64(TargetLowering::
120 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
122 case CCValAssign::BCvt:
123 - Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
124 + // fixupVariableFloatArgs() may create bitcasts from f128 to i128. But
125 + // SPARC does not support i128 natively. Lower it into two i64, see below.
126 + if (!VA.needsCustom() || VA.getValVT() != MVT::f128
127 + || VA.getLocVT() != MVT::i128)
128 + Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
133 + if (VA.needsCustom() && VA.getValVT() == MVT::f128
134 + && VA.getLocVT() == MVT::i128) {
135 + // Store and reload into the interger register reg and reg+1.
136 + unsigned Offset = 8 * (VA.getLocReg() - SP::I0);
137 + unsigned StackOffset = Offset + Subtarget->getStackPointerBias() + 128;
138 + SDValue StackPtr = DAG.getRegister(SP::O6, getPointerTy());
139 + SDValue HiPtrOff = DAG.getIntPtrConstant(StackOffset);
140 + HiPtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr,
142 + SDValue LoPtrOff = DAG.getIntPtrConstant(StackOffset + 8);
143 + LoPtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr,
146 + // Store to %sp+BIAS+128+Offset
147 + SDValue Store = DAG.getStore(Chain, DL, Arg, HiPtrOff,
148 + MachinePointerInfo(),
150 + // Load into Reg and Reg+1
151 + SDValue Hi64 = DAG.getLoad(MVT::i64, DL, Store, HiPtrOff,
152 + MachinePointerInfo(),
153 + false, false, false, 0);
154 + SDValue Lo64 = DAG.getLoad(MVT::i64, DL, Store, LoPtrOff,
155 + MachinePointerInfo(),
156 + false, false, false, 0);
157 + RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()),
159 + RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()+1),
164 // The custom bit on an i32 return value indicates that it should be
165 // passed in the high bits of the register.
166 if (VA.getValVT() == MVT::i32 && VA.needsCustom()) {