Home | History | Annotate | Download | only in InstCombine
      1 ; RUN: opt -instcombine -S < %s | FileCheck %s
      2 
      3 %overflow.result = type {i8, i1}
      4 
      5 declare %overflow.result @llvm.uadd.with.overflow.i8(i8, i8)
      6 declare %overflow.result @llvm.umul.with.overflow.i8(i8, i8)
      7 declare double @llvm.powi.f64(double, i32) nounwind readonly
      8 declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone
      9 declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone
     10 declare i32 @llvm.ctpop.i32(i32) nounwind readnone
     11 declare i8 @llvm.ctlz.i8(i8, i1) nounwind readnone
     12 
     13 define i8 @uaddtest1(i8 %A, i8 %B) {
     14   %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 %A, i8 %B)
     15   %y = extractvalue %overflow.result %x, 0
     16   ret i8 %y
     17 ; CHECK-LABEL: @uaddtest1(
     18 ; CHECK-NEXT: %y = add i8 %A, %B
     19 ; CHECK-NEXT: ret i8 %y
     20 }
     21 
     22 define i8 @uaddtest2(i8 %A, i8 %B, i1* %overflowPtr) {
     23   %and.A = and i8 %A, 127
     24   %and.B = and i8 %B, 127
     25   %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 %and.A, i8 %and.B)
     26   %y = extractvalue %overflow.result %x, 0
     27   %z = extractvalue %overflow.result %x, 1
     28   store i1 %z, i1* %overflowPtr
     29   ret i8 %y
     30 ; CHECK-LABEL: @uaddtest2(
     31 ; CHECK-NEXT: %and.A = and i8 %A, 127
     32 ; CHECK-NEXT: %and.B = and i8 %B, 127
     33 ; CHECK-NEXT: %x = add nuw i8 %and.A, %and.B
     34 ; CHECK-NEXT: store i1 false, i1* %overflowPtr
     35 ; CHECK-NEXT: ret i8 %x
     36 }
     37 
     38 define i8 @uaddtest3(i8 %A, i8 %B, i1* %overflowPtr) {
     39   %or.A = or i8 %A, -128
     40   %or.B = or i8 %B, -128
     41   %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 %or.A, i8 %or.B)
     42   %y = extractvalue %overflow.result %x, 0
     43   %z = extractvalue %overflow.result %x, 1
     44   store i1 %z, i1* %overflowPtr
     45   ret i8 %y
     46 ; CHECK-LABEL: @uaddtest3(
     47 ; CHECK-NEXT: %or.A = or i8 %A, -128
     48 ; CHECK-NEXT: %or.B = or i8 %B, -128
     49 ; CHECK-NEXT: %x = add i8 %or.A, %or.B
     50 ; CHECK-NEXT: store i1 true, i1* %overflowPtr
     51 ; CHECK-NEXT: ret i8 %x
     52 }
     53 
     54 define i8 @uaddtest4(i8 %A, i1* %overflowPtr) {
     55   %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 undef, i8 %A)
     56   %y = extractvalue %overflow.result %x, 0
     57   %z = extractvalue %overflow.result %x, 1
     58   store i1 %z, i1* %overflowPtr
     59   ret i8 %y
     60 ; CHECK-LABEL: @uaddtest4(
     61 ; CHECK-NEXT: ret i8 undef
     62 }
     63 
     64 define i8 @uaddtest5(i8 %A, i1* %overflowPtr) {
     65   %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 0, i8 %A)
     66   %y = extractvalue %overflow.result %x, 0
     67   %z = extractvalue %overflow.result %x, 1
     68   store i1 %z, i1* %overflowPtr
     69   ret i8 %y
     70 ; CHECK-LABEL: @uaddtest5(
     71 ; CHECK: ret i8 %A
     72 }
     73 
     74 define i1 @uaddtest6(i8 %A, i8 %B) {
     75   %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 %A, i8 -4)
     76   %z = extractvalue %overflow.result %x, 1
     77   ret i1 %z
     78 ; CHECK-LABEL: @uaddtest6(
     79 ; CHECK-NEXT: %z = icmp ugt i8 %A, 3
     80 ; CHECK-NEXT: ret i1 %z
     81 }
     82 
     83 define i8 @uaddtest7(i8 %A, i8 %B) {
     84   %x = call %overflow.result @llvm.uadd.with.overflow.i8(i8 %A, i8 %B)
     85   %z = extractvalue %overflow.result %x, 0
     86   ret i8 %z
     87 ; CHECK-LABEL: @uaddtest7(
     88 ; CHECK-NEXT: %z = add i8 %A, %B
     89 ; CHECK-NEXT: ret i8 %z
     90 }
     91 
     92 
     93 define i8 @umultest1(i8 %A, i1* %overflowPtr) {
     94   %x = call %overflow.result @llvm.umul.with.overflow.i8(i8 0, i8 %A)
     95   %y = extractvalue %overflow.result %x, 0
     96   %z = extractvalue %overflow.result %x, 1
     97   store i1 %z, i1* %overflowPtr
     98   ret i8 %y
     99 ; CHECK-LABEL: @umultest1(
    100 ; CHECK-NEXT: store i1 false, i1* %overflowPtr
    101 ; CHECK-NEXT: ret i8 0
    102 }
    103 
    104 define i8 @umultest2(i8 %A, i1* %overflowPtr) {
    105   %x = call %overflow.result @llvm.umul.with.overflow.i8(i8 1, i8 %A)
    106   %y = extractvalue %overflow.result %x, 0
    107   %z = extractvalue %overflow.result %x, 1
    108   store i1 %z, i1* %overflowPtr
    109   ret i8 %y
    110 ; CHECK-LABEL: @umultest2(
    111 ; CHECK-NEXT: store i1 false, i1* %overflowPtr
    112 ; CHECK-NEXT: ret i8 %A
    113 }
    114 
    115 %ov.result.32 = type { i32, i1 }
    116 declare %ov.result.32 @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone
    117 
    118 define i32 @umultest3(i32 %n) nounwind {
    119   %shr = lshr i32 %n, 2
    120   %mul = call %ov.result.32 @llvm.umul.with.overflow.i32(i32 %shr, i32 3)
    121   %ov = extractvalue %ov.result.32 %mul, 1
    122   %res = extractvalue %ov.result.32 %mul, 0
    123   %ret = select i1 %ov, i32 -1, i32 %res
    124   ret i32 %ret
    125 ; CHECK-LABEL: @umultest3(
    126 ; CHECK-NEXT: shr
    127 ; CHECK-NEXT: mul nuw
    128 ; CHECK-NEXT: ret
    129 }
    130 
    131 define i32 @umultest4(i32 %n) nounwind {
    132   %shr = lshr i32 %n, 1
    133   %mul = call %ov.result.32 @llvm.umul.with.overflow.i32(i32 %shr, i32 4)
    134   %ov = extractvalue %ov.result.32 %mul, 1
    135   %res = extractvalue %ov.result.32 %mul, 0
    136   %ret = select i1 %ov, i32 -1, i32 %res
    137   ret i32 %ret
    138 ; CHECK-LABEL: @umultest4(
    139 ; CHECK: umul.with.overflow
    140 }
    141 
    142 define void @powi(double %V, double *%P) {
    143 entry:
    144   %A = tail call double @llvm.powi.f64(double %V, i32 -1) nounwind
    145   store volatile double %A, double* %P
    146 
    147   %B = tail call double @llvm.powi.f64(double %V, i32 0) nounwind
    148   store volatile double %B, double* %P
    149 
    150   %C = tail call double @llvm.powi.f64(double %V, i32 1) nounwind
    151   store volatile double %C, double* %P
    152   ret void
    153 ; CHECK-LABEL: @powi(
    154 ; CHECK: %A = fdiv double 1.0{{.*}}, %V
    155 ; CHECK: store volatile double %A, 
    156 ; CHECK: store volatile double 1.0 
    157 ; CHECK: store volatile double %V
    158 }
    159 
    160 define i32 @cttz(i32 %a) {
    161 entry:
    162   %or = or i32 %a, 8
    163   %and = and i32 %or, -8
    164   %count = tail call i32 @llvm.cttz.i32(i32 %and, i1 true) nounwind readnone
    165   ret i32 %count
    166 ; CHECK-LABEL: @cttz(
    167 ; CHECK-NEXT: entry:
    168 ; CHECK-NEXT: ret i32 3
    169 }
    170 
    171 define i8 @ctlz(i8 %a) {
    172 entry:
    173   %or = or i8 %a, 32
    174   %and = and i8 %or, 63
    175   %count = tail call i8 @llvm.ctlz.i8(i8 %and, i1 true) nounwind readnone
    176   ret i8 %count
    177 ; CHECK-LABEL: @ctlz(
    178 ; CHECK-NEXT: entry:
    179 ; CHECK-NEXT: ret i8 2
    180 }
    181 
    182 define void @cmp.simplify(i32 %a, i32 %b, i1* %c) {
    183 entry:
    184   %lz = tail call i32 @llvm.ctlz.i32(i32 %a, i1 false) nounwind readnone
    185   %lz.cmp = icmp eq i32 %lz, 32
    186   store volatile i1 %lz.cmp, i1* %c
    187   %tz = tail call i32 @llvm.cttz.i32(i32 %a, i1 false) nounwind readnone
    188   %tz.cmp = icmp ne i32 %tz, 32
    189   store volatile i1 %tz.cmp, i1* %c
    190   %pop = tail call i32 @llvm.ctpop.i32(i32 %b) nounwind readnone
    191   %pop.cmp = icmp eq i32 %pop, 0
    192   store volatile i1 %pop.cmp, i1* %c
    193   ret void
    194 ; CHECK: @cmp.simplify
    195 ; CHECK-NEXT: entry:
    196 ; CHECK-NEXT: %lz.cmp = icmp eq i32 %a, 0
    197 ; CHECK-NEXT: store volatile i1 %lz.cmp, i1* %c
    198 ; CHECK-NEXT: %tz.cmp = icmp ne i32 %a, 0
    199 ; CHECK-NEXT: store volatile i1 %tz.cmp, i1* %c
    200 ; CHECK-NEXT: %pop.cmp = icmp eq i32 %b, 0
    201 ; CHECK-NEXT: store volatile i1 %pop.cmp, i1* %c
    202 }
    203 
    204 define i32 @cttz_simplify1a(i32 %x) nounwind readnone ssp {
    205   %tmp1 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
    206   %shr3 = lshr i32 %tmp1, 5
    207   ret i32 %shr3
    208 
    209 ; CHECK-LABEL: @cttz_simplify1a(
    210 ; CHECK: icmp eq i32 %x, 0
    211 ; CHECK-NEXT: zext i1
    212 ; CHECK-NEXT: ret i32
    213 }
    214 
    215 define i32 @cttz_simplify1b(i32 %x) nounwind readnone ssp {
    216   %tmp1 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
    217   %shr3 = lshr i32 %tmp1, 5
    218   ret i32 %shr3
    219 
    220 ; CHECK-LABEL: @cttz_simplify1b(
    221 ; CHECK-NEXT: ret i32 0
    222 }
    223 
    224 define i32 @ctlz_undef(i32 %Value) nounwind {
    225   %ctlz = call i32 @llvm.ctlz.i32(i32 0, i1 true)
    226   ret i32 %ctlz
    227 
    228 ; CHECK-LABEL: @ctlz_undef(
    229 ; CHECK-NEXT: ret i32 undef
    230 }
    231 
    232 define i32 @cttz_undef(i32 %Value) nounwind {
    233   %cttz = call i32 @llvm.cttz.i32(i32 0, i1 true)
    234   ret i32 %cttz
    235 
    236 ; CHECK-LABEL: @cttz_undef(
    237 ; CHECK-NEXT: ret i32 undef
    238 }
    239 
    240 define i32 @ctlz_select(i32 %Value) nounwind {
    241   %tobool = icmp ne i32 %Value, 0
    242   %ctlz = call i32 @llvm.ctlz.i32(i32 %Value, i1 true)
    243   %s = select i1 %tobool, i32 %ctlz, i32 32
    244   ret i32 %s
    245 
    246 ; CHECK-LABEL: @ctlz_select(
    247 ; CHECK: select i1 %tobool, i32 %ctlz, i32 32
    248 }
    249 
    250 define i32 @cttz_select(i32 %Value) nounwind {
    251   %tobool = icmp ne i32 %Value, 0
    252   %cttz = call i32 @llvm.cttz.i32(i32 %Value, i1 true)
    253   %s = select i1 %tobool, i32 %cttz, i32 32
    254   ret i32 %s
    255 
    256 ; CHECK-LABEL: @cttz_select(
    257 ; CHECK: select i1 %tobool, i32 %cttz, i32 32
    258 }
    259