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 constant) 5; ((x ^ y) & M) ^ y 6; Unfold it to 7; (x & M) | (y & ~M) 8 9define i4 @scalar0 (i4 %x, i4 %y) { 10; CHECK-LABEL: @scalar0( 11; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X:%.*]], 1 12; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y:%.*]], -2 13; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] 14; CHECK-NEXT: ret i4 [[R]] 15; 16 %n0 = xor i4 %x, %y 17 %n1 = and i4 %n0, 1 18 %r = xor i4 %n1, %y 19 ret i4 %r 20} 21 22define i4 @scalar1 (i4 %x, i4 %y) { 23; CHECK-LABEL: @scalar1( 24; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X:%.*]], -2 25; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y:%.*]], 1 26; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] 27; CHECK-NEXT: ret i4 [[R]] 28; 29 %n0 = xor i4 %x, %y 30 %n1 = and i4 %n0, -2 31 %r = xor i4 %n1, %y 32 ret i4 %r 33} 34 35; ============================================================================ ; 36; Various cases with %x and/or %y being a constant 37; ============================================================================ ; 38 39define i4 @in_constant_varx_mone(i4 %x, i4 %mask) { 40; CHECK-LABEL: @in_constant_varx_mone( 41; CHECK-NEXT: [[R1:%.*]] = or i4 [[X:%.*]], -2 42; CHECK-NEXT: ret i4 [[R1]] 43; 44 %n0 = xor i4 %x, -1 ; %x 45 %n1 = and i4 %n0, 1 46 %r = xor i4 %n1, -1 47 ret i4 %r 48} 49 50define i4 @in_constant_varx_14(i4 %x, i4 %mask) { 51; CHECK-LABEL: @in_constant_varx_14( 52; CHECK-NEXT: [[R1:%.*]] = or i4 [[X:%.*]], -2 53; CHECK-NEXT: ret i4 [[R1]] 54; 55 %n0 = xor i4 %x, 14 ; %x 56 %n1 = and i4 %n0, 1 57 %r = xor i4 %n1, 14 58 ret i4 %r 59} 60 61define i4 @in_constant_mone_vary(i4 %y, i4 %mask) { 62; CHECK-LABEL: @in_constant_mone_vary( 63; CHECK-NEXT: [[N0:%.*]] = and i4 [[Y:%.*]], 1 64; CHECK-NEXT: [[N1:%.*]] = xor i4 [[N0]], 1 65; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]] 66; CHECK-NEXT: ret i4 [[R]] 67; 68 %n0 = xor i4 %y, -1 ; %x 69 %n1 = and i4 %n0, 1 70 %r = xor i4 %n1, %y 71 ret i4 %r 72} 73 74define i4 @in_constant_14_vary(i4 %y, i4 %mask) { 75; CHECK-LABEL: @in_constant_14_vary( 76; CHECK-NEXT: [[R:%.*]] = and i4 [[Y:%.*]], -2 77; CHECK-NEXT: ret i4 [[R]] 78; 79 %n0 = xor i4 %y, 14 ; %x 80 %n1 = and i4 %n0, 1 81 %r = xor i4 %n1, %y 82 ret i4 %r 83} 84 85; ============================================================================ ; 86; Commutativity 87; ============================================================================ ; 88 89; Used to make sure that the IR complexity sorting does not interfere. 90declare i4 @gen4() 91 92define i4 @c_1_0_0 (i4 %x, i4 %y) { 93; CHECK-LABEL: @c_1_0_0( 94; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X:%.*]], -2 95; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y:%.*]], 1 96; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] 97; CHECK-NEXT: ret i4 [[R]] 98; 99 %n0 = xor i4 %y, %x ; swapped order 100 %n1 = and i4 %n0, -2 101 %r = xor i4 %n1, %y 102 ret i4 %r 103} 104 105define i4 @c_0_1_0 (i4 %x, i4 %y) { 106; CHECK-LABEL: @c_0_1_0( 107; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[Y:%.*]], -2 108; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[X:%.*]], 1 109; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] 110; CHECK-NEXT: ret i4 [[R]] 111; 112 %n0 = xor i4 %x, %y 113 %n1 = and i4 %n0, -2 114 %r = xor i4 %n1, %x ; %x instead of %y 115 ret i4 %r 116} 117 118define i4 @c_0_0_1 () { 119; CHECK-LABEL: @c_0_0_1( 120; CHECK-NEXT: [[X:%.*]] = call i4 @gen4() 121; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4() 122; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X]], -2 123; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y]], 1 124; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] 125; CHECK-NEXT: ret i4 [[R]] 126; 127 %x = call i4 @gen4() 128 %y = call i4 @gen4() 129 %n0 = xor i4 %x, %y 130 %n1 = and i4 %n0, -2 131 %r = xor i4 %y, %n1 ; swapped order 132 ret i4 %r 133} 134 135define i4 @c_1_1_0 (i4 %x, i4 %y) { 136; CHECK-LABEL: @c_1_1_0( 137; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[Y:%.*]], -2 138; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[X:%.*]], 1 139; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] 140; CHECK-NEXT: ret i4 [[R]] 141; 142 %n0 = xor i4 %y, %x ; swapped order 143 %n1 = and i4 %n0, -2 144 %r = xor i4 %n1, %x ; %x instead of %y 145 ret i4 %r 146} 147 148define i4 @c_1_0_1 (i4 %x) { 149; CHECK-LABEL: @c_1_0_1( 150; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4() 151; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X:%.*]], -2 152; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y]], 1 153; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] 154; CHECK-NEXT: ret i4 [[R]] 155; 156 %y = call i4 @gen4() 157 %n0 = xor i4 %y, %x ; swapped order 158 %n1 = and i4 %n0, -2 159 %r = xor i4 %y, %n1 ; swapped order 160 ret i4 %r 161} 162 163define i4 @c_0_1_1 (i4 %y) { 164; CHECK-LABEL: @c_0_1_1( 165; CHECK-NEXT: [[X:%.*]] = call i4 @gen4() 166; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[Y:%.*]], -2 167; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[X]], 1 168; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] 169; CHECK-NEXT: ret i4 [[R]] 170; 171 %x = call i4 @gen4() 172 %n0 = xor i4 %x, %y 173 %n1 = and i4 %n0, -2 174 %r = xor i4 %x, %n1 ; swapped order, %x instead of %y 175 ret i4 %r 176} 177 178define i4 @c_1_1_1 () { 179; CHECK-LABEL: @c_1_1_1( 180; CHECK-NEXT: [[X:%.*]] = call i4 @gen4() 181; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4() 182; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[Y]], -2 183; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[X]], 1 184; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] 185; CHECK-NEXT: ret i4 [[R]] 186; 187 %x = call i4 @gen4() 188 %y = call i4 @gen4() 189 %n0 = xor i4 %y, %x ; swapped order 190 %n1 = and i4 %n0, -2 191 %r = xor i4 %x, %n1 ; swapped order, %x instead of %y 192 ret i4 %r 193} 194 195define i4 @commutativity_constant_14_vary(i4 %y, i4 %mask) { 196; CHECK-LABEL: @commutativity_constant_14_vary( 197; CHECK-NEXT: [[R:%.*]] = and i4 [[Y:%.*]], -2 198; CHECK-NEXT: ret i4 [[R]] 199; 200 %n0 = xor i4 %y, 14 ; %x 201 %n1 = and i4 %n0, 1 202 %r = xor i4 %y, %n1 ; swapped 203 ret i4 %r 204} 205 206; ============================================================================ ; 207; Negative tests. Should not be folded. 208; ============================================================================ ; 209 210; One use only. 211 212declare void @use4(i4) 213 214define i4 @n_oneuse_D (i4 %x, i4 %y) { 215; CHECK-LABEL: @n_oneuse_D( 216; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]] 217; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], -2 218; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]] 219; CHECK-NEXT: call void @use4(i4 [[N0]]) 220; CHECK-NEXT: ret i4 [[R]] 221; 222 %n0 = xor i4 %x, %y ; two uses of %n0, which is going to be replaced 223 %n1 = and i4 %n0, -2 224 %r = xor i4 %n1, %y 225 call void @use4(i4 %n0) 226 ret i4 %r 227} 228 229define i4 @n_oneuse_A (i4 %x, i4 %y) { 230; CHECK-LABEL: @n_oneuse_A( 231; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]] 232; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], -2 233; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]] 234; CHECK-NEXT: call void @use4(i4 [[N1]]) 235; CHECK-NEXT: ret i4 [[R]] 236; 237 %n0 = xor i4 %x, %y 238 %n1 = and i4 %n0, -2 ; two uses of %n1, which is going to be replaced 239 %r = xor i4 %n1, %y 240 call void @use4(i4 %n1) 241 ret i4 %r 242} 243 244define i4 @n_oneuse_AD (i4 %x, i4 %y) { 245; CHECK-LABEL: @n_oneuse_AD( 246; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]] 247; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], -2 248; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]] 249; CHECK-NEXT: call void @use4(i4 [[N0]]) 250; CHECK-NEXT: call void @use4(i4 [[N1]]) 251; CHECK-NEXT: ret i4 [[R]] 252; 253 %n0 = xor i4 %x, %y 254 %n1 = and i4 %n0, -2 ; two uses of %n1, which is going to be replaced 255 %r = xor i4 %n1, %y 256 call void @use4(i4 %n0) 257 call void @use4(i4 %n1) 258 ret i4 %r 259} 260 261; Mask is not constant 262 263define i4 @n_var_mask (i4 %x, i4 %y, i4 %m) { 264; CHECK-LABEL: @n_var_mask( 265; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]] 266; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], [[M:%.*]] 267; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]] 268; CHECK-NEXT: ret i4 [[R]] 269; 270 %n0 = xor i4 %x, %y 271 %n1 = and i4 %n0, %m 272 %r = xor i4 %n1, %y 273 ret i4 %r 274} 275 276; Some third variable is used 277 278define i4 @n_third_var (i4 %x, i4 %y, i4 %z) { 279; CHECK-LABEL: @n_third_var( 280; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]] 281; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], -2 282; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Z:%.*]] 283; CHECK-NEXT: ret i4 [[R]] 284; 285 %n0 = xor i4 %x, %y 286 %n1 = and i4 %n0, -2 287 %r = xor i4 %n1, %z ; not %x or %y 288 ret i4 %r 289} 290