Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc < %s -stress-early-ifcvt -aarch64-atomic-cfg-tidy=0 | FileCheck %s
      2 target triple = "arm64-apple-macosx"
      3 
      4 ; CHECK: mm2
      5 define i32 @mm2(i32* nocapture %p, i32 %n) nounwind uwtable readonly ssp {
      6 entry:
      7   br label %do.body
      8 
      9 ; CHECK: do.body
     10 ; Loop body has no branches before the backedge.
     11 ; CHECK-NOT: LBB
     12 do.body:
     13   %max.0 = phi i32 [ 0, %entry ], [ %max.1, %do.cond ]
     14   %min.0 = phi i32 [ 0, %entry ], [ %min.1, %do.cond ]
     15   %n.addr.0 = phi i32 [ %n, %entry ], [ %dec, %do.cond ]
     16   %p.addr.0 = phi i32* [ %p, %entry ], [ %incdec.ptr, %do.cond ]
     17   %incdec.ptr = getelementptr inbounds i32, i32* %p.addr.0, i64 1
     18   %0 = load i32, i32* %p.addr.0, align 4
     19   %cmp = icmp sgt i32 %0, %max.0
     20   br i1 %cmp, label %do.cond, label %if.else
     21 
     22 if.else:
     23   %cmp1 = icmp slt i32 %0, %min.0
     24   %.min.0 = select i1 %cmp1, i32 %0, i32 %min.0
     25   br label %do.cond
     26 
     27 do.cond:
     28   %max.1 = phi i32 [ %0, %do.body ], [ %max.0, %if.else ]
     29   %min.1 = phi i32 [ %min.0, %do.body ], [ %.min.0, %if.else ]
     30 ; CHECK: cbnz
     31   %dec = add i32 %n.addr.0, -1
     32   %tobool = icmp eq i32 %dec, 0
     33   br i1 %tobool, label %do.end, label %do.body
     34 
     35 do.end:
     36   %sub = sub nsw i32 %max.1, %min.1
     37   ret i32 %sub
     38 }
     39 
     40 ; CHECK-LABEL: fold_inc_true_32:
     41 ; CHECK: {{subs.*wzr,|cmp}} w2, #1
     42 ; CHECK-NEXT: csinc w0, w1, w0, eq
     43 ; CHECK-NEXT: ret
     44 define i32 @fold_inc_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
     45 entry:
     46   %tobool = icmp eq i32 %c, 1
     47   %inc = add nsw i32 %x, 1
     48   br i1 %tobool, label %eq_bb, label %done
     49 
     50 eq_bb:
     51   br label %done
     52 
     53 done:
     54   %cond = phi i32 [ %y, %eq_bb ], [ %inc, %entry ]
     55   ret i32 %cond
     56 }
     57 
     58 ; CHECK-LABEL: fold_inc_true_64:
     59 ; CHECK: {{subs.*xzr,|cmp}} x2, #1
     60 ; CHECK-NEXT: csinc x0, x1, x0, eq
     61 ; CHECK-NEXT: ret
     62 define i64 @fold_inc_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
     63 entry:
     64   %tobool = icmp eq i64 %c, 1
     65   %inc = add nsw i64 %x, 1
     66   br i1 %tobool, label %eq_bb, label %done
     67 
     68 eq_bb:
     69   br label %done
     70 
     71 done:
     72   %cond = phi i64 [ %y, %eq_bb ], [ %inc, %entry ]
     73   ret i64 %cond
     74 }
     75 
     76 ; CHECK-LABEL: fold_inc_false_32:
     77 ; CHECK: {{subs.*wzr,|cmp}} w2, #1
     78 ; CHECK-NEXT: csinc w0, w1, w0, ne
     79 ; CHECK-NEXT: ret
     80 define i32 @fold_inc_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
     81 entry:
     82   %tobool = icmp eq i32 %c, 1
     83   %inc = add nsw i32 %x, 1
     84   br i1 %tobool, label %eq_bb, label %done
     85 
     86 eq_bb:
     87   br label %done
     88 
     89 done:
     90   %cond = phi i32 [ %inc, %eq_bb ], [ %y, %entry ]
     91   ret i32 %cond
     92 }
     93 
     94 ; CHECK-LABEL: fold_inc_false_64:
     95 ; CHECK: {{subs.*xzr,|cmp}} x2, #1
     96 ; CHECK-NEXT: csinc x0, x1, x0, ne
     97 ; CHECK-NEXT: ret
     98 define i64 @fold_inc_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
     99 entry:
    100   %tobool = icmp eq i64 %c, 1
    101   %inc = add nsw i64 %x, 1
    102   br i1 %tobool, label %eq_bb, label %done
    103 
    104 eq_bb:
    105   br label %done
    106 
    107 done:
    108   %cond = phi i64 [ %inc, %eq_bb ], [ %y, %entry ]
    109   ret i64 %cond
    110 }
    111 
    112 ; CHECK-LABEL: fold_inv_true_32:
    113 ; CHECK: {{subs.*wzr,|cmp}} w2, #1
    114 ; CHECK-NEXT: csinv w0, w1, w0, eq
    115 ; CHECK-NEXT: ret
    116 define i32 @fold_inv_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
    117 entry:
    118   %tobool = icmp eq i32 %c, 1
    119   %inv = xor i32 %x, -1
    120   br i1 %tobool, label %eq_bb, label %done
    121 
    122 eq_bb:
    123   br label %done
    124 
    125 done:
    126   %cond = phi i32 [ %y, %eq_bb ], [ %inv, %entry ]
    127   ret i32 %cond
    128 }
    129 
    130 ; CHECK-LABEL: fold_inv_true_64:
    131 ; CHECK: {{subs.*xzr,|cmp}} x2, #1
    132 ; CHECK-NEXT: csinv x0, x1, x0, eq
    133 ; CHECK-NEXT: ret
    134 define i64 @fold_inv_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
    135 entry:
    136   %tobool = icmp eq i64 %c, 1
    137   %inv = xor i64 %x, -1
    138   br i1 %tobool, label %eq_bb, label %done
    139 
    140 eq_bb:
    141   br label %done
    142 
    143 done:
    144   %cond = phi i64 [ %y, %eq_bb ], [ %inv, %entry ]
    145   ret i64 %cond
    146 }
    147 
    148 ; CHECK-LABEL: fold_inv_false_32:
    149 ; CHECK: {{subs.*wzr,|cmp}} w2, #1
    150 ; CHECK-NEXT: csinv w0, w1, w0, ne
    151 ; CHECK-NEXT: ret
    152 define i32 @fold_inv_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
    153 entry:
    154   %tobool = icmp eq i32 %c, 1
    155   %inv = xor i32 %x, -1
    156   br i1 %tobool, label %eq_bb, label %done
    157 
    158 eq_bb:
    159   br label %done
    160 
    161 done:
    162   %cond = phi i32 [ %inv, %eq_bb ], [ %y, %entry ]
    163   ret i32 %cond
    164 }
    165 
    166 ; CHECK-LABEL: fold_inv_false_64:
    167 ; CHECK: {{subs.*xzr,|cmp}} x2, #1
    168 ; CHECK-NEXT: csinv x0, x1, x0, ne
    169 ; CHECK-NEXT: ret
    170 define i64 @fold_inv_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
    171 entry:
    172   %tobool = icmp eq i64 %c, 1
    173   %inv = xor i64 %x, -1
    174   br i1 %tobool, label %eq_bb, label %done
    175 
    176 eq_bb:
    177   br label %done
    178 
    179 done:
    180   %cond = phi i64 [ %inv, %eq_bb ], [ %y, %entry ]
    181   ret i64 %cond
    182 }
    183 
    184 ; CHECK-LABEL: fold_neg_true_32:
    185 ; CHECK: {{subs.*wzr,|cmp}} w2, #1
    186 ; CHECK-NEXT: csneg w0, w1, w0, eq
    187 ; CHECK-NEXT: ret
    188 define i32 @fold_neg_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
    189 entry:
    190   %tobool = icmp eq i32 %c, 1
    191   %neg = sub nsw i32 0, %x
    192   br i1 %tobool, label %eq_bb, label %done
    193 
    194 eq_bb:
    195   br label %done
    196 
    197 done:
    198   %cond = phi i32 [ %y, %eq_bb ], [ %neg, %entry ]
    199   ret i32 %cond
    200 }
    201 
    202 ; CHECK-LABEL: fold_neg_true_64:
    203 ; CHECK: {{subs.*xzr,|cmp}} x2, #1
    204 ; CHECK-NEXT: csneg x0, x1, x0, eq
    205 ; CHECK-NEXT: ret
    206 define i64 @fold_neg_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
    207 entry:
    208   %tobool = icmp eq i64 %c, 1
    209   %neg = sub nsw i64 0, %x
    210   br i1 %tobool, label %eq_bb, label %done
    211 
    212 eq_bb:
    213   br label %done
    214 
    215 done:
    216   %cond = phi i64 [ %y, %eq_bb ], [ %neg, %entry ]
    217   ret i64 %cond
    218 }
    219 
    220 ; CHECK-LABEL: fold_neg_false_32:
    221 ; CHECK: {{subs.*wzr,|cmp}} w2, #1
    222 ; CHECK-NEXT: csneg w0, w1, w0, ne
    223 ; CHECK-NEXT: ret
    224 define i32 @fold_neg_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
    225 entry:
    226   %tobool = icmp eq i32 %c, 1
    227   %neg = sub nsw i32 0, %x
    228   br i1 %tobool, label %eq_bb, label %done
    229 
    230 eq_bb:
    231   br label %done
    232 
    233 done:
    234   %cond = phi i32 [ %neg, %eq_bb ], [ %y, %entry ]
    235   ret i32 %cond
    236 }
    237 
    238 ; CHECK-LABEL: fold_neg_false_64:
    239 ; CHECK: {{subs.*xzr,|cmp}} x2, #1
    240 ; CHECK-NEXT: csneg x0, x1, x0, ne
    241 ; CHECK-NEXT: ret
    242 define i64 @fold_neg_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
    243 entry:
    244   %tobool = icmp eq i64 %c, 1
    245   %neg = sub nsw i64 0, %x
    246   br i1 %tobool, label %eq_bb, label %done
    247 
    248 eq_bb:
    249   br label %done
    250 
    251 done:
    252   %cond = phi i64 [ %neg, %eq_bb ], [ %y, %entry ]
    253   ret i64 %cond
    254 }
    255 
    256 ; CHECK: cbnz_32
    257 ; CHECK: {{subs.*wzr,|cmp}} w2, #0
    258 ; CHECK-NEXT: csel w0, w1, w0, ne
    259 ; CHECK-NEXT: ret
    260 define i32 @cbnz_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
    261 entry:
    262   %tobool = icmp eq i32 %c, 0
    263   br i1 %tobool, label %eq_bb, label %done
    264 
    265 eq_bb:
    266   br label %done
    267 
    268 done:
    269   %cond = phi i32 [ %x, %eq_bb ], [ %y, %entry ]
    270   ret i32 %cond
    271 }
    272 
    273 ; CHECK: cbnz_64
    274 ; CHECK: {{subs.*xzr,|cmp}} x2, #0
    275 ; CHECK-NEXT: csel x0, x1, x0, ne
    276 ; CHECK-NEXT: ret
    277 define i64 @cbnz_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
    278 entry:
    279   %tobool = icmp eq i64 %c, 0
    280   br i1 %tobool, label %eq_bb, label %done
    281 
    282 eq_bb:
    283   br label %done
    284 
    285 done:
    286   %cond = phi i64 [ %x, %eq_bb ], [ %y, %entry ]
    287   ret i64 %cond
    288 }
    289 
    290 ; CHECK: cbz_32
    291 ; CHECK: {{subs.*wzr,|cmp}} w2, #0
    292 ; CHECK-NEXT: csel w0, w1, w0, eq
    293 ; CHECK-NEXT: ret
    294 define i32 @cbz_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
    295 entry:
    296   %tobool = icmp ne i32 %c, 0
    297   br i1 %tobool, label %ne_bb, label %done
    298 
    299 ne_bb:
    300   br label %done
    301 
    302 done:
    303   %cond = phi i32 [ %x, %ne_bb ], [ %y, %entry ]
    304   ret i32 %cond
    305 }
    306 
    307 ; CHECK: cbz_64
    308 ; CHECK: {{subs.*xzr,|cmp}} x2, #0
    309 ; CHECK-NEXT: csel x0, x1, x0, eq
    310 ; CHECK-NEXT: ret
    311 define i64 @cbz_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
    312 entry:
    313   %tobool = icmp ne i64 %c, 0
    314   br i1 %tobool, label %ne_bb, label %done
    315 
    316 ne_bb:
    317   br label %done
    318 
    319 done:
    320   %cond = phi i64 [ %x, %ne_bb ], [ %y, %entry ]
    321   ret i64 %cond
    322 }
    323 
    324 ; CHECK: tbnz_32
    325 ; CHECK: {{ands.*xzr,|tst}} w2, #0x80
    326 ; CHECK-NEXT: csel w0, w1, w0, ne
    327 ; CHECK-NEXT: ret
    328 define i32 @tbnz_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
    329 entry:
    330   %mask = and i32 %c, 128
    331   %tobool = icmp eq i32 %mask, 0
    332   br i1 %tobool, label %eq_bb, label %done
    333 
    334 eq_bb:
    335   br label %done
    336 
    337 done:
    338   %cond = phi i32 [ %x, %eq_bb ], [ %y, %entry ]
    339   ret i32 %cond
    340 }
    341 
    342 ; CHECK: tbnz_64
    343 ; CHECK: {{ands.*xzr,|tst}} x2, #0x8000000000000000
    344 ; CHECK-NEXT: csel x0, x1, x0, ne
    345 ; CHECK-NEXT: ret
    346 define i64 @tbnz_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
    347 entry:
    348   %mask = and i64 %c, 9223372036854775808
    349   %tobool = icmp eq i64 %mask, 0
    350   br i1 %tobool, label %eq_bb, label %done
    351 
    352 eq_bb:
    353   br label %done
    354 
    355 done:
    356   %cond = phi i64 [ %x, %eq_bb ], [ %y, %entry ]
    357   ret i64 %cond
    358 }
    359 
    360 ; CHECK: tbz_32
    361 ; CHECK: {{ands.*xzr,|tst}} w2, #0x80
    362 ; CHECK-NEXT: csel w0, w1, w0, eq
    363 ; CHECK-NEXT: ret
    364 define i32 @tbz_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
    365 entry:
    366   %mask = and i32 %c, 128
    367   %tobool = icmp ne i32 %mask, 0
    368   br i1 %tobool, label %ne_bb, label %done
    369 
    370 ne_bb:
    371   br label %done
    372 
    373 done:
    374   %cond = phi i32 [ %x, %ne_bb ], [ %y, %entry ]
    375   ret i32 %cond
    376 }
    377 
    378 ; CHECK: tbz_64
    379 ; CHECK: {{ands.*xzr,|tst}} x2, #0x8000000000000000
    380 ; CHECK-NEXT: csel x0, x1, x0, eq
    381 ; CHECK-NEXT: ret
    382 define i64 @tbz_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
    383 entry:
    384   %mask = and i64 %c, 9223372036854775808
    385   %tobool = icmp ne i64 %mask, 0
    386   br i1 %tobool, label %ne_bb, label %done
    387 
    388 ne_bb:
    389   br label %done
    390 
    391 done:
    392   %cond = phi i64 [ %x, %ne_bb ], [ %y, %entry ]
    393   ret i64 %cond
    394 }
    395 
    396 ; This function from 175.vpr folds an ADDWri into a CSINC.
    397 ; Remember to clear the kill flag on the ADDWri.
    398 define i32 @get_ytrack_to_xtracks() nounwind ssp {
    399 entry:
    400   br label %for.body
    401 
    402 for.body:
    403   %x0 = load i32, i32* undef, align 4
    404   br i1 undef, label %if.then.i146, label %is_sbox.exit155
    405 
    406 if.then.i146:
    407   %add8.i143 = add nsw i32 0, %x0
    408   %rem.i144 = srem i32 %add8.i143, %x0
    409   %add9.i145 = add i32 %rem.i144, 1
    410   br label %is_sbox.exit155
    411 
    412 is_sbox.exit155:                                  ; preds = %if.then.i146, %for.body
    413   %seg_offset.0.i151 = phi i32 [ %add9.i145, %if.then.i146 ], [ undef, %for.body ]
    414   %idxprom15.i152 = sext i32 %seg_offset.0.i151 to i64
    415   %arrayidx18.i154 = getelementptr inbounds i32, i32* null, i64 %idxprom15.i152
    416   %x1 = load i32, i32* %arrayidx18.i154, align 4
    417   br i1 undef, label %for.body51, label %for.body
    418 
    419 for.body51:                                       ; preds = %is_sbox.exit155
    420   call fastcc void @get_switch_type(i32 %x1, i32 undef, i16 signext undef, i16 signext undef, i16* undef)
    421   unreachable
    422 }
    423 declare fastcc void @get_switch_type(i32, i32, i16 signext, i16 signext, i16* nocapture) nounwind ssp
    424