]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/patches/patch-r262261-llvm-r198145-sparc.diff
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / patches / patch-r262261-llvm-r198145-sparc.diff
1 Pull in r198145 from upstream llvm trunk (by Venkatraman Govindaraju):
2
3   [SparcV9]: Implement lowering of long double (fp128) arguments in Sparc64 ABI.
4   Also, pass fp128 arguments to varargs through integer registers if necessary.
5
6 Introduced here: http://svnweb.freebsd.org/changeset/base/262261
7
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:
13  }
14  
15  declare i32 @use_buf(i32, i8*)
16 +
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) {
26 +entry:
27 +  %0 = fadd fp128 %a, %b
28 +  ret fp128 %0
29 +}
30 +
31 +declare i64 @receive_fp128(i64 %a, ...)
32 +
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) {
40 +entry:
41 +  %0 = call i64 (i64, ...)* @receive_fp128(i64 %a, fp128 %b)
42 +  ret i64 %0
43 +}
44 +
45 +
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");
58  
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);
64    unsigned Reg = 0;
65  
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;
74  
75    // Promote to register when possible, otherwise use the stack slot.
76    if (Reg) {
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
83      // varargs functions.
84 -    if (!VA.isRegLoc() || VA.getLocVT() != MVT::f64)
85 +    if (!VA.isRegLoc() || (ValTy != MVT::f64 && ValTy != MVT::f128))
86        continue;
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
90      CCValAssign NewVA;
91  
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?");
98  
99      if (Offset < 6*8) {
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);
109 +      else {
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);
115 +      }
116      } else {
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);
121        break;
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);
129        break;
130      }
131  
132      if (VA.isRegLoc()) {
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,
141 +                                       HiPtrOff);
142 +        SDValue LoPtrOff = DAG.getIntPtrConstant(StackOffset + 8);
143 +        LoPtrOff         = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr,
144 +                                       LoPtrOff);
145 +
146 +        // Store to %sp+BIAS+128+Offset
147 +        SDValue Store = DAG.getStore(Chain, DL, Arg, HiPtrOff,
148 +                                     MachinePointerInfo(),
149 +                                     false, false, 0);
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()),
158 +                                            Hi64));
159 +        RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()+1),
160 +                                            Lo64));
161 +        continue;
162 +      }
163 +
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()) {