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