Home | History | Annotate | Download | only in InstSimplify
      1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
      2 ; RUN: opt < %s -instsimplify -S | FileCheck %s
      3 
      4 define i32 @zero_dividend(i32 %A) {
      5 ; CHECK-LABEL: @zero_dividend(
      6 ; CHECK-NEXT:    ret i32 0
      7 ;
      8   %B = urem i32 0, %A
      9   ret i32 %B
     10 }
     11 
     12 define <2 x i32> @zero_dividend_vector(<2 x i32> %A) {
     13 ; CHECK-LABEL: @zero_dividend_vector(
     14 ; CHECK-NEXT:    ret <2 x i32> zeroinitializer
     15 ;
     16   %B = srem <2 x i32> zeroinitializer, %A
     17   ret <2 x i32> %B
     18 }
     19 
     20 define <2 x i32> @zero_dividend_vector_undef_elt(<2 x i32> %A) {
     21 ; CHECK-LABEL: @zero_dividend_vector_undef_elt(
     22 ; CHECK-NEXT:    ret <2 x i32> zeroinitializer
     23 ;
     24   %B = urem <2 x i32> <i32 undef, i32 0>, %A
     25   ret <2 x i32> %B
     26 }
     27 
     28 ; Division-by-zero is undef. UB in any vector lane means the whole op is undef.
     29 
     30 define <2 x i8> @srem_zero_elt_vec_constfold(<2 x i8> %x) {
     31 ; CHECK-LABEL: @srem_zero_elt_vec_constfold(
     32 ; CHECK-NEXT:    ret <2 x i8> undef
     33 ;
     34   %rem = srem <2 x i8> <i8 1, i8 2>, <i8 0, i8 -42>
     35   ret <2 x i8> %rem
     36 }
     37 
     38 define <2 x i8> @urem_zero_elt_vec_constfold(<2 x i8> %x) {
     39 ; CHECK-LABEL: @urem_zero_elt_vec_constfold(
     40 ; CHECK-NEXT:    ret <2 x i8> undef
     41 ;
     42   %rem = urem <2 x i8> <i8 1, i8 2>, <i8 42, i8 0>
     43   ret <2 x i8> %rem
     44 }
     45 
     46 define <2 x i8> @srem_zero_elt_vec(<2 x i8> %x) {
     47 ; CHECK-LABEL: @srem_zero_elt_vec(
     48 ; CHECK-NEXT:    ret <2 x i8> undef
     49 ;
     50   %rem = srem <2 x i8> %x, <i8 -42, i8 0>
     51   ret <2 x i8> %rem
     52 }
     53 
     54 define <2 x i8> @urem_zero_elt_vec(<2 x i8> %x) {
     55 ; CHECK-LABEL: @urem_zero_elt_vec(
     56 ; CHECK-NEXT:    ret <2 x i8> undef
     57 ;
     58   %rem = urem <2 x i8> %x, <i8 0, i8 42>
     59   ret <2 x i8> %rem
     60 }
     61 
     62 define <2 x i8> @srem_undef_elt_vec(<2 x i8> %x) {
     63 ; CHECK-LABEL: @srem_undef_elt_vec(
     64 ; CHECK-NEXT:    ret <2 x i8> undef
     65 ;
     66   %rem = srem <2 x i8> %x, <i8 -42, i8 undef>
     67   ret <2 x i8> %rem
     68 }
     69 
     70 define <2 x i8> @urem_undef_elt_vec(<2 x i8> %x) {
     71 ; CHECK-LABEL: @urem_undef_elt_vec(
     72 ; CHECK-NEXT:    ret <2 x i8> undef
     73 ;
     74   %rem = urem <2 x i8> %x, <i8 undef, i8 42>
     75   ret <2 x i8> %rem
     76 }
     77 
     78 ; Division-by-zero is undef. UB in any vector lane means the whole op is undef.
     79 ; Thus, we can simplify this: if any element of 'y' is 0, we can do anything.
     80 ; Therefore, assume that all elements of 'y' must be 1.
     81 
     82 define <2 x i1> @srem_bool_vec(<2 x i1> %x, <2 x i1> %y) {
     83 ; CHECK-LABEL: @srem_bool_vec(
     84 ; CHECK-NEXT:    ret <2 x i1> zeroinitializer
     85 ;
     86   %rem = srem <2 x i1> %x, %y
     87   ret <2 x i1> %rem
     88 }
     89 
     90 define <2 x i1> @urem_bool_vec(<2 x i1> %x, <2 x i1> %y) {
     91 ; CHECK-LABEL: @urem_bool_vec(
     92 ; CHECK-NEXT:    ret <2 x i1> zeroinitializer
     93 ;
     94   %rem = urem <2 x i1> %x, %y
     95   ret <2 x i1> %rem
     96 }
     97 
     98 define <2 x i32> @zext_bool_urem_divisor_vec(<2 x i1> %x, <2 x i32> %y) {
     99 ; CHECK-LABEL: @zext_bool_urem_divisor_vec(
    100 ; CHECK-NEXT:    ret <2 x i32> zeroinitializer
    101 ;
    102   %ext = zext <2 x i1> %x to <2 x i32>
    103   %r = urem <2 x i32> %y, %ext
    104   ret <2 x i32> %r
    105 }
    106 
    107 define i32 @zext_bool_srem_divisor(i1 %x, i32 %y) {
    108 ; CHECK-LABEL: @zext_bool_srem_divisor(
    109 ; CHECK-NEXT:    ret i32 0
    110 ;
    111   %ext = zext i1 %x to i32
    112   %r = srem i32 %y, %ext
    113   ret i32 %r
    114 }
    115 
    116 define i32 @select1(i32 %x, i1 %b) {
    117 ; CHECK-LABEL: @select1(
    118 ; CHECK-NEXT:    ret i32 0
    119 ;
    120   %rhs = select i1 %b, i32 %x, i32 1
    121   %rem = srem i32 %x, %rhs
    122   ret i32 %rem
    123 }
    124 
    125 define i32 @select2(i32 %x, i1 %b) {
    126 ; CHECK-LABEL: @select2(
    127 ; CHECK-NEXT:    ret i32 0
    128 ;
    129   %rhs = select i1 %b, i32 %x, i32 1
    130   %rem = urem i32 %x, %rhs
    131   ret i32 %rem
    132 }
    133 
    134 define i32 @rem1(i32 %x, i32 %n) {
    135 ; CHECK-LABEL: @rem1(
    136 ; CHECK-NEXT:    [[MOD:%.*]] = srem i32 [[X:%.*]], [[N:%.*]]
    137 ; CHECK-NEXT:    ret i32 [[MOD]]
    138 ;
    139   %mod = srem i32 %x, %n
    140   %mod1 = srem i32 %mod, %n
    141   ret i32 %mod1
    142 }
    143 
    144 define i32 @rem2(i32 %x, i32 %n) {
    145 ; CHECK-LABEL: @rem2(
    146 ; CHECK-NEXT:    [[MOD:%.*]] = urem i32 [[X:%.*]], [[N:%.*]]
    147 ; CHECK-NEXT:    ret i32 [[MOD]]
    148 ;
    149   %mod = urem i32 %x, %n
    150   %mod1 = urem i32 %mod, %n
    151   ret i32 %mod1
    152 }
    153 
    154 define i32 @rem3(i32 %x, i32 %n) {
    155 ; CHECK-LABEL: @rem3(
    156 ; CHECK-NEXT:    [[MOD:%.*]] = srem i32 [[X:%.*]], [[N:%.*]]
    157 ; CHECK-NEXT:    [[MOD1:%.*]] = urem i32 [[MOD]], [[N]]
    158 ; CHECK-NEXT:    ret i32 [[MOD1]]
    159 ;
    160   %mod = srem i32 %x, %n
    161   %mod1 = urem i32 %mod, %n
    162   ret i32 %mod1
    163 }
    164 
    165 define i32 @urem_dividend_known_smaller_than_constant_divisor(i32 %x) {
    166 ; CHECK-LABEL: @urem_dividend_known_smaller_than_constant_divisor(
    167 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 250
    168 ; CHECK-NEXT:    ret i32 [[AND]]
    169 ;
    170   %and = and i32 %x, 250
    171   %r = urem i32 %and, 251
    172   ret i32 %r
    173 }
    174 
    175 define i32 @not_urem_dividend_known_smaller_than_constant_divisor(i32 %x) {
    176 ; CHECK-LABEL: @not_urem_dividend_known_smaller_than_constant_divisor(
    177 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 251
    178 ; CHECK-NEXT:    [[R:%.*]] = urem i32 [[AND]], 251
    179 ; CHECK-NEXT:    ret i32 [[R]]
    180 ;
    181   %and = and i32 %x, 251
    182   %r = urem i32 %and, 251
    183   ret i32 %r
    184 }
    185 
    186 define i32 @urem_constant_dividend_known_smaller_than_divisor(i32 %x) {
    187 ; CHECK-LABEL: @urem_constant_dividend_known_smaller_than_divisor(
    188 ; CHECK-NEXT:    ret i32 250
    189 ;
    190   %or = or i32 %x, 251
    191   %r = urem i32 250, %or
    192   ret i32 %r
    193 }
    194 
    195 define i32 @not_urem_constant_dividend_known_smaller_than_divisor(i32 %x) {
    196 ; CHECK-LABEL: @not_urem_constant_dividend_known_smaller_than_divisor(
    197 ; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], 251
    198 ; CHECK-NEXT:    [[R:%.*]] = urem i32 251, [[OR]]
    199 ; CHECK-NEXT:    ret i32 [[R]]
    200 ;
    201   %or = or i32 %x, 251
    202   %r = urem i32 251, %or
    203   ret i32 %r
    204 }
    205 
    206 ; This would require computing known bits on both x and y. Is it worth doing?
    207 
    208 define i32 @urem_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
    209 ; CHECK-LABEL: @urem_dividend_known_smaller_than_divisor(
    210 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 250
    211 ; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], 251
    212 ; CHECK-NEXT:    [[R:%.*]] = urem i32 [[AND]], [[OR]]
    213 ; CHECK-NEXT:    ret i32 [[R]]
    214 ;
    215   %and = and i32 %x, 250
    216   %or = or i32 %y, 251
    217   %r = urem i32 %and, %or
    218   ret i32 %r
    219 }
    220 
    221 define i32 @not_urem_dividend_known_smaller_than_divisor(i32 %x, i32 %y) {
    222 ; CHECK-LABEL: @not_urem_dividend_known_smaller_than_divisor(
    223 ; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 251
    224 ; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], 251
    225 ; CHECK-NEXT:    [[R:%.*]] = urem i32 [[AND]], [[OR]]
    226 ; CHECK-NEXT:    ret i32 [[R]]
    227 ;
    228   %and = and i32 %x, 251
    229   %or = or i32 %y, 251
    230   %r = urem i32 %and, %or
    231   ret i32 %r
    232 }
    233 
    234 declare i32 @external()
    235 
    236 define i32 @rem4() {
    237 ; CHECK-LABEL: @rem4(
    238 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @external(), !range !0
    239 ; CHECK-NEXT:    ret i32 [[CALL]]
    240 ;
    241   %call = call i32 @external(), !range !0
    242   %urem = urem i32 %call, 3
    243   ret i32 %urem
    244 }
    245 
    246 !0 = !{i32 0, i32 3}
    247 
    248 define i32 @rem5(i32 %x, i32 %y) {
    249 ; CHECK-LABEL: @rem5(
    250 ; CHECK-NEXT:    ret i32 0
    251 ;
    252   %shl = shl nsw i32 %x, %y
    253   %mod = srem i32 %shl, %x
    254   ret i32 %mod
    255 }
    256 
    257 define <2 x i32> @rem6(<2 x i32> %x, <2 x i32> %y) {
    258 ; CHECK-LABEL: @rem6(
    259 ; CHECK-NEXT:    ret <2 x i32> zeroinitializer
    260 ;
    261   %shl = shl nsw <2 x i32> %x, %y
    262   %mod = srem <2 x i32> %shl, %x
    263   ret <2 x i32> %mod
    264 }
    265 
    266 ; make sure the previous fold doesn't take place for wrapped shifts
    267 
    268 define i32 @rem7(i32 %x, i32 %y) {
    269 ; CHECK-LABEL: @rem7(
    270 ; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
    271 ; CHECK-NEXT:    [[MOD:%.*]] = srem i32 [[SHL]], [[X]]
    272 ; CHECK-NEXT:    ret i32 [[MOD]]
    273 ;
    274   %shl = shl i32 %x, %y
    275   %mod = srem i32 %shl, %x
    276   ret i32 %mod
    277 }
    278 
    279 define i32 @rem8(i32 %x, i32 %y) {
    280 ; CHECK-LABEL: @rem8(
    281 ; CHECK-NEXT:    ret i32 0
    282 ;
    283   %shl = shl nuw i32 %x, %y
    284   %mod = urem i32 %shl, %x
    285   ret i32 %mod
    286 }
    287 
    288 define <2 x i32> @rem9(<2 x i32> %x, <2 x i32> %y) {
    289 ; CHECK-LABEL: @rem9(
    290 ; CHECK-NEXT:    ret <2 x i32> zeroinitializer
    291 ;
    292   %shl = shl nuw <2 x i32> %x, %y
    293   %mod = urem <2 x i32> %shl, %x
    294   ret <2 x i32> %mod
    295 }
    296 
    297 ; make sure the previous fold doesn't take place for wrapped shifts
    298 
    299 define i32 @rem10(i32 %x, i32 %y) {
    300 ; CHECK-LABEL: @rem10(
    301 ; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[X:%.*]], [[Y:%.*]]
    302 ; CHECK-NEXT:    [[MOD:%.*]] = urem i32 [[SHL]], [[X]]
    303 ; CHECK-NEXT:    ret i32 [[MOD]]
    304 ;
    305   %shl = shl i32 %x, %y
    306   %mod = urem i32 %shl, %x
    307   ret i32 %mod
    308 }
    309 
    310 define i32 @srem_with_sext_bool_divisor(i1 %x, i32 %y) {
    311 ; CHECK-LABEL: @srem_with_sext_bool_divisor(
    312 ; CHECK-NEXT:    ret i32 0
    313 ;
    314   %s = sext i1 %x to i32
    315   %r = srem i32 %y, %s
    316   ret i32 %r
    317 }
    318 
    319 define <2 x i32> @srem_with_sext_bool_divisor_vec(<2 x i1> %x, <2 x i32> %y) {
    320 ; CHECK-LABEL: @srem_with_sext_bool_divisor_vec(
    321 ; CHECK-NEXT:    ret <2 x i32> zeroinitializer
    322 ;
    323   %s = sext <2 x i1> %x to <2 x i32>
    324   %r = srem <2 x i32> %y, %s
    325   ret <2 x i32> %r
    326 }
    327 
    328