InstCombine: Teach most integer add/sub/mul/div combines how to deal with vectors.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199602 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Benjamin Kramer 2014-01-19 15:24:22 +00:00
parent 3f6a9d705a
commit 0487faa97b
9 changed files with 225 additions and 83 deletions

View File

@ -851,8 +851,8 @@ static Constant *AddOne(Constant *C) {
}
/// SubOne - Subtract one from a ConstantInt.
static Constant *SubOne(ConstantInt *C) {
return ConstantInt::get(C->getContext(), C->getValue()-1);
static Constant *SubOne(Constant *C) {
return ConstantExpr::getAdd(C, ConstantInt::getAllOnesValue(C->getType()));
}
@ -861,23 +861,20 @@ static Constant *SubOne(ConstantInt *C) {
// non-constant operand of the multiply, and set CST to point to the multiplier.
// Otherwise, return null.
//
static inline Value *dyn_castFoldableMul(Value *V, ConstantInt *&CST) {
if (!V->hasOneUse() || !V->getType()->isIntegerTy())
static inline Value *dyn_castFoldableMul(Value *V, Constant *&CST) {
if (!V->hasOneUse() || !V->getType()->isIntOrIntVectorTy())
return 0;
Instruction *I = dyn_cast<Instruction>(V);
if (I == 0) return 0;
if (I->getOpcode() == Instruction::Mul)
if ((CST = dyn_cast<ConstantInt>(I->getOperand(1))))
if ((CST = dyn_cast<Constant>(I->getOperand(1))))
return I->getOperand(0);
if (I->getOpcode() == Instruction::Shl)
if ((CST = dyn_cast<ConstantInt>(I->getOperand(1)))) {
if ((CST = dyn_cast<Constant>(I->getOperand(1)))) {
// The multiplier is really 1 << CST.
uint32_t BitWidth = cast<IntegerType>(V->getType())->getBitWidth();
uint32_t CSTVal = CST->getLimitedValue(BitWidth);
CST = ConstantInt::get(V->getType()->getContext(),
APInt::getOneBitSet(BitWidth, CSTVal));
CST = ConstantExpr::getShl(ConstantInt::get(V->getType(), 1), CST);
return I->getOperand(0);
}
return 0;
@ -987,7 +984,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
if (Instruction *NV = FoldOpIntoPhi(I))
return NV;
if (I.getType()->isIntegerTy(1))
if (I.getType()->getScalarType()->isIntegerTy(1))
return BinaryOperator::CreateXor(LHS, RHS);
// X + X --> X << 1
@ -1017,21 +1014,23 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
return BinaryOperator::CreateSub(LHS, V);
ConstantInt *C2;
if (Value *X = dyn_castFoldableMul(LHS, C2)) {
if (X == RHS) // X*C + X --> X * (C+1)
return BinaryOperator::CreateMul(RHS, AddOne(C2));
{
Constant *C2;
if (Value *X = dyn_castFoldableMul(LHS, C2)) {
if (X == RHS) // X*C + X --> X * (C+1)
return BinaryOperator::CreateMul(RHS, AddOne(C2));
// X*C1 + X*C2 --> X * (C1+C2)
ConstantInt *C1;
if (X == dyn_castFoldableMul(RHS, C1))
return BinaryOperator::CreateMul(X, ConstantExpr::getAdd(C1, C2));
// X*C1 + X*C2 --> X * (C1+C2)
Constant *C1;
if (X == dyn_castFoldableMul(RHS, C1))
return BinaryOperator::CreateMul(X, ConstantExpr::getAdd(C1, C2));
}
// X + X*C --> X * (C+1)
if (dyn_castFoldableMul(RHS, C2) == LHS)
return BinaryOperator::CreateMul(LHS, AddOne(C2));
}
// X + X*C --> X * (C+1)
if (dyn_castFoldableMul(RHS, C2) == LHS)
return BinaryOperator::CreateMul(LHS, AddOne(C2));
// A+B --> A|B iff A and B have no bits set in common.
if (IntegerType *IT = dyn_cast<IntegerType>(I.getType())) {
APInt LHSKnownOne(IT->getBitWidth(), 0);
@ -1071,12 +1070,16 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
}
}
if (ConstantInt *CRHS = dyn_cast<ConstantInt>(RHS)) {
Value *X = 0;
if (match(LHS, m_Not(m_Value(X)))) // ~X + C --> (C-1) - X
if (Constant *CRHS = dyn_cast<Constant>(RHS)) {
Value *X;
if (match(LHS, m_Not(m_Value(X)))) // ~X + C --> (C-1) - X
return BinaryOperator::CreateSub(SubOne(CRHS), X);
}
if (ConstantInt *CRHS = dyn_cast<ConstantInt>(RHS)) {
// (X & FF00) + xx00 -> (X+xx00) & FF00
Value *X;
ConstantInt *C2;
if (LHS->hasOneUse() &&
match(LHS, m_And(m_Value(X), m_ConstantInt(C2))) &&
CRHS->getValue() == (CRHS->getValue() & C2->getValue())) {
@ -1381,12 +1384,37 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
if (match(Op0, m_AllOnes()))
return BinaryOperator::CreateNot(Op1);
if (ConstantInt *C = dyn_cast<ConstantInt>(Op0)) {
if (Constant *C = dyn_cast<Constant>(Op0)) {
// C - ~X == X + (1+C)
Value *X = 0;
if (match(Op1, m_Not(m_Value(X))))
return BinaryOperator::CreateAdd(X, AddOne(C));
// Try to fold constant sub into select arguments.
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
if (Instruction *R = FoldOpIntoSelect(I, SI))
return R;
// C-(X+C2) --> (C-C2)-X
Constant *C2;
if (match(Op1, m_Add(m_Value(X), m_Constant(C2))))
return BinaryOperator::CreateSub(ConstantExpr::getSub(C, C2), X);
if (SimplifyDemandedInstructionBits(I))
return &I;
// Fold (sub 0, (zext bool to B)) --> (sext bool to B)
if (C->isNullValue() && match(Op1, m_ZExt(m_Value(X))))
if (X->getType()->getScalarType()->isIntegerTy(1))
return CastInst::CreateSExtOrBitCast(X, Op1->getType());
// Fold (sub 0, (sext bool to B)) --> (zext bool to B)
if (C->isNullValue() && match(Op1, m_SExt(m_Value(X))))
if (X->getType()->getScalarType()->isIntegerTy(1))
return CastInst::CreateZExtOrBitCast(X, Op1->getType());
}
if (ConstantInt *C = dyn_cast<ConstantInt>(Op0)) {
// -(X >>u 31) -> (X >>s 31)
// -(X >>s 31) -> (X >>u 31)
if (C->isZero()) {
@ -1401,29 +1429,6 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
CI->getValue() == I.getType()->getPrimitiveSizeInBits()-1)
return BinaryOperator::CreateLShr(X, CI);
}
// Try to fold constant sub into select arguments.
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
if (Instruction *R = FoldOpIntoSelect(I, SI))
return R;
// C-(X+C2) --> (C-C2)-X
ConstantInt *C2;
if (match(Op1, m_Add(m_Value(X), m_ConstantInt(C2))))
return BinaryOperator::CreateSub(ConstantExpr::getSub(C, C2), X);
if (SimplifyDemandedInstructionBits(I))
return &I;
// Fold (sub 0, (zext bool to B)) --> (sext bool to B)
if (C->isZero() && match(Op1, m_ZExt(m_Value(X))))
if (X->getType()->isIntegerTy(1))
return CastInst::CreateSExtOrBitCast(X, Op1->getType());
// Fold (sub 0, (sext bool to B)) --> (zext bool to B)
if (C->isZero() && match(Op1, m_SExt(m_Value(X))))
if (X->getType()->isIntegerTy(1))
return CastInst::CreateZExtOrBitCast(X, Op1->getType());
}
@ -1441,7 +1446,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
if (Op1->hasOneUse()) {
Value *X = 0, *Y = 0, *Z = 0;
Constant *C = 0;
ConstantInt *CI = 0;
Constant *CI = 0;
// (X - (Y - Z)) --> (X + (Z - Y)).
if (match(Op1, m_Sub(m_Value(Y), m_Value(Z))))
@ -1466,13 +1471,13 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
return BinaryOperator::CreateShl(XNeg, Y);
// X - X*C --> X * (1-C)
if (match(Op1, m_Mul(m_Specific(Op0), m_ConstantInt(CI)))) {
if (match(Op1, m_Mul(m_Specific(Op0), m_Constant(CI)))) {
Constant *CP1 = ConstantExpr::getSub(ConstantInt::get(I.getType(),1), CI);
return BinaryOperator::CreateMul(Op0, CP1);
}
// X - X<<C --> X * (1-(1<<C))
if (match(Op1, m_Shl(m_Specific(Op0), m_ConstantInt(CI)))) {
if (match(Op1, m_Shl(m_Specific(Op0), m_Constant(CI)))) {
Constant *One = ConstantInt::get(I.getType(), 1);
C = ConstantExpr::getSub(One, ConstantExpr::getShl(One, CI));
return BinaryOperator::CreateMul(Op0, C);
@ -1487,19 +1492,19 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
// X - A*CI -> X + A*-CI
// X - CI*A -> X + A*-CI
if (match(Op1, m_Mul(m_Value(A), m_ConstantInt(CI))) ||
match(Op1, m_Mul(m_ConstantInt(CI), m_Value(A)))) {
if (match(Op1, m_Mul(m_Value(A), m_Constant(CI))) ||
match(Op1, m_Mul(m_Constant(CI), m_Value(A)))) {
Value *NewMul = Builder->CreateMul(A, ConstantExpr::getNeg(CI));
return BinaryOperator::CreateAdd(Op0, NewMul);
}
}
ConstantInt *C1;
Constant *C1;
if (Value *X = dyn_castFoldableMul(Op0, C1)) {
if (X == Op1) // X*C - X --> X * (C-1)
return BinaryOperator::CreateMul(Op1, SubOne(C1));
ConstantInt *C2; // X*C1 - X*C2 -> X * (C1-C2)
Constant *C2; // X*C1 - X*C2 -> X * (C1-C2)
if (X == dyn_castFoldableMul(Op1, C2))
return BinaryOperator::CreateMul(X, ConstantExpr::getSub(C1, C2));
}

View File

@ -158,15 +158,6 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
}
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
// Canonicalize (X+C1)*CI -> X*CI+C1*CI.
{ Value *X; ConstantInt *C1;
if (Op0->hasOneUse() &&
match(Op0, m_Add(m_Value(X), m_ConstantInt(C1)))) {
Value *Add = Builder->CreateMul(X, CI);
return BinaryOperator::CreateAdd(Add, Builder->CreateMul(C1, CI));
}
}
// (Y - X) * (-(2**n)) -> (X - Y) * (2**n), for positive nonzero n
// (Y + const) * (-(2**n)) -> (-constY) * (2**n), for positive nonzero n
// The "* (2**n)" thus becomes a potential shifting opportunity.
@ -201,6 +192,16 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
if (isa<PHINode>(Op0))
if (Instruction *NV = FoldOpIntoPhi(I))
return NV;
// Canonicalize (X+C1)*CI -> X*CI+C1*CI.
{
Value *X;
Constant *C1;
if (match(Op0, m_OneUse(m_Add(m_Value(X), m_Constant(C1))))) {
Value *Add = Builder->CreateMul(X, Op1);
return BinaryOperator::CreateAdd(Add, Builder->CreateMul(C1, Op1));
}
}
}
if (Value *Op0v = dyn_castNegVal(Op0)) // -X * -Y = X*Y
@ -247,7 +248,7 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
}
/// i1 mul -> i1 and.
if (I.getType()->isIntegerTy(1))
if (I.getType()->getScalarType()->isIntegerTy(1))
return BinaryOperator::CreateAnd(Op0, Op1);
// X*(1 << Y) --> X << Y
@ -882,13 +883,11 @@ Instruction *InstCombiner::visitUDiv(BinaryOperator &I) {
return Common;
// (x lshr C1) udiv C2 --> x udiv (C2 << C1)
if (ConstantInt *C2 = dyn_cast<ConstantInt>(Op1)) {
if (Constant *C2 = dyn_cast<Constant>(Op1)) {
Value *X;
ConstantInt *C1;
if (match(Op0, m_LShr(m_Value(X), m_ConstantInt(C1)))) {
APInt NC = C2->getValue().shl(C1->getLimitedValue(C1->getBitWidth()-1));
return BinaryOperator::CreateUDiv(X, Builder->getInt(NC));
}
Constant *C1;
if (match(Op0, m_LShr(m_Value(X), m_Constant(C1))))
return BinaryOperator::CreateUDiv(X, ConstantExpr::getShl(C2, C1));
}
// (zext A) udiv (zext B) --> zext (A udiv B)
@ -942,11 +941,11 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
if (Instruction *Common = commonIDivTransforms(I))
return Common;
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
// sdiv X, -1 == -X
if (RHS->isAllOnesValue())
return BinaryOperator::CreateNeg(Op0);
// sdiv X, -1 == -X
if (match(Op1, m_AllOnes()))
return BinaryOperator::CreateNeg(Op0);
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
// sdiv X, C --> ashr exact X, log2(C)
if (I.isExact() && RHS->getValue().isNonNegative() &&
RHS->getValue().isPowerOf2()) {
@ -954,7 +953,9 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) {
RHS->getValue().exactLogBase2());
return BinaryOperator::CreateExactAShr(Op0, ShAmt, I.getName());
}
}
if (Constant *RHS = dyn_cast<Constant>(Op1)) {
// -X/C --> X/-C provided the negation doesn't overflow.
if (SubOperator *Sub = dyn_cast<SubOperator>(Op0))
if (match(Sub->getOperand(0), m_Zero()) && Sub->hasNoSignedWrap())
@ -1149,7 +1150,7 @@ Instruction *InstCombiner::commonIRemTransforms(BinaryOperator &I) {
if (isa<SelectInst>(Op1) && SimplifyDivRemOfSelect(I))
return &I;
if (isa<ConstantInt>(Op1)) {
if (isa<Constant>(Op1)) {
if (Instruction *Op0I = dyn_cast<Instruction>(Op0)) {
if (SelectInst *SI = dyn_cast<SelectInst>(Op0I)) {
if (Instruction *R = FoldOpIntoSelect(I, SI))

View File

@ -41,3 +41,38 @@ define i32 @test4(i32 %A) {
; CHECK-NEXT: ret i32 %B
}
define <2 x i1> @test5(<2 x i1> %A, <2 x i1> %B) {
%add = add <2 x i1> %A, %B
ret <2 x i1> %add
; CHECK-LABEL: @test5(
; CHECK-NEXT: %add = xor <2 x i1> %A, %B
; CHECK-NEXT: ret <2 x i1> %add
}
define <2 x i64> @test6(<2 x i64> %A) {
%shl = shl <2 x i64> %A, <i64 2, i64 3>
%add = add <2 x i64> %shl, %A
ret <2 x i64> %add
; CHECK-LABEL: @test6(
; CHECK-NEXT: %add = mul <2 x i64> %A, <i64 5, i64 9>
; CHECK-NEXT: ret <2 x i64> %add
}
define <2 x i64> @test7(<2 x i64> %A) {
%shl = shl <2 x i64> %A, <i64 2, i64 3>
%mul = mul <2 x i64> %A, <i64 3, i64 4>
%add = add <2 x i64> %shl, %mul
ret <2 x i64> %add
; CHECK-LABEL: @test7(
; CHECK-NEXT: %add = mul <2 x i64> %A, <i64 7, i64 12>
; CHECK-NEXT: ret <2 x i64> %add
}
define <2 x i64> @test8(<2 x i64> %A) {
%xor = xor <2 x i64> %A, <i64 -1, i64 -1>
%add = add <2 x i64> %xor, <i64 2, i64 3>
ret <2 x i64> %add
; CHECK-LABEL: @test8(
; CHECK-NEXT: %add = sub <2 x i64> <i64 1, i64 2>, %A
; CHECK-NEXT: ret <2 x i64> %add
}

View File

@ -131,4 +131,28 @@ define i32 @test15(i32 %a, i32 %b) nounwind {
; CHECK-NEXT: ret i32
}
define <2 x i64> @test16(<2 x i64> %x) nounwind {
%shr = lshr <2 x i64> %x, <i64 3, i64 5>
%div = udiv <2 x i64> %shr, <i64 4, i64 6>
ret <2 x i64> %div
; CHECK-LABEL: @test16(
; CHECK-NEXT: udiv <2 x i64> %x, <i64 32, i64 192>
; CHECK-NEXT: ret <2 x i64>
}
define <2 x i64> @test17(<2 x i64> %x) nounwind {
%neg = sub nsw <2 x i64> zeroinitializer, %x
%div = sdiv <2 x i64> %neg, <i64 3, i64 4>
ret <2 x i64> %div
; CHECK-LABEL: @test17(
; CHECK-NEXT: sdiv <2 x i64> %x, <i64 -3, i64 -4>
; CHECK-NEXT: ret <2 x i64>
}
define <2 x i64> @test18(<2 x i64> %x) nounwind {
%div = sdiv <2 x i64> %x, <i64 -1, i64 -1>
ret <2 x i64> %div
; CHECK-LABEL: @test18(
; CHECK-NEXT: sub <2 x i64> zeroinitializer, %x
; CHECK-NEXT: ret <2 x i64>
}

View File

@ -181,3 +181,19 @@ define i32 @test19(i32 %A, i32 %B) {
ret i32 %H
; CHECK: ret i32 0
}
define <2 x i64> @test20(<2 x i64> %A) {
; CHECK-LABEL: @test20(
%B = add <2 x i64> %A, <i64 12, i64 14>
%C = mul <2 x i64> %B, <i64 3, i64 2>
ret <2 x i64> %C
; CHECK: mul <2 x i64> %A, <i64 3, i64 2>
; CHECK: add <2 x i64> %{{.}}, <i64 36, i64 28>
}
define <2 x i1> @test21(<2 x i1> %A, <2 x i1> %B) {
; CHECK-LABEL: @test21(
%C = mul <2 x i1> %A, %B
ret <2 x i1> %C
; CHECK: %C = and <2 x i1> %A, %B
}

View File

@ -204,3 +204,12 @@ define i32 @test19(i32 %x, i32 %y) {
%E = urem i32 %y, %D
ret i32 %E
}
define <2 x i64> @test20(<2 x i64> %X, <2 x i1> %C) {
; CHECK-LABEL: @test20(
; CHECK-NEXT: select <2 x i1> %C, <2 x i64> <i64 1, i64 2>, <2 x i64> zeroinitializer
; CHECK-NEXT: ret <2 x i64>
%V = select <2 x i1> %C, <2 x i64> <i64 1, i64 2>, <2 x i64> <i64 8, i64 9>
%R = urem <2 x i64> %V, <i64 2, i64 3>
ret <2 x i64> %R
}

View File

@ -391,4 +391,56 @@ define i16 @test30_as1(i8 addrspace(1)* %foo, i16 %i, i16 %j) {
ret i16 %sub
}
define <2 x i64> @test31(<2 x i64> %A) {
%xor = xor <2 x i64> %A, <i64 -1, i64 -1>
%sub = sub <2 x i64> <i64 2, i64 3>, %xor
ret <2 x i64> %sub
; CHECK-LABEL: @test31(
; CHECK-NEXT: %sub = add <2 x i64> %A, <i64 3, i64 4>
; CHECK-NEXT: ret <2 x i64> %sub
}
define <2 x i64> @test32(<2 x i64> %A) {
%add = add <2 x i64> %A, <i64 -1, i64 -1>
%sub = sub <2 x i64> <i64 2, i64 3>, %add
ret <2 x i64> %sub
; CHECK-LABEL: @test32(
; CHECK-NEXT: %sub = sub <2 x i64> <i64 3, i64 4>
; CHECK-NEXT: ret <2 x i64> %sub
}
define <2 x i64> @test33(<2 x i1> %A) {
%ext = zext <2 x i1> %A to <2 x i64>
%sub = sub <2 x i64> zeroinitializer, %ext
ret <2 x i64> %sub
; CHECK-LABEL: @test33(
; CHECK-NEXT: %sub = sext <2 x i1> %A to <2 x i64>
; CHECK-NEXT: ret <2 x i64> %sub
}
define <2 x i64> @test34(<2 x i1> %A) {
%ext = sext <2 x i1> %A to <2 x i64>
%sub = sub <2 x i64> zeroinitializer, %ext
ret <2 x i64> %sub
; CHECK-LABEL: @test34(
; CHECK-NEXT: %sub = zext <2 x i1> %A to <2 x i64>
; CHECK-NEXT: ret <2 x i64> %sub
}
define <2 x i64> @test35(<2 x i64> %A) {
%mul = mul <2 x i64> %A, <i64 3, i64 4>
%sub = sub <2 x i64> %A, %mul
ret <2 x i64> %sub
; CHECK-LABEL: @test35(
; CHECK-NEXT: %sub = mul <2 x i64> %A, <i64 -2, i64 -3>
; CHECK-NEXT: ret <2 x i64> %sub
}
define <2 x i64> @test36(<2 x i64> %A) {
%shl = shl <2 x i64> %A, <i64 3, i64 4>
%sub = sub <2 x i64> %shl, %A
ret <2 x i64> %sub
; CHECK-LABEL: @test36(
; CHECK-NEXT: %sub = mul <2 x i64> %A, <i64 7, i64 15>
; CHECK-NEXT: ret <2 x i64> %sub
}

View File

@ -39,7 +39,7 @@ for.cond:
; CHECK: extractelement
for.body:
%dec43 = add <3 x i32> %input_1.addr.1, <i32 -1, i32 -1, i32 -1>
%sub44 = sub <3 x i32> zeroinitializer, %dec43
%sub44 = sub <3 x i32> <i32 -1, i32 -1, i32 -1>, %dec43
%div45 = sdiv <3 x i32> %input_2.addr.0, %sub44
br label %for.cond

View File

@ -387,7 +387,7 @@ for.end: ; preds = %for.cond
; return Foo.A[a];
; }
; CHECK-LABEL: define i32 @noAlias08(
; CHECK: sub nsw <4 x i32>
; CHECK: sub <4 x i32>
; CHECK: ret
define i32 @noAlias08(i32 %a) #0 {
@ -439,7 +439,7 @@ for.end: ; preds = %for.cond
; return Foo.A[a];
; }
; CHECK-LABEL: define i32 @noAlias09(
; CHECK: sub nsw <4 x i32>
; CHECK: sub <4 x i32>
; CHECK: ret
define i32 @noAlias09(i32 %a) #0 {
@ -491,7 +491,7 @@ for.end: ; preds = %for.cond
; return *(PA+a);
; }
; CHECK-LABEL: define i32 @noAlias10(
; CHECK-NOT: sub nsw <4 x i32>
; CHECK-NOT: sub {{.*}} <4 x i32>
; CHECK: ret
;
; TODO: This test vectorizes (with run-time check) on real targets with -O3)
@ -721,7 +721,7 @@ for.end: ; preds = %for.cond
; return Foo.A[a];
; }
; CHECK-LABEL: define i32 @noAlias14(
; CHECK: sub nsw <4 x i32>
; CHECK: sub <4 x i32>
; CHECK: ret
define i32 @noAlias14(i32 %a) #0 {