Home | History | Annotate | Download | only in ARM
      1 ; RUN: llc < %s -mtriple=arm-apple-darwin | FileCheck %s
      2 ; RUN: llc < %s -mtriple=arm-apple-darwin | FileCheck %s --check-prefix=V7
      3 ; RUN: llc < %s -mtriple=armv8-none-linux-gnueabi | FileCheck %s -check-prefix=V8
      4 
      5 
      6 define i32 @f(i32 %a, i32 %b) nounwind ssp {
      7 entry:
      8 ; CHECK-LABEL: f:
      9 ; CHECK: subs
     10 ; CHECK-NOT: cmp
     11   %cmp = icmp sgt i32 %a, %b
     12   %sub = sub nsw i32 %a, %b
     13   %sub. = select i1 %cmp, i32 %sub, i32 0
     14   ret i32 %sub.
     15 }
     16 
     17 define i32 @g(i32 %a, i32 %b) nounwind ssp {
     18 entry:
     19 ; CHECK-LABEL: g:
     20 ; CHECK: subs
     21 ; CHECK-NOT: cmp
     22   %cmp = icmp slt i32 %a, %b
     23   %sub = sub nsw i32 %b, %a
     24   %sub. = select i1 %cmp, i32 %sub, i32 0
     25   ret i32 %sub.
     26 }
     27 
     28 define i32 @h(i32 %a, i32 %b) nounwind ssp {
     29 entry:
     30 ; CHECK-LABEL: h:
     31 ; CHECK: subs
     32 ; CHECK-NOT: cmp
     33   %cmp = icmp sgt i32 %a, 3
     34   %sub = sub nsw i32 %a, 3
     35   %sub. = select i1 %cmp, i32 %sub, i32 %b
     36   ret i32 %sub.
     37 }
     38 
     39 ; rdar://11725965
     40 define i32 @i(i32 %a, i32 %b) nounwind readnone ssp {
     41 entry:
     42 ; CHECK-LABEL: i:
     43 ; CHECK: subs
     44 ; CHECK-NOT: cmp
     45   %cmp = icmp ult i32 %a, %b
     46   %sub = sub i32 %b, %a
     47   %sub. = select i1 %cmp, i32 %sub, i32 0
     48   ret i32 %sub.
     49 }
     50 ; If CPSR is live-out, we can't remove cmp if there exists
     51 ; a swapped sub.
     52 define i32 @j(i32 %a, i32 %b) nounwind {
     53 entry:
     54 ; CHECK-LABEL: j:
     55 ; CHECK: sub
     56 ; CHECK: cmp
     57   %cmp = icmp eq i32 %b, %a
     58   %sub = sub nsw i32 %a, %b
     59   br i1 %cmp, label %if.then, label %if.else
     60 
     61 if.then:
     62   %cmp2 = icmp sgt i32 %b, %a
     63   %sel = select i1 %cmp2, i32 %sub, i32 %a
     64   ret i32 %sel
     65 
     66 if.else:
     67   ret i32 %sub
     68 }
     69 
     70 ; If the sub/rsb instruction is predicated, we can't use the flags.
     71 ; <rdar://problem/12263428>
     72 ; Test case from MultiSource/Benchmarks/Ptrdist/bc/number.s
     73 ; CHECK: bc_raise
     74 ; CHECK: rsbeq
     75 ; CHECK: cmp
     76 define i32 @bc_raise() nounwind ssp {
     77 entry:
     78   %val.2.i = select i1 undef, i32 0, i32 undef
     79   %sub.i = sub nsw i32 0, %val.2.i
     80   %retval.0.i = select i1 undef, i32 %val.2.i, i32 %sub.i
     81   %cmp1 = icmp eq i32 %retval.0.i, 0
     82   br i1 %cmp1, label %land.lhs.true, label %if.end11
     83 
     84 land.lhs.true:                                    ; preds = %num2long.exit
     85   ret i32 17
     86 
     87 if.end11:                                         ; preds = %num2long.exit
     88   ret i32 23
     89 }
     90 
     91 ; When considering the producer of cmp's src as the subsuming instruction,
     92 ; only consider that when the comparison is to 0.
     93 define i32 @cmp_src_nonzero(i32 %a, i32 %b, i32 %x, i32 %y) {
     94 entry:
     95 ; CHECK-LABEL: cmp_src_nonzero:
     96 ; CHECK: sub
     97 ; CHECK: cmp
     98   %sub = sub i32 %a, %b
     99   %cmp = icmp eq i32 %sub, 17
    100   %ret = select i1 %cmp, i32 %x, i32 %y
    101   ret i32 %ret
    102 }
    103 
    104 define float @float_sel(i32 %a, i32 %b, float %x, float %y) {
    105 entry:
    106 ; CHECK-LABEL: float_sel:
    107 ; CHECK-NOT: cmp
    108 ; V8-LABEL: float_sel:
    109 ; V8-NOT: cmp
    110 ; V8: vseleq.f32
    111   %sub = sub i32 %a, %b
    112   %cmp = icmp eq i32 %sub, 0
    113   %ret = select i1 %cmp, float %x, float %y
    114   ret float %ret
    115 }
    116 
    117 define double @double_sel(i32 %a, i32 %b, double %x, double %y) {
    118 entry:
    119 ; CHECK-LABEL: double_sel:
    120 ; CHECK-NOT: cmp
    121 ; V8-LABEL: double_sel:
    122 ; V8-NOT: cmp
    123 ; V8: vseleq.f64
    124   %sub = sub i32 %a, %b
    125   %cmp = icmp eq i32 %sub, 0
    126   %ret = select i1 %cmp, double %x, double %y
    127   ret double %ret
    128 }
    129 
    130 @t = common global i32 0
    131 define double @double_sub(i32 %a, i32 %b, double %x, double %y) {
    132 entry:
    133 ; CHECK-LABEL: double_sub:
    134 ; CHECK: subs
    135 ; CHECK-NOT: cmp
    136 ; V8-LABEL: double_sub:
    137 ; V8: vsel
    138   %cmp = icmp sgt i32 %a, %b
    139   %sub = sub i32 %a, %b
    140   store i32 %sub, i32* @t
    141   %ret = select i1 %cmp, double %x, double %y
    142   ret double %ret
    143 }
    144 
    145 define double @double_sub_swap(i32 %a, i32 %b, double %x, double %y) {
    146 entry:
    147 ; V7-LABEL: double_sub_swap:
    148 ; V7-NOT: cmp
    149 ; V7: subs
    150 ; V8-LABEL: double_sub_swap:
    151 ; V8-NOT: subs
    152 ; V8: cmp
    153 ; V8: vsel
    154   %cmp = icmp sgt i32 %a, %b
    155   %sub = sub i32 %b, %a
    156   %ret = select i1 %cmp, double %x, double %y
    157   store i32 %sub, i32* @t
    158   ret double %ret
    159 }
    160 
    161 declare void @abort()
    162 declare void @exit(i32)
    163 
    164 ; If the comparison uses the V bit (signed overflow/underflow), we can't
    165 ; omit the comparison.
    166 define i32 @cmp_slt0(i32 %a, i32 %b, i32 %x, i32 %y) {
    167 entry:
    168 ; CHECK-LABEL: cmp_slt0
    169 ; CHECK: sub
    170 ; CHECK: cmp
    171 ; CHECK: bge
    172   %load = load i32, i32* @t, align 4
    173   %sub = sub i32 %load, 17
    174   %cmp = icmp slt i32 %sub, 0
    175   br i1 %cmp, label %if.then, label %if.else
    176 
    177 if.then:
    178   call void @abort()
    179   unreachable
    180 
    181 if.else:
    182   call void @exit(i32 0)
    183   unreachable
    184 }
    185 
    186 ; Same for the C bit. (Note the ult X, 0 is trivially
    187 ; false, so the DAG combiner may or may not optimize it).
    188 define i32 @cmp_ult0(i32 %a, i32 %b, i32 %x, i32 %y) {
    189 entry:
    190 ; CHECK-LABEL: cmp_ult0
    191 ; CHECK: sub
    192 ; CHECK: cmp
    193 ; CHECK: bhs
    194   %load = load i32, i32* @t, align 4
    195   %sub = sub i32 %load, 17
    196   %cmp = icmp ult i32 %sub, 0
    197   br i1 %cmp, label %if.then, label %if.else
    198 
    199 if.then:
    200   call void @abort()
    201   unreachable
    202 
    203 if.else:
    204   call void @exit(i32 0)
    205   unreachable
    206 }
    207