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