mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
Use helper introduced in 8020be0b8 to simplify ValueTracking [NFC]
Direct rewrite of the code the helper was extracted from.
This commit is contained in:
parent
709be793e4
commit
86325e758d
@ -755,7 +755,7 @@ constexpr unsigned MaxAnalysisRecursionDepth = 6;
|
||||
/// %inc = binop %iv, %step
|
||||
/// NOTE: This is intentional simple. If you want the ability to analyze
|
||||
/// non-trivial loop conditons, see ScalarEvolution instead.
|
||||
bool matchSimpleRecurrence(PHINode *P, BinaryOperator *&BO,
|
||||
bool matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO,
|
||||
Value *&Start, Value *&Step);
|
||||
|
||||
/// Return true if RHS is known to be implied true by LHS. Return false if
|
||||
|
@ -1371,136 +1371,115 @@ static void computeKnownBitsFromOperator(const Operator *I,
|
||||
}
|
||||
case Instruction::PHI: {
|
||||
const PHINode *P = cast<PHINode>(I);
|
||||
// Handle the case of a simple two-predecessor recurrence PHI.
|
||||
// There's a lot more that could theoretically be done here, but
|
||||
// this is sufficient to catch some interesting cases.
|
||||
if (P->getNumIncomingValues() == 2) {
|
||||
for (unsigned i = 0; i != 2; ++i) {
|
||||
Value *L = P->getIncomingValue(i);
|
||||
Value *R = P->getIncomingValue(!i);
|
||||
Instruction *RInst = P->getIncomingBlock(!i)->getTerminator();
|
||||
Instruction *LInst = P->getIncomingBlock(i)->getTerminator();
|
||||
Operator *LU = dyn_cast<Operator>(L);
|
||||
if (!LU)
|
||||
continue;
|
||||
unsigned Opcode = LU->getOpcode();
|
||||
BinaryOperator *BO = nullptr;
|
||||
Value *R = nullptr, *L = nullptr;
|
||||
if (matchSimpleRecurrence(P, BO, R, L)) {
|
||||
// Handle the case of a simple two-predecessor recurrence PHI.
|
||||
// There's a lot more that could theoretically be done here, but
|
||||
// this is sufficient to catch some interesting cases.
|
||||
unsigned Opcode = BO->getOpcode();
|
||||
|
||||
// If this is a shift recurrence, we know the bits being shifted in.
|
||||
// We can combine that with information about the start value of the
|
||||
// recurrence to conclude facts about the result.
|
||||
if (Opcode == Instruction::LShr ||
|
||||
Opcode == Instruction::AShr ||
|
||||
Opcode == Instruction::Shl) {
|
||||
|
||||
// If this is a shift recurrence, we know the bits being shifted in.
|
||||
// We can combine that with information about the start value of the
|
||||
// recurrence to conclude facts about the result.
|
||||
if (Opcode == Instruction::LShr ||
|
||||
Opcode == Instruction::AShr ||
|
||||
Opcode == Instruction::Shl) {
|
||||
Value *LL = LU->getOperand(0);
|
||||
Value *LR = LU->getOperand(1);
|
||||
// Find a recurrence.
|
||||
if (LL == I)
|
||||
L = LR;
|
||||
else
|
||||
continue; // Check for recurrence with L and R flipped.
|
||||
// We have matched a recurrence of the form:
|
||||
// %iv = [R, %entry], [%iv.next, %backedge]
|
||||
// %iv.next = shift_op %iv, L
|
||||
|
||||
// We have matched a recurrence of the form:
|
||||
// %iv = [R, %entry], [%iv.next, %backedge]
|
||||
// %iv.next = shift_op %iv, L
|
||||
// Recurse with the phi context to avoid concern about whether facts
|
||||
// inferred hold at original context instruction. TODO: It may be
|
||||
// correct to use the original context. IF warranted, explore and
|
||||
// add sufficient tests to cover.
|
||||
Query RecQ = Q;
|
||||
RecQ.CxtI = P;
|
||||
computeKnownBits(R, DemandedElts, Known2, Depth + 1, RecQ);
|
||||
switch (Opcode) {
|
||||
case Instruction::Shl:
|
||||
// A shl recurrence will only increase the tailing zeros
|
||||
Known.Zero.setLowBits(Known2.countMinTrailingZeros());
|
||||
break;
|
||||
case Instruction::LShr:
|
||||
// A lshr recurrence will preserve the leading zeros of the
|
||||
// start value
|
||||
Known.Zero.setHighBits(Known2.countMinLeadingZeros());
|
||||
break;
|
||||
case Instruction::AShr:
|
||||
// An ashr recurrence will extend the initial sign bit
|
||||
Known.Zero.setHighBits(Known2.countMinLeadingZeros());
|
||||
Known.One.setHighBits(Known2.countMinLeadingOnes());
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
// Recurse with the phi context to avoid concern about whether facts
|
||||
// inferred hold at original context instruction. TODO: It may be
|
||||
// correct to use the original context. IF warranted, explore and
|
||||
// add sufficient tests to cover.
|
||||
Query RecQ = Q;
|
||||
RecQ.CxtI = P;
|
||||
computeKnownBits(R, DemandedElts, Known2, Depth + 1, RecQ);
|
||||
switch (Opcode) {
|
||||
case Instruction::Shl:
|
||||
// A shl recurrence will only increase the tailing zeros
|
||||
Known.Zero.setLowBits(Known2.countMinTrailingZeros());
|
||||
break;
|
||||
case Instruction::LShr:
|
||||
// A lshr recurrence will preserve the leading zeros of the
|
||||
// start value
|
||||
Known.Zero.setHighBits(Known2.countMinLeadingZeros());
|
||||
break;
|
||||
case Instruction::AShr:
|
||||
// An ashr recurrence will extend the initial sign bit
|
||||
Known.Zero.setHighBits(Known2.countMinLeadingZeros());
|
||||
Known.One.setHighBits(Known2.countMinLeadingOnes());
|
||||
break;
|
||||
};
|
||||
}
|
||||
// Check for operations that have the property that if
|
||||
// both their operands have low zero bits, the result
|
||||
// will have low zero bits.
|
||||
if (Opcode == Instruction::Add ||
|
||||
Opcode == Instruction::Sub ||
|
||||
Opcode == Instruction::And ||
|
||||
Opcode == Instruction::Or ||
|
||||
Opcode == Instruction::Mul) {
|
||||
// Change the context instruction to the "edge" that flows into the
|
||||
// phi. This is important because that is where the value is actually
|
||||
// "evaluated" even though it is used later somewhere else. (see also
|
||||
// D69571).
|
||||
Query RecQ = Q;
|
||||
|
||||
// Check for operations that have the property that if
|
||||
// both their operands have low zero bits, the result
|
||||
// will have low zero bits.
|
||||
if (Opcode == Instruction::Add ||
|
||||
Opcode == Instruction::Sub ||
|
||||
Opcode == Instruction::And ||
|
||||
Opcode == Instruction::Or ||
|
||||
Opcode == Instruction::Mul) {
|
||||
Value *LL = LU->getOperand(0);
|
||||
Value *LR = LU->getOperand(1);
|
||||
// Find a recurrence.
|
||||
if (LL == I)
|
||||
L = LR;
|
||||
else if (LR == I)
|
||||
L = LL;
|
||||
else
|
||||
continue; // Check for recurrence with L and R flipped.
|
||||
unsigned OpNum = P->getOperand(0) == R ? 0 : 1;
|
||||
Instruction *RInst = P->getIncomingBlock(OpNum)->getTerminator();
|
||||
Instruction *LInst = P->getIncomingBlock(1-OpNum)->getTerminator();
|
||||
|
||||
// Change the context instruction to the "edge" that flows into the
|
||||
// phi. This is important because that is where the value is actually
|
||||
// "evaluated" even though it is used later somewhere else. (see also
|
||||
// D69571).
|
||||
Query RecQ = Q;
|
||||
// Ok, we have a PHI of the form L op= R. Check for low
|
||||
// zero bits.
|
||||
RecQ.CxtI = RInst;
|
||||
computeKnownBits(R, Known2, Depth + 1, RecQ);
|
||||
|
||||
// Ok, we have a PHI of the form L op= R. Check for low
|
||||
// zero bits.
|
||||
RecQ.CxtI = RInst;
|
||||
computeKnownBits(R, Known2, Depth + 1, RecQ);
|
||||
// We need to take the minimum number of known bits
|
||||
KnownBits Known3(BitWidth);
|
||||
RecQ.CxtI = LInst;
|
||||
computeKnownBits(L, Known3, Depth + 1, RecQ);
|
||||
|
||||
// We need to take the minimum number of known bits
|
||||
KnownBits Known3(BitWidth);
|
||||
RecQ.CxtI = LInst;
|
||||
computeKnownBits(L, Known3, Depth + 1, RecQ);
|
||||
Known.Zero.setLowBits(std::min(Known2.countMinTrailingZeros(),
|
||||
Known3.countMinTrailingZeros()));
|
||||
|
||||
Known.Zero.setLowBits(std::min(Known2.countMinTrailingZeros(),
|
||||
Known3.countMinTrailingZeros()));
|
||||
|
||||
auto *OverflowOp = dyn_cast<OverflowingBinaryOperator>(LU);
|
||||
if (OverflowOp && Q.IIQ.hasNoSignedWrap(OverflowOp)) {
|
||||
// If initial value of recurrence is nonnegative, and we are adding
|
||||
// a nonnegative number with nsw, the result can only be nonnegative
|
||||
// or poison value regardless of the number of times we execute the
|
||||
// add in phi recurrence. If initial value is negative and we are
|
||||
// adding a negative number with nsw, the result can only be
|
||||
// negative or poison value. Similar arguments apply to sub and mul.
|
||||
//
|
||||
// (add non-negative, non-negative) --> non-negative
|
||||
// (add negative, negative) --> negative
|
||||
if (Opcode == Instruction::Add) {
|
||||
if (Known2.isNonNegative() && Known3.isNonNegative())
|
||||
Known.makeNonNegative();
|
||||
else if (Known2.isNegative() && Known3.isNegative())
|
||||
Known.makeNegative();
|
||||
}
|
||||
|
||||
// (sub nsw non-negative, negative) --> non-negative
|
||||
// (sub nsw negative, non-negative) --> negative
|
||||
else if (Opcode == Instruction::Sub && LL == I) {
|
||||
if (Known2.isNonNegative() && Known3.isNegative())
|
||||
Known.makeNonNegative();
|
||||
else if (Known2.isNegative() && Known3.isNonNegative())
|
||||
Known.makeNegative();
|
||||
}
|
||||
|
||||
// (mul nsw non-negative, non-negative) --> non-negative
|
||||
else if (Opcode == Instruction::Mul && Known2.isNonNegative() &&
|
||||
Known3.isNonNegative())
|
||||
auto *OverflowOp = dyn_cast<OverflowingBinaryOperator>(BO);
|
||||
if (OverflowOp && Q.IIQ.hasNoSignedWrap(OverflowOp)) {
|
||||
// If initial value of recurrence is nonnegative, and we are adding
|
||||
// a nonnegative number with nsw, the result can only be nonnegative
|
||||
// or poison value regardless of the number of times we execute the
|
||||
// add in phi recurrence. If initial value is negative and we are
|
||||
// adding a negative number with nsw, the result can only be
|
||||
// negative or poison value. Similar arguments apply to sub and mul.
|
||||
//
|
||||
// (add non-negative, non-negative) --> non-negative
|
||||
// (add negative, negative) --> negative
|
||||
if (Opcode == Instruction::Add) {
|
||||
if (Known2.isNonNegative() && Known3.isNonNegative())
|
||||
Known.makeNonNegative();
|
||||
else if (Known2.isNegative() && Known3.isNegative())
|
||||
Known.makeNegative();
|
||||
}
|
||||
|
||||
break;
|
||||
// (sub nsw non-negative, negative) --> non-negative
|
||||
// (sub nsw negative, non-negative) --> negative
|
||||
else if (Opcode == Instruction::Sub && BO->getOperand(0) == I) {
|
||||
if (Known2.isNonNegative() && Known3.isNegative())
|
||||
Known.makeNonNegative();
|
||||
else if (Known2.isNegative() && Known3.isNonNegative())
|
||||
Known.makeNegative();
|
||||
}
|
||||
|
||||
// (mul nsw non-negative, non-negative) --> non-negative
|
||||
else if (Opcode == Instruction::Mul && Known2.isNonNegative() &&
|
||||
Known3.isNonNegative())
|
||||
Known.makeNonNegative();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6053,7 +6032,7 @@ llvm::canConvertToMinOrMaxIntrinsic(ArrayRef<Value *> VL) {
|
||||
return {Intrinsic::not_intrinsic, false};
|
||||
}
|
||||
|
||||
bool llvm::matchSimpleRecurrence(PHINode *P, BinaryOperator *&BO,
|
||||
bool llvm::matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO,
|
||||
Value *&Start, Value *&Step) {
|
||||
// Handle the case of a simple two-predecessor recurrence PHI.
|
||||
// There's a lot more that could theoretically be done here, but
|
||||
|
Loading…
Reference in New Issue
Block a user