OSDN Git Service

NewGVN: Use def_chain iterator in singleReachablePhiPath instead of recursion
authorDaniel Berlin <dberlin@dberlin.org>
Sat, 1 Apr 2017 09:44:24 +0000 (09:44 +0000)
committerDaniel Berlin <dberlin@dberlin.org>
Sat, 1 Apr 2017 09:44:24 +0000 (09:44 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@299298 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Transforms/Utils/MemorySSA.h
lib/Transforms/Scalar/NewGVN.cpp

index 1b91796..25142cd 100644 (file)
@@ -1064,13 +1064,14 @@ upward_defs(const MemoryAccessPair &Pair) {
 /// no defining use (e.g. a MemoryPhi or liveOnEntry). Note that, when comparing
 /// against a null def_chain_iterator, this will compare equal only after
 /// walking said Phi/liveOnEntry.
+template <class T>
 struct def_chain_iterator
-    : public iterator_facade_base<def_chain_iterator, std::forward_iterator_tag,
-                                  MemoryAccess *> {
+    : public iterator_facade_base<def_chain_iterator<T>,
+                                  std::forward_iterator_tag, MemoryAccess *> {
   def_chain_iterator() : MA(nullptr) {}
-  def_chain_iterator(MemoryAccess *MA) : MA(MA) {}
+  def_chain_iterator(MA) : MA(MA) {}
 
-  MemoryAccess *operator*() const { return MA; }
+  operator*() const { return MA; }
 
   def_chain_iterator &operator++() {
     // N.B. liveOnEntry has a null defining access.
@@ -1084,16 +1085,17 @@ struct def_chain_iterator
   bool operator==(const def_chain_iterator &O) const { return MA == O.MA; }
 
 private:
-  MemoryAccess *MA;
+  MA;
 };
 
-inline iterator_range<def_chain_iterator>
-def_chain(MemoryAccess *MA, MemoryAccess *UpTo = nullptr) {
+template <class T>
+inline iterator_range<def_chain_iterator<T>>
+def_chain(T MA, MemoryAccess *UpTo = nullptr) {
 #ifdef EXPENSIVE_CHECKS
   assert((!UpTo || find(def_chain(MA), UpTo) != def_chain_iterator()) &&
          "UpTo isn't in the def chain!");
 #endif
-  return make_range(def_chain_iterator(MA), def_chain_iterator(UpTo));
+  return make_range(def_chain_iterator<T>(MA), def_chain_iterator<T>(UpTo));
 }
 
 } // end namespace llvm
index 9dbafec..34efa78 100644 (file)
@@ -1899,28 +1899,32 @@ bool NewGVN::singleReachablePHIPath(const MemoryAccess *First,
                                     const MemoryAccess *Second) const {
   if (First == Second)
     return true;
-
-  if (auto *FirstDef = dyn_cast<MemoryUseOrDef>(First)) {
-    auto *DefAccess = FirstDef->getDefiningAccess();
-    return singleReachablePHIPath(DefAccess, Second);
-  } else {
-    auto *MP = cast<MemoryPhi>(First);
-    auto ReachableOperandPred = [&](const Use &U) {
-      return ReachableEdges.count({MP->getIncomingBlock(U), MP->getBlock()});
-    };
-    auto FilteredPhiArgs =
-        make_filter_range(MP->operands(), ReachableOperandPred);
-    SmallVector<const Value *, 32> OperandList;
-    std::copy(FilteredPhiArgs.begin(), FilteredPhiArgs.end(),
-              std::back_inserter(OperandList));
-    bool Okay = OperandList.size() == 1;
-    if (!Okay)
-      Okay = std::equal(OperandList.begin(), OperandList.end(),
-                        OperandList.begin());
-    if (Okay)
-      return singleReachablePHIPath(cast<MemoryAccess>(OperandList[0]), Second);
+  if (MSSA->isLiveOnEntryDef(First))
     return false;
+  const auto *EndDef = First;
+  for (auto *ChainDef : def_chain(First)) {
+    if (ChainDef == Second)
+      return true;
+    if (MSSA->isLiveOnEntryDef(ChainDef))
+      return false;
+    EndDef = ChainDef;
   }
+  auto *MP = cast<MemoryPhi>(EndDef);
+  auto ReachableOperandPred = [&](const Use &U) {
+    return ReachableEdges.count({MP->getIncomingBlock(U), MP->getBlock()});
+  };
+  auto FilteredPhiArgs =
+      make_filter_range(MP->operands(), ReachableOperandPred);
+  SmallVector<const Value *, 32> OperandList;
+  std::copy(FilteredPhiArgs.begin(), FilteredPhiArgs.end(),
+            std::back_inserter(OperandList));
+  bool Okay = OperandList.size() == 1;
+  if (!Okay)
+    Okay =
+        std::equal(OperandList.begin(), OperandList.end(), OperandList.begin());
+  if (Okay)
+    return singleReachablePHIPath(cast<MemoryAccess>(OperandList[0]), Second);
+  return false;
 }
 
 // Verify the that the memory equivalence table makes sense relative to the