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