Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2418,6 +2418,7 @@ /// If A has one use, and M is inverted, we can convert it into: /// | D | /// ((x ^ y) & ~M) ^ x +/// If the M is constant, we want to unfold it to (x & M) | (y & ~M) static Instruction *visitMaskedMerge(BinaryOperator &I, InstCombiner::BuilderTy &Builder) { Value *B, *X, *D; @@ -2436,6 +2437,15 @@ return BinaryOperator::CreateXor(NewA, X); } + Constant *C; + if (D->hasOneUse() && match(M, m_Constant(C))) { + // Unfold. + Value *LHS = Builder.CreateAnd(X, C); + Value *iC = Builder.CreateNot(C); + Value *RHS = Builder.CreateAnd(B, iC); + return BinaryOperator::CreateOr(LHS, RHS); + } + return nullptr; } Index: test/Transforms/InstCombine/unfold-masked-merge-with-const-mask-scalar.ll =================================================================== --- test/Transforms/InstCombine/unfold-masked-merge-with-const-mask-scalar.ll +++ test/Transforms/InstCombine/unfold-masked-merge-with-const-mask-scalar.ll @@ -8,9 +8,9 @@ define i4 @scalar0 (i4 %x, i4 %y) { ; CHECK-LABEL: @scalar0( -; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], 1 -; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]] +; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X:%.*]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y:%.*]], -2 +; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i4 [[R]] ; %n0 = xor i4 %x, %y @@ -21,9 +21,9 @@ define i4 @scalar1 (i4 %x, i4 %y) { ; CHECK-LABEL: @scalar1( -; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], -2 -; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]] +; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X:%.*]], -2 +; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y:%.*]], 1 +; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i4 [[R]] ; %n0 = xor i4 %x, %y @@ -140,9 +140,9 @@ define i4 @c_1_0_0 (i4 %x, i4 %y) { ; CHECK-LABEL: @c_1_0_0( -; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], -2 -; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]] +; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X:%.*]], -2 +; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y:%.*]], 1 +; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i4 [[R]] ; %n0 = xor i4 %y, %x ; swapped order @@ -153,9 +153,9 @@ define i4 @c_0_1_0 (i4 %x, i4 %y) { ; CHECK-LABEL: @c_0_1_0( -; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], -2 -; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[Y:%.*]], -2 +; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[X:%.*]], 1 +; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i4 [[R]] ; %n0 = xor i4 %x, %y @@ -168,9 +168,9 @@ ; CHECK-LABEL: @c_0_0_1( ; CHECK-NEXT: [[X:%.*]] = call i4 @gen4() ; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4() -; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X]], [[Y]] -; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], -2 -; CHECK-NEXT: [[R:%.*]] = xor i4 [[Y]], [[N1]] +; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X]], -2 +; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y]], 1 +; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i4 [[R]] ; %x = call i4 @gen4() @@ -183,9 +183,9 @@ define i4 @c_1_1_0 (i4 %x, i4 %y) { ; CHECK-LABEL: @c_1_1_0( -; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], -2 -; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[Y:%.*]], -2 +; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[X:%.*]], 1 +; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i4 [[R]] ; %n0 = xor i4 %y, %x ; swapped order @@ -197,9 +197,9 @@ define i4 @c_1_0_1 (i4 %x) { ; CHECK-LABEL: @c_1_0_1( ; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4() -; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y]], [[X:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], -2 -; CHECK-NEXT: [[R:%.*]] = xor i4 [[Y]], [[N1]] +; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X:%.*]], -2 +; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[Y]], 1 +; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i4 [[R]] ; %y = call i4 @gen4() @@ -212,9 +212,9 @@ define i4 @c_0_1_1 (i4 %y) { ; CHECK-LABEL: @c_0_1_1( ; CHECK-NEXT: [[X:%.*]] = call i4 @gen4() -; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X]], [[Y:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], -2 -; CHECK-NEXT: [[R:%.*]] = xor i4 [[X]], [[N1]] +; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[Y:%.*]], -2 +; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[X]], 1 +; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i4 [[R]] ; %x = call i4 @gen4() @@ -228,9 +228,9 @@ ; CHECK-LABEL: @c_1_1_1( ; CHECK-NEXT: [[X:%.*]] = call i4 @gen4() ; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4() -; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y]], [[X]] -; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], -2 -; CHECK-NEXT: [[R:%.*]] = xor i4 [[X]], [[N1]] +; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[Y]], -2 +; CHECK-NEXT: [[TMP2:%.*]] = and i4 [[X]], 1 +; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i4 [[R]] ; %x = call i4 @gen4() Index: test/Transforms/InstCombine/unfold-masked-merge-with-const-mask-vector.ll =================================================================== --- test/Transforms/InstCombine/unfold-masked-merge-with-const-mask-vector.ll +++ test/Transforms/InstCombine/unfold-masked-merge-with-const-mask-vector.ll @@ -8,9 +8,9 @@ define <2 x i4> @splat (<2 x i4> %x, <2 x i4> %y) { ; CHECK-LABEL: @splat( -; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], -; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[Y:%.*]], +; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <2 x i4> [[R]] ; %n0 = xor <2 x i4> %x, %y @@ -21,9 +21,9 @@ define <3 x i4> @splat_undef (<3 x i4> %x, <3 x i4> %y) { ; CHECK-LABEL: @splat_undef( -; CHECK-NEXT: [[N0:%.*]] = xor <3 x i4> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and <3 x i4> [[N0]], -; CHECK-NEXT: [[R:%.*]] = xor <3 x i4> [[N1]], [[Y]] +; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i4> [[X:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i4> [[Y:%.*]], +; CHECK-NEXT: [[R:%.*]] = or <3 x i4> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <3 x i4> [[R]] ; %n0 = xor <3 x i4> %x, %y @@ -34,9 +34,9 @@ define <2 x i4> @nonsplat (<2 x i4> %x, <2 x i4> %y) { ; CHECK-LABEL: @nonsplat( -; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], -; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[Y:%.*]], +; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <2 x i4> [[R]] ; %n0 = xor <2 x i4> %x, %y @@ -153,9 +153,9 @@ define <2 x i4> @c_1_0_0 (<2 x i4> %x, <2 x i4> %y) { ; CHECK-LABEL: @c_1_0_0( -; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], -; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[N1]], [[Y]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[Y:%.*]], +; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <2 x i4> [[R]] ; %n0 = xor <2 x i4> %y, %x ; swapped order @@ -166,9 +166,9 @@ define <2 x i4> @c_0_1_0 (<2 x i4> %x, <2 x i4> %y) { ; CHECK-LABEL: @c_0_1_0( -; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], -; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[N1]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[Y:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <2 x i4> [[R]] ; %n0 = xor <2 x i4> %x, %y @@ -181,9 +181,9 @@ ; CHECK-LABEL: @c_0_0_1( ; CHECK-NEXT: [[X:%.*]] = call <2 x i4> @gen4() ; CHECK-NEXT: [[Y:%.*]] = call <2 x i4> @gen4() -; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X]], [[Y]] -; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], -; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[Y]], [[N1]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X]], +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[Y]], +; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <2 x i4> [[R]] ; %x = call <2 x i4> @gen4() @@ -196,9 +196,9 @@ define <2 x i4> @c_1_1_0 (<2 x i4> %x, <2 x i4> %y) { ; CHECK-LABEL: @c_1_1_0( -; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], -; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[N1]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[Y:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <2 x i4> [[R]] ; %n0 = xor <2 x i4> %y, %x ; swapped order @@ -210,9 +210,9 @@ define <2 x i4> @c_1_0_1 (<2 x i4> %x) { ; CHECK-LABEL: @c_1_0_1( ; CHECK-NEXT: [[Y:%.*]] = call <2 x i4> @gen4() -; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[Y]], [[X:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], -; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[Y]], [[N1]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[Y]], +; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <2 x i4> [[R]] ; %y = call <2 x i4> @gen4() @@ -225,9 +225,9 @@ define <2 x i4> @c_0_1_1 (<2 x i4> %y) { ; CHECK-LABEL: @c_0_1_1( ; CHECK-NEXT: [[X:%.*]] = call <2 x i4> @gen4() -; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X]], [[Y:%.*]] -; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], -; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[X]], [[N1]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[Y:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[X]], +; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <2 x i4> [[R]] ; %x = call <2 x i4> @gen4() @@ -241,9 +241,9 @@ ; CHECK-LABEL: @c_1_1_1( ; CHECK-NEXT: [[X:%.*]] = call <2 x i4> @gen4() ; CHECK-NEXT: [[Y:%.*]] = call <2 x i4> @gen4() -; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[Y]], [[X]] -; CHECK-NEXT: [[N1:%.*]] = and <2 x i4> [[N0]], -; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[X]], [[N1]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[Y]], +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i4> [[X]], +; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <2 x i4> [[R]] ; %x = call <2 x i4> @gen4()