mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
[KnownBits] Move AND, OR and XOR logic into KnownBits
Summary: There are at least three clients for KnownBits calculations: ValueTracking, SelectionDAG and GlobalISel. To reduce duplication the common logic should be moved out of these clients and into KnownBits itself. This patch does this for AND, OR and XOR calculations by implementing and using appropriate operator overloads KnownBits::operator& etc. Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D74060
This commit is contained in:
parent
98b95eeb1c
commit
87d37f4776
@ -240,8 +240,47 @@ public:
|
||||
/// Compute known bits resulting from adding LHS and RHS.
|
||||
static KnownBits computeForAddSub(bool Add, bool NSW, const KnownBits &LHS,
|
||||
KnownBits RHS);
|
||||
|
||||
/// Update known bits based on ANDing with RHS.
|
||||
KnownBits &operator&=(const KnownBits &RHS);
|
||||
|
||||
/// Update known bits based on ORing with RHS.
|
||||
KnownBits &operator|=(const KnownBits &RHS);
|
||||
|
||||
/// Update known bits based on XORing with RHS.
|
||||
KnownBits &operator^=(const KnownBits &RHS);
|
||||
};
|
||||
|
||||
inline KnownBits operator&(KnownBits LHS, const KnownBits &RHS) {
|
||||
LHS &= RHS;
|
||||
return LHS;
|
||||
}
|
||||
|
||||
inline KnownBits operator&(const KnownBits &LHS, KnownBits &&RHS) {
|
||||
RHS &= LHS;
|
||||
return std::move(RHS);
|
||||
}
|
||||
|
||||
inline KnownBits operator|(KnownBits LHS, const KnownBits &RHS) {
|
||||
LHS |= RHS;
|
||||
return LHS;
|
||||
}
|
||||
|
||||
inline KnownBits operator|(const KnownBits &LHS, KnownBits &&RHS) {
|
||||
RHS |= LHS;
|
||||
return std::move(RHS);
|
||||
}
|
||||
|
||||
inline KnownBits operator^(KnownBits LHS, const KnownBits &RHS) {
|
||||
LHS ^= RHS;
|
||||
return LHS;
|
||||
}
|
||||
|
||||
inline KnownBits operator^(const KnownBits &LHS, KnownBits &&RHS) {
|
||||
RHS ^= LHS;
|
||||
return std::move(RHS);
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -745,8 +745,7 @@ Constant *SymbolicallyEvaluateBinop(unsigned Opc, Constant *Op0, Constant *Op1,
|
||||
return Op1;
|
||||
}
|
||||
|
||||
Known0.Zero |= Known1.Zero;
|
||||
Known0.One &= Known1.One;
|
||||
Known0 &= Known1;
|
||||
if (Known0.isConstant())
|
||||
return ConstantInt::get(Op0->getType(), Known0.getConstant());
|
||||
}
|
||||
|
@ -1134,10 +1134,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
|
||||
computeKnownBits(I->getOperand(1), DemandedElts, Known, Depth + 1, Q);
|
||||
computeKnownBits(I->getOperand(0), DemandedElts, Known2, Depth + 1, Q);
|
||||
|
||||
// Output known-1 bits are only known if set in both the LHS & RHS.
|
||||
Known.One &= Known2.One;
|
||||
// Output known-0 are known to be clear if zero in either the LHS | RHS.
|
||||
Known.Zero |= Known2.Zero;
|
||||
Known &= Known2;
|
||||
|
||||
// and(x, add (x, -1)) is a common idiom that always clears the low bit;
|
||||
// here we handle the more general case of adding any odd number by
|
||||
@ -1158,22 +1155,14 @@ static void computeKnownBitsFromOperator(const Operator *I,
|
||||
computeKnownBits(I->getOperand(1), DemandedElts, Known, Depth + 1, Q);
|
||||
computeKnownBits(I->getOperand(0), DemandedElts, Known2, Depth + 1, Q);
|
||||
|
||||
// Output known-0 bits are only known if clear in both the LHS & RHS.
|
||||
Known.Zero &= Known2.Zero;
|
||||
// Output known-1 are known to be set if set in either the LHS | RHS.
|
||||
Known.One |= Known2.One;
|
||||
Known |= Known2;
|
||||
break;
|
||||
case Instruction::Xor: {
|
||||
case Instruction::Xor:
|
||||
computeKnownBits(I->getOperand(1), DemandedElts, Known, Depth + 1, Q);
|
||||
computeKnownBits(I->getOperand(0), DemandedElts, Known2, Depth + 1, Q);
|
||||
|
||||
// Output known-0 bits are known if clear or set in both the LHS & RHS.
|
||||
APInt KnownZeroOut = (Known.Zero & Known2.Zero) | (Known.One & Known2.One);
|
||||
// Output known-1 are known to be set if set in only one of the LHS, RHS.
|
||||
Known.One = (Known.Zero & Known2.One) | (Known.One & Known2.Zero);
|
||||
Known.Zero = std::move(KnownZeroOut);
|
||||
Known ^= Known2;
|
||||
break;
|
||||
}
|
||||
case Instruction::Mul: {
|
||||
bool NSW = Q.IIQ.hasNoSignedWrap(cast<OverflowingBinaryOperator>(I));
|
||||
computeKnownBitsMul(I->getOperand(0), I->getOperand(1), NSW, DemandedElts,
|
||||
|
@ -233,11 +233,7 @@ void GISelKnownBits::computeKnownBitsImpl(Register R, KnownBits &Known,
|
||||
computeKnownBitsImpl(MI.getOperand(1).getReg(), Known2, DemandedElts,
|
||||
Depth + 1);
|
||||
|
||||
// Output known-0 bits are known if clear or set in both the LHS & RHS.
|
||||
APInt KnownZeroOut = (Known.Zero & Known2.Zero) | (Known.One & Known2.One);
|
||||
// Output known-1 are known to be set if set in only one of the LHS, RHS.
|
||||
Known.One = (Known.Zero & Known2.One) | (Known.One & Known2.Zero);
|
||||
Known.Zero = KnownZeroOut;
|
||||
Known ^= Known2;
|
||||
break;
|
||||
}
|
||||
case TargetOpcode::G_PTR_ADD: {
|
||||
@ -263,10 +259,7 @@ void GISelKnownBits::computeKnownBitsImpl(Register R, KnownBits &Known,
|
||||
computeKnownBitsImpl(MI.getOperand(1).getReg(), Known2, DemandedElts,
|
||||
Depth + 1);
|
||||
|
||||
// Output known-1 bits are only known if set in both the LHS & RHS.
|
||||
Known.One &= Known2.One;
|
||||
// Output known-0 are known to be clear if zero in either the LHS | RHS.
|
||||
Known.Zero |= Known2.Zero;
|
||||
Known &= Known2;
|
||||
break;
|
||||
}
|
||||
case TargetOpcode::G_OR: {
|
||||
@ -276,10 +269,7 @@ void GISelKnownBits::computeKnownBitsImpl(Register R, KnownBits &Known,
|
||||
computeKnownBitsImpl(MI.getOperand(1).getReg(), Known2, DemandedElts,
|
||||
Depth + 1);
|
||||
|
||||
// Output known-0 bits are only known if clear in both the LHS & RHS.
|
||||
Known.Zero &= Known2.Zero;
|
||||
// Output known-1 are known to be set if set in either the LHS | RHS.
|
||||
Known.One |= Known2.One;
|
||||
Known |= Known2;
|
||||
break;
|
||||
}
|
||||
case TargetOpcode::G_MUL: {
|
||||
|
@ -2757,35 +2757,23 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
|
||||
break;
|
||||
}
|
||||
case ISD::AND:
|
||||
// If either the LHS or the RHS are Zero, the result is zero.
|
||||
Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
|
||||
Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
|
||||
|
||||
// Output known-1 bits are only known if set in both the LHS & RHS.
|
||||
Known.One &= Known2.One;
|
||||
// Output known-0 are known to be clear if zero in either the LHS | RHS.
|
||||
Known.Zero |= Known2.Zero;
|
||||
Known &= Known2;
|
||||
break;
|
||||
case ISD::OR:
|
||||
Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
|
||||
Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
|
||||
|
||||
// Output known-0 bits are only known if clear in both the LHS & RHS.
|
||||
Known.Zero &= Known2.Zero;
|
||||
// Output known-1 are known to be set if set in either the LHS | RHS.
|
||||
Known.One |= Known2.One;
|
||||
Known |= Known2;
|
||||
break;
|
||||
case ISD::XOR: {
|
||||
case ISD::XOR:
|
||||
Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
|
||||
Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
|
||||
|
||||
// Output known-0 bits are known if clear or set in both the LHS & RHS.
|
||||
APInt KnownZeroOut = (Known.Zero & Known2.Zero) | (Known.One & Known2.One);
|
||||
// Output known-1 are known to be set if set in only one of the LHS, RHS.
|
||||
Known.One = (Known.Zero & Known2.One) | (Known.One & Known2.Zero);
|
||||
Known.Zero = KnownZeroOut;
|
||||
Known ^= Known2;
|
||||
break;
|
||||
}
|
||||
case ISD::MUL: {
|
||||
Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
|
||||
Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
|
||||
|
@ -861,7 +861,7 @@ bool TargetLowering::SimplifyDemandedBits(
|
||||
return false;
|
||||
}
|
||||
|
||||
KnownBits Known2, KnownOut;
|
||||
KnownBits Known2;
|
||||
switch (Op.getOpcode()) {
|
||||
case ISD::TargetConstant:
|
||||
llvm_unreachable("Can't simplify this node");
|
||||
@ -1171,10 +1171,7 @@ bool TargetLowering::SimplifyDemandedBits(
|
||||
if (ShrinkDemandedOp(Op, BitWidth, DemandedBits, TLO))
|
||||
return true;
|
||||
|
||||
// Output known-1 bits are only known if set in both the LHS & RHS.
|
||||
Known.One &= Known2.One;
|
||||
// Output known-0 are known to be clear if zero in either the LHS | RHS.
|
||||
Known.Zero |= Known2.Zero;
|
||||
Known &= Known2;
|
||||
break;
|
||||
}
|
||||
case ISD::OR: {
|
||||
@ -1217,10 +1214,7 @@ bool TargetLowering::SimplifyDemandedBits(
|
||||
if (ShrinkDemandedOp(Op, BitWidth, DemandedBits, TLO))
|
||||
return true;
|
||||
|
||||
// Output known-0 bits are only known if clear in both the LHS & RHS.
|
||||
Known.Zero &= Known2.Zero;
|
||||
// Output known-1 are known to be set if set in either the LHS | RHS.
|
||||
Known.One |= Known2.One;
|
||||
Known |= Known2;
|
||||
break;
|
||||
}
|
||||
case ISD::XOR: {
|
||||
@ -1266,11 +1260,6 @@ bool TargetLowering::SimplifyDemandedBits(
|
||||
if (DemandedBits.isSubsetOf(Known.Zero | Known2.Zero))
|
||||
return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::OR, dl, VT, Op0, Op1));
|
||||
|
||||
// Output known-0 bits are known if clear or set in both the LHS & RHS.
|
||||
KnownOut.Zero = (Known.Zero & Known2.Zero) | (Known.One & Known2.One);
|
||||
// Output known-1 are known to be set if set in only one of the LHS, RHS.
|
||||
KnownOut.One = (Known.Zero & Known2.One) | (Known.One & Known2.Zero);
|
||||
|
||||
if (ConstantSDNode *C = isConstOrConstSplat(Op1)) {
|
||||
// If one side is a constant, and all of the known set bits on the other
|
||||
// side are also set in the constant, turn this into an AND, as we know
|
||||
@ -1298,7 +1287,7 @@ bool TargetLowering::SimplifyDemandedBits(
|
||||
}
|
||||
}
|
||||
|
||||
Known = std::move(KnownOut);
|
||||
Known ^= Known2;
|
||||
break;
|
||||
}
|
||||
case ISD::SELECT:
|
||||
|
@ -82,3 +82,28 @@ KnownBits KnownBits::computeForAddSub(bool Add, bool NSW,
|
||||
|
||||
return KnownOut;
|
||||
}
|
||||
|
||||
KnownBits &KnownBits::operator&=(const KnownBits &RHS) {
|
||||
// Result bit is 0 if either operand bit is 0.
|
||||
Zero |= RHS.Zero;
|
||||
// Result bit is 1 if both operand bits are 1.
|
||||
One &= RHS.One;
|
||||
return *this;
|
||||
}
|
||||
|
||||
KnownBits &KnownBits::operator|=(const KnownBits &RHS) {
|
||||
// Result bit is 0 if both operand bits are 0.
|
||||
Zero &= RHS.Zero;
|
||||
// Result bit is 1 if either operand bit is 1.
|
||||
One |= RHS.One;
|
||||
return *this;
|
||||
}
|
||||
|
||||
KnownBits &KnownBits::operator^=(const KnownBits &RHS) {
|
||||
// Result bit is 0 if both operand bits are 0 or both are 1.
|
||||
APInt Z = (Zero & RHS.Zero) | (One & RHS.One);
|
||||
// Result bit is 1 if one operand bit is 0 and the other is 1.
|
||||
One = (Zero & RHS.One) | (One & RHS.Zero);
|
||||
Zero = std::move(Z);
|
||||
return *this;
|
||||
}
|
||||
|
@ -33256,10 +33256,7 @@ void X86TargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
|
||||
Known = DAG.computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
|
||||
Known2 = DAG.computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
|
||||
|
||||
// Output known-0 bits are only known if clear in both the LHS & RHS.
|
||||
Known.Zero &= Known2.Zero;
|
||||
// Output known-1 are known to be set if set in either the LHS | RHS.
|
||||
Known.One |= Known2.One;
|
||||
Known |= Known2;
|
||||
break;
|
||||
}
|
||||
case X86ISD::PSADBW: {
|
||||
|
@ -176,15 +176,12 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
||||
assert(!RHSKnown.hasConflict() && "Bits known to be one AND zero?");
|
||||
assert(!LHSKnown.hasConflict() && "Bits known to be one AND zero?");
|
||||
|
||||
// Output known-0 are known to be clear if zero in either the LHS | RHS.
|
||||
APInt IKnownZero = RHSKnown.Zero | LHSKnown.Zero;
|
||||
// Output known-1 bits are only known if set in both the LHS & RHS.
|
||||
APInt IKnownOne = RHSKnown.One & LHSKnown.One;
|
||||
Known = LHSKnown & RHSKnown;
|
||||
|
||||
// If the client is only demanding bits that we know, return the known
|
||||
// constant.
|
||||
if (DemandedMask.isSubsetOf(IKnownZero|IKnownOne))
|
||||
return Constant::getIntegerValue(VTy, IKnownOne);
|
||||
if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
|
||||
return Constant::getIntegerValue(VTy, Known.One);
|
||||
|
||||
// If all of the demanded bits are known 1 on one side, return the other.
|
||||
// These bits cannot contribute to the result of the 'and'.
|
||||
@ -197,8 +194,6 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
||||
if (ShrinkDemandedConstant(I, 1, DemandedMask & ~LHSKnown.Zero))
|
||||
return I;
|
||||
|
||||
Known.Zero = std::move(IKnownZero);
|
||||
Known.One = std::move(IKnownOne);
|
||||
break;
|
||||
}
|
||||
case Instruction::Or: {
|
||||
@ -210,15 +205,12 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
||||
assert(!RHSKnown.hasConflict() && "Bits known to be one AND zero?");
|
||||
assert(!LHSKnown.hasConflict() && "Bits known to be one AND zero?");
|
||||
|
||||
// Output known-0 bits are only known if clear in both the LHS & RHS.
|
||||
APInt IKnownZero = RHSKnown.Zero & LHSKnown.Zero;
|
||||
// Output known-1 are known. to be set if s.et in either the LHS | RHS.
|
||||
APInt IKnownOne = RHSKnown.One | LHSKnown.One;
|
||||
Known = LHSKnown | RHSKnown;
|
||||
|
||||
// If the client is only demanding bits that we know, return the known
|
||||
// constant.
|
||||
if (DemandedMask.isSubsetOf(IKnownZero|IKnownOne))
|
||||
return Constant::getIntegerValue(VTy, IKnownOne);
|
||||
if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
|
||||
return Constant::getIntegerValue(VTy, Known.One);
|
||||
|
||||
// If all of the demanded bits are known zero on one side, return the other.
|
||||
// These bits cannot contribute to the result of the 'or'.
|
||||
@ -231,8 +223,6 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
||||
if (ShrinkDemandedConstant(I, 1, DemandedMask))
|
||||
return I;
|
||||
|
||||
Known.Zero = std::move(IKnownZero);
|
||||
Known.One = std::move(IKnownOne);
|
||||
break;
|
||||
}
|
||||
case Instruction::Xor: {
|
||||
@ -242,17 +232,12 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
||||
assert(!RHSKnown.hasConflict() && "Bits known to be one AND zero?");
|
||||
assert(!LHSKnown.hasConflict() && "Bits known to be one AND zero?");
|
||||
|
||||
// Output known-0 bits are known if clear or set in both the LHS & RHS.
|
||||
APInt IKnownZero = (RHSKnown.Zero & LHSKnown.Zero) |
|
||||
(RHSKnown.One & LHSKnown.One);
|
||||
// Output known-1 are known to be set if set in only one of the LHS, RHS.
|
||||
APInt IKnownOne = (RHSKnown.Zero & LHSKnown.One) |
|
||||
(RHSKnown.One & LHSKnown.Zero);
|
||||
Known = LHSKnown ^ RHSKnown;
|
||||
|
||||
// If the client is only demanding bits that we know, return the known
|
||||
// constant.
|
||||
if (DemandedMask.isSubsetOf(IKnownZero|IKnownOne))
|
||||
return Constant::getIntegerValue(VTy, IKnownOne);
|
||||
if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
|
||||
return Constant::getIntegerValue(VTy, Known.One);
|
||||
|
||||
// If all of the demanded bits are known zero on one side, return the other.
|
||||
// These bits cannot contribute to the result of the 'xor'.
|
||||
@ -312,10 +297,6 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
|
||||
return InsertNewInstWith(NewXor, *I);
|
||||
}
|
||||
|
||||
// Output known-0 bits are known if clear or set in both the LHS & RHS.
|
||||
Known.Zero = std::move(IKnownZero);
|
||||
// Output known-1 are known to be set if set in only one of the LHS, RHS.
|
||||
Known.One = std::move(IKnownOne);
|
||||
break;
|
||||
}
|
||||
case Instruction::Select: {
|
||||
@ -877,15 +858,12 @@ Value *InstCombiner::SimplifyMultipleUseDemandedBits(Instruction *I,
|
||||
computeKnownBits(I->getOperand(0), LHSKnown, Depth + 1,
|
||||
CxtI);
|
||||
|
||||
// Output known-0 are known to be clear if zero in either the LHS | RHS.
|
||||
APInt IKnownZero = RHSKnown.Zero | LHSKnown.Zero;
|
||||
// Output known-1 bits are only known if set in both the LHS & RHS.
|
||||
APInt IKnownOne = RHSKnown.One & LHSKnown.One;
|
||||
Known = LHSKnown & RHSKnown;
|
||||
|
||||
// If the client is only demanding bits that we know, return the known
|
||||
// constant.
|
||||
if (DemandedMask.isSubsetOf(IKnownZero|IKnownOne))
|
||||
return Constant::getIntegerValue(ITy, IKnownOne);
|
||||
if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
|
||||
return Constant::getIntegerValue(ITy, Known.One);
|
||||
|
||||
// If all of the demanded bits are known 1 on one side, return the other.
|
||||
// These bits cannot contribute to the result of the 'and' in this
|
||||
@ -895,8 +873,6 @@ Value *InstCombiner::SimplifyMultipleUseDemandedBits(Instruction *I,
|
||||
if (DemandedMask.isSubsetOf(RHSKnown.Zero | LHSKnown.One))
|
||||
return I->getOperand(1);
|
||||
|
||||
Known.Zero = std::move(IKnownZero);
|
||||
Known.One = std::move(IKnownOne);
|
||||
break;
|
||||
}
|
||||
case Instruction::Or: {
|
||||
@ -908,15 +884,12 @@ Value *InstCombiner::SimplifyMultipleUseDemandedBits(Instruction *I,
|
||||
computeKnownBits(I->getOperand(0), LHSKnown, Depth + 1,
|
||||
CxtI);
|
||||
|
||||
// Output known-0 bits are only known if clear in both the LHS & RHS.
|
||||
APInt IKnownZero = RHSKnown.Zero & LHSKnown.Zero;
|
||||
// Output known-1 are known to be set if set in either the LHS | RHS.
|
||||
APInt IKnownOne = RHSKnown.One | LHSKnown.One;
|
||||
Known = LHSKnown | RHSKnown;
|
||||
|
||||
// If the client is only demanding bits that we know, return the known
|
||||
// constant.
|
||||
if (DemandedMask.isSubsetOf(IKnownZero|IKnownOne))
|
||||
return Constant::getIntegerValue(ITy, IKnownOne);
|
||||
if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
|
||||
return Constant::getIntegerValue(ITy, Known.One);
|
||||
|
||||
// If all of the demanded bits are known zero on one side, return the
|
||||
// other. These bits cannot contribute to the result of the 'or' in this
|
||||
@ -926,8 +899,6 @@ Value *InstCombiner::SimplifyMultipleUseDemandedBits(Instruction *I,
|
||||
if (DemandedMask.isSubsetOf(RHSKnown.One | LHSKnown.Zero))
|
||||
return I->getOperand(1);
|
||||
|
||||
Known.Zero = std::move(IKnownZero);
|
||||
Known.One = std::move(IKnownOne);
|
||||
break;
|
||||
}
|
||||
case Instruction::Xor: {
|
||||
@ -938,17 +909,12 @@ Value *InstCombiner::SimplifyMultipleUseDemandedBits(Instruction *I,
|
||||
computeKnownBits(I->getOperand(0), LHSKnown, Depth + 1,
|
||||
CxtI);
|
||||
|
||||
// Output known-0 bits are known if clear or set in both the LHS & RHS.
|
||||
APInt IKnownZero = (RHSKnown.Zero & LHSKnown.Zero) |
|
||||
(RHSKnown.One & LHSKnown.One);
|
||||
// Output known-1 are known to be set if set in only one of the LHS, RHS.
|
||||
APInt IKnownOne = (RHSKnown.Zero & LHSKnown.One) |
|
||||
(RHSKnown.One & LHSKnown.Zero);
|
||||
Known = LHSKnown ^ RHSKnown;
|
||||
|
||||
// If the client is only demanding bits that we know, return the known
|
||||
// constant.
|
||||
if (DemandedMask.isSubsetOf(IKnownZero|IKnownOne))
|
||||
return Constant::getIntegerValue(ITy, IKnownOne);
|
||||
if (DemandedMask.isSubsetOf(Known.Zero | Known.One))
|
||||
return Constant::getIntegerValue(ITy, Known.One);
|
||||
|
||||
// If all of the demanded bits are known zero on one side, return the
|
||||
// other.
|
||||
@ -957,10 +923,6 @@ Value *InstCombiner::SimplifyMultipleUseDemandedBits(Instruction *I,
|
||||
if (DemandedMask.isSubsetOf(LHSKnown.Zero))
|
||||
return I->getOperand(1);
|
||||
|
||||
// Output known-0 bits are known if clear or set in both the LHS & RHS.
|
||||
Known.Zero = std::move(IKnownZero);
|
||||
// Output known-1 are known to be set if set in only one of the LHS, RHS.
|
||||
Known.One = std::move(IKnownOne);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -127,6 +127,51 @@ TEST(KnownBitsTest, AddSubExhaustive) {
|
||||
TestAddSubExhaustive(false);
|
||||
}
|
||||
|
||||
TEST(KnownBitsTest, BinaryExhaustive) {
|
||||
unsigned Bits = 4;
|
||||
ForeachKnownBits(Bits, [&](const KnownBits &Known1) {
|
||||
ForeachKnownBits(Bits, [&](const KnownBits &Known2) {
|
||||
KnownBits KnownAnd(Bits), KnownOr(Bits), KnownXor(Bits);
|
||||
KnownAnd.Zero.setAllBits();
|
||||
KnownAnd.One.setAllBits();
|
||||
KnownOr.Zero.setAllBits();
|
||||
KnownOr.One.setAllBits();
|
||||
KnownXor.Zero.setAllBits();
|
||||
KnownXor.One.setAllBits();
|
||||
|
||||
ForeachNumInKnownBits(Known1, [&](const APInt &N1) {
|
||||
ForeachNumInKnownBits(Known2, [&](const APInt &N2) {
|
||||
APInt Res;
|
||||
|
||||
Res = N1 & N2;
|
||||
KnownAnd.One &= Res;
|
||||
KnownAnd.Zero &= ~Res;
|
||||
|
||||
Res = N1 | N2;
|
||||
KnownOr.One &= Res;
|
||||
KnownOr.Zero &= ~Res;
|
||||
|
||||
Res = N1 ^ N2;
|
||||
KnownXor.One &= Res;
|
||||
KnownXor.Zero &= ~Res;
|
||||
});
|
||||
});
|
||||
|
||||
KnownBits ComputedAnd = Known1 & Known2;
|
||||
EXPECT_EQ(KnownAnd.Zero, ComputedAnd.Zero);
|
||||
EXPECT_EQ(KnownAnd.One, ComputedAnd.One);
|
||||
|
||||
KnownBits ComputedOr = Known1 | Known2;
|
||||
EXPECT_EQ(KnownOr.Zero, ComputedOr.Zero);
|
||||
EXPECT_EQ(KnownOr.One, ComputedOr.One);
|
||||
|
||||
KnownBits ComputedXor = Known1 ^ Known2;
|
||||
EXPECT_EQ(KnownXor.Zero, ComputedXor.Zero);
|
||||
EXPECT_EQ(KnownXor.One, ComputedXor.One);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
TEST(KnownBitsTest, GetMinMaxVal) {
|
||||
unsigned Bits = 4;
|
||||
ForeachKnownBits(Bits, [&](const KnownBits &Known) {
|
||||
|
Loading…
Reference in New Issue
Block a user