Home | History | Annotate | Download | only in InstCombine
      1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
      2 ; RUN: opt < %s -instcombine -S | FileCheck %s
      3 
      4 ; If we have a masked merge, in the form of: (M is not constant)
      5 ;   ((x ^ y) & ~M) ^ y
      6 ; We can de-invert the M:
      7 ;   ((x ^ y) & M) ^ x
      8 
      9 define i4 @scalar (i4 %x, i4 %y, i4 %m) {
     10 ; CHECK-LABEL: @scalar(
     11 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
     12 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
     13 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
     14 ; CHECK-NEXT:    ret i4 [[R]]
     15 ;
     16   %im = xor i4 %m, -1
     17   %n0 = xor i4 %x, %y
     18   %n1 = and i4 %n0, %im
     19   %r  = xor i4 %n1, %y
     20   ret i4 %r
     21 }
     22 
     23 ; ============================================================================ ;
     24 ; Various cases with %x and/or %y being a constant
     25 ; ============================================================================ ;
     26 
     27 define i4 @in_constant_varx_mone_invmask(i4 %x, i4 %mask) {
     28 ; CHECK-LABEL: @in_constant_varx_mone_invmask(
     29 ; CHECK-NEXT:    [[N1_DEMORGAN:%.*]] = or i4 [[X:%.*]], [[MASK:%.*]]
     30 ; CHECK-NEXT:    ret i4 [[N1_DEMORGAN]]
     31 ;
     32   %notmask = xor i4 %mask, -1
     33   %n0 = xor i4 %x, -1 ; %x
     34   %n1 = and i4 %n0, %notmask
     35   %r = xor i4 %n1, -1
     36   ret i4 %r
     37 }
     38 
     39 define i4 @in_constant_varx_6_invmask(i4 %x, i4 %mask) {
     40 ; CHECK-LABEL: @in_constant_varx_6_invmask(
     41 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], 6
     42 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
     43 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
     44 ; CHECK-NEXT:    ret i4 [[R]]
     45 ;
     46   %notmask = xor i4 %mask, -1
     47   %n0 = xor i4 %x, 6 ; %x
     48   %n1 = and i4 %n0, %notmask
     49   %r = xor i4 %n1, 6
     50   ret i4 %r
     51 }
     52 
     53 define i4 @in_constant_mone_vary_invmask(i4 %y, i4 %mask) {
     54 ; CHECK-LABEL: @in_constant_mone_vary_invmask(
     55 ; CHECK-NEXT:    [[N1_DEMORGAN:%.*]] = or i4 [[Y:%.*]], [[MASK:%.*]]
     56 ; CHECK-NEXT:    [[N1:%.*]] = xor i4 [[N1_DEMORGAN]], -1
     57 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
     58 ; CHECK-NEXT:    ret i4 [[R]]
     59 ;
     60   %notmask = xor i4 %mask, -1
     61   %n0 = xor i4 -1, %y ; %x
     62   %n1 = and i4 %n0, %notmask
     63   %r = xor i4 %n1, %y
     64   ret i4 %r
     65 }
     66 
     67 define i4 @in_constant_6_vary_invmask(i4 %y, i4 %mask) {
     68 ; CHECK-LABEL: @in_constant_6_vary_invmask(
     69 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], 6
     70 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
     71 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], 6
     72 ; CHECK-NEXT:    ret i4 [[R]]
     73 ;
     74   %notmask = xor i4 %mask, -1
     75   %n0 = xor i4 %y, 6 ; %x
     76   %n1 = and i4 %n0, %notmask
     77   %r = xor i4 %n1, %y
     78   ret i4 %r
     79 }
     80 
     81 ; ============================================================================ ;
     82 ; Commutativity
     83 ; ============================================================================ ;
     84 
     85 ; Used to make sure that the IR complexity sorting does not interfere.
     86 declare i4 @gen4()
     87 
     88 ; FIXME: should the  %n1 = and i4 %im, %n0  swapped order pattern be tested?
     89 
     90 define i4 @c_1_0_0 (i4 %x, i4 %y, i4 %m) {
     91 ; CHECK-LABEL: @c_1_0_0(
     92 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
     93 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
     94 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
     95 ; CHECK-NEXT:    ret i4 [[R]]
     96 ;
     97   %im = xor i4 %m, -1
     98   %n0 = xor i4 %y, %x ; swapped order
     99   %n1 = and i4 %n0, %im
    100   %r  = xor i4 %n1, %y
    101   ret i4 %r
    102 }
    103 
    104 define i4 @c_0_1_0 (i4 %x, i4 %y, i4 %m) {
    105 ; CHECK-LABEL: @c_0_1_0(
    106 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
    107 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
    108 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
    109 ; CHECK-NEXT:    ret i4 [[R]]
    110 ;
    111   %im = xor i4 %m, -1
    112   %n0 = xor i4 %x, %y
    113   %n1 = and i4 %n0, %im
    114   %r  = xor i4 %n1, %x ; %x instead of %y
    115   ret i4 %r
    116 }
    117 
    118 define i4 @c_0_0_1 (i4 %m) {
    119 ; CHECK-LABEL: @c_0_0_1(
    120 ; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
    121 ; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
    122 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X]], [[Y]]
    123 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
    124 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
    125 ; CHECK-NEXT:    ret i4 [[R]]
    126 ;
    127   %im = xor i4 %m, -1
    128   %x  = call i4 @gen4()
    129   %y  = call i4 @gen4()
    130   %n0 = xor i4 %x, %y
    131   %n1 = and i4 %n0, %im
    132   %r  = xor i4 %y, %n1 ; swapped order
    133   ret i4 %r
    134 }
    135 
    136 define i4 @c_1_1_0 (i4 %x, i4 %y, i4 %m) {
    137 ; CHECK-LABEL: @c_1_1_0(
    138 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
    139 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
    140 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
    141 ; CHECK-NEXT:    ret i4 [[R]]
    142 ;
    143   %im = xor i4 %m, -1
    144   %n0 = xor i4 %y, %x ; swapped order
    145   %n1 = and i4 %n0, %im
    146   %r  = xor i4 %n1, %x ; %x instead of %y
    147   ret i4 %r
    148 }
    149 
    150 define i4 @c_1_0_1 (i4 %x, i4 %m) {
    151 ; CHECK-LABEL: @c_1_0_1(
    152 ; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
    153 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y]], [[X:%.*]]
    154 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
    155 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
    156 ; CHECK-NEXT:    ret i4 [[R]]
    157 ;
    158   %im = xor i4 %m, -1
    159   %y  = call i4 @gen4()
    160   %n0 = xor i4 %y, %x ; swapped order
    161   %n1 = and i4 %n0, %im
    162   %r  = xor i4 %y, %n1 ; swapped order
    163   ret i4 %r
    164 }
    165 
    166 define i4 @c_0_1_1 (i4 %y, i4 %m) {
    167 ; CHECK-LABEL: @c_0_1_1(
    168 ; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
    169 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X]], [[Y:%.*]]
    170 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
    171 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
    172 ; CHECK-NEXT:    ret i4 [[R]]
    173 ;
    174   %im = xor i4 %m, -1
    175   %x  = call i4 @gen4()
    176   %n0 = xor i4 %x, %y
    177   %n1 = and i4 %n0, %im
    178   %r  = xor i4 %x, %n1 ; swapped order, %x instead of %y
    179   ret i4 %r
    180 }
    181 
    182 define i4 @c_1_1_1 (i4 %m) {
    183 ; CHECK-LABEL: @c_1_1_1(
    184 ; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
    185 ; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
    186 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y]], [[X]]
    187 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
    188 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
    189 ; CHECK-NEXT:    ret i4 [[R]]
    190 ;
    191   %im = xor i4 %m, -1
    192   %x  = call i4 @gen4()
    193   %y  = call i4 @gen4()
    194   %n0 = xor i4 %y, %x ; swapped order
    195   %n1 = and i4 %n0, %im
    196   %r  = xor i4 %x, %n1 ; swapped order, %x instead of %y
    197   ret i4 %r
    198 }
    199 
    200 define i4 @commutativity_constant_varx_6_invmask(i4 %x, i4 %mask) {
    201 ; CHECK-LABEL: @commutativity_constant_varx_6_invmask(
    202 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], 6
    203 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
    204 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
    205 ; CHECK-NEXT:    ret i4 [[R]]
    206 ;
    207   %notmask = xor i4 %mask, -1
    208   %n0 = xor i4 %x, 6 ; %x
    209   %n1 = and i4 %notmask, %n0 ; swapped
    210   %r = xor i4 %n1, 6
    211   ret i4 %r
    212 }
    213 
    214 define i4 @commutativity_constant_6_vary_invmask(i4 %y, i4 %mask) {
    215 ; CHECK-LABEL: @commutativity_constant_6_vary_invmask(
    216 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], 6
    217 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
    218 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], 6
    219 ; CHECK-NEXT:    ret i4 [[R]]
    220 ;
    221   %notmask = xor i4 %mask, -1
    222   %n0 = xor i4 %y, 6 ; %x
    223   %n1 = and i4 %notmask, %n0 ; swapped
    224   %r = xor i4 %n1, %y
    225   ret i4 %r
    226 }
    227 
    228 ; ============================================================================ ;
    229 ; Negative tests. Should not be folded.
    230 ; ============================================================================ ;
    231 
    232 ; One use only.
    233 
    234 declare void @use4(i4)
    235 
    236 define i4 @n_oneuse_D_is_ok (i4 %x, i4 %y, i4 %m) {
    237 ; CHECK-LABEL: @n_oneuse_D_is_ok(
    238 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
    239 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
    240 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
    241 ; CHECK-NEXT:    call void @use4(i4 [[N0]])
    242 ; CHECK-NEXT:    ret i4 [[R]]
    243 ;
    244   %im = xor i4 %m, -1
    245   %n0 = xor i4 %x, %y ; two uses of %n0, THIS IS OK!
    246   %n1 = and i4 %n0, %im
    247   %r  = xor i4 %n1, %y
    248   call void @use4(i4 %n0)
    249   ret i4 %r
    250 }
    251 
    252 define i4 @n_oneuse_A (i4 %x, i4 %y, i4 %m) {
    253 ; CHECK-LABEL: @n_oneuse_A(
    254 ; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], -1
    255 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
    256 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
    257 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
    258 ; CHECK-NEXT:    call void @use4(i4 [[N1]])
    259 ; CHECK-NEXT:    ret i4 [[R]]
    260 ;
    261   %im = xor i4 %m, -1
    262   %n0 = xor i4 %x, %y
    263   %n1 = and i4 %n0, %im ; two uses of %n1, which is going to be replaced
    264   %r  = xor i4 %n1, %y
    265   call void @use4(i4 %n1)
    266   ret i4 %r
    267 }
    268 
    269 define i4 @n_oneuse_AD (i4 %x, i4 %y, i4 %m) {
    270 ; CHECK-LABEL: @n_oneuse_AD(
    271 ; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], -1
    272 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
    273 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
    274 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
    275 ; CHECK-NEXT:    call void @use4(i4 [[N0]])
    276 ; CHECK-NEXT:    call void @use4(i4 [[N1]])
    277 ; CHECK-NEXT:    ret i4 [[R]]
    278 ;
    279   %im = xor i4 %m, -1
    280   %n0 = xor i4 %x, %y
    281   %n1 = and i4 %n0, %im ; two uses of %n1, which is going to be replaced
    282   %r  = xor i4 %n1, %y
    283   call void @use4(i4 %n0)
    284   call void @use4(i4 %n1)
    285   ret i4 %r
    286 }
    287 
    288 ; Some third variable is used
    289 
    290 define i4 @n_third_var (i4 %x, i4 %y, i4 %z, i4 %m) {
    291 ; CHECK-LABEL: @n_third_var(
    292 ; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], -1
    293 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
    294 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
    295 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Z:%.*]]
    296 ; CHECK-NEXT:    ret i4 [[R]]
    297 ;
    298   %im = xor i4 %m, -1
    299   %n0 = xor i4 %x, %y
    300   %n1 = and i4 %n0, %im
    301   %r  = xor i4 %n1, %z ; not %x or %y
    302   ret i4 %r
    303 }
    304 
    305 define i4 @n_badxor (i4 %x, i4 %y, i4 %m) {
    306 ; CHECK-LABEL: @n_badxor(
    307 ; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], 1
    308 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
    309 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
    310 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
    311 ; CHECK-NEXT:    ret i4 [[R]]
    312 ;
    313   %im = xor i4 %m, 1 ; not -1
    314   %n0 = xor i4 %x, %y
    315   %n1 = and i4 %n0, %im
    316   %r  = xor i4 %n1, %y
    317   ret i4 %r
    318 }
    319