[llvm] 8020be0 - Add a helper for matching simple recurrence cycles

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 26 10:21:35 PST 2021


Author: Philip Reames
Date: 2021-02-26T10:21:23-08:00
New Revision: 8020be0b8b57e0d29d93f0a4a5b2e9bbfd2242e7

URL: https://github.com/llvm/llvm-project/commit/8020be0b8b57e0d29d93f0a4a5b2e9bbfd2242e7
DIFF: https://github.com/llvm/llvm-project/commit/8020be0b8b57e0d29d93f0a4a5b2e9bbfd2242e7.diff

LOG: 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.  :)

Added: 
    

Modified: 
    llvm/include/llvm/Analysis/ValueTracking.h
    llvm/lib/Analysis/ValueTracking.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 1dbb8bf7f688..93a8464f6d65 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -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.

diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 520c7f98b9be..b93d70abce71 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -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,


        


More information about the llvm-commits mailing list