Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc < %s -march=aarch64 -mtriple=aarch64-linux-gnu | FileCheck %s
      2 
      3 ; marked as external to prevent possible optimizations
      4 @a = external global i32
      5 @b = external global i32
      6 @c = external global i32
      7 @d = external global i32
      8 
      9 ; (a > 10 && b == c) || (a >= 10 && b == d)
     10 define i32 @combine_gt_ge_10() #0 {
     11 ; CHECK-LABEL: combine_gt_ge_10
     12 ; CHECK: cmp
     13 ; CHECK: b.le
     14 ; CHECK: ret
     15 ; CHECK-NOT: cmp
     16 ; CHECK: b.lt
     17 entry:
     18   %0 = load i32, i32* @a, align 4
     19   %cmp = icmp sgt i32 %0, 10
     20   br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
     21 
     22 land.lhs.true:                                    ; preds = %entry
     23   %1 = load i32, i32* @b, align 4
     24   %2 = load i32, i32* @c, align 4
     25   %cmp1 = icmp eq i32 %1, %2
     26   br i1 %cmp1, label %return, label %land.lhs.true3
     27 
     28 lor.lhs.false:                                    ; preds = %entry
     29   %cmp2 = icmp sgt i32 %0, 9
     30   br i1 %cmp2, label %land.lhs.true3, label %if.end
     31 
     32 land.lhs.true3:                                   ; preds = %lor.lhs.false, %land.lhs.true
     33   %3 = load i32, i32* @b, align 4
     34   %4 = load i32, i32* @d, align 4
     35   %cmp4 = icmp eq i32 %3, %4
     36   br i1 %cmp4, label %return, label %if.end
     37 
     38 if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
     39   br label %return
     40 
     41 return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
     42   %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
     43   ret i32 %retval.0
     44 }
     45 
     46 ; (a > 5 && b == c) || (a < 5 && b == d)
     47 define i32 @combine_gt_lt_5() #0 {
     48 ; CHECK-LABEL: combine_gt_lt_5
     49 ; CHECK: cmp
     50 ; CHECK: b.le
     51 ; CHECK: ret
     52 ; CHECK-NOT: cmp
     53 ; CHECK: b.ge
     54 entry:
     55   %0 = load i32, i32* @a, align 4
     56   %cmp = icmp sgt i32 %0, 5
     57   br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
     58 
     59 land.lhs.true:                                    ; preds = %entry
     60   %1 = load i32, i32* @b, align 4
     61   %2 = load i32, i32* @c, align 4
     62   %cmp1 = icmp eq i32 %1, %2
     63   br i1 %cmp1, label %return, label %if.end
     64 
     65 lor.lhs.false:                                    ; preds = %entry
     66   %cmp2 = icmp slt i32 %0, 5
     67   br i1 %cmp2, label %land.lhs.true3, label %if.end
     68 
     69 land.lhs.true3:                                   ; preds = %lor.lhs.false
     70   %3 = load i32, i32* @b, align 4
     71   %4 = load i32, i32* @d, align 4
     72   %cmp4 = icmp eq i32 %3, %4
     73   br i1 %cmp4, label %return, label %if.end
     74 
     75 if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
     76   br label %return
     77 
     78 return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
     79   %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
     80   ret i32 %retval.0
     81 }
     82 
     83 ; (a < 5 && b == c) || (a <= 5 && b == d)
     84 define i32 @combine_lt_ge_5() #0 {
     85 ; CHECK-LABEL: combine_lt_ge_5
     86 ; CHECK: cmp
     87 ; CHECK: b.ge
     88 ; CHECK: ret
     89 ; CHECK-NOT: cmp
     90 ; CHECK: b.gt
     91 entry:
     92   %0 = load i32, i32* @a, align 4
     93   %cmp = icmp slt i32 %0, 5
     94   br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
     95 
     96 land.lhs.true:                                    ; preds = %entry
     97   %1 = load i32, i32* @b, align 4
     98   %2 = load i32, i32* @c, align 4
     99   %cmp1 = icmp eq i32 %1, %2
    100   br i1 %cmp1, label %return, label %land.lhs.true3
    101 
    102 lor.lhs.false:                                    ; preds = %entry
    103   %cmp2 = icmp slt i32 %0, 6
    104   br i1 %cmp2, label %land.lhs.true3, label %if.end
    105 
    106 land.lhs.true3:                                   ; preds = %lor.lhs.false, %land.lhs.true
    107   %3 = load i32, i32* @b, align 4
    108   %4 = load i32, i32* @d, align 4
    109   %cmp4 = icmp eq i32 %3, %4
    110   br i1 %cmp4, label %return, label %if.end
    111 
    112 if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false
    113   br label %return
    114 
    115 return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
    116   %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
    117   ret i32 %retval.0
    118 }
    119 
    120 ; (a < 5 && b == c) || (a > 5 && b == d)
    121 define i32 @combine_lt_gt_5() #0 {
    122 ; CHECK-LABEL: combine_lt_gt_5
    123 ; CHECK: cmp
    124 ; CHECK: b.ge
    125 ; CHECK: ret
    126 ; CHECK-NOT: cmp
    127 ; CHECK: b.le
    128 entry:
    129   %0 = load i32, i32* @a, align 4
    130   %cmp = icmp slt i32 %0, 5
    131   br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
    132 
    133 land.lhs.true:                                    ; preds = %entry
    134   %1 = load i32, i32* @b, align 4
    135   %2 = load i32, i32* @c, align 4
    136   %cmp1 = icmp eq i32 %1, %2
    137   br i1 %cmp1, label %return, label %if.end
    138 
    139 lor.lhs.false:                                    ; preds = %entry
    140   %cmp2 = icmp sgt i32 %0, 5
    141   br i1 %cmp2, label %land.lhs.true3, label %if.end
    142 
    143 land.lhs.true3:                                   ; preds = %lor.lhs.false
    144   %3 = load i32, i32* @b, align 4
    145   %4 = load i32, i32* @d, align 4
    146   %cmp4 = icmp eq i32 %3, %4
    147   br i1 %cmp4, label %return, label %if.end
    148 
    149 if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
    150   br label %return
    151 
    152 return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
    153   %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
    154   ret i32 %retval.0
    155 }
    156 
    157 ; (a > -5 && b == c) || (a < -5 && b == d)
    158 define i32 @combine_gt_lt_n5() #0 {
    159 ; CHECK-LABEL: combine_gt_lt_n5
    160 ; CHECK: cmn
    161 ; CHECK: b.le
    162 ; CHECK: ret
    163 ; CHECK-NOT: cmn
    164 ; CHECK: b.ge
    165 entry:
    166   %0 = load i32, i32* @a, align 4
    167   %cmp = icmp sgt i32 %0, -5
    168   br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
    169 
    170 land.lhs.true:                                    ; preds = %entry
    171   %1 = load i32, i32* @b, align 4
    172   %2 = load i32, i32* @c, align 4
    173   %cmp1 = icmp eq i32 %1, %2
    174   br i1 %cmp1, label %return, label %if.end
    175 
    176 lor.lhs.false:                                    ; preds = %entry
    177   %cmp2 = icmp slt i32 %0, -5
    178   br i1 %cmp2, label %land.lhs.true3, label %if.end
    179 
    180 land.lhs.true3:                                   ; preds = %lor.lhs.false
    181   %3 = load i32, i32* @b, align 4
    182   %4 = load i32, i32* @d, align 4
    183   %cmp4 = icmp eq i32 %3, %4
    184   br i1 %cmp4, label %return, label %if.end
    185 
    186 if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
    187   br label %return
    188 
    189 return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
    190   %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
    191   ret i32 %retval.0
    192 }
    193 
    194 ; (a < -5 && b == c) || (a > -5 && b == d)
    195 define i32 @combine_lt_gt_n5() #0 {
    196 ; CHECK-LABEL: combine_lt_gt_n5
    197 ; CHECK: cmn
    198 ; CHECK: b.ge
    199 ; CHECK: ret
    200 ; CHECK-NOT: cmn
    201 ; CHECK: b.le
    202 entry:
    203   %0 = load i32, i32* @a, align 4
    204   %cmp = icmp slt i32 %0, -5
    205   br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
    206 
    207 land.lhs.true:                                    ; preds = %entry
    208   %1 = load i32, i32* @b, align 4
    209   %2 = load i32, i32* @c, align 4
    210   %cmp1 = icmp eq i32 %1, %2
    211   br i1 %cmp1, label %return, label %if.end
    212 
    213 lor.lhs.false:                                    ; preds = %entry
    214   %cmp2 = icmp sgt i32 %0, -5
    215   br i1 %cmp2, label %land.lhs.true3, label %if.end
    216 
    217 land.lhs.true3:                                   ; preds = %lor.lhs.false
    218   %3 = load i32, i32* @b, align 4
    219   %4 = load i32, i32* @d, align 4
    220   %cmp4 = icmp eq i32 %3, %4
    221   br i1 %cmp4, label %return, label %if.end
    222 
    223 if.end:                                           ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true
    224   br label %return
    225 
    226 return:                                           ; preds = %if.end, %land.lhs.true3, %land.lhs.true
    227   %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
    228   ret i32 %retval.0
    229 }
    230 
    231 %struct.Struct = type { i64, i64 }
    232 
    233 @glob = internal unnamed_addr global %struct.Struct* null, align 8
    234 
    235 declare %struct.Struct* @Update(%struct.Struct*) #1
    236 
    237 ; no checks for this case, it just should be processed without errors
    238 define void @combine_non_adjacent_cmp_br(%struct.Struct* nocapture readonly %hdCall) #0 {
    239 entry:
    240   %size = getelementptr inbounds %struct.Struct, %struct.Struct* %hdCall, i64 0, i32 0
    241   %0 = load i64, i64* %size, align 8
    242   br label %land.rhs
    243 
    244 land.rhs:
    245   %rp.06 = phi i64 [ %0, %entry ], [ %sub, %while.body ]
    246   %1 = load i64, i64* inttoptr (i64 24 to i64*), align 8
    247   %cmp2 = icmp sgt i64 %1, 0
    248   br i1 %cmp2, label %while.body, label %while.end
    249 
    250 while.body:
    251   %2 = load %struct.Struct*, %struct.Struct** @glob, align 8
    252   %call = tail call %struct.Struct* @Update(%struct.Struct* %2) #2
    253   %sub = add nsw i64 %rp.06, -2
    254   %cmp = icmp slt i64 %0, %rp.06
    255   br i1 %cmp, label %land.rhs, label %while.end
    256 
    257 while.end:
    258   ret void
    259 }
    260 
    261 ; undefined external to prevent possible optimizations
    262 declare void @do_something() #1
    263 
    264 define i32 @do_nothing_if_resultant_opcodes_would_differ() #0 {
    265 ; CHECK-LABEL: do_nothing_if_resultant_opcodes_would_differ
    266 ; CHECK: cmn
    267 ; CHECK: b.gt
    268 ; CHECK: cmp
    269 ; CHECK: b.gt
    270 entry:
    271   %0 = load i32, i32* @a, align 4
    272   %cmp4 = icmp slt i32 %0, -1
    273   br i1 %cmp4, label %while.body.preheader, label %while.end
    274 
    275 while.body.preheader:                             ; preds = %entry
    276   br label %while.body
    277 
    278 while.body:                                       ; preds = %while.body, %while.body.preheader
    279   %i.05 = phi i32 [ %inc, %while.body ], [ %0, %while.body.preheader ]
    280   tail call void @do_something() #2
    281   %inc = add nsw i32 %i.05, 1
    282   %cmp = icmp slt i32 %i.05, 0
    283   br i1 %cmp, label %while.body, label %while.cond.while.end_crit_edge
    284 
    285 while.cond.while.end_crit_edge:                   ; preds = %while.body
    286   %.pre = load i32, i32* @a, align 4
    287   br label %while.end
    288 
    289 while.end:                                        ; preds = %while.cond.while.end_crit_edge, %entry
    290   %1 = phi i32 [ %.pre, %while.cond.while.end_crit_edge ], [ %0, %entry ]
    291   %cmp1 = icmp slt i32 %1, 2
    292   br i1 %cmp1, label %land.lhs.true, label %if.end
    293 
    294 land.lhs.true:                                    ; preds = %while.end
    295   %2 = load i32, i32* @b, align 4
    296   %3 = load i32, i32* @d, align 4
    297   %cmp2 = icmp eq i32 %2, %3
    298   br i1 %cmp2, label %return, label %if.end
    299 
    300 if.end:                                           ; preds = %land.lhs.true, %while.end
    301   br label %return
    302 
    303 return:                                           ; preds = %if.end, %land.lhs.true
    304   %retval.0 = phi i32 [ 0, %if.end ], [ 123, %land.lhs.true ]
    305   ret i32 %retval.0
    306 }
    307 
    308 define i32 @do_nothing_if_compares_can_not_be_adjusted_to_each_other() #0 {
    309 ; CHECK-LABEL: do_nothing_if_compares_can_not_be_adjusted_to_each_other
    310 ; CHECK: cmp
    311 ; CHECK: b.gt
    312 ; CHECK: cmn
    313 ; CHECK: b.lt
    314 entry:
    315   %0 = load i32, i32* @a, align 4
    316   %cmp4 = icmp slt i32 %0, 1
    317   br i1 %cmp4, label %while.body.preheader, label %while.end
    318 
    319 while.body.preheader:                             ; preds = %entry
    320   br label %while.body
    321 
    322 while.body:                                       ; preds = %while.body, %while.body.preheader
    323   %i.05 = phi i32 [ %inc, %while.body ], [ %0, %while.body.preheader ]
    324   tail call void @do_something() #2
    325   %inc = add nsw i32 %i.05, 1
    326   %cmp = icmp slt i32 %i.05, 0
    327   br i1 %cmp, label %while.body, label %while.end.loopexit
    328 
    329 while.end.loopexit:                               ; preds = %while.body
    330   br label %while.end
    331 
    332 while.end:                                        ; preds = %while.end.loopexit, %entry
    333   %1 = load i32, i32* @c, align 4
    334   %cmp1 = icmp sgt i32 %1, -3
    335   br i1 %cmp1, label %land.lhs.true, label %if.end
    336 
    337 land.lhs.true:                                    ; preds = %while.end
    338   %2 = load i32, i32* @b, align 4
    339   %3 = load i32, i32* @d, align 4
    340   %cmp2 = icmp eq i32 %2, %3
    341   br i1 %cmp2, label %return, label %if.end
    342 
    343 if.end:                                           ; preds = %land.lhs.true, %while.end
    344   br label %return
    345 
    346 return:                                           ; preds = %if.end, %land.lhs.true
    347   %retval.0 = phi i32 [ 0, %if.end ], [ 123, %land.lhs.true ]
    348   ret i32 %retval.0
    349 }
    350 
    351 ; Test in the following case, we don't hit 'cmp' and trigger a false positive
    352 ; cmp  w19, #0
    353 ; cinc w0, w19, gt
    354 ; ...
    355 ; fcmp d8, #0.0
    356 ; b.gt .LBB0_5
    357 
    358 define i32 @fcmpri(i32 %argc, i8** nocapture readonly %argv) {
    359 
    360 ; CHECK-LABEL: fcmpri:
    361 ; CHECK: cmp w0, #2
    362 ; CHECK: b.lt .LBB9_3
    363 ; CHECK-NOT: cmp w0, #1
    364 ; CHECK-NOT: b.le .LBB9_3
    365 
    366 ; CHECK-LABEL-DAG: .LBB9_3
    367 ; CHECK: cmp w19, #0
    368 ; CHECK: fcmp d8, #0.0
    369 ; CHECK-NOT: cmp w19, #1
    370 ; CHECK-NOT: b.ge .LBB9_5
    371 
    372 entry:
    373   %cmp = icmp sgt i32 %argc, 1
    374   br i1 %cmp, label %land.lhs.true, label %if.end
    375 
    376 land.lhs.true:                                    ; preds = %entry
    377   %arrayidx = getelementptr inbounds i8*, i8** %argv, i64 1
    378   %0 = load i8*, i8** %arrayidx, align 8
    379   %cmp1 = icmp eq i8* %0, null
    380   br i1 %cmp1, label %if.end, label %return
    381 
    382 if.end:                                           ; preds = %land.lhs.true, %entry
    383   %call = call i32 @zoo(i32 1)
    384   %call2 = call double @yoo(i32 -1)
    385   %cmp4 = icmp sgt i32 %call, 0
    386   %add = zext i1 %cmp4 to i32
    387   %cond = add nsw i32 %add, %call
    388   %call7 = call i32 @xoo(i32 %cond, i32 2)
    389   %cmp9 = fcmp ogt double %call2, 0.000000e+00
    390   br i1 %cmp9, label %cond.end14, label %cond.false12
    391 
    392 cond.false12:                                     ; preds = %if.end
    393   %sub = fadd fast double %call2, -1.000000e+00
    394   br label %cond.end14
    395 
    396 cond.end14:                                       ; preds = %if.end, %cond.false12
    397   %cond15 = phi double [ %sub, %cond.false12 ], [ %call2, %if.end ]
    398   %call16 = call i32 @woo(double %cond15, double -2.000000e+00)
    399   br label %return
    400 
    401 return:                                           ; preds = %land.lhs.true, %cond.end14
    402   %retval.0 = phi i32 [ 4, %cond.end14 ], [ 3, %land.lhs.true ]
    403   ret i32 %retval.0
    404 }
    405 
    406 define void @cmp_shifted(i32 %in, i32 %lhs, i32 %rhs) {
    407 ; CHECK-LABEL: cmp_shifted:
    408 ; CHECK: cmp w0, #1
    409 ; [...]
    410 ; CHECK: cmp w0, #2, lsl #12
    411 
    412   %tst_low = icmp sgt i32 %in, 0
    413   br i1 %tst_low, label %true, label %false
    414 
    415 true:
    416   call i32 @zoo(i32 128)
    417   ret void
    418 
    419 false:
    420   %tst = icmp sgt i32 %in, 8191
    421   br i1 %tst, label %truer, label %falser
    422 
    423 truer:
    424   call i32 @zoo(i32 42)
    425   ret void
    426 
    427 falser:
    428   call i32 @zoo(i32 1)
    429   ret void
    430 }
    431 
    432 declare i32 @zoo(i32)
    433 
    434 declare double @yoo(i32)
    435 
    436 declare i32 @xoo(i32, i32)
    437 
    438 declare i32 @woo(double, double)
    439