Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc < %s -mcpu=cyclone -verify-machineinstrs -aarch64-ccmp -aarch64-stress-ccmp | FileCheck %s
      2 target triple = "arm64-apple-ios"
      3 
      4 ; CHECK: single_same
      5 ; CHECK: cmp w0, #5
      6 ; CHECK-NEXT: ccmp w1, #17, #4, ne
      7 ; CHECK-NEXT: b.ne
      8 ; CHECK: %if.then
      9 ; CHECK: bl _foo
     10 ; CHECK: %if.end
     11 define i32 @single_same(i32 %a, i32 %b) nounwind ssp {
     12 entry:
     13   %cmp = icmp eq i32 %a, 5
     14   %cmp1 = icmp eq i32 %b, 17
     15   %or.cond = or i1 %cmp, %cmp1
     16   br i1 %or.cond, label %if.then, label %if.end
     17 
     18 if.then:
     19   %call = tail call i32 @foo() nounwind
     20   br label %if.end
     21 
     22 if.end:
     23   ret i32 7
     24 }
     25 
     26 ; Different condition codes for the two compares.
     27 ; CHECK: single_different
     28 ; CHECK: cmp w0, #6
     29 ; CHECK-NEXT: ccmp w1, #17, #0, ge
     30 ; CHECK-NEXT: b.eq
     31 ; CHECK: %if.then
     32 ; CHECK: bl _foo
     33 ; CHECK: %if.end
     34 define i32 @single_different(i32 %a, i32 %b) nounwind ssp {
     35 entry:
     36   %cmp = icmp sle i32 %a, 5
     37   %cmp1 = icmp ne i32 %b, 17
     38   %or.cond = or i1 %cmp, %cmp1
     39   br i1 %or.cond, label %if.then, label %if.end
     40 
     41 if.then:
     42   %call = tail call i32 @foo() nounwind
     43   br label %if.end
     44 
     45 if.end:
     46   ret i32 7
     47 }
     48 
     49 ; Second block clobbers the flags, can't convert (easily).
     50 ; CHECK: single_flagclobber
     51 ; CHECK: cmp
     52 ; CHECK: b.eq
     53 ; CHECK: cmp
     54 ; CHECK: b.gt
     55 define i32 @single_flagclobber(i32 %a, i32 %b) nounwind ssp {
     56 entry:
     57   %cmp = icmp eq i32 %a, 5
     58   br i1 %cmp, label %if.then, label %lor.lhs.false
     59 
     60 lor.lhs.false:                                    ; preds = %entry
     61   %cmp1 = icmp slt i32 %b, 7
     62   %mul = shl nsw i32 %b, 1
     63   %add = add nsw i32 %b, 1
     64   %cond = select i1 %cmp1, i32 %mul, i32 %add
     65   %cmp2 = icmp slt i32 %cond, 17
     66   br i1 %cmp2, label %if.then, label %if.end
     67 
     68 if.then:                                          ; preds = %lor.lhs.false, %entry
     69   %call = tail call i32 @foo() nounwind
     70   br label %if.end
     71 
     72 if.end:                                           ; preds = %if.then, %lor.lhs.false
     73   ret i32 7
     74 }
     75 
     76 ; Second block clobbers the flags and ends with a tbz terminator.
     77 ; CHECK: single_flagclobber_tbz
     78 ; CHECK: cmp
     79 ; CHECK: b.eq
     80 ; CHECK: cmp
     81 ; CHECK: tbz
     82 define i32 @single_flagclobber_tbz(i32 %a, i32 %b) nounwind ssp {
     83 entry:
     84   %cmp = icmp eq i32 %a, 5
     85   br i1 %cmp, label %if.then, label %lor.lhs.false
     86 
     87 lor.lhs.false:                                    ; preds = %entry
     88   %cmp1 = icmp slt i32 %b, 7
     89   %mul = shl nsw i32 %b, 1
     90   %add = add nsw i32 %b, 1
     91   %cond = select i1 %cmp1, i32 %mul, i32 %add
     92   %and = and i32 %cond, 8
     93   %cmp2 = icmp ne i32 %and, 0
     94   br i1 %cmp2, label %if.then, label %if.end
     95 
     96 if.then:                                          ; preds = %lor.lhs.false, %entry
     97   %call = tail call i32 @foo() nounwind
     98   br label %if.end
     99 
    100 if.end:                                           ; preds = %if.then, %lor.lhs.false
    101   ret i32 7
    102 }
    103 
    104 ; Speculatively execute division by zero.
    105 ; The sdiv/udiv instructions do not trap when the divisor is zero, so they are
    106 ; safe to speculate.
    107 ; CHECK: speculate_division
    108 ; CHECK-NOT: cmp
    109 ; CHECK: sdiv
    110 ; CHECK: cmp
    111 ; CHECK-NEXT: ccmp
    112 define i32 @speculate_division(i32 %a, i32 %b) nounwind ssp {
    113 entry:
    114   %cmp = icmp sgt i32 %a, 0
    115   br i1 %cmp, label %land.lhs.true, label %if.end
    116 
    117 land.lhs.true:
    118   %div = sdiv i32 %b, %a
    119   %cmp1 = icmp slt i32 %div, 17
    120   br i1 %cmp1, label %if.then, label %if.end
    121 
    122 if.then:
    123   %call = tail call i32 @foo() nounwind
    124   br label %if.end
    125 
    126 if.end:
    127   ret i32 7
    128 }
    129 
    130 ; Floating point compare.
    131 ; CHECK: single_fcmp
    132 ; CHECK: cmp
    133 ; CHECK-NOT: b.
    134 ; CHECK: fccmp {{.*}}, #8, ge
    135 ; CHECK: b.lt
    136 define i32 @single_fcmp(i32 %a, float %b) nounwind ssp {
    137 entry:
    138   %cmp = icmp sgt i32 %a, 0
    139   br i1 %cmp, label %land.lhs.true, label %if.end
    140 
    141 land.lhs.true:
    142   %conv = sitofp i32 %a to float
    143   %div = fdiv float %b, %conv
    144   %cmp1 = fcmp oge float %div, 1.700000e+01
    145   br i1 %cmp1, label %if.then, label %if.end
    146 
    147 if.then:
    148   %call = tail call i32 @foo() nounwind
    149   br label %if.end
    150 
    151 if.end:
    152   ret i32 7
    153 }
    154 
    155 ; Chain multiple compares.
    156 ; CHECK: multi_different
    157 ; CHECK: cmp
    158 ; CHECK: ccmp
    159 ; CHECK: ccmp
    160 ; CHECK: b.
    161 define void @multi_different(i32 %a, i32 %b, i32 %c) nounwind ssp {
    162 entry:
    163   %cmp = icmp sgt i32 %a, %b
    164   br i1 %cmp, label %land.lhs.true, label %if.end
    165 
    166 land.lhs.true:
    167   %div = sdiv i32 %b, %a
    168   %cmp1 = icmp eq i32 %div, 5
    169   %cmp4 = icmp sgt i32 %div, %c
    170   %or.cond = and i1 %cmp1, %cmp4
    171   br i1 %or.cond, label %if.then, label %if.end
    172 
    173 if.then:
    174   %call = tail call i32 @foo() nounwind
    175   br label %if.end
    176 
    177 if.end:
    178   ret void
    179 }
    180 
    181 ; Convert a cbz in the head block.
    182 ; CHECK: cbz_head
    183 ; CHECK: cmp w0, #0
    184 ; CHECK: ccmp
    185 define i32 @cbz_head(i32 %a, i32 %b) nounwind ssp {
    186 entry:
    187   %cmp = icmp eq i32 %a, 0
    188   %cmp1 = icmp ne i32 %b, 17
    189   %or.cond = or i1 %cmp, %cmp1
    190   br i1 %or.cond, label %if.then, label %if.end
    191 
    192 if.then:
    193   %call = tail call i32 @foo() nounwind
    194   br label %if.end
    195 
    196 if.end:
    197   ret i32 7
    198 }
    199 
    200 ; Check that the immediate operand is in range. The ccmp instruction encodes a
    201 ; smaller range of immediates than subs/adds.
    202 ; The ccmp immediates must be in the range 0-31.
    203 ; CHECK: immediate_range
    204 ; CHECK-NOT: ccmp
    205 define i32 @immediate_range(i32 %a, i32 %b) nounwind ssp {
    206 entry:
    207   %cmp = icmp eq i32 %a, 5
    208   %cmp1 = icmp eq i32 %b, 32
    209   %or.cond = or i1 %cmp, %cmp1
    210   br i1 %or.cond, label %if.then, label %if.end
    211 
    212 if.then:
    213   %call = tail call i32 @foo() nounwind
    214   br label %if.end
    215 
    216 if.end:
    217   ret i32 7
    218 }
    219 
    220 ; Convert a cbz in the second block.
    221 ; CHECK: cbz_second
    222 ; CHECK: cmp w0, #0
    223 ; CHECK: ccmp w1, #0, #0, ne
    224 ; CHECK: b.eq
    225 define i32 @cbz_second(i32 %a, i32 %b) nounwind ssp {
    226 entry:
    227   %cmp = icmp eq i32 %a, 0
    228   %cmp1 = icmp ne i32 %b, 0
    229   %or.cond = or i1 %cmp, %cmp1
    230   br i1 %or.cond, label %if.then, label %if.end
    231 
    232 if.then:
    233   %call = tail call i32 @foo() nounwind
    234   br label %if.end
    235 
    236 if.end:
    237   ret i32 7
    238 }
    239 
    240 ; Convert a cbnz in the second block.
    241 ; CHECK: cbnz_second
    242 ; CHECK: cmp w0, #0
    243 ; CHECK: ccmp w1, #0, #4, ne
    244 ; CHECK: b.ne
    245 define i32 @cbnz_second(i32 %a, i32 %b) nounwind ssp {
    246 entry:
    247   %cmp = icmp eq i32 %a, 0
    248   %cmp1 = icmp eq i32 %b, 0
    249   %or.cond = or i1 %cmp, %cmp1
    250   br i1 %or.cond, label %if.then, label %if.end
    251 
    252 if.then:
    253   %call = tail call i32 @foo() nounwind
    254   br label %if.end
    255 
    256 if.end:
    257   ret i32 7
    258 }
    259 declare i32 @foo()
    260 
    261 %str1 = type { %str2 }
    262 %str2 = type { [24 x i8], i8*, i32, %str1*, i32, [4 x i8], %str1*, %str1*, %str1*, %str1*, %str1*, %str1*, %str1*, %str1*, %str1*, i8*, i8, i8*, %str1*, i8* }
    263 
    264 ; Test case distilled from 126.gcc.
    265 ; The phi in sw.bb.i.i gets multiple operands for the %entry predecessor.
    266 ; CHECK: build_modify_expr
    267 define void @build_modify_expr() nounwind ssp {
    268 entry:
    269   switch i32 undef, label %sw.bb.i.i [
    270     i32 69, label %if.end85
    271     i32 70, label %if.end85
    272     i32 71, label %if.end85
    273     i32 72, label %if.end85
    274     i32 73, label %if.end85
    275     i32 105, label %if.end85
    276     i32 106, label %if.end85
    277   ]
    278 
    279 if.end85:
    280   ret void
    281 
    282 sw.bb.i.i:
    283   %ref.tr.i.i = phi %str1* [ %0, %sw.bb.i.i ], [ undef, %entry ]
    284   %operands.i.i = getelementptr inbounds %str1* %ref.tr.i.i, i64 0, i32 0, i32 2
    285   %arrayidx.i.i = bitcast i32* %operands.i.i to %str1**
    286   %0 = load %str1** %arrayidx.i.i, align 8
    287   %code1.i.i.phi.trans.insert = getelementptr inbounds %str1* %0, i64 0, i32 0, i32 0, i64 16
    288   br label %sw.bb.i.i
    289 }
    290