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. :)
This commit is contained in:
@@ -748,6 +748,16 @@ constexpr unsigned MaxAnalysisRecursionDepth = 6;
|
||||
std::pair<Intrinsic::ID, bool>
|
||||
canConvertToMinOrMaxIntrinsic(ArrayRef<Value *> VL);
|
||||
|
||||
/// Attempt to match a simple recurrence cycle of the form:
|
||||
/// <Start, Op, Step> (using SCEV's notation)
|
||||
/// In IR, this might look like:
|
||||
/// %iv = phi Ty [%Start, %Entry], [%Inc, %backedge]
|
||||
/// %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,
|
||||
Value *&Start, Value *&Step);
|
||||
|
||||
/// Return true if RHS is known to be implied true by LHS. Return false if
|
||||
/// RHS is known to be implied false by LHS. Otherwise, return None if no
|
||||
/// implication can be made.
|
||||
|
||||
@@ -6053,6 +6053,70 @@ llvm::canConvertToMinOrMaxIntrinsic(ArrayRef<Value *> VL) {
|
||||
return {Intrinsic::not_intrinsic, false};
|
||||
}
|
||||
|
||||
bool llvm::matchSimpleRecurrence(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
|
||||
// this is sufficient to catch some interesting cases.
|
||||
if (P->getNumIncomingValues() != 2)
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i != 2; ++i) {
|
||||
Value *L = P->getIncomingValue(i);
|
||||
Value *R = P->getIncomingValue(!i);
|
||||
Operator *LU = dyn_cast<Operator>(L);
|
||||
if (!LU)
|
||||
continue;
|
||||
unsigned Opcode = LU->getOpcode();
|
||||
|
||||
switch (Opcode) {
|
||||
default:
|
||||
continue;
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr:
|
||||
case Instruction::Shl: {
|
||||
Value *LL = LU->getOperand(0);
|
||||
Value *LR = LU->getOperand(1);
|
||||
// Find a recurrence.
|
||||
if (LL == P)
|
||||
L = LR;
|
||||
else
|
||||
continue; // Check for recurrence with L and R flipped.
|
||||
|
||||
break; // Match!
|
||||
}
|
||||
|
||||
// TODO: Expand list -- xor, mul, div, gep, uaddo, etc..
|
||||
case Instruction::Add:
|
||||
case Instruction::Sub:
|
||||
case Instruction::And:
|
||||
case Instruction::Or:
|
||||
case Instruction::Mul: {
|
||||
Value *LL = LU->getOperand(0);
|
||||
Value *LR = LU->getOperand(1);
|
||||
// Find a recurrence.
|
||||
if (LL == P)
|
||||
L = LR;
|
||||
else if (LR == P)
|
||||
L = LL;
|
||||
else
|
||||
continue; // Check for recurrence with L and R flipped.
|
||||
|
||||
break; // Match!
|
||||
}
|
||||
};
|
||||
|
||||
// We have matched a recurrence of the form:
|
||||
// %iv = [R, %entry], [%iv.next, %backedge]
|
||||
// %iv.next = binop %iv, L
|
||||
BO = cast<BinaryOperator>(LU);
|
||||
Start = R;
|
||||
Step = L;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Return true if "icmp Pred LHS RHS" is always true.
|
||||
static bool isTruePredicate(CmpInst::Predicate Pred, const Value *LHS,
|
||||
const Value *RHS, const DataLayout &DL,
|
||||
|
||||
Reference in New Issue
Block a user