[InstCombine] Use commutable matchers and m_OneUse in visitSub to shorten code. Add missing test cases.

In one case I removed commute handling for a multiply with a constant since we'll eventually get the constant on the right hand side.

llvm-svn: 299863
This commit is contained in:
Craig Topper 2017-04-10 18:09:25 +00:00
parent 59d309c7b5
commit 0d830ff7bf
2 changed files with 133 additions and 15 deletions

View File

@ -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);
}

View File

@ -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:%.*]], <i32 8, i32 6>
; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret <2 x i32> [[SUB]]
;
%mul = mul <2 x i32> %y, <i32 -8, i32 -6>
%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:%.*]], <i32 3, i32 3>
; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret <2 x i32> [[SUB]]
;
%mul = mul <2 x i32> %y, <i32 -8, i32 -8>
%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:%.*]], <i32 8, i32 -8>
; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret <2 x i32> [[SUB]]
;
%mul = mul <2 x i32> %y, <i32 -8, i32 8>
%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:%.*]], <i32 8, i32 6>
; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret <2 x i32> [[SUB]]
;
%mul = mul <2 x i32> <i32 -8, i32 -6>, %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:%.*]], <i32 3, i32 3>
; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret <2 x i32> [[SUB]]
;
%mul = mul <2 x i32> <i32 -8, i32 -8>, %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:%.*]], <i32 8, i32 -8>
; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[TMP1]], [[X:%.*]]
; CHECK-NEXT: ret <2 x i32> [[SUB]]
;
%mul = mul <2 x i32> <i32 -8, i32 8>, %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:%.*]]