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