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