Skip to content

Commit 8020be0

Browse files
committed
Add a helper for matching simple recurrence cycles
This helper came up in another review, and I've got about 4 different patches with copies of this copied into it. Time to precommit the routine. :)
1 parent 27f9ed7 commit 8020be0

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

llvm/include/llvm/Analysis/ValueTracking.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,16 @@ constexpr unsigned MaxAnalysisRecursionDepth = 6;
748748
std::pair<Intrinsic::ID, bool>
749749
canConvertToMinOrMaxIntrinsic(ArrayRef<Value *> VL);
750750

751+
/// Attempt to match a simple recurrence cycle of the form:
752+
/// <Start, Op, Step> (using SCEV's notation)
753+
/// In IR, this might look like:
754+
/// %iv = phi Ty [%Start, %Entry], [%Inc, %backedge]
755+
/// %inc = binop %iv, %step
756+
/// NOTE: This is intentional simple. If you want the ability to analyze
757+
/// non-trivial loop conditons, see ScalarEvolution instead.
758+
bool matchSimpleRecurrence(PHINode *P, BinaryOperator *&BO,
759+
Value *&Start, Value *&Step);
760+
751761
/// Return true if RHS is known to be implied true by LHS. Return false if
752762
/// RHS is known to be implied false by LHS. Otherwise, return None if no
753763
/// implication can be made.

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6053,6 +6053,70 @@ llvm::canConvertToMinOrMaxIntrinsic(ArrayRef<Value *> VL) {
60536053
return {Intrinsic::not_intrinsic, false};
60546054
}
60556055

6056+
bool llvm::matchSimpleRecurrence(PHINode *P, BinaryOperator *&BO,
6057+
Value *&Start, Value *&Step) {
6058+
// Handle the case of a simple two-predecessor recurrence PHI.
6059+
// There's a lot more that could theoretically be done here, but
6060+
// this is sufficient to catch some interesting cases.
6061+
if (P->getNumIncomingValues() != 2)
6062+
return false;
6063+
6064+
for (unsigned i = 0; i != 2; ++i) {
6065+
Value *L = P->getIncomingValue(i);
6066+
Value *R = P->getIncomingValue(!i);
6067+
Operator *LU = dyn_cast<Operator>(L);
6068+
if (!LU)
6069+
continue;
6070+
unsigned Opcode = LU->getOpcode();
6071+
6072+
switch (Opcode) {
6073+
default:
6074+
continue;
6075+
case Instruction::LShr:
6076+
case Instruction::AShr:
6077+
case Instruction::Shl: {
6078+
Value *LL = LU->getOperand(0);
6079+
Value *LR = LU->getOperand(1);
6080+
// Find a recurrence.
6081+
if (LL == P)
6082+
L = LR;
6083+
else
6084+
continue; // Check for recurrence with L and R flipped.
6085+
6086+
break; // Match!
6087+
}
6088+
6089+
// TODO: Expand list -- xor, mul, div, gep, uaddo, etc..
6090+
case Instruction::Add:
6091+
case Instruction::Sub:
6092+
case Instruction::And:
6093+
case Instruction::Or:
6094+
case Instruction::Mul: {
6095+
Value *LL = LU->getOperand(0);
6096+
Value *LR = LU->getOperand(1);
6097+
// Find a recurrence.
6098+
if (LL == P)
6099+
L = LR;
6100+
else if (LR == P)
6101+
L = LL;
6102+
else
6103+
continue; // Check for recurrence with L and R flipped.
6104+
6105+
break; // Match!
6106+
}
6107+
};
6108+
6109+
// We have matched a recurrence of the form:
6110+
// %iv = [R, %entry], [%iv.next, %backedge]
6111+
// %iv.next = binop %iv, L
6112+
BO = cast<BinaryOperator>(LU);
6113+
Start = R;
6114+
Step = L;
6115+
return true;
6116+
}
6117+
return false;
6118+
}
6119+
60566120
/// Return true if "icmp Pred LHS RHS" is always true.
60576121
static bool isTruePredicate(CmpInst::Predicate Pred, const Value *LHS,
60586122
const Value *RHS, const DataLayout &DL,

0 commit comments

Comments
 (0)