Home | History | Annotate | Download | only in InstCombine
      1 ; RUN: opt -S -instcombine < %s | FileCheck %s
      2 
      3 ; return mul(zext x, zext y) > MAX
      4 define i32 @pr4917_1(i32 %x, i32 %y) nounwind {
      5 ; CHECK-LABEL: @pr4917_1(
      6 entry:
      7   %l = zext i32 %x to i64
      8   %r = zext i32 %y to i64
      9 ; CHECK-NOT: zext i32
     10   %mul64 = mul i64 %l, %r
     11 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y)
     12   %overflow = icmp ugt i64 %mul64, 4294967295
     13 ; CHECK: extractvalue { i32, i1 } [[MUL]], 1
     14   %retval = zext i1 %overflow to i32
     15   ret i32 %retval
     16 }
     17 
     18 ; return mul(zext x, zext y) >= MAX+1
     19 define i32 @pr4917_1a(i32 %x, i32 %y) nounwind {
     20 ; CHECK-LABEL: @pr4917_1a(
     21 entry:
     22   %l = zext i32 %x to i64
     23   %r = zext i32 %y to i64
     24 ; CHECK-NOT: zext i32
     25   %mul64 = mul i64 %l, %r
     26 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y)
     27   %overflow = icmp uge i64 %mul64, 4294967296
     28 ; CHECK: extractvalue { i32, i1 } [[MUL]], 1
     29   %retval = zext i1 %overflow to i32
     30   ret i32 %retval
     31 }
     32 
     33 ; mul(zext x, zext y) > MAX
     34 ; mul(x, y) is used
     35 define i32 @pr4917_2(i32 %x, i32 %y) nounwind {
     36 ; CHECK-LABEL: @pr4917_2(
     37 entry:
     38   %l = zext i32 %x to i64
     39   %r = zext i32 %y to i64
     40 ; CHECK-NOT: zext i32
     41   %mul64 = mul i64 %l, %r
     42 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y)
     43   %overflow = icmp ugt i64 %mul64, 4294967295
     44 ; CHECK-DAG: [[VAL:%.*]] = extractvalue { i32, i1 } [[MUL]], 0
     45   %mul32 = trunc i64 %mul64 to i32
     46 ; CHECK-DAG: [[OVFL:%.*]] = extractvalue { i32, i1 } [[MUL]], 1
     47   %retval = select i1 %overflow, i32 %mul32, i32 111
     48 ; CHECK: select i1 [[OVFL]], i32 [[VAL]]
     49   ret i32 %retval
     50 }
     51 
     52 ; return mul(zext x, zext y) > MAX
     53 ; mul is used in non-truncate
     54 define i64 @pr4917_3(i32 %x, i32 %y) nounwind {
     55 ; CHECK-LABEL: @pr4917_3(
     56 entry:
     57   %l = zext i32 %x to i64
     58   %r = zext i32 %y to i64
     59   %mul64 = mul i64 %l, %r
     60 ; CHECK-NOT: umul.with.overflow.i32
     61   %overflow = icmp ugt i64 %mul64, 4294967295
     62   %retval = select i1 %overflow, i64 %mul64, i64 111
     63   ret i64 %retval
     64 }
     65 
     66 ; return mul(zext x, zext y) <= MAX
     67 define i32 @pr4917_4(i32 %x, i32 %y) nounwind {
     68 ; CHECK-LABEL: @pr4917_4(
     69 entry:
     70   %l = zext i32 %x to i64
     71   %r = zext i32 %y to i64
     72 ; CHECK-NOT: zext i32
     73   %mul64 = mul i64 %l, %r
     74 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y)
     75   %overflow = icmp ule i64 %mul64, 4294967295
     76 ; CHECK: extractvalue { i32, i1 } [[MUL]], 1
     77 ; CHECK: xor
     78   %retval = zext i1 %overflow to i32
     79   ret i32 %retval
     80 }
     81 
     82 ; return mul(zext x, zext y) < MAX+1
     83 define i32 @pr4917_4a(i32 %x, i32 %y) nounwind {
     84 ; CHECK-LABEL: @pr4917_4a(
     85 entry:
     86   %l = zext i32 %x to i64
     87   %r = zext i32 %y to i64
     88 ; CHECK-NOT: zext i32
     89   %mul64 = mul i64 %l, %r
     90 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y)
     91   %overflow = icmp ult i64 %mul64, 4294967296
     92 ; CHECK: extractvalue { i32, i1 } [[MUL]], 1
     93 ; CHECK: xor
     94   %retval = zext i1 %overflow to i32
     95   ret i32 %retval
     96 }
     97 
     98 ; operands of mul are of different size
     99 define i32 @pr4917_5(i32 %x, i8 %y) nounwind {
    100 ; CHECK-LABEL: @pr4917_5(
    101 entry:
    102   %l = zext i32 %x to i64
    103   %r = zext i8 %y to i64
    104 ; CHECK: [[Y:%.*]] = zext i8 %y to i32
    105   %mul64 = mul i64 %l, %r
    106   %overflow = icmp ugt i64 %mul64, 4294967295
    107   %mul32 = trunc i64 %mul64 to i32
    108 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 [[Y]])
    109 ; CHECK-DAG: [[VAL:%.*]] = extractvalue { i32, i1 } [[MUL]], 0
    110 ; CHECK-DAG: [[OVFL:%.*]] = extractvalue { i32, i1 } [[MUL]], 1
    111   %retval = select i1 %overflow, i32 %mul32, i32 111
    112 ; CHECK: select i1 [[OVFL]], i32 [[VAL]]
    113   ret i32 %retval
    114 }
    115 
    116 ; mul(zext x, zext y) != zext trunc mul
    117 define i32 @pr4918_1(i32 %x, i32 %y) nounwind {
    118 ; CHECK-LABEL: @pr4918_1(
    119 entry:
    120   %l = zext i32 %x to i64
    121   %r = zext i32 %y to i64
    122   %mul64 = mul i64 %l, %r
    123 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y)
    124   %part32 = trunc i64 %mul64 to i32
    125   %part64 = zext i32 %part32 to i64
    126   %overflow = icmp ne i64 %mul64, %part64
    127 ; CHECK: [[OVFL:%.*]] = extractvalue { i32, i1 } [[MUL:%.*]], 1
    128   %retval = zext i1 %overflow to i32
    129   ret i32 %retval
    130 }
    131 
    132 ; mul(zext x, zext y) == zext trunc mul
    133 define i32 @pr4918_2(i32 %x, i32 %y) nounwind {
    134 ; CHECK-LABEL: @pr4918_2(
    135 entry:
    136   %l = zext i32 %x to i64
    137   %r = zext i32 %y to i64
    138   %mul64 = mul i64 %l, %r
    139 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y)
    140   %part32 = trunc i64 %mul64 to i32
    141   %part64 = zext i32 %part32 to i64
    142   %overflow = icmp eq i64 %mul64, %part64
    143 ; CHECK: extractvalue { i32, i1 } [[MUL]]
    144   %retval = zext i1 %overflow to i32
    145 ; CHECK: xor
    146   ret i32 %retval
    147 }
    148 
    149 ; zext trunc mul != mul(zext x, zext y)
    150 define i32 @pr4918_3(i32 %x, i32 %y) nounwind {
    151 ; CHECK-LABEL: @pr4918_3(
    152 entry:
    153   %l = zext i32 %x to i64
    154   %r = zext i32 %y to i64
    155   %mul64 = mul i64 %l, %r
    156 ; CHECK: [[MUL:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y)
    157   %part32 = trunc i64 %mul64 to i32
    158   %part64 = zext i32 %part32 to i64
    159   %overflow = icmp ne i64 %part64, %mul64
    160 ; CHECK: extractvalue { i32, i1 } [[MUL]], 1
    161   %retval = zext i1 %overflow to i32
    162   ret i32 %retval
    163 }
    164 
    165 define <4 x i32> @pr20113(<4 x i16> %a, <4 x i16> %b) {
    166 ; CHECK-LABEL: @pr20113
    167 ; CHECK-NOT: mul.with.overflow
    168 ; CHECK: ret
    169   %vmovl.i.i726 = zext <4 x i16> %a to <4 x i32>
    170   %vmovl.i.i712 = zext <4 x i16> %b to <4 x i32>
    171   %mul.i703 = mul <4 x i32> %vmovl.i.i712, %vmovl.i.i726
    172   %tmp = icmp sge <4 x i32> %mul.i703, zeroinitializer
    173   %vcgez.i = sext <4 x i1> %tmp to <4 x i32>
    174   ret <4 x i32> %vcgez.i
    175 }
    176