diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index f66726e2fc33..f821bf75e44a 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1633,18 +1633,16 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { // (sub (or A, B) (xor A, B)) --> (and A, B) { - Value *A = nullptr, *B = nullptr; + Value *A, *B; if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && - (match(Op0, m_Or(m_Specific(A), m_Specific(B))) || - match(Op0, m_Or(m_Specific(B), m_Specific(A))))) + match(Op0, m_c_Or(m_Specific(A), m_Specific(B)))) return BinaryOperator::CreateAnd(A, B); } - if (Op0->hasOneUse()) { - Value *Y = nullptr; + { + Value *Y; // ((X | Y) - X) --> (~X & Y) - if (match(Op0, m_Or(m_Value(Y), m_Specific(Op1))) || - match(Op0, m_Or(m_Specific(Op1), m_Value(Y)))) + if (match(Op0, m_OneUse(m_c_Or(m_Value(Y), m_Specific(Op1))))) return BinaryOperator::CreateAnd( Y, Builder->CreateNot(Op1, Op1->getName() + ".not")); } @@ -1652,7 +1650,6 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { if (Op1->hasOneUse()) { Value *X = nullptr, *Y = nullptr, *Z = nullptr; Constant *C = nullptr; - Constant *CI = nullptr; // (X - (Y - Z)) --> (X + (Z - Y)). if (match(Op1, m_Sub(m_Value(Y), m_Value(Z)))) @@ -1661,8 +1658,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { // (X - (X & Y)) --> (X & ~Y) // - if (match(Op1, m_And(m_Value(Y), m_Specific(Op0))) || - match(Op1, m_And(m_Specific(Op0), m_Value(Y)))) + if (match(Op1, m_c_And(m_Value(Y), m_Specific(Op0)))) return BinaryOperator::CreateAnd(Op0, Builder->CreateNot(Y, Y->getName() + ".not")); @@ -1690,14 +1686,14 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { // X - A*-B -> X + A*B // X - -A*B -> X + A*B Value *A, *B; - if (match(Op1, m_Mul(m_Value(A), m_Neg(m_Value(B)))) || - match(Op1, m_Mul(m_Neg(m_Value(A)), m_Value(B)))) + Constant *CI; + if (match(Op1, m_c_Mul(m_Value(A), m_Neg(m_Value(B))))) return BinaryOperator::CreateAdd(Op0, Builder->CreateMul(A, B)); // X - A*CI -> X + A*-CI - // X - CI*A -> X + A*-CI - if (match(Op1, m_Mul(m_Value(A), m_Constant(CI))) || - match(Op1, m_Mul(m_Constant(CI), m_Value(A)))) { + // No need to handle commuted multiply because multiply handling will + // ensure constant will be move to the right hand side. + if (match(Op1, m_Mul(m_Value(A), m_Constant(CI)))) { Value *NewMul = Builder->CreateMul(A, ConstantExpr::getNeg(CI)); return BinaryOperator::CreateAdd(Op0, NewMul); } diff --git a/llvm/test/Transforms/InstCombine/sub.ll b/llvm/test/Transforms/InstCombine/sub.ll index ac38e5ef413b..4c7047636e03 100644 --- a/llvm/test/Transforms/InstCombine/sub.ll +++ b/llvm/test/Transforms/InstCombine/sub.ll @@ -62,6 +62,17 @@ define i32 @test6(i32 %A, i32 %B) { ret i32 %D } +define i32 @test6commuted(i32 %A, i32 %B) { +; CHECK-LABEL: @test6commuted( +; CHECK-NEXT: [[B_NOT:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[D:%.*]] = and i32 [[B_NOT]], [[A:%.*]] +; CHECK-NEXT: ret i32 [[D]] +; + %C = and i32 %B, %A + %D = sub i32 %A, %C + ret i32 %D +} + define i32 @test7(i32 %A) { ; CHECK-LABEL: @test7( ; CHECK-NEXT: [[B:%.*]] = xor i32 [[A:%.*]], -1 @@ -395,6 +406,83 @@ define i32 @test27(i32 %x, i32 %y) { ret i32 %sub } +define <2 x i32> @test27vec(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: @test27vec( +; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[Y:%.*]], +; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret <2 x i32> [[SUB]] +; + %mul = mul <2 x i32> %y, + %sub = sub <2 x i32> %x, %mul + ret <2 x i32> %sub +} + +define <2 x i32> @test27vecsplat(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: @test27vecsplat( +; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> [[Y:%.*]], +; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret <2 x i32> [[SUB]] +; + %mul = mul <2 x i32> %y, + %sub = sub <2 x i32> %x, %mul + ret <2 x i32> %sub +} + +define <2 x i32> @test27vecmixed(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: @test27vecmixed( +; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[Y:%.*]], +; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret <2 x i32> [[SUB]] +; + %mul = mul <2 x i32> %y, + %sub = sub <2 x i32> %x, %mul + ret <2 x i32> %sub +} + +define i32 @test27commuted(i32 %x, i32 %y) { +; CHECK-LABEL: @test27commuted( +; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[Y:%.*]], 3 +; CHECK-NEXT: [[SUB:%.*]] = add i32 [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[SUB]] +; + %mul = mul i32 -8, %y + %sub = sub i32 %x, %mul + ret i32 %sub +} + +define <2 x i32> @test27commutedvec(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: @test27commutedvec( +; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[Y:%.*]], +; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret <2 x i32> [[SUB]] +; + %mul = mul <2 x i32> , %y + %sub = sub <2 x i32> %x, %mul + ret <2 x i32> %sub +} + +define <2 x i32> @test27commutedvecsplat(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: @test27commutedvecsplat( +; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> [[Y:%.*]], +; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret <2 x i32> [[SUB]] +; + %mul = mul <2 x i32> , %y + %sub = sub <2 x i32> %x, %mul + ret <2 x i32> %sub +} + +define <2 x i32> @test27commutedvecmixed(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: @test27commutedvecmixed( +; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[Y:%.*]], +; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret <2 x i32> [[SUB]] +; + %mul = mul <2 x i32> , %y + %sub = sub <2 x i32> %x, %mul + ret <2 x i32> %sub +} + define i32 @test28(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @test28( ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[Z:%.*]], [[Y:%.*]] @@ -407,6 +495,18 @@ define i32 @test28(i32 %x, i32 %y, i32 %z) { ret i32 %sub } +define i32 @test28commuted(i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: @test28commuted( +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[Y:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[SUB:%.*]] = add i32 [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[SUB]] +; + %neg = sub i32 0, %z + %mul = mul i32 %y, %neg + %sub = sub i32 %x, %mul + ret i32 %sub +} + define i64 @test29(i8* %foo, i64 %i, i64 %j) { ; CHECK-LABEL: @test29( ; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[I:%.*]], [[J:%.*]] @@ -614,6 +714,17 @@ define i32 @test45(i32 %x, i32 %y) { ret i32 %sub } +define i32 @test45commuted(i32 %x, i32 %y) { +; CHECK-LABEL: @test45commuted( +; CHECK-NEXT: [[SUB:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i32 [[SUB]] +; + %or = or i32 %x, %y + %xor = xor i32 %y, %x + %sub = sub i32 %or, %xor + ret i32 %sub +} + define i32 @test46(i32 %x, i32 %y) { ; CHECK-LABEL: @test46( ; CHECK-NEXT: [[X_NOT:%.*]] = xor i32 [[X:%.*]], -1 @@ -625,6 +736,17 @@ define i32 @test46(i32 %x, i32 %y) { ret i32 %sub } +define i32 @test46commuted(i32 %x, i32 %y) { +; CHECK-LABEL: @test46commuted( +; CHECK-NEXT: [[X_NOT:%.*]] = xor i32 [[X:%.*]], -1 +; CHECK-NEXT: [[SUB:%.*]] = and i32 [[X_NOT]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[SUB]] +; + %or = or i32 %y, %x + %sub = sub i32 %or, %x + ret i32 %sub +} + define i32 @test47(i1 %A, i32 %B, i32 %C, i32 %D) { ; CHECK-LABEL: @test47( ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[D:%.*]], [[C:%.*]]