288 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; If we have a masked merge, in the form of: (M is constant)5; ((x ^ y) & M) ^ y6; Unfold it to7; (x & M) | (y & ~M)8 9define i4 @scalar0 (i4 %x, i4 %y) {10; CHECK-LABEL: @scalar0(11; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X:%.*]], 112; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y:%.*]], -213; CHECK-NEXT: [[R:%.*]] = or disjoint i4 [[TMP1]], [[TMP2]]14; CHECK-NEXT: ret i4 [[R]]15;16 %n0 = xor i4 %x, %y17 %n1 = and i4 %n0, 118 %r = xor i4 %n1, %y19 ret i4 %r20}21 22define i4 @scalar1 (i4 %x, i4 %y) {23; CHECK-LABEL: @scalar1(24; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X:%.*]], -225; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y:%.*]], 126; CHECK-NEXT: [[R:%.*]] = or disjoint i4 [[TMP1]], [[TMP2]]27; CHECK-NEXT: ret i4 [[R]]28;29 %n0 = xor i4 %x, %y30 %n1 = and i4 %n0, -231 %r = xor i4 %n1, %y32 ret i4 %r33}34 35; ============================================================================ ;36; Various cases with %x and/or %y being a constant37; ============================================================================ ;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:%.*]], -242; CHECK-NEXT: ret i4 [[R1]]43;44 %n0 = xor i4 %x, -1 ; %x45 %n1 = and i4 %n0, 146 %r = xor i4 %n1, -147 ret i4 %r48}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:%.*]], -253; CHECK-NEXT: ret i4 [[R1]]54;55 %n0 = xor i4 %x, 14 ; %x56 %n1 = and i4 %n0, 157 %r = xor i4 %n1, 1458 ret i4 %r59}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:%.*]], 164; CHECK-NEXT: ret i4 [[R1]]65;66 %n0 = xor i4 %y, -1 ; %x67 %n1 = and i4 %n0, 168 %r = xor i4 %n1, %y69 ret i4 %r70}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:%.*]], -275; CHECK-NEXT: ret i4 [[R]]76;77 %n0 = xor i4 %y, 14 ; %x78 %n1 = and i4 %n0, 179 %r = xor i4 %n1, %y80 ret i4 %r81}82 83; ============================================================================ ;84; Commutativity85; ============================================================================ ;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:%.*]], -293; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y:%.*]], 194; CHECK-NEXT: [[R:%.*]] = or disjoint i4 [[TMP1]], [[TMP2]]95; CHECK-NEXT: ret i4 [[R]]96;97 %n0 = xor i4 %y, %x ; swapped order98 %n1 = and i4 %n0, -299 %r = xor i4 %n1, %y100 ret i4 %r101}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:%.*]], -2106; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[X:%.*]], 1107; CHECK-NEXT: [[R:%.*]] = or disjoint i4 [[TMP1]], [[TMP2]]108; CHECK-NEXT: ret i4 [[R]]109;110 %n0 = xor i4 %x, %y111 %n1 = and i4 %n0, -2112 %r = xor i4 %n1, %x ; %x instead of %y113 ret i4 %r114}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]], -2121; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y]], 1122; 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, %y128 %n1 = and i4 %n0, -2129 %r = xor i4 %y, %n1 ; swapped order130 ret i4 %r131}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:%.*]], -2136; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[X:%.*]], 1137; CHECK-NEXT: [[R:%.*]] = or disjoint i4 [[TMP1]], [[TMP2]]138; CHECK-NEXT: ret i4 [[R]]139;140 %n0 = xor i4 %y, %x ; swapped order141 %n1 = and i4 %n0, -2142 %r = xor i4 %n1, %x ; %x instead of %y143 ret i4 %r144}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:%.*]], -2150; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y]], 1151; 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 order156 %n1 = and i4 %n0, -2157 %r = xor i4 %y, %n1 ; swapped order158 ret i4 %r159}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:%.*]], -2165; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[X]], 1166; 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, %y171 %n1 = and i4 %n0, -2172 %r = xor i4 %x, %n1 ; swapped order, %x instead of %y173 ret i4 %r174}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]], -2181; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[X]], 1182; 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 order188 %n1 = and i4 %n0, -2189 %r = xor i4 %x, %n1 ; swapped order, %x instead of %y190 ret i4 %r191}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:%.*]], -2196; CHECK-NEXT: ret i4 [[R]]197;198 %n0 = xor i4 %y, 14 ; %x199 %n1 = and i4 %n0, 1200 %r = xor i4 %y, %n1 ; swapped201 ret i4 %r202}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]], -2216; 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 replaced221 %n1 = and i4 %n0, -2222 %r = xor i4 %n1, %y223 call void @use4(i4 %n0)224 ret i4 %r225}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]], -2231; 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, %y236 %n1 = and i4 %n0, -2 ; two uses of %n1, which is going to be replaced237 %r = xor i4 %n1, %y238 call void @use4(i4 %n1)239 ret i4 %r240}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]], -2246; 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, %y252 %n1 = and i4 %n0, -2 ; two uses of %n1, which is going to be replaced253 %r = xor i4 %n1, %y254 call void @use4(i4 %n0)255 call void @use4(i4 %n1)256 ret i4 %r257}258 259; Mask is not constant260 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, %y269 %n1 = and i4 %n0, %m270 %r = xor i4 %n1, %y271 ret i4 %r272}273 274; Some third variable is used275 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]], -2280; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Z:%.*]]281; CHECK-NEXT: ret i4 [[R]]282;283 %n0 = xor i4 %x, %y284 %n1 = and i4 %n0, -2285 %r = xor i4 %n1, %z ; not %x or %y286 ret i4 %r287}288