1 ; RUN: opt -codegenprepare -mtriple=arm64-apple=ios -S -o - %s | FileCheck --check-prefix=OPT %s 2 ; RUN: llc < %s -march=arm64 | FileCheck %s 3 %struct.X = type { i8, i8, [2 x i8] } 4 %struct.Y = type { i32, i8 } 5 %struct.Z = type { i8, i8, [2 x i8], i16 } 6 %struct.A = type { i64, i8 } 7 8 define void @foo(%struct.X* nocapture %x, %struct.Y* nocapture %y) nounwind optsize ssp { 9 ; CHECK-LABEL: foo: 10 ; CHECK: ubfx 11 ; CHECK-NOT: and 12 ; CHECK: ret 13 14 %tmp = bitcast %struct.X* %x to i32* 15 %tmp1 = load i32, i32* %tmp, align 4 16 %b = getelementptr inbounds %struct.Y, %struct.Y* %y, i64 0, i32 1 17 %bf.clear = lshr i32 %tmp1, 3 18 %bf.clear.lobit = and i32 %bf.clear, 1 19 %frombool = trunc i32 %bf.clear.lobit to i8 20 store i8 %frombool, i8* %b, align 1 21 ret void 22 } 23 24 define i32 @baz(i64 %cav1.coerce) nounwind { 25 ; CHECK-LABEL: baz: 26 ; CHECK: sbfx w0, w0, #0, #4 27 %tmp = trunc i64 %cav1.coerce to i32 28 %tmp1 = shl i32 %tmp, 28 29 %bf.val.sext = ashr exact i32 %tmp1, 28 30 ret i32 %bf.val.sext 31 } 32 33 define i32 @bar(i64 %cav1.coerce) nounwind { 34 ; CHECK-LABEL: bar: 35 ; CHECK: sbfx w0, w0, #4, #6 36 %tmp = trunc i64 %cav1.coerce to i32 37 %cav1.sroa.0.1.insert = shl i32 %tmp, 22 38 %tmp1 = ashr i32 %cav1.sroa.0.1.insert, 26 39 ret i32 %tmp1 40 } 41 42 define void @fct1(%struct.Z* nocapture %x, %struct.A* nocapture %y) nounwind optsize ssp { 43 ; CHECK-LABEL: fct1: 44 ; CHECK: ubfx 45 ; CHECK-NOT: and 46 ; CHECK: ret 47 48 %tmp = bitcast %struct.Z* %x to i64* 49 %tmp1 = load i64, i64* %tmp, align 4 50 %b = getelementptr inbounds %struct.A, %struct.A* %y, i64 0, i32 0 51 %bf.clear = lshr i64 %tmp1, 3 52 %bf.clear.lobit = and i64 %bf.clear, 1 53 store i64 %bf.clear.lobit, i64* %b, align 8 54 ret void 55 } 56 57 define i64 @fct2(i64 %cav1.coerce) nounwind { 58 ; CHECK-LABEL: fct2: 59 ; CHECK: sbfx x0, x0, #0, #36 60 %tmp = shl i64 %cav1.coerce, 28 61 %bf.val.sext = ashr exact i64 %tmp, 28 62 ret i64 %bf.val.sext 63 } 64 65 define i64 @fct3(i64 %cav1.coerce) nounwind { 66 ; CHECK-LABEL: fct3: 67 ; CHECK: sbfx x0, x0, #4, #38 68 %cav1.sroa.0.1.insert = shl i64 %cav1.coerce, 22 69 %tmp1 = ashr i64 %cav1.sroa.0.1.insert, 26 70 ret i64 %tmp1 71 } 72 73 define void @fct4(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp { 74 entry: 75 ; CHECK-LABEL: fct4: 76 ; CHECK: ldr [[REG1:x[0-9]+]], 77 ; CHECK-NEXT: bfxil [[REG1]], x1, #16, #24 78 ; CHECK-NEXT: str [[REG1]], 79 ; CHECK-NEXT: ret 80 %0 = load i64, i64* %y, align 8 81 %and = and i64 %0, -16777216 82 %shr = lshr i64 %x, 16 83 %and1 = and i64 %shr, 16777215 84 %or = or i64 %and, %and1 85 store i64 %or, i64* %y, align 8 86 ret void 87 } 88 89 define void @fct5(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp { 90 entry: 91 ; CHECK-LABEL: fct5: 92 ; CHECK: ldr [[REG1:w[0-9]+]], 93 ; CHECK-NEXT: bfxil [[REG1]], w1, #16, #3 94 ; CHECK-NEXT: str [[REG1]], 95 ; CHECK-NEXT: ret 96 %0 = load i32, i32* %y, align 8 97 %and = and i32 %0, -8 98 %shr = lshr i32 %x, 16 99 %and1 = and i32 %shr, 7 100 %or = or i32 %and, %and1 101 store i32 %or, i32* %y, align 8 102 ret void 103 } 104 105 ; Check if we can still catch bfm instruction when we drop some low bits 106 define void @fct6(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp { 107 entry: 108 ; CHECK-LABEL: fct6: 109 ; CHECK: ldr [[REG1:w[0-9]+]], 110 ; CHECK-NEXT: bfxil [[REG1]], w1, #16, #3 111 ; lsr is an alias of ubfm 112 ; CHECK-NEXT: lsr [[REG2:w[0-9]+]], [[REG1]], #2 113 ; CHECK-NEXT: str [[REG2]], 114 ; CHECK-NEXT: ret 115 %0 = load i32, i32* %y, align 8 116 %and = and i32 %0, -8 117 %shr = lshr i32 %x, 16 118 %and1 = and i32 %shr, 7 119 %or = or i32 %and, %and1 120 %shr1 = lshr i32 %or, 2 121 store i32 %shr1, i32* %y, align 8 122 ret void 123 } 124 125 126 ; Check if we can still catch bfm instruction when we drop some high bits 127 define void @fct7(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp { 128 entry: 129 ; CHECK-LABEL: fct7: 130 ; CHECK: ldr [[REG1:w[0-9]+]], 131 ; CHECK-NEXT: bfxil [[REG1]], w1, #16, #3 132 ; lsl is an alias of ubfm 133 ; CHECK-NEXT: lsl [[REG2:w[0-9]+]], [[REG1]], #2 134 ; CHECK-NEXT: str [[REG2]], 135 ; CHECK-NEXT: ret 136 %0 = load i32, i32* %y, align 8 137 %and = and i32 %0, -8 138 %shr = lshr i32 %x, 16 139 %and1 = and i32 %shr, 7 140 %or = or i32 %and, %and1 141 %shl = shl i32 %or, 2 142 store i32 %shl, i32* %y, align 8 143 ret void 144 } 145 146 147 ; Check if we can still catch bfm instruction when we drop some low bits 148 ; (i64 version) 149 define void @fct8(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp { 150 entry: 151 ; CHECK-LABEL: fct8: 152 ; CHECK: ldr [[REG1:x[0-9]+]], 153 ; CHECK-NEXT: bfxil [[REG1]], x1, #16, #3 154 ; lsr is an alias of ubfm 155 ; CHECK-NEXT: lsr [[REG2:x[0-9]+]], [[REG1]], #2 156 ; CHECK-NEXT: str [[REG2]], 157 ; CHECK-NEXT: ret 158 %0 = load i64, i64* %y, align 8 159 %and = and i64 %0, -8 160 %shr = lshr i64 %x, 16 161 %and1 = and i64 %shr, 7 162 %or = or i64 %and, %and1 163 %shr1 = lshr i64 %or, 2 164 store i64 %shr1, i64* %y, align 8 165 ret void 166 } 167 168 169 ; Check if we can still catch bfm instruction when we drop some high bits 170 ; (i64 version) 171 define void @fct9(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp { 172 entry: 173 ; CHECK-LABEL: fct9: 174 ; CHECK: ldr [[REG1:x[0-9]+]], 175 ; CHECK-NEXT: bfxil [[REG1]], x1, #16, #3 176 ; lsr is an alias of ubfm 177 ; CHECK-NEXT: lsl [[REG2:x[0-9]+]], [[REG1]], #2 178 ; CHECK-NEXT: str [[REG2]], 179 ; CHECK-NEXT: ret 180 %0 = load i64, i64* %y, align 8 181 %and = and i64 %0, -8 182 %shr = lshr i64 %x, 16 183 %and1 = and i64 %shr, 7 184 %or = or i64 %and, %and1 185 %shl = shl i64 %or, 2 186 store i64 %shl, i64* %y, align 8 187 ret void 188 } 189 190 ; Check if we can catch bfm instruction when lsb is 0 (i.e., no lshr) 191 ; (i32 version) 192 define void @fct10(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp { 193 entry: 194 ; CHECK-LABEL: fct10: 195 ; CHECK: ldr [[REG1:w[0-9]+]], 196 ; CHECK-NEXT: bfxil [[REG1]], w1, #0, #3 197 ; lsl is an alias of ubfm 198 ; CHECK-NEXT: lsl [[REG2:w[0-9]+]], [[REG1]], #2 199 ; CHECK-NEXT: str [[REG2]], 200 ; CHECK-NEXT: ret 201 %0 = load i32, i32* %y, align 8 202 %and = and i32 %0, -8 203 %and1 = and i32 %x, 7 204 %or = or i32 %and, %and1 205 %shl = shl i32 %or, 2 206 store i32 %shl, i32* %y, align 8 207 ret void 208 } 209 210 ; Check if we can catch bfm instruction when lsb is 0 (i.e., no lshr) 211 ; (i64 version) 212 define void @fct11(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp { 213 entry: 214 ; CHECK-LABEL: fct11: 215 ; CHECK: ldr [[REG1:x[0-9]+]], 216 ; CHECK-NEXT: bfxil [[REG1]], x1, #0, #3 217 ; lsl is an alias of ubfm 218 ; CHECK-NEXT: lsl [[REG2:x[0-9]+]], [[REG1]], #2 219 ; CHECK-NEXT: str [[REG2]], 220 ; CHECK-NEXT: ret 221 %0 = load i64, i64* %y, align 8 222 %and = and i64 %0, -8 223 %and1 = and i64 %x, 7 224 %or = or i64 %and, %and1 225 %shl = shl i64 %or, 2 226 store i64 %shl, i64* %y, align 8 227 ret void 228 } 229 230 define zeroext i1 @fct12bis(i32 %tmp2) unnamed_addr nounwind ssp align 2 { 231 ; CHECK-LABEL: fct12bis: 232 ; CHECK-NOT: and 233 ; CHECK: ubfx w0, w0, #11, #1 234 %and.i.i = and i32 %tmp2, 2048 235 %tobool.i.i = icmp ne i32 %and.i.i, 0 236 ret i1 %tobool.i.i 237 } 238 239 ; Check if we can still catch bfm instruction when we drop some high bits 240 ; and some low bits 241 define void @fct12(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp { 242 entry: 243 ; CHECK-LABEL: fct12: 244 ; CHECK: ldr [[REG1:w[0-9]+]], 245 ; CHECK-NEXT: bfxil [[REG1]], w1, #16, #3 246 ; lsr is an alias of ubfm 247 ; CHECK-NEXT: ubfx [[REG2:w[0-9]+]], [[REG1]], #2, #28 248 ; CHECK-NEXT: str [[REG2]], 249 ; CHECK-NEXT: ret 250 %0 = load i32, i32* %y, align 8 251 %and = and i32 %0, -8 252 %shr = lshr i32 %x, 16 253 %and1 = and i32 %shr, 7 254 %or = or i32 %and, %and1 255 %shl = shl i32 %or, 2 256 %shr2 = lshr i32 %shl, 4 257 store i32 %shr2, i32* %y, align 8 258 ret void 259 } 260 261 ; Check if we can still catch bfm instruction when we drop some high bits 262 ; and some low bits 263 ; (i64 version) 264 define void @fct13(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp { 265 entry: 266 ; CHECK-LABEL: fct13: 267 ; CHECK: ldr [[REG1:x[0-9]+]], 268 ; CHECK-NEXT: bfxil [[REG1]], x1, #16, #3 269 ; lsr is an alias of ubfm 270 ; CHECK-NEXT: ubfx [[REG2:x[0-9]+]], [[REG1]], #2, #60 271 ; CHECK-NEXT: str [[REG2]], 272 ; CHECK-NEXT: ret 273 %0 = load i64, i64* %y, align 8 274 %and = and i64 %0, -8 275 %shr = lshr i64 %x, 16 276 %and1 = and i64 %shr, 7 277 %or = or i64 %and, %and1 278 %shl = shl i64 %or, 2 279 %shr2 = lshr i64 %shl, 4 280 store i64 %shr2, i64* %y, align 8 281 ret void 282 } 283 284 285 ; Check if we can still catch bfm instruction when we drop some high bits 286 ; and some low bits 287 define void @fct14(i32* nocapture %y, i32 %x, i32 %x1) nounwind optsize inlinehint ssp { 288 entry: 289 ; CHECK-LABEL: fct14: 290 ; CHECK: ldr [[REG1:w[0-9]+]], 291 ; CHECK-NEXT: bfxil [[REG1]], w1, #16, #8 292 ; lsr is an alias of ubfm 293 ; CHECK-NEXT: lsr [[REG2:w[0-9]+]], [[REG1]], #4 294 ; CHECK-NEXT: bfxil [[REG2]], w2, #5, #3 295 ; lsl is an alias of ubfm 296 ; CHECK-NEXT: lsl [[REG3:w[0-9]+]], [[REG2]], #2 297 ; CHECK-NEXT: str [[REG3]], 298 ; CHECK-NEXT: ret 299 %0 = load i32, i32* %y, align 8 300 %and = and i32 %0, -256 301 %shr = lshr i32 %x, 16 302 %and1 = and i32 %shr, 255 303 %or = or i32 %and, %and1 304 %shl = lshr i32 %or, 4 305 %and2 = and i32 %shl, -8 306 %shr1 = lshr i32 %x1, 5 307 %and3 = and i32 %shr1, 7 308 %or1 = or i32 %and2, %and3 309 %shl1 = shl i32 %or1, 2 310 store i32 %shl1, i32* %y, align 8 311 ret void 312 } 313 314 ; Check if we can still catch bfm instruction when we drop some high bits 315 ; and some low bits 316 ; (i64 version) 317 define void @fct15(i64* nocapture %y, i64 %x, i64 %x1) nounwind optsize inlinehint ssp { 318 entry: 319 ; CHECK-LABEL: fct15: 320 ; CHECK: ldr [[REG1:x[0-9]+]], 321 ; CHECK-NEXT: bfxil [[REG1]], x1, #16, #8 322 ; lsr is an alias of ubfm 323 ; CHECK-NEXT: lsr [[REG2:x[0-9]+]], [[REG1]], #4 324 ; CHECK-NEXT: bfxil [[REG2]], x2, #5, #3 325 ; lsl is an alias of ubfm 326 ; CHECK-NEXT: lsl [[REG3:x[0-9]+]], [[REG2]], #2 327 ; CHECK-NEXT: str [[REG3]], 328 ; CHECK-NEXT: ret 329 %0 = load i64, i64* %y, align 8 330 %and = and i64 %0, -256 331 %shr = lshr i64 %x, 16 332 %and1 = and i64 %shr, 255 333 %or = or i64 %and, %and1 334 %shl = lshr i64 %or, 4 335 %and2 = and i64 %shl, -8 336 %shr1 = lshr i64 %x1, 5 337 %and3 = and i64 %shr1, 7 338 %or1 = or i64 %and2, %and3 339 %shl1 = shl i64 %or1, 2 340 store i64 %shl1, i64* %y, align 8 341 ret void 342 } 343 344 ; Check if we can still catch bfm instruction when we drop some high bits 345 ; and some low bits and a masking operation has to be kept 346 define void @fct16(i32* nocapture %y, i32 %x) nounwind optsize inlinehint ssp { 347 entry: 348 ; CHECK-LABEL: fct16: 349 ; CHECK: ldr [[REG1:w[0-9]+]], 350 ; Create the constant 351 ; CHECK: movz [[REGCST:w[0-9]+]], #0x1a, lsl #16 352 ; CHECK: movk [[REGCST]], #0x8160 353 ; Do the masking 354 ; CHECK: and [[REG2:w[0-9]+]], [[REG1]], [[REGCST]] 355 ; CHECK-NEXT: bfxil [[REG2]], w1, #16, #3 356 ; lsr is an alias of ubfm 357 ; CHECK-NEXT: ubfx [[REG3:w[0-9]+]], [[REG2]], #2, #28 358 ; CHECK-NEXT: str [[REG3]], 359 ; CHECK-NEXT: ret 360 %0 = load i32, i32* %y, align 8 361 %and = and i32 %0, 1737056 362 %shr = lshr i32 %x, 16 363 %and1 = and i32 %shr, 7 364 %or = or i32 %and, %and1 365 %shl = shl i32 %or, 2 366 %shr2 = lshr i32 %shl, 4 367 store i32 %shr2, i32* %y, align 8 368 ret void 369 } 370 371 372 ; Check if we can still catch bfm instruction when we drop some high bits 373 ; and some low bits and a masking operation has to be kept 374 ; (i64 version) 375 define void @fct17(i64* nocapture %y, i64 %x) nounwind optsize inlinehint ssp { 376 entry: 377 ; CHECK-LABEL: fct17: 378 ; CHECK: ldr [[REG1:x[0-9]+]], 379 ; Create the constant 380 ; CHECK: movz w[[REGCST:[0-9]+]], #0x1a, lsl #16 381 ; CHECK: movk w[[REGCST]], #0x8160 382 ; Do the masking 383 ; CHECK: and [[REG2:x[0-9]+]], [[REG1]], x[[REGCST]] 384 ; CHECK-NEXT: bfxil [[REG2]], x1, #16, #3 385 ; lsr is an alias of ubfm 386 ; CHECK-NEXT: ubfx [[REG3:x[0-9]+]], [[REG2]], #2, #60 387 ; CHECK-NEXT: str [[REG3]], 388 ; CHECK-NEXT: ret 389 %0 = load i64, i64* %y, align 8 390 %and = and i64 %0, 1737056 391 %shr = lshr i64 %x, 16 392 %and1 = and i64 %shr, 7 393 %or = or i64 %and, %and1 394 %shl = shl i64 %or, 2 395 %shr2 = lshr i64 %shl, 4 396 store i64 %shr2, i64* %y, align 8 397 ret void 398 } 399 400 define i64 @fct18(i32 %xor72) nounwind ssp { 401 ; CHECK-LABEL: fct18: 402 ; CHECK: ubfx x0, x0, #9, #8 403 %shr81 = lshr i32 %xor72, 9 404 %conv82 = zext i32 %shr81 to i64 405 %result = and i64 %conv82, 255 406 ret i64 %result 407 } 408 409 ; Using the access to the global array to keep the instruction and control flow. 410 @first_ones = external global [65536 x i8] 411 412 ; Function Attrs: nounwind readonly ssp 413 define i32 @fct19(i64 %arg1) nounwind readonly ssp { 414 ; CHECK-LABEL: fct19: 415 entry: 416 %x.sroa.1.0.extract.shift = lshr i64 %arg1, 16 417 %x.sroa.1.0.extract.trunc = trunc i64 %x.sroa.1.0.extract.shift to i16 418 %x.sroa.3.0.extract.shift = lshr i64 %arg1, 32 419 %x.sroa.5.0.extract.shift = lshr i64 %arg1, 48 420 %tobool = icmp eq i64 %x.sroa.5.0.extract.shift, 0 421 br i1 %tobool, label %if.end, label %if.then 422 423 if.then: ; preds = %entry 424 %arrayidx3 = getelementptr inbounds [65536 x i8], [65536 x i8]* @first_ones, i64 0, i64 %x.sroa.5.0.extract.shift 425 %0 = load i8, i8* %arrayidx3, align 1 426 %conv = zext i8 %0 to i32 427 br label %return 428 429 ; OPT-LABEL: if.end 430 if.end: ; preds = %entry 431 ; OPT: lshr 432 ; CHECK: ubfx [[REG1:x[0-9]+]], [[REG2:x[0-9]+]], #32, #16 433 %x.sroa.3.0.extract.trunc = trunc i64 %x.sroa.3.0.extract.shift to i16 434 %tobool6 = icmp eq i16 %x.sroa.3.0.extract.trunc, 0 435 ; CHECK: cbz 436 br i1 %tobool6, label %if.end13, label %if.then7 437 438 ; OPT-LABEL: if.then7 439 if.then7: ; preds = %if.end 440 ; OPT: lshr 441 ; "and" should be combined to "ubfm" while "ubfm" should be removed by cse. 442 ; So neither of them should be in the assemble code. 443 ; CHECK-NOT: and 444 ; CHECK-NOT: ubfm 445 %idxprom10 = and i64 %x.sroa.3.0.extract.shift, 65535 446 %arrayidx11 = getelementptr inbounds [65536 x i8], [65536 x i8]* @first_ones, i64 0, i64 %idxprom10 447 %1 = load i8, i8* %arrayidx11, align 1 448 %conv12 = zext i8 %1 to i32 449 %add = add nsw i32 %conv12, 16 450 br label %return 451 452 ; OPT-LABEL: if.end13 453 if.end13: ; preds = %if.end 454 ; OPT: lshr 455 ; OPT: trunc 456 ; CHECK: ubfx [[REG3:x[0-9]+]], [[REG4:x[0-9]+]], #16, #16 457 %tobool16 = icmp eq i16 %x.sroa.1.0.extract.trunc, 0 458 ; CHECK: cbz 459 br i1 %tobool16, label %return, label %if.then17 460 461 ; OPT-LABEL: if.then17 462 if.then17: ; preds = %if.end13 463 ; OPT: lshr 464 ; "and" should be combined to "ubfm" while "ubfm" should be removed by cse. 465 ; So neither of them should be in the assemble code. 466 ; CHECK-NOT: and 467 ; CHECK-NOT: ubfm 468 %idxprom20 = and i64 %x.sroa.1.0.extract.shift, 65535 469 %arrayidx21 = getelementptr inbounds [65536 x i8], [65536 x i8]* @first_ones, i64 0, i64 %idxprom20 470 %2 = load i8, i8* %arrayidx21, align 1 471 %conv22 = zext i8 %2 to i32 472 %add23 = add nsw i32 %conv22, 32 473 br label %return 474 475 return: ; preds = %if.end13, %if.then17, %if.then7, %if.then 476 ; CHECK: ret 477 %retval.0 = phi i32 [ %conv, %if.then ], [ %add, %if.then7 ], [ %add23, %if.then17 ], [ 64, %if.end13 ] 478 ret i32 %retval.0 479 } 480 481 ; Make sure we do not assert if the immediate in and is bigger than i64. 482 ; PR19503. 483 ; OPT-LABEL: @fct20 484 ; OPT: lshr 485 ; OPT-NOT: lshr 486 ; OPT: ret 487 ; CHECK-LABEL: fct20: 488 ; CHECK: ret 489 define i80 @fct20(i128 %a, i128 %b) { 490 entry: 491 %shr = lshr i128 %a, 18 492 %conv = trunc i128 %shr to i80 493 %tobool = icmp eq i128 %b, 0 494 br i1 %tobool, label %then, label %end 495 then: 496 %and = and i128 %shr, 483673642326615442599424 497 %conv2 = trunc i128 %and to i80 498 br label %end 499 end: 500 %conv3 = phi i80 [%conv, %entry], [%conv2, %then] 501 ret i80 %conv3 502 } 503 504 ; Check if we can still catch UBFX when "AND" is used by SHL. 505 ; CHECK-LABEL: fct21: 506 ; CHECK: ubfx 507 @arr = external global [8 x [64 x i64]] 508 define i64 @fct21(i64 %x) { 509 entry: 510 %shr = lshr i64 %x, 4 511 %and = and i64 %shr, 15 512 %arrayidx = getelementptr inbounds [8 x [64 x i64]], [8 x [64 x i64]]* @arr, i64 0, i64 0, i64 %and 513 %0 = load i64, i64* %arrayidx, align 8 514 ret i64 %0 515 } 516 517 define i16 @test_ignored_rightbits(i32 %dst, i32 %in) { 518 ; CHECK-LABEL: test_ignored_rightbits: 519 520 %positioned_field = shl i32 %in, 3 521 %positioned_masked_field = and i32 %positioned_field, 120 522 %masked_dst = and i32 %dst, 7 523 %insertion = or i32 %masked_dst, %positioned_masked_field 524 ; CHECK: {{bfm|bfi|bfxil}} 525 526 %shl16 = shl i32 %insertion, 8 527 %or18 = or i32 %shl16, %insertion 528 %conv19 = trunc i32 %or18 to i16 529 ; CHECK: bfi {{w[0-9]+}}, {{w[0-9]+}}, #8, #7 530 531 ret i16 %conv19 532 } 533