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