diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index d49153e4823..7f22bcce09f 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -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(V); if (I == 0) return 0; if (I->getOpcode() == Instruction::Mul) - if ((CST = dyn_cast(I->getOperand(1)))) + if ((CST = dyn_cast(I->getOperand(1)))) return I->getOperand(0); if (I->getOpcode() == Instruction::Shl) - if ((CST = dyn_cast(I->getOperand(1)))) { + if ((CST = dyn_cast(I->getOperand(1)))) { // The multiplier is really 1 << CST. - uint32_t BitWidth = cast(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(I.getType())) { APInt LHSKnownOne(IT->getBitWidth(), 0); @@ -1071,12 +1070,16 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { } } - if (ConstantInt *CRHS = dyn_cast(RHS)) { - Value *X = 0; - if (match(LHS, m_Not(m_Value(X)))) // ~X + C --> (C-1) - X + if (Constant *CRHS = dyn_cast(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(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(Op0)) { + if (Constant *C = dyn_cast(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(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(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(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< X * (1-(1< 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)); } diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index e6c04f51dad..738756a5a28 100644 --- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -158,15 +158,6 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) { } if (ConstantInt *CI = dyn_cast(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(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(Op1)) { + if (Constant *C2 = dyn_cast(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(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(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(Op1)) { // -X/C --> X/-C provided the negation doesn't overflow. if (SubOperator *Sub = dyn_cast(Op0)) if (match(Sub->getOperand(0), m_Zero()) && Sub->hasNoSignedWrap()) @@ -1149,7 +1150,7 @@ Instruction *InstCombiner::commonIRemTransforms(BinaryOperator &I) { if (isa(Op1) && SimplifyDivRemOfSelect(I)) return &I; - if (isa(Op1)) { + if (isa(Op1)) { if (Instruction *Op0I = dyn_cast(Op0)) { if (SelectInst *SI = dyn_cast(Op0I)) { if (Instruction *R = FoldOpIntoSelect(I, SI)) diff --git a/test/Transforms/InstCombine/add2.ll b/test/Transforms/InstCombine/add2.ll index 0964bc00d1c..67d560e500a 100644 --- a/test/Transforms/InstCombine/add2.ll +++ b/test/Transforms/InstCombine/add2.ll @@ -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, + %add = add <2 x i64> %shl, %A + ret <2 x i64> %add +; CHECK-LABEL: @test6( +; CHECK-NEXT: %add = mul <2 x i64> %A, +; CHECK-NEXT: ret <2 x i64> %add +} + +define <2 x i64> @test7(<2 x i64> %A) { + %shl = shl <2 x i64> %A, + %mul = mul <2 x i64> %A, + %add = add <2 x i64> %shl, %mul + ret <2 x i64> %add +; CHECK-LABEL: @test7( +; CHECK-NEXT: %add = mul <2 x i64> %A, +; CHECK-NEXT: ret <2 x i64> %add +} + +define <2 x i64> @test8(<2 x i64> %A) { + %xor = xor <2 x i64> %A, + %add = add <2 x i64> %xor, + ret <2 x i64> %add +; CHECK-LABEL: @test8( +; CHECK-NEXT: %add = sub <2 x i64> , %A +; CHECK-NEXT: ret <2 x i64> %add +} diff --git a/test/Transforms/InstCombine/div.ll b/test/Transforms/InstCombine/div.ll index f67fd1c51be..1bf486fa336 100644 --- a/test/Transforms/InstCombine/div.ll +++ b/test/Transforms/InstCombine/div.ll @@ -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, + %div = udiv <2 x i64> %shr, + ret <2 x i64> %div +; CHECK-LABEL: @test16( +; CHECK-NEXT: udiv <2 x i64> %x, +; 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, + ret <2 x i64> %div +; CHECK-LABEL: @test17( +; CHECK-NEXT: sdiv <2 x i64> %x, +; CHECK-NEXT: ret <2 x i64> +} + +define <2 x i64> @test18(<2 x i64> %x) nounwind { + %div = sdiv <2 x i64> %x, + ret <2 x i64> %div +; CHECK-LABEL: @test18( +; CHECK-NEXT: sub <2 x i64> zeroinitializer, %x +; CHECK-NEXT: ret <2 x i64> +} diff --git a/test/Transforms/InstCombine/mul.ll b/test/Transforms/InstCombine/mul.ll index 94fc1183c55..d19bedc7a10 100644 --- a/test/Transforms/InstCombine/mul.ll +++ b/test/Transforms/InstCombine/mul.ll @@ -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, + %C = mul <2 x i64> %B, + ret <2 x i64> %C +; CHECK: mul <2 x i64> %A, +; CHECK: add <2 x i64> %{{.}}, +} + +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 +} diff --git a/test/Transforms/InstCombine/rem.ll b/test/Transforms/InstCombine/rem.ll index 22fd90bf7a7..9f07702681e 100644 --- a/test/Transforms/InstCombine/rem.ll +++ b/test/Transforms/InstCombine/rem.ll @@ -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> , <2 x i64> zeroinitializer +; CHECK-NEXT: ret <2 x i64> + %V = select <2 x i1> %C, <2 x i64> , <2 x i64> + %R = urem <2 x i64> %V, + ret <2 x i64> %R +} diff --git a/test/Transforms/InstCombine/sub.ll b/test/Transforms/InstCombine/sub.ll index 36c523bd7b7..41d803c8bdd 100644 --- a/test/Transforms/InstCombine/sub.ll +++ b/test/Transforms/InstCombine/sub.ll @@ -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, + %sub = sub <2 x i64> , %xor + ret <2 x i64> %sub +; CHECK-LABEL: @test31( +; CHECK-NEXT: %sub = add <2 x i64> %A, +; CHECK-NEXT: ret <2 x i64> %sub +} +define <2 x i64> @test32(<2 x i64> %A) { + %add = add <2 x i64> %A, + %sub = sub <2 x i64> , %add + ret <2 x i64> %sub +; CHECK-LABEL: @test32( +; CHECK-NEXT: %sub = sub <2 x i64> +; 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, + %sub = sub <2 x i64> %A, %mul + ret <2 x i64> %sub +; CHECK-LABEL: @test35( +; CHECK-NEXT: %sub = mul <2 x i64> %A, +; CHECK-NEXT: ret <2 x i64> %sub +} + +define <2 x i64> @test36(<2 x i64> %A) { + %shl = shl <2 x i64> %A, + %sub = sub <2 x i64> %shl, %A + ret <2 x i64> %sub +; CHECK-LABEL: @test36( +; CHECK-NEXT: %sub = mul <2 x i64> %A, +; CHECK-NEXT: ret <2 x i64> %sub +} diff --git a/test/Transforms/InstCombine/vec_phi_extract.ll b/test/Transforms/InstCombine/vec_phi_extract.ll index b0f365ba796..1d778a000fb 100644 --- a/test/Transforms/InstCombine/vec_phi_extract.ll +++ b/test/Transforms/InstCombine/vec_phi_extract.ll @@ -39,7 +39,7 @@ for.cond: ; CHECK: extractelement for.body: %dec43 = add <3 x i32> %input_1.addr.1, - %sub44 = sub <3 x i32> zeroinitializer, %dec43 + %sub44 = sub <3 x i32> , %dec43 %div45 = sdiv <3 x i32> %input_2.addr.0, %sub44 br label %for.cond diff --git a/test/Transforms/LoopVectorize/global_alias.ll b/test/Transforms/LoopVectorize/global_alias.ll index 0118fb47412..d64d67f6a5b 100644 --- a/test/Transforms/LoopVectorize/global_alias.ll +++ b/test/Transforms/LoopVectorize/global_alias.ll @@ -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 {