blob: 2eca76a4a4e30ae99d228c1b9225f1c2155bb8fa [file] [log] [blame]
Tim Northover854c9272015-02-09 01:20:53 +00001; RUN: opt -S -deadargelim %s | FileCheck %s
2
3; Case 0: the basic example: an entire aggregate use is returned, but it's
4; actually only used in ways we can eliminate. We gain benefit from analysing
5; the "use" and applying its results to all sub-values.
6
7; CHECK-LABEL: define internal void @agguse_dead()
8
9define internal { i32, i32 } @agguse_dead() {
10 ret { i32, i32 } { i32 0, i32 1 }
11}
12
13define internal { i32, i32 } @test_agguse_dead() {
14 %val = call { i32, i32 } @agguse_dead()
15 ret { i32, i32 } %val
16}
17
18
19
20; Case 1: an opaque use of the aggregate exists (in this case dead). Otherwise
21; only one value is used, so function can be simplified.
22
23; CHECK-LABEL: define internal i32 @rets_independent_if_agguse_dead()
24; CHECK: [[RET:%.*]] = extractvalue { i32, i32 } { i32 0, i32 1 }, 1
25; CHECK: ret i32 [[RET]]
26
27define internal { i32, i32 } @rets_independent_if_agguse_dead() {
28 ret { i32, i32 } { i32 0, i32 1 }
29}
30
31define internal { i32, i32 } @test_rets_independent_if_agguse_dead(i1 %tst) {
32 %val = call { i32, i32 } @rets_independent_if_agguse_dead()
33 br i1 %tst, label %use_1, label %use_aggregate
34
35use_1:
36 ; This use can be classified as applying only to ret 1.
37 %val0 = extractvalue { i32, i32 } %val, 1
38 call void @callee(i32 %val0)
39 ret { i32, i32 } undef
40
41use_aggregate:
42 ; This use is assumed to apply to both 0 and 1.
43 ret { i32, i32 } %val
44}
45
46; Case 2: an opaque use of the aggregate exists (in this case *live*). Other
47; uses shouldn't matter.
48
49; CHECK-LABEL: define internal { i32, i32 } @rets_live_agguse()
50; CHECK: ret { i32, i32 } { i32 0, i32 1 }
51
52define internal { i32, i32 } @rets_live_agguse() {
53 ret { i32, i32} { i32 0, i32 1 }
54}
55
56define { i32, i32 } @test_rets_live_aggues(i1 %tst) {
57 %val = call { i32, i32 } @rets_live_agguse()
58 br i1 %tst, label %use_1, label %use_aggregate
59
60use_1:
61 ; This use can be classified as applying only to ret 1.
62 %val0 = extractvalue { i32, i32 } %val, 1
63 call void @callee(i32 %val0)
64 ret { i32, i32 } undef
65
66use_aggregate:
67 ; This use is assumed to apply to both 0 and 1.
68 ret { i32, i32 } %val
69}
70
Tim Northover705d2af2015-02-09 01:21:00 +000071declare void @callee(i32)
72
73; Case 3: the insertvalue meant %in was live if ret-slot-1 was, but we were only
74; tracking multiple ret-slots for struct types. So %in was eliminated
75; incorrectly.
76
77; CHECK-LABEL: define internal [2 x i32] @array_rets_have_multiple_slots(i32 %in)
78
79define internal [2 x i32] @array_rets_have_multiple_slots(i32 %in) {
80 %ret = insertvalue [2 x i32] undef, i32 %in, 1
81 ret [2 x i32] %ret
82}
83
84define [2 x i32] @test_array_rets_have_multiple_slots() {
85 %res = call [2 x i32] @array_rets_have_multiple_slots(i32 42)
86 ret [2 x i32] %res
87}
88
89; Case 4: we can remove some retvals from the array. It's nice to produce an
90; array again having done so (rather than converting it to a struct).
91
92; CHECK-LABEL: define internal [2 x i32] @can_shrink_arrays()
93; CHECK: [[VAL0:%.*]] = extractvalue [3 x i32] [i32 42, i32 43, i32 44], 0
94; CHECK: [[RESTMP:%.*]] = insertvalue [2 x i32] undef, i32 [[VAL0]], 0
95; CHECK: [[VAL2:%.*]] = extractvalue [3 x i32] [i32 42, i32 43, i32 44], 2
96; CHECK: [[RES:%.*]] = insertvalue [2 x i32] [[RESTMP]], i32 [[VAL2]], 1
97; CHECK: ret [2 x i32] [[RES]]
98
99; CHECK-LABEL: define void @test_can_shrink_arrays()
100
101define internal [3 x i32] @can_shrink_arrays() {
102 ret [3 x i32] [i32 42, i32 43, i32 44]
103}
104
105define void @test_can_shrink_arrays() {
106 %res = call [3 x i32] @can_shrink_arrays()
107
108 %res.0 = extractvalue [3 x i32] %res, 0
109 call void @callee(i32 %res.0)
110
111 %res.2 = extractvalue [3 x i32] %res, 2
112 call void @callee(i32 %res.2)
113
114 ret void
115}
Tim Northover43c0d2d2015-02-10 19:49:18 +0000116
117; Case 5: %in gets passed directly to the return. It should mark be marked as
118; used if *any* of the return values are, not just if value 0 is.
119
120; CHECK-LABEL: define internal i32 @ret_applies_to_all({ i32, i32 } %in)
121; CHECK: [[RET:%.*]] = extractvalue { i32, i32 } %in, 1
122; CHECK: ret i32 [[RET]]
123
124define internal {i32, i32} @ret_applies_to_all({i32, i32} %in) {
125 ret {i32, i32} %in
126}
127
128define i32 @test_ret_applies_to_all() {
129 %val = call {i32, i32} @ret_applies_to_all({i32, i32} {i32 42, i32 43})
130 %ret = extractvalue {i32, i32} %val, 1
131 ret i32 %ret
132}
Tim Northover02438032015-02-11 23:13:11 +0000133
134; Case 6: When considering @mid, the return instruciton has sub-value 0
135; unconditionally live, but 1 only conditionally live. Since at that level we're
136; applying the results to the whole of %res, this means %res is live and cannot
137; be reduced. There is scope for further optimisation here (though not visible
138; in this test-case).
139
140; CHECK-LABEL: define internal { i8*, i32 } @inner()
141
142define internal {i8*, i32} @mid() {
143 %res = call {i8*, i32} @inner()
144 %intval = extractvalue {i8*, i32} %res, 1
145 %tst = icmp eq i32 %intval, 42
146 br i1 %tst, label %true, label %true
147
148true:
149 ret {i8*, i32} %res
150}
151
152define internal {i8*, i32} @inner() {
153 ret {i8*, i32} {i8* null, i32 42}
154}
155
156define internal i8 @outer() {
157 %res = call {i8*, i32} @mid()
158 %resptr = extractvalue {i8*, i32} %res, 0
159
David Blaikiea79ac142015-02-27 21:17:42 +0000160 %val = load i8, i8* %resptr
Tim Northover02438032015-02-11 23:13:11 +0000161 ret i8 %val
David Majnemerfa36bde2015-09-23 15:41:09 +0000162}
163
164define internal { i32 } @agg_ret() {
165entry:
166 unreachable
167}
168
169; CHECK-LABEL: define void @PR24906
170; CHECK: %[[invoke:.*]] = invoke i32 @agg_ret()
171; CHECK: %[[oldret:.*]] = insertvalue { i32 } undef, i32 %[[invoke]], 0
172; CHECK: phi { i32 } [ %[[oldret]],
173define void @PR24906() personality i32 (i32)* undef {
174entry:
175 %tmp2 = invoke { i32 } @agg_ret()
176 to label %bb3 unwind label %bb4
177
178bb3:
179 %tmp3 = phi { i32 } [ %tmp2, %entry ]
180 unreachable
181
182bb4:
183 %tmp4 = landingpad { i8*, i32 }
184 cleanup
185 unreachable
186}