1 ; 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 9 define internal { i32, i32 } @agguse_dead() { 10 ret { i32, i32 } { i32 0, i32 1 } 11 } 12 13 define 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 27 define internal { i32, i32 } @rets_independent_if_agguse_dead() { 28 ret { i32, i32 } { i32 0, i32 1 } 29 } 30 31 define 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 35 use_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 41 use_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 52 define internal { i32, i32 } @rets_live_agguse() { 53 ret { i32, i32} { i32 0, i32 1 } 54 } 55 56 define { 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 60 use_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 66 use_aggregate: 67 ; This use is assumed to apply to both 0 and 1. 68 ret { i32, i32 } %val 69 } 70 71 declare 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 79 define 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 84 define [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 101 define internal [3 x i32] @can_shrink_arrays() { 102 ret [3 x i32] [i32 42, i32 43, i32 44] 103 } 104 105 define 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 } 116 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 124 define internal {i32, i32} @ret_applies_to_all({i32, i32} %in) { 125 ret {i32, i32} %in 126 } 127 128 define 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 } 133 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 142 define 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 148 true: 149 ret {i8*, i32} %res 150 } 151 152 define internal {i8*, i32} @inner() { 153 ret {i8*, i32} {i8* null, i32 42} 154 } 155 156 define internal i8 @outer() { 157 %res = call {i8*, i32} @mid() 158 %resptr = extractvalue {i8*, i32} %res, 0 159 160 %val = load i8, i8* %resptr 161 ret i8 %val 162 } 163 164 define internal { i32 } @agg_ret() { 165 entry: 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]], 173 define void @PR24906() personality i32 (i32)* undef { 174 entry: 175 %tmp2 = invoke { i32 } @agg_ret() 176 to label %bb3 unwind label %bb4 177 178 bb3: 179 %tmp3 = phi { i32 } [ %tmp2, %entry ] 180 unreachable 181 182 bb4: 183 %tmp4 = landingpad { i8*, i32 } 184 cleanup 185 unreachable 186 } 187