OLD | NEW |
(Empty) | |
| 1 ; This tests the optimization where producers and consumers of i1 (bool) |
| 2 ; variables are combined to implicitly use flags instead of explicitly using |
| 3 ; stack or register variables. |
| 4 |
| 5 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 | FileCheck %s |
| 6 |
| 7 declare void @use_value(i32) |
| 8 |
| 9 ; Basic cmp/branch folding. |
| 10 define i32 @fold_cmp_br(i32 %arg1, i32 %arg2) { |
| 11 entry: |
| 12 %cmp1 = icmp slt i32 %arg1, %arg2 |
| 13 br i1 %cmp1, label %branch1, label %branch2 |
| 14 branch1: |
| 15 ret i32 1 |
| 16 branch2: |
| 17 ret i32 2 |
| 18 } |
| 19 |
| 20 ; CHECK-LABEL: fold_cmp_br |
| 21 ; CHECK: cmp |
| 22 ; CHECK: jge |
| 23 |
| 24 |
| 25 ; Cmp/branch folding with intervening instructions. |
| 26 define i32 @fold_cmp_br_intervening_insts(i32 %arg1, i32 %arg2) { |
| 27 entry: |
| 28 %cmp1 = icmp slt i32 %arg1, %arg2 |
| 29 call void @use_value(i32 %arg1) |
| 30 br i1 %cmp1, label %branch1, label %branch2 |
| 31 branch1: |
| 32 ret i32 1 |
| 33 branch2: |
| 34 ret i32 2 |
| 35 } |
| 36 |
| 37 ; CHECK-LABEL: fold_cmp_br_intervening_insts |
| 38 ; CHECK-NOT: cmp |
| 39 ; CHECK: call |
| 40 ; CHECK: cmp |
| 41 ; CHECK: jge |
| 42 |
| 43 |
| 44 ; Cmp/branch non-folding because of live-out. |
| 45 define i32 @no_fold_cmp_br_liveout(i32 %arg1, i32 %arg2) { |
| 46 entry: |
| 47 %cmp1 = icmp slt i32 %arg1, %arg2 |
| 48 br label %next |
| 49 next: |
| 50 br i1 %cmp1, label %branch1, label %branch2 |
| 51 branch1: |
| 52 ret i32 1 |
| 53 branch2: |
| 54 ret i32 2 |
| 55 } |
| 56 |
| 57 ; CHECK-LABEL: no_fold_cmp_br_liveout |
| 58 ; CHECK: cmp |
| 59 ; CHECK: set |
| 60 ; CHECK: cmp |
| 61 ; CHECK: je |
| 62 |
| 63 |
| 64 ; Cmp/branch non-folding because of extra non-whitelisted uses. |
| 65 define i32 @no_fold_cmp_br_non_whitelist(i32 %arg1, i32 %arg2) { |
| 66 entry: |
| 67 %cmp1 = icmp slt i32 %arg1, %arg2 |
| 68 %result = zext i1 %cmp1 to i32 |
| 69 br i1 %cmp1, label %branch1, label %branch2 |
| 70 branch1: |
| 71 ret i32 %result |
| 72 branch2: |
| 73 ret i32 2 |
| 74 } |
| 75 |
| 76 ; CHECK-LABEL: no_fold_cmp_br_non_whitelist |
| 77 ; CHECK: cmp |
| 78 ; CHECK: set |
| 79 ; CHECK: movzx |
| 80 ; CHECK: cmp |
| 81 ; CHECK: je |
| 82 |
| 83 |
| 84 ; Basic cmp/select folding. |
| 85 define i32 @fold_cmp_select(i32 %arg1, i32 %arg2) { |
| 86 entry: |
| 87 %cmp1 = icmp slt i32 %arg1, %arg2 |
| 88 %result = select i1 %cmp1, i32 %arg1, i32 %arg2 |
| 89 ret i32 %result |
| 90 } |
| 91 |
| 92 ; CHECK-LABEL: fold_cmp_select |
| 93 ; CHECK: cmp |
| 94 ; CHECK: jl |
| 95 ; CHECK: mov |
| 96 |
| 97 |
| 98 ; 64-bit cmp/select folding. |
| 99 define i64 @fold_cmp_select_64(i64 %arg1, i64 %arg2) { |
| 100 entry: |
| 101 %arg1_trunc = trunc i64 %arg1 to i32 |
| 102 %arg2_trunc = trunc i64 %arg2 to i32 |
| 103 %cmp1 = icmp slt i32 %arg1_trunc, %arg2_trunc |
| 104 %result = select i1 %cmp1, i64 %arg1, i64 %arg2 |
| 105 ret i64 %result |
| 106 } |
| 107 |
| 108 ; CHECK-LABEL: fold_cmp_select_64 |
| 109 ; CHECK: cmp |
| 110 ; CHECK: jl |
| 111 ; CHECK: mov |
| 112 ; CHECK: mov |
| 113 |
| 114 |
| 115 ; Cmp/select folding with intervening instructions. |
| 116 define i32 @fold_cmp_select_intervening_insts(i32 %arg1, i32 %arg2) { |
| 117 entry: |
| 118 %cmp1 = icmp slt i32 %arg1, %arg2 |
| 119 call void @use_value(i32 %arg1) |
| 120 %result = select i1 %cmp1, i32 %arg1, i32 %arg2 |
| 121 ret i32 %result |
| 122 } |
| 123 |
| 124 ; CHECK-LABEL: fold_cmp_select_intervening_insts |
| 125 ; CHECK-NOT: cmp |
| 126 ; CHECK: call |
| 127 ; CHECK: cmp |
| 128 ; CHECK: jl |
| 129 ; CHECK: mov |
| 130 |
| 131 |
| 132 ; Cmp/multi-select folding. |
| 133 define i32 @fold_cmp_select_multi(i32 %arg1, i32 %arg2) { |
| 134 entry: |
| 135 %cmp1 = icmp slt i32 %arg1, %arg2 |
| 136 %a = select i1 %cmp1, i32 %arg1, i32 %arg2 |
| 137 %b = select i1 %cmp1, i32 %arg2, i32 %arg1 |
| 138 %c = select i1 %cmp1, i32 123, i32 %arg1 |
| 139 %partial = add i32 %a, %b |
| 140 %result = add i32 %partial, %c |
| 141 ret i32 %result |
| 142 } |
| 143 |
| 144 ; CHECK-LABEL: fold_cmp_select_multi |
| 145 ; CHECK: cmp |
| 146 ; CHECK: jl |
| 147 ; CHECK: cmp |
| 148 ; CHECK: jl |
| 149 ; CHECK: cmp |
| 150 ; CHECK: jl |
| 151 ; CHECK: add |
| 152 ; CHECK: add |
| 153 |
| 154 |
| 155 ; Cmp/multi-select non-folding because of live-out. |
| 156 define i32 @no_fold_cmp_select_multi_liveout(i32 %arg1, i32 %arg2) { |
| 157 entry: |
| 158 %cmp1 = icmp slt i32 %arg1, %arg2 |
| 159 %a = select i1 %cmp1, i32 %arg1, i32 %arg2 |
| 160 %b = select i1 %cmp1, i32 %arg2, i32 %arg1 |
| 161 br label %next |
| 162 next: |
| 163 %c = select i1 %cmp1, i32 123, i32 %arg1 |
| 164 %partial = add i32 %a, %b |
| 165 %result = add i32 %partial, %c |
| 166 ret i32 %result |
| 167 } |
| 168 |
| 169 ; CHECK-LABEL: no_fold_cmp_select_multi_liveout |
| 170 ; CHECK: set |
| 171 ; CHECK: cmp |
| 172 ; CHECK: jne |
| 173 ; CHECK: cmp |
| 174 ; CHECK: jne |
| 175 ; CHECK: cmp |
| 176 ; CHECK: jne |
| 177 ; CHECK: add |
| 178 ; CHECK: add |
| 179 |
| 180 |
| 181 ; Cmp/multi-select non-folding because of extra non-whitelisted uses. |
| 182 define i32 @no_fold_cmp_select_multi_non_whitelist(i32 %arg1, i32 %arg2) { |
| 183 entry: |
| 184 %cmp1 = icmp slt i32 %arg1, %arg2 |
| 185 %a = select i1 %cmp1, i32 %arg1, i32 %arg2 |
| 186 %b = select i1 %cmp1, i32 %arg2, i32 %arg1 |
| 187 %c = select i1 %cmp1, i32 123, i32 %arg1 |
| 188 %ext = zext i1 %cmp1 to i32 |
| 189 %partial1 = add i32 %a, %b |
| 190 %partial2 = add i32 %partial1, %c |
| 191 %result = add i32 %partial2, %ext |
| 192 ret i32 %result |
| 193 } |
| 194 |
| 195 ; CHECK-LABEL: no_fold_cmp_select_multi_non_whitelist |
| 196 ; CHECK: set |
| 197 ; CHECK: cmp |
| 198 ; CHECK: jne |
| 199 ; CHECK: cmp |
| 200 ; CHECK: jne |
| 201 ; CHECK: cmp |
| 202 ; CHECK: jne |
| 203 ; CHECK: movzx |
| 204 ; CHECK: add |
| 205 ; CHECK: add |
| 206 ; CHECK: add |
OLD | NEW |