brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · 784ac3a Raw
187 lines · plain
1; RUN: opt -S -passes=deadargelim %s | FileCheck %s2 3; Case 0: the basic example: an entire aggregate use is returned, but it's4; actually only used in ways we can eliminate. We gain benefit from analysing5; 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 } %val16}17 18 19 20; Case 1: an opaque use of the aggregate exists (in this case dead). Otherwise21; 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 }, 125; 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_aggregate34 35use_1:36  ; This use can be classified as applying only to ret 1.37  %val0 = extractvalue { i32, i32 } %val, 138  call void @callee(i32 %val0)39  ret { i32, i32 } poison40 41use_aggregate:42  ; This use is assumed to apply to both 0 and 1.43  ret { i32, i32 } %val44}45 46; Case 2: an opaque use of the aggregate exists (in this case *live*). Other47; 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_aggregate59 60use_1:61  ; This use can be classified as applying only to ret 1.62  %val0 = extractvalue { i32, i32 } %val, 163  call void @callee(i32 %val0)64  ret { i32, i32 } poison65 66use_aggregate:67  ; This use is assumed to apply to both 0 and 1.68  ret { i32, i32 } %val69}70 71declare void @callee(i32)72 73; Case 3: the insertvalue meant %in was live if ret-slot-1 was, but we were only74; tracking multiple ret-slots for struct types. So %in was eliminated75; 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] poison, i32 %in, 181  ret [2 x i32] %ret82}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] %res87}88 89; Case 4: we can remove some retvals from the array. It's nice to produce an90; 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], 094; CHECK: [[RESTMP:%.*]] = insertvalue [2 x i32] poison, i32 [[VAL0]], 095; CHECK: [[VAL2:%.*]] = extractvalue [3 x i32] [i32 42, i32 43, i32 44], 296; CHECK: [[RES:%.*]] = insertvalue [2 x i32] [[RESTMP]], i32 [[VAL2]], 197; 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, 0109  call void @callee(i32 %res.0)110 111  %res.2 = extractvalue [3 x i32] %res, 2112  call void @callee(i32 %res.2)113 114  ret void115}116 117; Case 5: %in gets passed directly to the return. It should mark be marked as118; 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, 1122; CHECK: ret i32 [[RET]]123 124define internal {i32, i32} @ret_applies_to_all({i32, i32} %in) {125  ret {i32, i32} %in126}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, 1131  ret i32 %ret132}133 134; Case 6: When considering @mid, the return instruciton has sub-value 0135; unconditionally live, but 1 only conditionally live. Since at that level we're136; applying the results to the whole of %res, this means %res is live and cannot137; be reduced. There is scope for further optimisation here (though not visible138; in this test-case).139 140; CHECK-LABEL: define internal { ptr, i32 } @inner()141 142define internal {ptr, i32} @mid() {143  %res = call {ptr, i32} @inner()144  %intval = extractvalue {ptr, i32} %res, 1145  %tst = icmp eq i32 %intval, 42146  br i1 %tst, label %true, label %true147 148true:149  ret {ptr, i32} %res150}151 152define internal {ptr, i32} @inner() {153  ret {ptr, i32} {ptr null, i32 42}154}155 156define internal i8 @outer() {157  %res = call {ptr, i32} @mid()158  %resptr = extractvalue {ptr, i32} %res, 0159 160  %val = load i8, ptr %resptr161  ret i8 %val162}163 164define internal { i32 } @agg_ret() {165entry:166  unreachable167}168 169; CHECK-LABEL: define void @PR24906170; CHECK: %[[invoke:.*]] = invoke i32 @agg_ret()171; CHECK: %[[oldret:.*]] = insertvalue { i32 } poison, i32 %[[invoke]], 0172; CHECK: phi { i32 } [ %[[oldret]],173define void @PR24906() personality ptr poison {174entry:175  %tmp2 = invoke { i32 } @agg_ret()176          to label %bb3 unwind label %bb4177 178bb3:179  %tmp3 = phi { i32 } [ %tmp2, %entry ]180  unreachable181 182bb4:183  %tmp4 = landingpad { ptr, i32 }184          cleanup185  unreachable186}187