[llvm] 23524fd - [ValueTracking] Replace recursion with Worklist

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 27 14:45:04 PDT 2020


Author: Vitaly Buka
Date: 2020-08-27T14:44:49-07:00
New Revision: 23524fdecef990dffc619d3463b1977cfb946136

URL: https://github.com/llvm/llvm-project/commit/23524fdecef990dffc619d3463b1977cfb946136
DIFF: https://github.com/llvm/llvm-project/commit/23524fdecef990dffc619d3463b1977cfb946136.diff

LOG: [ValueTracking] Replace recursion with Worklist

Now findAllocaForValue can handle nontrivial phi cycles.

Added: 
    

Modified: 
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/unittests/Analysis/ValueTrackingTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index bcb182a6dc1d..74097bbb2151 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4330,57 +4330,44 @@ bool llvm::getUnderlyingObjectsForCodeGen(const Value *V,
   return true;
 }
 
-static AllocaInst *
-findAllocaForValue(Value *V, DenseMap<Value *, AllocaInst *> &AllocaForValue,
-                   bool OffsetZero) {
-  if (AllocaInst *AI = dyn_cast<AllocaInst>(V))
-    return AI;
-  // See if we've already calculated (or started to calculate) alloca for a
-  // given value.
-  auto I = AllocaForValue.find(V);
-  if (I != AllocaForValue.end())
-    return I->second;
-  // Store 0 while we're calculating alloca for value V to avoid
-  // infinite recursion if the value references itself.
-  AllocaForValue[V] = nullptr;
-  AllocaInst *Res = nullptr;
-  if (CastInst *CI = dyn_cast<CastInst>(V))
-    Res = findAllocaForValue(CI->getOperand(0), AllocaForValue, OffsetZero);
-  else if (PHINode *PN = dyn_cast<PHINode>(V)) {
-    for (Value *IncValue : PN->incoming_values()) {
-      // Allow self-referencing phi-nodes.
-      if (IncValue == PN)
-        continue;
-      AllocaInst *IncValueAI =
-          findAllocaForValue(IncValue, AllocaForValue, OffsetZero);
-      // AI for incoming values should exist and should all be equal.
-      if (IncValueAI == nullptr || (Res != nullptr && IncValueAI != Res))
+AllocaInst *llvm::findAllocaForValue(Value *V, bool OffsetZero) {
+  AllocaInst *Result = nullptr;
+  SmallPtrSet<Value *, 4> Visited;
+  SmallVector<Value *, 4> Worklist;
+
+  auto AddWork = [&](Value *V) {
+    if (Visited.insert(V).second)
+      Worklist.push_back(V);
+  };
+
+  AddWork(V);
+  do {
+    V = Worklist.pop_back_val();
+    assert(Visited.count(V));
+
+    if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
+      if (Result && Result != AI)
         return nullptr;
-      Res = IncValueAI;
-    }
-  } else if (auto *SI = dyn_cast<SelectInst>(V)) {
-    Res = findAllocaForValue(SI->getTrueValue(), AllocaForValue, OffsetZero);
-    if (!Res)
-      return nullptr;
-    AllocaInst *F =
-        findAllocaForValue(SI->getFalseValue(), AllocaForValue, OffsetZero);
-    if (F != Res)
-      return nullptr;
-  } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(V)) {
-    if (OffsetZero && !GEP->hasAllZeroIndices())
+      Result = AI;
+    } else if (CastInst *CI = dyn_cast<CastInst>(V)) {
+      AddWork(CI->getOperand(0));
+    } else if (PHINode *PN = dyn_cast<PHINode>(V)) {
+      for (Value *IncValue : PN->incoming_values())
+        AddWork(IncValue);
+    } else if (auto *SI = dyn_cast<SelectInst>(V)) {
+      AddWork(SI->getTrueValue());
+      AddWork(SI->getFalseValue());
+    } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(V)) {
+      if (OffsetZero && !GEP->hasAllZeroIndices())
+        return nullptr;
+      AddWork(GEP->getPointerOperand());
+    } else {
       return nullptr;
-    Res = findAllocaForValue(GEP->getPointerOperand(), AllocaForValue,
-                             OffsetZero);
-  }
-  if (Res)
-    AllocaForValue[V] = Res;
-  return Res;
-}
+    }
+  } while (!Worklist.empty());
 
-AllocaInst *llvm::findAllocaForValue(Value *V, bool OffsetZero) {
-  DenseMap<Value *, AllocaInst *> AllocaForValue;
-  return ::findAllocaForValue(V, AllocaForValue, OffsetZero);
-}
+  return Result;
+};
 
 static bool onlyUsedByLifetimeMarkersOrDroppableInstsHelper(
     const Value *V, bool AllowLifetime, bool AllowDroppable) {

diff  --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp
index d60bdbb4a29b..3df5dc1fb82d 100644
--- a/llvm/unittests/Analysis/ValueTrackingTest.cpp
+++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp
@@ -1532,7 +1532,7 @@ const FindAllocaForValueTestParams FindAllocaForValueTests[] = {
       exit:
         ret void
       })",
-     false, false},
+     true, false},
 
     {R"(
       define void @test(i1 %cond, i64* %a) {


        


More information about the llvm-commits mailing list