Home | History | Annotate | Download | only in DeadArgElim
      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