llvm.org GIT mirror llvm / f072171
Merging r244889: ------------------------------------------------------------------------ r244889 | uweigand | 2015-08-13 06:37:06 -0700 (Thu, 13 Aug 2015) | 22 lines [SystemZ] Support large LLVM IR struct return values Recent mesa/llvmpipe crashes on SystemZ due to a failed assertion when attempting to compile a routine with a return type of { <4 x float>, <4 x float>, <4 x float>, <4 x float> } on a system without vector instruction support. This is because after legalizing the vector type, we get a return value consisting of 16 floats, which cannot all be returned in registers. Usually, what should happen in this case is that the target's CanLowerReturn routine rejects the return type, in which case SelectionDAG falls back to implementing a structure return in memory via implicit reference. However, the SystemZ target never actually implemented any CanLowerReturn routine, and thus would accept any struct return type. This patch fixes the crash by implementing CanLowerReturn. As a side effect, this also handles fp128 return values, fixing a todo that was noted in SystemZCallingConv.td. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_37@244909 91177308-0d34-0410-b5e6-96231b3b80d8 Hans Wennborg 4 years ago
8 changed file(s) with 279 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
5252 CCIfSubtarget<"hasVector()",
5353 CCIfType<[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64],
5454 CCAssignToReg<[V24, V26, V28, V30, V25, V27, V29, V31]>>>
55
56 // ABI-compliant code returns long double by reference, but that conversion
57 // is left to higher-level code. Perhaps we could add an f128 definition
58 // here for code that doesn't care about the ABI?
5955 ]>;
6056
6157 //===----------------------------------------------------------------------===//
11721172 }
11731173
11741174 return Chain;
1175 }
1176
1177 bool SystemZTargetLowering::
1178 CanLowerReturn(CallingConv::ID CallConv,
1179 MachineFunction &MF, bool isVarArg,
1180 const SmallVectorImpl &Outs,
1181 LLVMContext &Context) const {
1182 // Detect unsupported vector return types.
1183 if (Subtarget.hasVector())
1184 VerifyVectorTypes(Outs);
1185
1186 SmallVector RetLocs;
1187 CCState RetCCInfo(CallConv, isVarArg, MF, RetLocs, Context);
1188 return RetCCInfo.CheckReturn(Outs, RetCC_SystemZ);
11751189 }
11761190
11771191 SDValue
422422 SDValue LowerCall(CallLoweringInfo &CLI,
423423 SmallVectorImpl &InVals) const override;
424424
425 bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
426 bool isVarArg,
427 const SmallVectorImpl &Outs,
428 LLVMContext &Context) const override;
425429 SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
426430 const SmallVectorImpl &Outs,
427431 const SmallVectorImpl &OutVals,
123123 store fp128 %y, fp128 *%r2
124124 ret void
125125 }
126
127 ; Explicit fp128 return values are likewise passed indirectly.
128 define fp128 @f14(fp128 %r3) {
129 ; CHECK-LABEL: f14:
130 ; CHECK: ld %f0, 0(%r3)
131 ; CHECK: ld %f2, 8(%r3)
132 ; CHECK: axbr %f0, %f0
133 ; CHECK: std %f0, 0(%r2)
134 ; CHECK: std %f2, 8(%r2)
135 ; CHECK: br %r14
136 %y = fadd fp128 %r3, %r3
137 ret fp128 %y
138 }
139
0 ; Test multiple return values (LLVM ABI extension)
1 ;
2 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
3
4 ; Up to four integer return values fit into GPRs.
5 define { i64, i64, i64, i64 } @f1() {
6 ; CHECK-LABEL: f1:
7 ; CHECK: lghi %r2, 0
8 ; CHECK: lghi %r3, 1
9 ; CHECK: lghi %r4, 2
10 ; CHECK: lghi %r5, 3
11 ; CHECK: br %r14
12 ret { i64, i64, i64, i64 } { i64 0, i64 1, i64 2, i64 3 }
13 }
14
15 ; More than four integer return values use sret.
16 define { i64, i64, i64, i64, i64 } @f2() {
17 ; CHECK-LABEL: f2:
18 ; CHECK: mvghi 32(%r2), 4
19 ; CHECK: mvghi 24(%r2), 3
20 ; CHECK: mvghi 16(%r2), 2
21 ; CHECK: mvghi 8(%r2), 1
22 ; CHECK: mvghi 0(%r2), 0
23 ; CHECK: br %r14
24 ret { i64, i64, i64, i64, i64 } { i64 0, i64 1, i64 2, i64 3, i64 4 }
25 }
26
27 ; Up to four floating-point return values fit into FPRs.
28 define { double, double, double, double } @f3() {
29 ; CHECK-LABEL: f3:
30 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
31 ; CHECK: ldeb %f0, 0([[TMP]])
32 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
33 ; CHECK: ldeb %f2, 0([[TMP]])
34 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
35 ; CHECK: ldeb %f4, 0([[TMP]])
36 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
37 ; CHECK: ldeb %f6, 0([[TMP]])
38 ; CHECK: br %r14
39 ret { double, double, double, double }
40 { double 1.0, double 2.0, double 3.0, double 4.0 }
41 }
42
43 ; More than four floating-point return values use sret.
44 define { double, double, double, double, double } @f4() {
45 ; CHECK-LABEL: f4:
46 ; CHECK: llihh [[TMP:%r[0-5]]], 16404
47 ; CHECK: stg [[TMP]], 32(%r2)
48 ; CHECK: llihh [[TMP:%r[0-5]]], 16400
49 ; CHECK: stg [[TMP]], 24(%r2)
50 ; CHECK: llihh [[TMP:%r[0-5]]], 16392
51 ; CHECK: stg [[TMP]], 16(%r2)
52 ; CHECK: llihh [[TMP:%r[0-5]]], 16384
53 ; CHECK: stg [[TMP]], 8(%r2)
54 ; CHECK: llihh [[TMP:%r[0-5]]], 16368
55 ; CHECK: stg [[TMP]], 0(%r2)
56 ; CHECK: br %r14
57 ret { double, double, double, double, double }
58 { double 1.0, double 2.0, double 3.0, double 4.0, double 5.0 }
59 }
0 ; Test calling functions with multiple return values (LLVM ABI extension)
1 ;
2 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
3
4 ; Up to four integer return values fit into GPRs.
5 declare { i64, i64, i64, i64 } @bar1()
6
7 define i64 @f1() {
8 ; CHECK-LABEL: f1:
9 ; CHECK: brasl %r14, bar1
10 ; CHECK: lgr %r2, %r5
11 ; CHECK: br %r14
12 %mret = call { i64, i64, i64, i64 } @bar1()
13 %ret = extractvalue { i64, i64, i64, i64 } %mret, 3
14 ret i64 %ret
15 }
16
17 ; More than four integer return values use sret.
18 declare { i64, i64, i64, i64, i64 } @bar2()
19
20 define i64 @f2() {
21 ; CHECK-LABEL: f2:
22 ; CHECK: la %r2, 160(%r15)
23 ; CHECK: brasl %r14, bar2
24 ; CHECK: lg %r2, 192(%r15)
25 ; CHECK: br %r14
26 %mret = call { i64, i64, i64, i64, i64 } @bar2()
27 %ret = extractvalue { i64, i64, i64, i64, i64 } %mret, 4
28 ret i64 %ret
29 }
30
31 ; Up to four floating-point return values fit into GPRs.
32 declare { double, double, double, double } @bar3()
33
34 define double @f3() {
35 ; CHECK-LABEL: f3:
36 ; CHECK: brasl %r14, bar3
37 ; CHECK: ldr %f0, %f6
38 ; CHECK: br %r14
39 %mret = call { double, double, double, double } @bar3()
40 %ret = extractvalue { double, double, double, double } %mret, 3
41 ret double %ret
42 }
43
44 ; More than four integer return values use sret.
45 declare { double, double, double, double, double } @bar4()
46
47 define double @f4() {
48 ; CHECK-LABEL: f4:
49 ; CHECK: la %r2, 160(%r15)
50 ; CHECK: brasl %r14, bar4
51 ; CHECK: ld %f0, 192(%r15)
52 ; CHECK: br %r14
53 %mret = call { double, double, double, double, double } @bar4()
54 %ret = extractvalue { double, double, double, double, double } %mret, 4
55 ret double %ret
56 }
0 ; Test multiple return values (LLVM ABI extension)
1 ;
2 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s
3
4 ; Up to eight vector return values fit into VRs.
5 define { <2 x double>, <2 x double>, <2 x double>, <2 x double>,
6 <2 x double>, <2 x double>, <2 x double>, <2 x double> } @f1() {
7 ; CHECK-LABEL: f1:
8 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
9 ; CHECK: vl %v24, 0([[TMP]])
10 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
11 ; CHECK: vl %v26, 0([[TMP]])
12 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
13 ; CHECK: vl %v28, 0([[TMP]])
14 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
15 ; CHECK: vl %v30, 0([[TMP]])
16 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
17 ; CHECK: vl %v25, 0([[TMP]])
18 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
19 ; CHECK: vl %v27, 0([[TMP]])
20 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
21 ; CHECK: vl %v29, 0([[TMP]])
22 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
23 ; CHECK: vl %v31, 0([[TMP]])
24 ; CHECK: br %r14
25 ret { <2 x double>, <2 x double>, <2 x double>, <2 x double>,
26 <2 x double>, <2 x double>, <2 x double>, <2 x double> }
27 { <2 x double> ,
28 <2 x double> ,
29 <2 x double> ,
30 <2 x double> ,
31 <2 x double> ,
32 <2 x double> ,
33 <2 x double> ,
34 <2 x double> }
35 }
36
37 ; More than eight vector return values use sret.
38 define { <2 x double>, <2 x double>, <2 x double>, <2 x double>,
39 <2 x double>, <2 x double>, <2 x double>, <2 x double>,
40 <2 x double> } @f2() {
41 ; CHECK-LABEL: f2:
42 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
43 ; CHECK: vl [[VTMP:%v[0-9]+]], 0([[TMP]])
44 ; CHECK: vst [[VTMP]], 128(%r2)
45 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
46 ; CHECK: vl [[VTMP:%v[0-9]+]], 0([[TMP]])
47 ; CHECK: vst [[VTMP]], 112(%r2)
48 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
49 ; CHECK: vl [[VTMP:%v[0-9]+]], 0([[TMP]])
50 ; CHECK: vst [[VTMP]], 96(%r2)
51 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
52 ; CHECK: vl [[VTMP:%v[0-9]+]], 0([[TMP]])
53 ; CHECK: vst [[VTMP]], 80(%r2)
54 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
55 ; CHECK: vl [[VTMP:%v[0-9]+]], 0([[TMP]])
56 ; CHECK: vst [[VTMP]], 64(%r2)
57 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
58 ; CHECK: vl [[VTMP:%v[0-9]+]], 0([[TMP]])
59 ; CHECK: vst [[VTMP]], 48(%r2)
60 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
61 ; CHECK: vl [[VTMP:%v[0-9]+]], 0([[TMP]])
62 ; CHECK: vst [[VTMP]], 32(%r2)
63 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
64 ; CHECK: vl [[VTMP:%v[0-9]+]], 0([[TMP]])
65 ; CHECK: vst [[VTMP]], 16(%r2)
66 ; CHECK: larl [[TMP:%r[0-5]]], .LCPI
67 ; CHECK: vl [[VTMP:%v[0-9]+]], 0([[TMP]])
68 ; CHECK: vst [[VTMP]], 0(%r2)
69 ; CHECK: br %r14
70 ret { <2 x double>, <2 x double>, <2 x double>, <2 x double>,
71 <2 x double>, <2 x double>, <2 x double>, <2 x double>,
72 <2 x double> }
73 { <2 x double> ,
74 <2 x double> ,
75 <2 x double> ,
76 <2 x double> ,
77 <2 x double> ,
78 <2 x double> ,
79 <2 x double> ,
80 <2 x double> ,
81 <2 x double> }
82 }
0 ; Test calling functions with multiple return values (LLVM ABI extension)
1 ;
2 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s
3
4 ; Up to eight vector return values fit into VRs.
5 declare { <2 x double>, <2 x double>, <2 x double>, <2 x double>,
6 <2 x double>, <2 x double>, <2 x double>, <2 x double> } @bar1()
7
8 define <2 x double> @f1() {
9 ; CHECK-LABEL: f1:
10 ; CHECK: brasl %r14, bar1
11 ; CHECK: vlr %v24, %v31
12 ; CHECK: br %r14
13 %mret = call { <2 x double>, <2 x double>,
14 <2 x double>, <2 x double>,
15 <2 x double>, <2 x double>,
16 <2 x double>, <2 x double> } @bar1()
17 %ret = extractvalue { <2 x double>, <2 x double>,
18 <2 x double>, <2 x double>,
19 <2 x double>, <2 x double>,
20 <2 x double>, <2 x double> } %mret, 7
21 ret <2 x double> %ret
22 }
23
24 ; More than eight vector return values use sret.
25 declare { <2 x double>, <2 x double>, <2 x double>, <2 x double>,
26 <2 x double>, <2 x double>, <2 x double>, <2 x double>,
27 <2 x double> } @bar2()
28
29 define <2 x double> @f2() {
30 ; CHECK-LABEL: f2:
31 ; CHECK: la %r2, 160(%r15)
32 ; CHECK: brasl %r14, bar2
33 ; CHECK: vl %v24, 288(%r15)
34 ; CHECK: br %r14
35 %mret = call { <2 x double>, <2 x double>,
36 <2 x double>, <2 x double>,
37 <2 x double>, <2 x double>,
38 <2 x double>, <2 x double>,
39 <2 x double> } @bar2()
40 %ret = extractvalue { <2 x double>, <2 x double>,
41 <2 x double>, <2 x double>,
42 <2 x double>, <2 x double>,
43 <2 x double>, <2 x double>,
44 <2 x double> } %mret, 8
45 ret <2 x double> %ret
46 }