diff options
author | Philip Reames <listmail@philipreames.com> | 2021-02-26 10:46:28 -0800 |
---|---|---|
committer | Philip Reames <listmail@philipreames.com> | 2021-02-26 10:47:26 -0800 |
commit | ebd3aeba273736596163d498c38cc32e743bed31 (patch) | |
tree | ae460d79ac45275cad16ac2e56ad1a88e55b82d9 /llvm/lib/Analysis/ValueTracking.cpp | |
parent | e4dd614ae81194b0a50361a91f8bd4364916ef2e (diff) | |
download | llvm-ebd3aeba273736596163d498c38cc32e743bed31.zip llvm-ebd3aeba273736596163d498c38cc32e743bed31.tar.gz llvm-ebd3aeba273736596163d498c38cc32e743bed31.tar.bz2 |
Use helper introduced in 8020be0b8 to simplify ValueTracking [NFC]
Direct rewrite of the code the helper was extracted from.
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 231 |
1 files changed, 105 insertions, 126 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index b93d70a..07084c0 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -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(); - - - // 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 - - // 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; - }; - } + 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) { + + // 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; + }; + } - // 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. - - // 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); - - // 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())); - - 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()) + // 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; + + unsigned OpNum = P->getOperand(0) == R ? 0 : 1; + Instruction *RInst = P->getIncomingBlock(OpNum)->getTerminator(); + Instruction *LInst = P->getIncomingBlock(1-OpNum)->getTerminator(); + + // 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); + + Known.Zero.setLowBits(std::min(Known2.countMinTrailingZeros(), + Known3.countMinTrailingZeros())); + + 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 |