[Constant Hoisting] Lazily compute the idom and cache the result.
authorJuergen Ributzka <juergen@apple.com>
Fri, 21 Mar 2014 06:04:39 +0000 (06:04 +0000)
committerJuergen Ributzka <juergen@apple.com>
Fri, 21 Mar 2014 06:04:39 +0000 (06:04 +0000)
Related to <rdar://problem/16381500>

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204434 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/ConstantHoisting.cpp

index 25fef5f500ff9d168eb4de86048744e8d247a897..89df2b496f36475652c11538159bda8d9c480466 100644 (file)
@@ -87,9 +87,10 @@ struct ConstantCandidate {
 struct RebasedConstantInfo {
   ConstantUseListType Uses;
   Constant *Offset;
+  mutable BasicBlock *IDom;
 
   RebasedConstantInfo(ConstantUseListType &&Uses, Constant *Offset)
-    : Uses(Uses), Offset(Offset) { }
+    : Uses(Uses), Offset(Offset), IDom(nullptr) { }
 };
 
 /// \brief A base constant and all its rebased constants.
@@ -152,6 +153,17 @@ private:
     Entry = nullptr;
   }
 
+  /// \brief Find the common dominator of all uses and cache the result for
+  /// future lookup.
+  BasicBlock *getIDom(const RebasedConstantInfo &RCI) const {
+    if (RCI.IDom)
+      return RCI.IDom;
+    RCI.IDom = findIDomOfAllUses(RCI.Uses);
+    assert(RCI.IDom && "Invalid IDom.");
+    return RCI.IDom;
+  }
+
+  BasicBlock *findIDomOfAllUses(const ConstantUseListType &Uses) const;
   Instruction *findMatInsertPt(Instruction *Inst, unsigned Idx = ~0U) const;
   Instruction *findConstantInsertionPoint(const ConstantInfo &ConstInfo) const;
   void collectConstantCandidates(Instruction *Inst, unsigned Idx,
@@ -202,6 +214,32 @@ bool ConstantHoisting::runOnFunction(Function &Fn) {
   return MadeChange;
 }
 
+/// \brief Find nearest common dominator of all uses.
+/// FIXME: Replace this with NearestCommonDominator once it is in common code.
+BasicBlock *
+ConstantHoisting::findIDomOfAllUses(const ConstantUseListType &Uses) const {
+  // Collect all basic blocks.
+  SmallPtrSet<BasicBlock *, 8> BBs;
+  for (auto const &U : Uses)
+    BBs.insert(findMatInsertPt(U.Inst, U.OpndIdx)->getParent());
+
+  if (BBs.count(Entry))
+    return Entry;
+
+  while (BBs.size() >= 2) {
+    BasicBlock *BB, *BB1, *BB2;
+    BB1 = *BBs.begin();
+    BB2 = *std::next(BBs.begin());
+    BB = DT->findNearestCommonDominator(BB1, BB2);
+    if (BB == Entry)
+      return Entry;
+    BBs.erase(BB1);
+    BBs.erase(BB2);
+    BBs.insert(BB);
+  }
+  assert((BBs.size() == 1) && "Expected only one element.");
+  return *BBs.begin();
+}
 
 /// \brief Find the constant materialization insertion point.
 Instruction *ConstantHoisting::findMatInsertPt(Instruction *Inst,
@@ -224,11 +262,12 @@ Instruction *ConstantHoisting::findMatInsertPt(Instruction *Inst,
 Instruction *ConstantHoisting::
 findConstantInsertionPoint(const ConstantInfo &ConstInfo) const {
   assert(!ConstInfo.RebasedConstants.empty() && "Invalid constant info entry.");
-  // Collect all basic blocks.
+  // Collect all IDoms.
   SmallPtrSet<BasicBlock *, 8> BBs;
   for (auto const &RCI : ConstInfo.RebasedConstants)
-    for (auto const &U : RCI.Uses)
-      BBs.insert(U.Inst->getParent());
+    BBs.insert(getIDom(RCI));
+
+  assert(!BBs.empty() && "No dominators!?");
 
   if (BBs.count(Entry))
     return &Entry->front();