-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[ValueTracking] Support GEPs in matchSimpleRecurrence. #123518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1577,7 +1577,7 @@ static void computeKnownBitsFromOperator(const Operator *I, | |
| } | ||
| case Instruction::PHI: { | ||
| const PHINode *P = cast<PHINode>(I); | ||
| BinaryOperator *BO = nullptr; | ||
| Instruction *BO = nullptr; | ||
| Value *R = nullptr, *L = nullptr; | ||
| if (matchSimpleRecurrence(P, BO, R, L)) { | ||
| // Handle the case of a simple two-predecessor recurrence PHI. | ||
|
|
@@ -1641,6 +1641,7 @@ static void computeKnownBitsFromOperator(const Operator *I, | |
| case Instruction::Sub: | ||
| case Instruction::And: | ||
| case Instruction::Or: | ||
| case Instruction::GetElementPtr: | ||
| case 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 | ||
|
|
@@ -1659,6 +1660,11 @@ static void computeKnownBitsFromOperator(const Operator *I, | |
|
|
||
| // We need to take the minimum number of known bits | ||
| KnownBits Known3(BitWidth); | ||
| if (BitWidth != getBitWidth(L->getType(), Q.DL)) { | ||
|
||
| assert(isa<GetElementPtrInst>(BO) && | ||
| "Bitwidth should only be different for GEPs."); | ||
| break; | ||
| } | ||
| RecQ.CxtI = LInst; | ||
| computeKnownBits(L, DemandedElts, Known3, RecQ, Depth + 1); | ||
|
|
||
|
|
@@ -1821,6 +1827,7 @@ static void computeKnownBitsFromOperator(const Operator *I, | |
| Known.resetAll(); | ||
| } | ||
| } | ||
|
|
||
| if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { | ||
| switch (II->getIntrinsicID()) { | ||
| default: | ||
|
|
@@ -2351,7 +2358,7 @@ void computeKnownBits(const Value *V, const APInt &DemandedElts, | |
| /// always a power of two (or zero). | ||
| static bool isPowerOfTwoRecurrence(const PHINode *PN, bool OrZero, | ||
| SimplifyQuery &Q, unsigned Depth) { | ||
| BinaryOperator *BO = nullptr; | ||
| Instruction *BO = nullptr; | ||
| Value *Start = nullptr, *Step = nullptr; | ||
| if (!matchSimpleRecurrence(PN, BO, Start, Step)) | ||
| return false; | ||
|
|
@@ -2389,7 +2396,7 @@ static bool isPowerOfTwoRecurrence(const PHINode *PN, bool OrZero, | |
| // Divisor must be a power of two. | ||
| // If OrZero is false, cannot guarantee induction variable is non-zero after | ||
| // division, same for Shr, unless it is exact division. | ||
| return (OrZero || Q.IIQ.isExact(BO)) && | ||
| return (OrZero || Q.IIQ.isExact(cast<BinaryOperator>(BO))) && | ||
| isKnownToBeAPowerOfTwo(Step, false, Q, Depth); | ||
| case Instruction::Shl: | ||
| return OrZero || Q.IIQ.hasNoUnsignedWrap(BO) || Q.IIQ.hasNoSignedWrap(BO); | ||
|
|
@@ -2398,7 +2405,7 @@ static bool isPowerOfTwoRecurrence(const PHINode *PN, bool OrZero, | |
| return false; | ||
| [[fallthrough]]; | ||
| case Instruction::LShr: | ||
| return OrZero || Q.IIQ.isExact(BO); | ||
| return OrZero || Q.IIQ.isExact(cast<BinaryOperator>(BO)); | ||
| default: | ||
| return false; | ||
| } | ||
|
|
@@ -2810,7 +2817,7 @@ static bool rangeMetadataExcludesValue(const MDNode* Ranges, const APInt& Value) | |
| /// Try to detect a recurrence that monotonically increases/decreases from a | ||
| /// non-zero starting value. These are common as induction variables. | ||
| static bool isNonZeroRecurrence(const PHINode *PN) { | ||
| BinaryOperator *BO = nullptr; | ||
| Instruction *BO = nullptr; | ||
| Value *Start = nullptr, *Step = nullptr; | ||
| const APInt *StartC, *StepC; | ||
| if (!matchSimpleRecurrence(PN, BO, Start, Step) || | ||
|
|
@@ -3648,9 +3655,9 @@ getInvertibleOperands(const Operator *Op1, | |
| // If PN1 and PN2 are both recurrences, can we prove the entire recurrences | ||
| // are a single invertible function of the start values? Note that repeated | ||
| // application of an invertible function is also invertible | ||
| BinaryOperator *BO1 = nullptr; | ||
| Instruction *BO1 = nullptr; | ||
| Value *Start1 = nullptr, *Step1 = nullptr; | ||
| BinaryOperator *BO2 = nullptr; | ||
| Instruction *BO2 = nullptr; | ||
| Value *Start2 = nullptr, *Step2 = nullptr; | ||
| if (PN1->getParent() != PN2->getParent() || | ||
| !matchSimpleRecurrence(PN1, BO1, Start1, Step1) || | ||
|
|
@@ -9125,6 +9132,14 @@ static bool matchTwoInputRecurrence(const PHINode *PN, InstTy *&Inst, | |
| for (unsigned I = 0; I != 2; ++I) { | ||
| if (auto *Operation = dyn_cast<InstTy>(PN->getIncomingValue(I)); | ||
| Operation && Operation->getNumOperands() >= 2) { | ||
| Value *LR; | ||
| if (match(Operation, m_PtrAdd(m_Specific(PN), m_Value(LR)))) { | ||
dtcxzyw marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Inst = Operation; | ||
| Init = PN->getIncomingValue(!I); | ||
| OtherOp = LR; | ||
| return true; | ||
| } | ||
|
|
||
| Value *LHS = Operation->getOperand(0); | ||
| Value *RHS = Operation->getOperand(1); | ||
| if (LHS != PN && RHS != PN) | ||
|
|
@@ -9147,12 +9162,24 @@ bool llvm::matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO, | |
| // Or: | ||
| // %iv = [Start, %entry], [%iv.next, %backedge] | ||
| // %iv.next = binop Step, %iv | ||
| return matchTwoInputRecurrence(P, BO, Start, Step); | ||
| return matchTwoInputRecurrence(P, BO, Start, Step) && isa<BinaryOperator>(BO); | ||
| } | ||
|
|
||
| bool llvm::matchSimpleRecurrence(const PHINode *P, Instruction *&BO, | ||
| Value *&Start, Value *&Step) { | ||
| // We try to match a recurrence of the form: | ||
| // %iv = [Start, %entry], [%iv.next, %backedge] | ||
| // %iv.next = binop %iv, Step | ||
| // Or: | ||
| // %iv = [Start, %entry], [%iv.next, %backedge] | ||
| // %iv.next = binop Step, %iv | ||
| return matchTwoInputRecurrence(P, BO, Start, Step) && | ||
| isa<BinaryOperator, GetElementPtrInst>(BO); | ||
| } | ||
|
|
||
| bool llvm::matchSimpleRecurrence(const BinaryOperator *I, PHINode *&P, | ||
| bool llvm::matchSimpleRecurrence(const Instruction *I, PHINode *&P, | ||
| Value *&Start, Value *&Step) { | ||
| BinaryOperator *BO = nullptr; | ||
| Instruction *BO = nullptr; | ||
| P = dyn_cast<PHINode>(I->getOperand(0)); | ||
| if (!P) | ||
| P = dyn_cast<PHINode>(I->getOperand(1)); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think BO should be renamed.That's probably not worth it given the large amount of unrelated diffs it will create.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could rename it as NFC after the change lands?