From 3bedbd9d71eabed61bc7fd4a77d1b5b2bf27cf52 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 7 Feb 2006 07:27:52 +0000 Subject: [PATCH] Make MaskedValueIsZero take a uint64_t instead of a ConstantIntegral as a mask. This allows the code to be simpler and more efficient. Also, generalize some of the cases in MVIZ a bit, making it slightly more aggressive. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26035 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 127 ++++++++---------- 1 file changed, 58 insertions(+), 69 deletions(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 87b25f7e4b4..0d23f44799e 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -406,20 +406,19 @@ static ConstantInt *SubOne(ConstantInt *C) { } /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use -/// this predicate to simplify operations downstream. V and Mask are known to -/// be the same type. -static bool MaskedValueIsZero(Value *V, ConstantIntegral *Mask, - unsigned Depth = 0) { +/// this predicate to simplify operations downstream. Mask is known to be zero +/// for bits that V cannot have. +static bool MaskedValueIsZero(Value *V, uint64_t Mask, unsigned Depth = 0) { // Note, we cannot consider 'undef' to be "IsZero" here. The problem is that // we cannot optimize based on the assumption that it is zero without changing - // to to an explicit zero. If we don't change it to zero, other code could + // it to be an explicit zero. If we don't change it to zero, other code could // optimized based on the contradictory assumption that it is non-zero. // Because instcombine aggressively folds operations with undef args anyway, // this won't lose us code quality. - if (Mask->isNullValue()) + if (Mask == 0) return true; if (ConstantIntegral *CI = dyn_cast(V)) - return ConstantExpr::getAnd(CI, Mask)->isNullValue(); + return (CI->getRawValue() & Mask) == 0; if (Depth == 6) return false; // Limit search depth. @@ -427,12 +426,9 @@ static bool MaskedValueIsZero(Value *V, ConstantIntegral *Mask, switch (I->getOpcode()) { case Instruction::And: // (X & C1) & C2 == 0 iff C1 & C2 == 0. - if (ConstantIntegral *CI = dyn_cast(I->getOperand(1))) { - ConstantIntegral *C1C2 = - cast(ConstantExpr::getAnd(CI, Mask)); - if (MaskedValueIsZero(I->getOperand(0), C1C2, Depth+1)) - return true; - } + if (ConstantIntegral *CI = dyn_cast(I->getOperand(1))) + return MaskedValueIsZero(I->getOperand(0), CI->getRawValue() & Mask, + Depth+1); // If either the LHS or the RHS are MaskedValueIsZero, the result is zero. return MaskedValueIsZero(I->getOperand(1), Mask, Depth+1) || MaskedValueIsZero(I->getOperand(0), Mask, Depth+1); @@ -448,41 +444,34 @@ static bool MaskedValueIsZero(Value *V, ConstantIntegral *Mask, case Instruction::Cast: { const Type *SrcTy = I->getOperand(0)->getType(); if (SrcTy == Type::BoolTy) - return (Mask->getRawValue() & 1) == 0; + return (Mask & 1) == 0; + if (!SrcTy->isInteger()) return false; - if (SrcTy->isInteger()) { - // (cast X to int) & C2 == 0 iff could not have contained C2. - if (SrcTy->isUnsigned() && // Only handle zero ext. - ConstantExpr::getCast(Mask, SrcTy)->isNullValue()) - return true; - - // If this is a noop cast, recurse. - if ((SrcTy->isSigned() && SrcTy->getUnsignedVersion() == I->getType())|| - SrcTy->getSignedVersion() == I->getType()) { - Constant *NewMask = - ConstantExpr::getCast(Mask, I->getOperand(0)->getType()); - return MaskedValueIsZero(I->getOperand(0), - cast(NewMask), Depth+1); - } - } + // (cast X to int) & C2 == 0 iff could not have contained C2. + if (SrcTy->isUnsigned()) // Only handle zero ext. + return MaskedValueIsZero(I->getOperand(0), + Mask & SrcTy->getIntegralTypeMask(), Depth+1); + + // If this is a noop or trunc cast, recurse. + if (SrcTy->getPrimitiveSizeInBits() >= + I->getType()->getPrimitiveSizeInBits()) + return MaskedValueIsZero(I->getOperand(0), + Mask & SrcTy->getIntegralTypeMask(), Depth+1); break; } case Instruction::Shl: // (shl X, C1) & C2 == 0 iff (X & C2 >>u C1) == 0 if (ConstantUInt *SA = dyn_cast(I->getOperand(1))) - return MaskedValueIsZero(I->getOperand(0), - cast(ConstantExpr::getUShr(Mask, SA)), + return MaskedValueIsZero(I->getOperand(0), Mask >> SA->getValue(), Depth+1); break; case Instruction::Shr: // (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0 if (ConstantUInt *SA = dyn_cast(I->getOperand(1))) if (I->getType()->isUnsigned()) { - Constant *C1 = ConstantIntegral::getAllOnesValue(I->getType()); - C1 = ConstantExpr::getShr(C1, SA); - C1 = ConstantExpr::getAnd(C1, Mask); - if (C1->isNullValue()) - return true; + Mask <<= SA->getValue(); + Mask &= I->getType()->getIntegralTypeMask(); + return MaskedValueIsZero(I->getOperand(0), Mask, Depth+1); } break; } @@ -877,10 +866,9 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { } if (Found) { // This is a sign extend if the top bits are known zero. - Constant *Mask = ConstantInt::getAllOnesValue(XorLHS->getType()); - Mask = ConstantExpr::getShl(Mask, - ConstantInt::get(Type::UByteTy, 64-(TySizeBits-Size))); - if (!MaskedValueIsZero(XorLHS, cast(Mask))) + uint64_t Mask = XorLHS->getType()->getIntegralTypeMask(); + Mask <<= 64-(TySizeBits-Size); + if (!MaskedValueIsZero(XorLHS, Mask)) Size = 0; // Not a sign ext, but can't be any others either. goto FoundSExt; } @@ -1375,10 +1363,10 @@ Instruction *InstCombiner::visitDiv(BinaryOperator &I) { return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); if (I.getType()->isSigned()) { - // If the top bits of both operands are zero (i.e. we can prove they are + // If the sign bits of both operands are zero (i.e. we can prove they are // unsigned inputs), turn this into a udiv. - ConstantIntegral *MaskV = ConstantSInt::getMinValue(I.getType()); - if (MaskedValueIsZero(Op1, MaskV) && MaskedValueIsZero(Op0, MaskV)) { + uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1); + if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) { const Type *NTy = Op0->getType()->getUnsignedVersion(); Instruction *LHS = new CastInst(Op0, NTy, Op0->getName()); InsertNewInstBefore(LHS, I); @@ -1430,8 +1418,8 @@ Instruction *InstCombiner::visitRem(BinaryOperator &I) { // If the top bits of both operands are zero (i.e. we can prove they are // unsigned inputs), turn this into a urem. - ConstantIntegral *MaskV = ConstantSInt::getMinValue(I.getType()); - if (MaskedValueIsZero(Op1, MaskV) && MaskedValueIsZero(Op0, MaskV)) { + uint64_t Mask = 1ULL << (I.getType()->getPrimitiveSizeInBits()-1); + if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) { const Type *NTy = Op0->getType()->getUnsignedVersion(); Instruction *LHS = new CastInst(Op0, NTy, Op0->getName()); InsertNewInstBefore(LHS, I); @@ -1888,11 +1876,9 @@ Value *InstCombiner::FoldLogicalPlusAnd(Value *LHS, Value *RHS, // is all N is, ignore it. unsigned MB, ME; if (isRunOfOnes(Mask, MB, ME)) { // begin/end bit of run, inclusive - Constant *Mask = ConstantInt::getAllOnesValue(RHS->getType()); - Mask = ConstantExpr::getUShr(Mask, - ConstantInt::get(Type::UByteTy, - (64-MB+1))); - if (MaskedValueIsZero(RHS, cast(Mask))) + uint64_t Mask = RHS->getType()->getIntegralTypeMask(); + Mask >>= 64-MB+1; + if (MaskedValueIsZero(RHS, Mask)) break; } } @@ -1939,13 +1925,13 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) { return BinaryOperator::createAnd(X, ConstantExpr::getAnd(C1, AndRHS)); } - if (MaskedValueIsZero(Op0, AndRHS)) // LHS & RHS == 0 + if (MaskedValueIsZero(Op0, AndRHS->getZExtValue())) // LHS & RHS == 0 return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); // If the mask is not masking out any bits, there is no reason to do the // and in the first place. - ConstantIntegral *NotAndRHS = - cast(ConstantExpr::getNot(AndRHS)); + uint64_t NotAndRHS = // ~ANDRHS + AndRHS->getZExtValue()^Op0->getType()->getIntegralTypeMask(); if (MaskedValueIsZero(Op0, NotAndRHS)) return ReplaceInstUsesWith(I, Op0); @@ -1964,9 +1950,9 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) { case Instruction::Or: // (X ^ V) & C2 --> (X & C2) iff (V & C2) == 0 // (X | V) & C2 --> (X & C2) iff (V & C2) == 0 - if (MaskedValueIsZero(Op0LHS, AndRHS)) + if (MaskedValueIsZero(Op0LHS, AndRHS->getZExtValue())) return BinaryOperator::createAnd(Op0RHS, AndRHS); - if (MaskedValueIsZero(Op0RHS, AndRHS)) + if (MaskedValueIsZero(Op0RHS, AndRHS->getZExtValue())) return BinaryOperator::createAnd(Op0LHS, AndRHS); // If the mask is only needed on one incoming arm, push it up. @@ -1979,7 +1965,7 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) { return BinaryOperator::create( cast(Op0I)->getOpcode(), Op0LHS, NewRHS); } - if (!isa(NotAndRHS) && + if (!isa(Op0RHS) && MaskedValueIsZero(Op0RHS, NotAndRHS)) { // Not masking anything out for the RHS, move to LHS. Instruction *NewLHS = BinaryOperator::createAnd(Op0LHS, AndRHS, @@ -1993,8 +1979,8 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) { break; case Instruction::And: // (X & V) & C2 --> 0 iff (V & C2) == 0 - if (MaskedValueIsZero(Op0LHS, AndRHS) || - MaskedValueIsZero(Op0RHS, AndRHS)) + if (MaskedValueIsZero(Op0LHS, AndRHS->getZExtValue()) || + MaskedValueIsZero(Op0RHS, AndRHS->getZExtValue())) return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); break; case Instruction::Add: @@ -2239,8 +2225,8 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { if (ConstantIntegral *RHS = dyn_cast(Op1)) { // If X is known to only contain bits that already exist in RHS, just // replace this instruction with RHS directly. - if (MaskedValueIsZero(Op0, - cast(ConstantExpr::getNot(RHS)))) + if (MaskedValueIsZero(Op0, + RHS->getZExtValue()^RHS->getType()->getIntegralTypeMask())) return ReplaceInstUsesWith(I, RHS); ConstantInt *C1 = 0; Value *X = 0; @@ -2282,7 +2268,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { // (X^C)|Y -> (X|Y)^C iff Y&C == 0 if (Op0->hasOneUse() && match(Op0, m_Xor(m_Value(A), m_ConstantInt(C1))) && - MaskedValueIsZero(Op1, C1)) { + MaskedValueIsZero(Op1, C1->getZExtValue())) { Instruction *NOr = BinaryOperator::createOr(A, Op1, Op0->getName()); Op0->setName(""); return BinaryOperator::createXor(InsertNewInstBefore(NOr, I), C1); @@ -2290,7 +2276,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { // Y|(X^C) -> (X|Y)^C iff Y&C == 0 if (Op1->hasOneUse() && match(Op1, m_Xor(m_Value(A), m_ConstantInt(C1))) && - MaskedValueIsZero(Op0, C1)) { + MaskedValueIsZero(Op0, C1->getZExtValue())) { Instruction *NOr = BinaryOperator::createOr(A, Op0, Op1->getName()); Op0->setName(""); return BinaryOperator::createXor(InsertNewInstBefore(NOr, I), C1); @@ -2312,18 +2298,18 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { if ((C2->getRawValue() & (C2->getRawValue()+1)) == 0 && // C2 == 0+1+ match(A, m_Add(m_Value(V1), m_Value(V2)))) { // Add commutes, try both ways. - if (V1 == B && MaskedValueIsZero(V2, C2)) + if (V1 == B && MaskedValueIsZero(V2, C2->getZExtValue())) return ReplaceInstUsesWith(I, A); - if (V2 == B && MaskedValueIsZero(V1, C2)) + if (V2 == B && MaskedValueIsZero(V1, C2->getZExtValue())) return ReplaceInstUsesWith(I, A); } // Or commutes, try both ways. if ((C1->getRawValue() & (C1->getRawValue()+1)) == 0 && match(B, m_Add(m_Value(V1), m_Value(V2)))) { // Add commutes, try both ways. - if (V1 == A && MaskedValueIsZero(V2, C1)) + if (V1 == A && MaskedValueIsZero(V2, C1->getZExtValue())) return ReplaceInstUsesWith(I, B); - if (V2 == A && MaskedValueIsZero(V1, C1)) + if (V2 == A && MaskedValueIsZero(V1, C1->getZExtValue())) return ReplaceInstUsesWith(I, B); } } @@ -3599,7 +3585,8 @@ Instruction *InstCombiner::visitShiftInst(ShiftInst &I) { // See if we can turn a signed shr into an unsigned shr. if (!isLeftShift && I.getType()->isSigned()) { - if (MaskedValueIsZero(Op0, ConstantInt::getMinValue(I.getType()))) { + if (MaskedValueIsZero(Op0, + 1ULL << (I.getType()->getPrimitiveSizeInBits()-1))) { Value *V = InsertCastBefore(Op0, I.getType()->getUnsignedVersion(), I); V = InsertNewInstBefore(new ShiftInst(Instruction::Shr, V, Op1, I.getName()), I); @@ -4373,7 +4360,8 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) { Constant *Not1 = ConstantExpr::getNot(ConstantInt::get(Op0->getType(), 1)); // cast (X != 0) to int --> X if X&~1 == 0 - if (MaskedValueIsZero(Op0, cast(Not1))) { + if (MaskedValueIsZero(Op0, + cast(Not1)->getZExtValue())) { if (CI.getType() == Op0->getType()) return ReplaceInstUsesWith(CI, Op0); else @@ -4415,7 +4403,8 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) { if (Op1C->getRawValue() == 1) { Constant *Not1 = ConstantExpr::getNot(ConstantInt::get(Op0->getType(), 1)); - if (MaskedValueIsZero(Op0, cast(Not1))) { + if (MaskedValueIsZero(Op0, + cast(Not1)->getZExtValue())) { if (CI.getType() == Op0->getType()) return ReplaceInstUsesWith(CI, Op0); else -- 2.34.1