OLD | NEW |
(Empty) | |
| 1 ; RUN: opt < %s -nacl-expand-ints -S | FileCheck %s |
| 2 ; Test large integer expansion for operations required for large packed |
| 3 ; bitfields. |
| 4 |
| 5 ; CHECK-LABEL: @simpleload |
| 6 define void @simpleload(i32* %a) { |
| 7 ; CHECK: %a96.loty = bitcast i96* %a96 to i64* |
| 8 ; CHECK-NEXT: %load.lo = load i64* %a96.loty |
| 9 ; CHECK-NEXT: %a96.hi.gep = getelementptr i64* %a96.loty, i32 1 |
| 10 ; CHECK-NEXT: %a96.hity = bitcast i64* %a96.hi.gep to i32* |
| 11 ; CHECK-NEXT: %load.hi = load i32* %a96.hity |
| 12 %a96 = bitcast i32* %a to i96* |
| 13 %load = load i96* %a96 |
| 14 |
| 15 ; CHECK: %a128.loty = bitcast i128* %a128 to i64* |
| 16 ; CHECK-NEXT: %load128.lo = load i64* %a128.loty |
| 17 ; CHECK-NEXT: %a128.hi.gep = getelementptr i64* %a128.loty, i32 1 |
| 18 ; CHECK-NEXT: %load128.hi = load i64* %a128.hi.gep |
| 19 %a128 = bitcast i32* %a to i128* |
| 20 %load128 = load i128* %a128 |
| 21 |
| 22 ; CHECK: %a256.loty = bitcast i256* %a256 to i64* |
| 23 ; CHECK-NEXT: %load256.lo = load i64* %a256.loty |
| 24 ; CHECK-NEXT: %a256.hi.gep = getelementptr i64* %a256.loty, i32 1 |
| 25 ; CHECK-NEXT: %a256.hity = bitcast i64* %a256.hi.gep to i192* |
| 26 ; intermediate expansion: %load256.hi = load i192* %a256.hity |
| 27 ; CHECK-NEXT: %a256.hity.loty = bitcast i192* %a256.hity to i64* |
| 28 ; CHECK-NEXT: %load256.hi.lo = load i64* %a256.hity.loty |
| 29 ; CHECK-NEXT: %a256.hity.hi.gep = getelementptr i64* %a256.hity.loty, i32 1 |
| 30 ; CHECK-NEXT: %a256.hity.hity = bitcast i64* %a256.hity.hi.gep to i128* |
| 31 ; intermediate expansion: %load256.hi.hi = load i128* %a256.hity.hity |
| 32 ; CHECK-NEXT: %a256.hity.hity.loty = bitcast i128* %a256.hity.hity to i64* |
| 33 ; CHECK-NEXT: %load256.hi.hi.lo = load i64* %a256.hity.hity.loty |
| 34 ; CHECK-NEXT: %a256.hity.hity.hi.gep = getelementptr i64* %a256.hity.hity.loty,
i32 1 |
| 35 ; CHECK-NEXT: %load256.hi.hi.hi = load i64* %a256.hity.hity.hi.gep |
| 36 %a256 = bitcast i32* %a to i256* |
| 37 %load256 = load i256* %a256 |
| 38 ret void |
| 39 } |
| 40 |
| 41 ; CHECK-LABEL: @loadalign |
| 42 define void @loadalign(i32* %a) { |
| 43 %a96 = bitcast i32* %a to i96* |
| 44 |
| 45 ; CHECK: %load.lo = load{{.*}}, align 16 |
| 46 ; CHECK: %load.hi = load{{.*}}, align 8 |
| 47 %load = load i96* %a96, align 16 |
| 48 |
| 49 ; CHECK: %loadnoalign.lo = load{{.*}}, align 8 |
| 50 ; CHECK: %loadnoalign.hi = load{{.*}}, align 8 |
| 51 %loadnoalign = load i96* %a96 |
| 52 |
| 53 ; CHECK: %load4.lo = load{{.*}}, align 4 |
| 54 ; CHECK: %load4.hi = load{{.*}}, align 4 |
| 55 %load4 = load i96* %a96, align 4 |
| 56 |
| 57 %a256 = bitcast i32* %a to i256* |
| 58 ; CHECK: %load256.lo = load{{.*}}, align 16 |
| 59 ; CHECK: %load256.hi.lo = load{{.*}}, align 8 |
| 60 ; CHECK: %load256.hi.hi.lo = load{{.*}}, align 8 |
| 61 ; CHECK: %load256.hi.hi.hi = load{{.*}}, align 8 |
| 62 %load256 = load i256* %a256, align 16 |
| 63 ret void |
| 64 } |
| 65 |
| 66 ; CHECK-LABEL: @simplestore |
| 67 define void @simplestore(i32* %a, i32* %b) { |
| 68 %a96 = bitcast i32* %a to i96* |
| 69 %b96 = bitcast i32* %b to i96* |
| 70 %load96 = load i96* %a96 |
| 71 ; CHECK: %b96.loty = bitcast i96* %b96 to i64* |
| 72 ; CHECK-NEXT: store i64 %load96.lo, i64* %b96.loty |
| 73 ; CHECK-NEXT: %b96.hi.gep = getelementptr i64* %b96.loty, i32 1 |
| 74 ; CHECK-NEXT: %b96.hity = bitcast i64* %b96.hi.gep to i32* |
| 75 ; CHECK-NEXT: store i32 %load96.hi, i32* %b96.hity |
| 76 store i96 %load96, i96* %b96 |
| 77 |
| 78 %a128 = bitcast i32* %a to i128* |
| 79 %b128 = bitcast i32* %b to i128* |
| 80 %load128 = load i128* %a128 |
| 81 ; CHECK: %b128.loty = bitcast i128* %b128 to i64* |
| 82 ; CHECK-NEXT: store i64 %load128.lo, i64* %b128.loty |
| 83 ; CHECK-NEXT: %b128.hi.gep = getelementptr i64* %b128.loty, i32 1 |
| 84 ; CHECK-NEXT: store i64 %load128.hi, i64* %b128.hi.gep |
| 85 store i128 %load128, i128* %b128 |
| 86 |
| 87 %a256 = bitcast i32* %a to i256* |
| 88 %b256 = bitcast i32* %b to i256* |
| 89 %load256 = load i256* %a256 |
| 90 |
| 91 ; CHECK: %b256.loty = bitcast i256* %b256 to i64* |
| 92 ; CHECK-NEXT: store i64 %load256.lo, i64* %b256.loty |
| 93 ; CHECK-NEXT: %b256.hi.gep = getelementptr i64* %b256.loty, i32 1 |
| 94 ; CHECK-NEXT: %b256.hity = bitcast i64* %b256.hi.gep to i192* |
| 95 ; CHECK-NEXT: %b256.hity.loty = bitcast i192* %b256.hity to i64* |
| 96 ; CHECK-NEXT: store i64 %load256.hi.lo, i64* %b256.hity.loty |
| 97 ; CHECK-NEXT: %b256.hity.hi.gep = getelementptr i64* %b256.hity.loty, i32 1 |
| 98 ; CHECK-NEXT: %b256.hity.hity = bitcast i64* %b256.hity.hi.gep to i128* |
| 99 ; CHECK-NEXT: %b256.hity.hity.loty = bitcast i128* %b256.hity.hity to i64* |
| 100 ; CHECK-NEXT: store i64 %load256.hi.hi.lo, i64* %b256.hity.hity.loty |
| 101 ; CHECK-NEXT: %b256.hity.hity.hi.gep = getelementptr i64* %b256.hity.hity.loty,
i32 1 |
| 102 ; CHECK-NEXT: store i64 %load256.hi.hi.hi, i64* %b256.hity.hity.hi.gep |
| 103 store i256 %load256, i256* %b256 |
| 104 ret void |
| 105 } |
| 106 |
| 107 ; CHECK-LABEL: @storealign |
| 108 define void @storealign(i32* %a, i32* %b) { |
| 109 %a96 = bitcast i32* %a to i96* |
| 110 %b96 = bitcast i32* %b to i96* |
| 111 %load96 = load i96* %a96 |
| 112 |
| 113 ; CHECK: store i64 %load96.lo{{.*}}, align 16 |
| 114 ; CHECK: store i32 %load96.hi{{.*}}, align 8 |
| 115 store i96 %load96, i96* %b96, align 16 |
| 116 |
| 117 ; CHECK: store i64 %load96.lo{{.*}}, align 8 |
| 118 ; CHECK: store i32 %load96.hi{{.*}}, align 8 |
| 119 store i96 %load96, i96* %b96 |
| 120 |
| 121 ; CHECK: store i64 %load96.lo{{.*}}, align 4 |
| 122 ; CHECK: store i32 %load96.hi{{.*}}, align 4 |
| 123 store i96 %load96, i96* %b96, align 4 |
| 124 |
| 125 %a256 = bitcast i32* %a to i256* |
| 126 %b256 = bitcast i32* %b to i256* |
| 127 %load256 = load i256* %a256 |
| 128 ; CHECK: store i64 %load256.lo{{.*}}, align 16 |
| 129 ; CHECK: store i64 %load256.hi.lo{{.*}}, align 8 |
| 130 ; CHECK: store i64 %load256.hi.hi.lo{{.*}}, align 8 |
| 131 ; CHECK: store i64 %load256.hi.hi.hi{{.*}}, align 8 |
| 132 store i256 %load256, i256* %b256, align 16 |
| 133 ret void |
| 134 } |
| 135 |
| 136 |
| 137 ; Check that forward references are handled. |
| 138 ; CHECK-LABEL: @fwdref |
| 139 define void @fwdref(i32* %a, i32* %b) { |
| 140 entry: |
| 141 br label %block1 |
| 142 block2: |
| 143 %b96 = bitcast i32* %b to i96* |
| 144 ; CHECK: store i64 %load96.lo |
| 145 ; CHECK: store i32 %load96.hi |
| 146 store i96 %load96, i96* %b96 |
| 147 ret void |
| 148 block1: |
| 149 %a96 = bitcast i32* %a to i96* |
| 150 ; CHECK: load i64* %a96.loty |
| 151 ; CHECK: load i32* %a96.hity |
| 152 %load96 = load i96* %a96 |
| 153 br label %block2 |
| 154 } |
| 155 |
| 156 ; The subsequent tests use loads and stores to produce and consume the expanded |
| 157 ; values from the opcodes under test. |
| 158 ; CHECK-LABEL: @zext |
| 159 define void @zext(i32 %a, i64 %b, i8* %p) { |
| 160 %p96 = bitcast i8* %p to i96* |
| 161 %a96 = zext i32 %a to i96 |
| 162 ; CHECK: %a96.lo = zext i32 %a to i64 |
| 163 store i96 %a96, i96* %p96 |
| 164 ; CHECK: store i64 %a96.lo, i64* %p96.loty |
| 165 ; CHECK: store i32 0, i32* %p96.hity |
| 166 |
| 167 %b96 = zext i64 %b to i96 |
| 168 ; CHECK: store i64 %b, i64* %p96.loty |
| 169 ; CHECK: store i32 0, i32* %p96.hity |
| 170 store i96 %b96, i96* %p96 |
| 171 |
| 172 %p128 = bitcast i8* %p to i128* |
| 173 %c96 = load i96* %p96 |
| 174 ; CHECK: %a128.hi = zext i32 %c96.hi to i64 |
| 175 %a128 = zext i96 %c96 to i128 |
| 176 ; CHECK: store i64 %c96.lo, i64* %p128.loty |
| 177 ; CHECK: store i64 %a128.hi, i64* %p128.hi.gep |
| 178 store i128 %a128, i128* %p128 |
| 179 |
| 180 %p256 = bitcast i8* %p to i256* |
| 181 |
| 182 ; CHECK: %b256.lo = zext i32 %a to i64 |
| 183 %b256 = zext i32 %a to i256 |
| 184 ; CHECK: store i64 %b256.lo, i64* %p256.loty |
| 185 ; CHECK: store i64 0, i64* %p256.hity.loty |
| 186 ; CHECK: store i64 0, i64* %p256.hity.hity.loty |
| 187 ; CHECK: store i64 0, i64* %p256.hity.hity.hi.gep |
| 188 store i256 %b256, i256* %p256 |
| 189 |
| 190 ; CHECK: %c256.hi.lo = zext i32 %c96.hi to i64 |
| 191 %c256 = zext i96 %c96 to i256 |
| 192 ; CHECK: store i64 %c96.lo, i64* %p256.loty |
| 193 ; CHECK: store i64 %c256.hi.lo, i64* %p256.hity9.loty |
| 194 ; CHECK: store i64 0, i64* %p256.hity9.hity.loty |
| 195 ; CHECK: store i64 0, i64* %p256.hity9.hity.hi.gep |
| 196 store i256 %c256, i256* %p256 |
| 197 ret void |
| 198 } |
| 199 |
| 200 |
| 201 ; CHECK-LABEL: @bitwise |
| 202 define void @bitwise(i32* %a) { |
| 203 %a96p = bitcast i32* %a to i96* |
| 204 %a96 = load i96* %a96p |
| 205 %b96 = load i96* %a96p |
| 206 |
| 207 ; CHECK: %c96.lo = and i64 %a96.lo, %b96.lo |
| 208 ; CHECK: %c96.hi = and i32 %a96.hi, %b96.hi |
| 209 %c96 = and i96 %a96, %b96 |
| 210 ; CHECK: %d96.lo = or i64 %a96.lo, %c96.lo |
| 211 ; CHECK: %d96.hi = or i32 %a96.hi, %c96.hi |
| 212 %d96 = or i96 %a96, %c96 |
| 213 |
| 214 ; CHECK: %x96.lo = xor i64 %a96.lo, %c96.lo |
| 215 ; CHECK: %x96.hi = xor i32 %a96.hi, %c96.hi |
| 216 %x96 = xor i96 %a96, %c96 |
| 217 ret void |
| 218 } |
| 219 |
| 220 ; CHECK-LABEL: @truncs |
| 221 define void @truncs(i32* %p) { |
| 222 %p96 = bitcast i32* %p to i96* |
| 223 %a96 = load i96* %p96 |
| 224 |
| 225 ; CHECK: %t32 = trunc i64 %a96.lo to i32 |
| 226 %t32 = trunc i96 %a96 to i32 |
| 227 |
| 228 %b96 = load i96* %p96 |
| 229 ; Check that t64 refers directly to the low loaded value from %p96 |
| 230 ; CHECK: %t64 = load i64* %p96.loty |
| 231 %t64 = trunc i96 %b96 to i64 |
| 232 |
| 233 %c96 = load i96* %p96 |
| 234 ; Use the and to get a use of %t90.lo and check that it refers directly to |
| 235 ; %c96.lo |
| 236 ; CHECK: %t90.hi = trunc i32 %c96.hi to i26 |
| 237 ; CHECK: %a90.lo = and i64 %c96.lo, %c96.lo |
| 238 %t90 = trunc i96 %c96 to i90 |
| 239 %t90_2 = trunc i96 %c96 to i90 |
| 240 %a90 = and i90 %t90, %t90_2 |
| 241 ret void |
| 242 } |
| 243 |
| 244 ; CHECK-LABEL: @shls |
| 245 define void @shls(i32* %p) { |
| 246 %p96 = bitcast i32* %p to i96* |
| 247 %a96 = load i96* %p96 |
| 248 %p128 = bitcast i32* %p to i128* |
| 249 %a128 = load i128* %p128 |
| 250 %p192 = bitcast i32* %p to i192* |
| 251 %a192 = load i192* %p192 |
| 252 |
| 253 ; CHECK: %b96.lo = shl i64 %a96.lo, 5 |
| 254 ; CHECK-NEXT: %b96.lo.shr = lshr i64 %a96.lo, 59 |
| 255 ; CHECK-NEXT: %b96.lo.ext = trunc i64 %b96.lo.shr to i32 |
| 256 ; CHECK-NEXT: %b96.hi.shl = shl i32 %a96.hi, 5 |
| 257 ; CHECK-NEXT: %b96.or = or i32 %b96.lo.ext, %b96.hi.shl |
| 258 %b96 = shl i96 %a96, 5 |
| 259 |
| 260 ; CHECK: %d96.lo = shl i64 %a96.lo, 35 |
| 261 ; CHECK-NEXT: %d96.lo.shr = lshr i64 %a96.lo, 29 |
| 262 ; CHECK-NEXT: %d96.lo.ext = trunc i64 %d96.lo.shr to i32 |
| 263 ; CHECK: store i64 %d96.lo, i64* %p96.loty1 |
| 264 ; CHECK: store i32 %d96.lo.ext, i32* %p96.hity |
| 265 %d96 = shl i96 %a96, 35 |
| 266 store i96 %d96, i96* %p96 |
| 267 |
| 268 ; CHECK: %b128.lo = shl i64 %a128.lo, 35 |
| 269 ; CHECK-NEXT: %b128.lo.shr = lshr i64 %a128.lo, 29 |
| 270 ; CHECK-NEXT: %b128.hi.shl = shl i64 %a128.hi, 35 |
| 271 ; CHECK-NEXT: %b128.or = or i64 %b128.lo.shr, %b128.hi.shl |
| 272 %b128 = shl i128 %a128, 35 |
| 273 |
| 274 ; CHECK: %c96.lo.ext = trunc i64 %a96.lo to i32 |
| 275 ; CHECK-NEXT: %c96.lo.shl = shl i32 %c96.lo.ext, 8 |
| 276 ; CHECK: store i64 0, i64* %p96.loty |
| 277 %c96 = shl i96 %a96, 72 |
| 278 store i96 %c96, i96* %p96 |
| 279 |
| 280 ; CHECK: %c128.lo.shl = shl i64 %a128.lo, 36 |
| 281 ; CHECK: store i64 0, i64* %p128.loty |
| 282 %c128 = shl i128 %a128, 100 |
| 283 store i128 %c128, i128* %p128 |
| 284 |
| 285 ; %b192.lo = shl i64 %a192.lo, 35 |
| 286 ; %b192.lo.shr = lshr i64 %a192.lo, 29 |
| 287 ; %b192.hi.shl.lo = shl i64 %a192.hi.lo, 35 |
| 288 ; %b192.hi.shl.lo.shr = lshr i64 %a192.hi.lo, 29 |
| 289 ; %b192.hi.shl.hi.shl = shl i64 %a192.hi.hi, 35 |
| 290 ; %b192.hi.shl.or = or i64 %b192.hi.shl.lo.shr, %b192.hi.shl.hi.shl |
| 291 ; %b192.or.lo = or i64 %b192.lo.shr, %b192.hi.shl.lo |
| 292 ; %b192.or.hi = or i64 0, %b192.hi.shl.or |
| 293 %b192 = shl i192 %a192, 35 |
| 294 store i192 %b192, i192* %p192 |
| 295 |
| 296 ; %c192.lo.shl.lo = shl i64 %a192.lo, 36 |
| 297 ; %c192.lo.shl.lo.shr = lshr i64 %a192.lo, 28 |
| 298 ; %c192.hi.shl.lo.shl = shl i64 %a192.hi.lo, 36 |
| 299 ; %c192.or.lo = or i64 %c192.lo.shl.lo, 0 |
| 300 ; %c192.or.hi = or i64 %c192.lo.shl.lo.shr, %c192.hi.shl.lo.shl |
| 301 %c192 = shl i192 %a192, 100 |
| 302 store i192 %c192, i192* %p192 |
| 303 |
| 304 ret void |
| 305 } |
| 306 |
| 307 ; CHECK-LABEL: @lshrs |
| 308 define void @lshrs(i32* %p) { |
| 309 %p96 = bitcast i32* %p to i96* |
| 310 %a96 = load i96* %p96 |
| 311 %p128 = bitcast i32* %p to i128* |
| 312 %a128 = load i128* %p128 |
| 313 %p192 = bitcast i32* %p to i192* |
| 314 %a192 = load i192* %p192 |
| 315 |
| 316 ; CHECK: %b96.hi.shr = lshr i32 %a96.hi, 3 |
| 317 ; CHECK-NEXT: %b96.lo.ext = zext i32 %b96.hi.shr to i64 |
| 318 ; CHECK: store i32 0, i32* %p96.hity |
| 319 %b96 = lshr i96 %a96, 67 |
| 320 store i96 %b96, i96* %p96 |
| 321 |
| 322 ; CHECK: %c96.hi.ext = zext i32 %a96.hi to i64 |
| 323 ; CHECK-NEXT: %c96.hi.shl = shl i64 %c96.hi.ext, 19 |
| 324 ; CHECK-NEXT: %c96.lo.shr = lshr i64 %a96.lo, 45 |
| 325 ; CHECK-NEXT: %c96.lo = or i64 %c96.hi.shl, %c96.lo.shr |
| 326 ; CHECK: store i32 0, i32* %p96.hity |
| 327 %c96 = lshr i96 %a96, 45 |
| 328 store i96 %c96, i96* %p96 |
| 329 |
| 330 ; CHECK: %b128.hi.shr = lshr i64 %a128.hi, 3 |
| 331 ; CHECK: store i64 0, i64* %p128.hi.gep |
| 332 %b128 = lshr i128 %a128, 67 |
| 333 store i128 %b128, i128* %p128 |
| 334 |
| 335 ; CHECK: %d96.hi.ext = zext i32 %a96.hi to i64 |
| 336 ; CHECK-NEXT: %d96.hi.shl = shl i64 %d96.hi.ext, 47 |
| 337 ; CHECK-NEXT: %d96.lo.shr = lshr i64 %a96.lo, 17 |
| 338 ; CHECK-NEXT: %d96.lo = or i64 %d96.hi.shl, %d96.lo.shr |
| 339 ; CHECK-NEXT: %d96.hi = lshr i32 %a96.hi, 17 |
| 340 %d96 = lshr i96 %a96, 17 |
| 341 store i96 %d96, i96* %p96 |
| 342 |
| 343 ; CHECK: %c128.hi.shl = shl i64 %a128.hi, 21 |
| 344 ; CHECK-NEXT: %c128.lo.shr = lshr i64 %a128.lo, 43 |
| 345 ; CHECK-NEXT: %c128.lo = or i64 %c128.hi.shl, %c128.lo.shr |
| 346 ; CHECK-NEXT: %c128.hi = lshr i64 %a128.hi, 43 |
| 347 %c128 = lshr i128 %a128, 43 |
| 348 store i128 %c128, i128* %p128 |
| 349 |
| 350 %b192 = lshr i192 %a192, 100 |
| 351 store i192 %b192, i192* %p192 |
| 352 |
| 353 ret void |
| 354 } |
| 355 |
| 356 ; Make sure that the following doesn't assert out: it generates intermediate |
| 357 ; `trunc` instructions which get progressively smaller and smaller as the |
| 358 ; instructions are cut down. The final bitcode doesn't contain a `trunc` |
| 359 ; instruction. |
| 360 ; |
| 361 ; CHECK-LABEL: @lshr_big |
| 362 define void @lshr_big(i32* %a) { |
| 363 %p536 = bitcast i32* %a to i536* |
| 364 %loaded = load i536* %p536, align 4 |
| 365 %shifted = lshr i536 %loaded, 161 |
| 366 store i536 %shifted, i536* %p536 |
| 367 ret void |
| 368 } |
| 369 |
| 370 ; CHECK-LABEL: @ashrs |
| 371 define void @ashrs(i32* %p) { |
| 372 %p96 = bitcast i32* %p to i96* |
| 373 %a96 = load i96* %p96 |
| 374 %p128 = bitcast i32* %p to i128* |
| 375 %a128 = load i128* %p128 |
| 376 |
| 377 ; CHECK: %b96.hi.shr = ashr i32 %a96.hi, 3 |
| 378 ; CHECK-NEXT: %b96.lo.ext = sext i32 %b96.hi.shr to i64 |
| 379 ; CHECK-NEXT: %b96.hi = ashr i32 %a96.hi, 31 |
| 380 %b96 = ashr i96 %a96, 67 |
| 381 store i96 %b96, i96* %p96 |
| 382 |
| 383 ; CHECK: %c96.hi.ext = sext i32 %a96.hi to i64 |
| 384 ; CHECK-NEXT: %c96.hi.shl = shl i64 %c96.hi.ext, 19 |
| 385 ; CHECK-NEXT: %c96.lo.shr = lshr i64 %a96.lo, 45 |
| 386 ; CHECK-NEXT: %c96.lo = or i64 %c96.hi.shl, %c96.lo.shr |
| 387 ; CHECK-NEXT: %c96.hi = ashr i32 %a96.hi, 31 |
| 388 %c96 = ashr i96 %a96, 45 |
| 389 store i96 %c96, i96* %p96 |
| 390 |
| 391 ; CHECK: %b128.hi.shr = ashr i64 %a128.hi, 3 |
| 392 ; CHECK-NEXT: %b128.hi = ashr i64 %a128.hi, 63 |
| 393 ; CHECK: store i64 %b128.hi, i64* %p128.hi.gep |
| 394 %b128 = ashr i128 %a128, 67 |
| 395 store i128 %b128, i128* %p128 |
| 396 |
| 397 ; CHECK: %d96.hi.ext = sext i32 %a96.hi to i64 |
| 398 ; CHECK-NEXT: %d96.hi.shl = shl i64 %d96.hi.ext, 47 |
| 399 ; CHECK-NEXT: %d96.lo.shr = lshr i64 %a96.lo, 17 |
| 400 ; CHECK-NEXT: %d96.lo = or i64 %d96.hi.shl, %d96.lo.shr |
| 401 ; CHECK-NEXT: %d96.hi = ashr i32 %a96.hi, 17 |
| 402 %d96 = ashr i96 %a96, 17 |
| 403 store i96 %d96, i96* %p96 |
| 404 |
| 405 ; CHECK: %c128.hi.shl = shl i64 %a128.hi, 21 |
| 406 ; CHECK-NEXT: %c128.lo.shr = lshr i64 %a128.lo, 43 |
| 407 ; CHECK-NEXT: %c128.lo = or i64 %c128.hi.shl, %c128.lo.shr |
| 408 ; CHECK-NEXT: %c128.hi = ashr i64 %a128.hi, 43 |
| 409 %c128 = ashr i128 %a128, 43 |
| 410 store i128 %c128, i128* %p128 |
| 411 |
| 412 ret void |
| 413 } |
| 414 |
| 415 ; CHECK-LABEL: @adds |
| 416 define void @adds(i32 *%dest, i32* %lhs, i32* %rhs) { |
| 417 %d = bitcast i32* %dest to i96* |
| 418 %lp = bitcast i32* %lhs to i96* |
| 419 %lv = load i96* %lp |
| 420 %rp = bitcast i32* %rhs to i96* |
| 421 %rv = load i96* %rp |
| 422 |
| 423 ; CHECK: %result.lo = add i64 %lv.lo, %rv.lo |
| 424 ; CHECK-NEXT: %result.cmp = icmp ult i64 %lv.lo, %rv.lo |
| 425 ; CHECK-NEXT: %result.limit = select i1 %result.cmp, i64 %rv.lo, i64 %lv.lo |
| 426 ; CHECK-NEXT: %result.overflowed = icmp ult i64 %result.lo, %result.limit |
| 427 ; CHECK-NEXT: %result.carry = zext i1 %result.overflowed to i32 |
| 428 ; CHECK-NEXT: %result.hi = add i32 %lv.hi, %rv.hi |
| 429 ; CHECK-NEXT: %result.carried = add i32 %result.hi, %result.carry |
| 430 %result = add i96 %lv, %rv |
| 431 store i96 %result, i96* %d |
| 432 ret void |
| 433 } |
| 434 |
| 435 ; CHECK-LABEL: @subs |
| 436 define void @subs(i32 *%dest, i32* %lhs, i32* %rhs) { |
| 437 %d = bitcast i32* %dest to i96* |
| 438 %lp = bitcast i32* %lhs to i96* |
| 439 %lv = load i96* %lp |
| 440 %rp = bitcast i32* %rhs to i96* |
| 441 %rv = load i96* %rp |
| 442 |
| 443 ; CHECK: %result.borrow = icmp ult i64 %lv.lo, %rv.lo |
| 444 ; CHECK-NEXT: %result.borrowing = sext i1 %result.borrow to i32 |
| 445 ; CHECK-NEXT: %result.lo = sub i64 %lv.lo, %rv.lo |
| 446 ; CHECK-NEXT: %result.hi = sub i32 %lv.hi, %rv.hi |
| 447 ; CHECK-NEXT: %result.borrowed = add i32 %result.hi, %result.borrowing |
| 448 %result = sub i96 %lv, %rv |
| 449 store i96 %result, i96* %d |
| 450 ret void |
| 451 } |
| 452 |
| 453 ; CHECK-LABEL: @icmp_equality |
| 454 define void @icmp_equality(i32* %p) { |
| 455 %p96 = bitcast i32* %p to i96* |
| 456 %a96 = load i96* %p96 |
| 457 %b96 = load i96* %p96 |
| 458 |
| 459 ; CHECK: %eq.lo = icmp eq i64 %a96.lo, %b96.lo |
| 460 ; CHECK-NEXT: %eq.hi = icmp eq i32 %a96.hi, %b96.hi |
| 461 ; CHECK-NEXT: %eq = and i1 %eq.lo, %eq.hi |
| 462 %eq = icmp eq i96 %a96, %b96 |
| 463 |
| 464 ; CHECK: %ne.lo = icmp ne i64 %a96.lo, %b96.lo |
| 465 ; CHECK-NEXT: %ne.hi = icmp ne i32 %a96.hi, %b96.hi |
| 466 ; CHECK-NEXT: %ne = and i1 %ne.lo, %ne.hi |
| 467 %ne = icmp ne i96 %a96, %b96 |
| 468 ret void |
| 469 } |
| 470 |
| 471 ; CHECK-LABEL: @icmp_uge |
| 472 define void @icmp_uge(i32* %p) { |
| 473 %p96 = bitcast i32* %p to i96* |
| 474 %lv = load i96* %p96 |
| 475 %rv = load i96* %p96 |
| 476 ; Do an add. |
| 477 ; CHECK: %uge.lo = add i64 %lv.lo, %rv.lo |
| 478 ; CHECK-NEXT: %uge.cmp = icmp ult i64 %lv.lo, %rv.lo |
| 479 ; CHECK-NEXT: %uge.limit = select i1 %uge.cmp, i64 %rv.lo, i64 %lv.lo |
| 480 ; CHECK-NEXT: %uge.overflowed = icmp ult i64 %uge.lo, %uge.limit |
| 481 ; CHECK-NEXT: %uge.carry = zext i1 %uge.overflowed to i32 |
| 482 ; CHECK-NEXT: %uge.hi = add i32 %lv.hi, %rv.hi |
| 483 ; CHECK-NEXT: %uge.carried = add i32 %uge.hi, %uge.carry |
| 484 ; Do the hi carry. |
| 485 ; CHECK-NEXT: %uge.cmp4 = icmp ult i32 %lv.hi, %rv.hi |
| 486 ; CHECK-NEXT: %uge.limit5 = select i1 %uge.cmp4, i32 %rv.hi, i32 %lv.hi |
| 487 ; CHECK-NEXT: %uge = icmp ult i32 %uge.carried, %uge.limit5 |
| 488 %uge = icmp uge i96 %lv, %rv |
| 489 ret void |
| 490 } |
| 491 |
| 492 ; CHECK-LABEL: @icmp_ule |
| 493 define void @icmp_ule(i32* %p) { |
| 494 %p96 = bitcast i32* %p to i96* |
| 495 %lv = load i96* %p96 |
| 496 %rv = load i96* %p96 |
| 497 ; Do an add. |
| 498 ; CHECK: %ule.lo = add i64 %lv.lo, %rv.lo |
| 499 ; CHECK-NEXT: %ule.cmp = icmp ult i64 %lv.lo, %rv.lo |
| 500 ; CHECK-NEXT: %ule.limit = select i1 %ule.cmp, i64 %rv.lo, i64 %lv.lo |
| 501 ; CHECK-NEXT: %ule.overflowed = icmp ult i64 %ule.lo, %ule.limit |
| 502 ; CHECK-NEXT: %ule.carry = zext i1 %ule.overflowed to i32 |
| 503 ; CHECK-NEXT: %ule.hi = add i32 %lv.hi, %rv.hi |
| 504 ; CHECK-NEXT: %ule.carried = add i32 %ule.hi, %ule.carry |
| 505 ; Do the hi carry. |
| 506 ; CHECK-NEXT: %ule.cmp4 = icmp ult i32 %lv.hi, %rv.hi |
| 507 ; CHECK-NEXT: %ule.limit5 = select i1 %ule.cmp4, i32 %rv.hi, i32 %lv.hi |
| 508 ; CHECK-NEXT: %ule.overflowed6 = icmp ult i32 %ule.carried, %ule.limit5 |
| 509 ; Invert the carry result. |
| 510 ; CHECK-NEXT: %ule = xor i1 %ule.overflowed6, true |
| 511 %ule = icmp ule i96 %lv, %rv |
| 512 ret void |
| 513 } |
| 514 |
| 515 ; CHECK-LABEL: @icmp_ugt |
| 516 define void @icmp_ugt(i32* %p) { |
| 517 %p96 = bitcast i32* %p to i96* |
| 518 %lv = load i96* %p96 |
| 519 %rv = load i96* %p96 |
| 520 ; Do an add. |
| 521 ; CHECK: %ugt.lo = add i64 %lv.lo, %rv.lo |
| 522 ; CHECK-NEXT: %ugt.cmp = icmp ult i64 %lv.lo, %rv.lo |
| 523 ; CHECK-NEXT: %ugt.limit = select i1 %ugt.cmp, i64 %rv.lo, i64 %lv.lo |
| 524 ; CHECK-NEXT: %ugt.overflowed = icmp ult i64 %ugt.lo, %ugt.limit |
| 525 ; CHECK-NEXT: %ugt.carry = zext i1 %ugt.overflowed to i32 |
| 526 ; CHECK-NEXT: %ugt.hi = add i32 %lv.hi, %rv.hi |
| 527 ; CHECK-NEXT: %ugt.carried = add i32 %ugt.hi, %ugt.carry |
| 528 ; Do the hi carry. |
| 529 ; CHECK-NEXT: %ugt.cmp4 = icmp ult i32 %lv.hi, %rv.hi |
| 530 ; CHECK-NEXT: %ugt.limit5 = select i1 %ugt.cmp4, i32 %rv.hi, i32 %lv.hi |
| 531 ; CHECK-NEXT: %ugt.overflowed6 = icmp ult i32 %ugt.carried, %ugt.limit5 |
| 532 ; Equality comparison. |
| 533 ; CHECK-NEXT: %ugt.lo7 = icmp eq i64 %lv.lo, %rv.lo |
| 534 ; CHECK-NEXT: %ugt.hi8 = icmp eq i32 %lv.hi, %rv.hi |
| 535 ; CHECK-NEXT: %ugt.eq = and i1 %ugt.lo7, %ugt.hi8 |
| 536 ; Merge the hi carry and equality comparison results. |
| 537 ; CHECK-NEXT: %ugt = and i1 %ugt.overflowed6, %ugt.eq |
| 538 %ugt = icmp ugt i96 %lv, %rv |
| 539 ret void |
| 540 } |
| 541 |
| 542 ; CHECK-LABEL: @icmp_ult |
| 543 define void @icmp_ult(i32* %p) { |
| 544 %p96 = bitcast i32* %p to i96* |
| 545 %lv = load i96* %p96 |
| 546 %rv = load i96* %p96 |
| 547 ; Do an add. |
| 548 ; CHECK: %ult.lo = add i64 %lv.lo, %rv.lo |
| 549 ; CHECK-NEXT: %ult.cmp = icmp ult i64 %lv.lo, %rv.lo |
| 550 ; CHECK-NEXT: %ult.limit = select i1 %ult.cmp, i64 %rv.lo, i64 %lv.lo |
| 551 ; CHECK-NEXT: %ult.overflowed = icmp ult i64 %ult.lo, %ult.limit |
| 552 ; CHECK-NEXT: %ult.carry = zext i1 %ult.overflowed to i32 |
| 553 ; CHECK-NEXT: %ult.hi = add i32 %lv.hi, %rv.hi |
| 554 ; CHECK-NEXT: %ult.carried = add i32 %ult.hi, %ult.carry |
| 555 ; Do the hi carry. |
| 556 ; CHECK-NEXT: %ult.cmp4 = icmp ult i32 %lv.hi, %rv.hi |
| 557 ; CHECK-NEXT: %ult.limit5 = select i1 %ult.cmp4, i32 %rv.hi, i32 %lv.hi |
| 558 ; CHECK-NEXT: %ult.overflowed6 = icmp ult i32 %ult.carried, %ult.limit5 |
| 559 ; Invert the carry result. |
| 560 ; CHECK-NEXT: %ult7 = xor i1 %ult.overflowed6, true |
| 561 ; Equality comparison. |
| 562 ; CHECK-NEXT: %ult.lo8 = icmp eq i64 %lv.lo, %rv.lo |
| 563 ; CHECK-NEXT: %ult.hi9 = icmp eq i32 %lv.hi, %rv.hi |
| 564 ; CHECK-NEXT: %ult.eq = and i1 %ult.lo8, %ult.hi9 |
| 565 ; Merge the hi carry and equality comparison results. |
| 566 ; CHECK-NEXT: %ult = and i1 %ult7, %ult.eq |
| 567 %ult = icmp ult i96 %lv, %rv |
| 568 ret void |
| 569 } |
| 570 |
| 571 ; CHECK-LABEL: @selects |
| 572 define void @selects(i1 %c, i32* %pl, i32* %pr) { |
| 573 %pl96 = bitcast i32* %pl to i96* |
| 574 %pr96 = bitcast i32* %pr to i96* |
| 575 %l = load i96* %pl96 |
| 576 %r = load i96* %pr96 |
| 577 |
| 578 ; CHECK: %result.lo = select i1 %c, i64 %l.lo, i64 %r.lo |
| 579 ; CHECK-NEXT: %result.hi = select i1 %c, i32 %l.hi, i32 %r.hi |
| 580 %result = select i1 %c, i96 %l, i96 %r |
| 581 ret void |
| 582 } |
| 583 |
| 584 ; CHECK-LABEL: @phis1 |
| 585 define void @phis1() { |
| 586 entry: |
| 587 br label %label1 |
| 588 label1: |
| 589 br i1 undef, label %label2, label %end |
| 590 label2: |
| 591 br label %end |
| 592 end: |
| 593 ; CHECK: %foo.lo = phi i64 [ undef, %label1 ], [ undef, %label2 ] |
| 594 ; CHECK-NEXT: %foo.hi = phi i8 [ undef, %label1 ], [ undef, %label2 ] |
| 595 ; CHECK-NEXT: %bar.lo = and i64 %foo.lo, 137438953472 |
| 596 ; CHECK-NEXT: %bar.hi = and i8 %foo.hi, 0 |
| 597 %foo = phi i72 [ undef, %label1 ], [ undef, %label2 ] |
| 598 %bar = and i72 %foo, 137438953472 |
| 599 br i1 undef, label %label1, label %label2 |
| 600 } |
| 601 |
| 602 ; CHECK-LABEL: @phis2 |
| 603 define void @phis2() { |
| 604 entry: |
| 605 br label %label1 |
| 606 label1: |
| 607 ; CHECK: %foo.lo = phi i64 [ %bar.lo, %label2 ], [ undef, %entry ] |
| 608 ; CHECK-NEXT: %foo.hi = phi i8 [ %bar.hi, %label2 ], [ undef, %entry ] |
| 609 %foo = phi i72 [ %bar, %label2 ], [ undef, %entry ] |
| 610 br i1 undef, label %label2, label %end |
| 611 label2: |
| 612 ; CHECK: %bar.lo = load i64* undef, align 4 |
| 613 ; CHECK-NEXT: %bar.hi = load i8* undef, align 4 |
| 614 %bar = load i72* undef, align 4 |
| 615 br label %label1 |
| 616 end: |
| 617 ret void |
| 618 } |
OLD | NEW |