[llvm] r359226 - [ObjC][ARC] Let ARC optimizer bail out if the number of pointer states

Akira Hatanaka via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 25 12:42:56 PDT 2019


Author: ahatanak
Date: Thu Apr 25 12:42:55 2019
New Revision: 359226

URL: http://llvm.org/viewvc/llvm-project?rev=359226&view=rev
Log:
[ObjC][ARC] Let ARC optimizer bail out if the number of pointer states
it keeps track of becomes too large

ARC optimizer does a top-down and a bottom-up traversal of the whole
function to pair up retain and release instructions and remove them.
This can be expensive if the number of instructions in the function and
pointer states it tracks are large since it has to look at each pointer
state and determine whether the instruction being visited can
potentially use the pointer.

This patch adds a command line option that sets a limit to the number of
pointers it tracks.

rdar://problem/49477063

Differential Revision: https://reviews.llvm.org/D61100

Added:
    llvm/trunk/test/Transforms/ObjCARC/opt-max-ptr-states.ll
Modified:
    llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp

Modified: llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp?rev=359226&r1=359225&r2=359226&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp (original)
+++ llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp Thu Apr 25 12:42:55 2019
@@ -73,6 +73,11 @@ using namespace llvm::objcarc;
 
 #define DEBUG_TYPE "objc-arc-opts"
 
+static cl::opt<unsigned> MaxPtrStates("arc-opt-max-ptr-states",
+    cl::Hidden,
+    cl::desc("Maximum number of ptr states the optimizer keeps track of"),
+    cl::init(4095));
+
 /// \defgroup ARCUtilities Utility declarations/definitions specific to ARC.
 /// @{
 
@@ -219,6 +224,10 @@ namespace {
       return !PerPtrTopDown.empty();
     }
 
+    unsigned top_down_ptr_list_size() const {
+      return std::distance(top_down_ptr_begin(), top_down_ptr_end());
+    }
+
     using bottom_up_ptr_iterator = decltype(PerPtrBottomUp)::iterator;
     using const_bottom_up_ptr_iterator =
         decltype(PerPtrBottomUp)::const_iterator;
@@ -237,6 +246,10 @@ namespace {
       return !PerPtrBottomUp.empty();
     }
 
+    unsigned bottom_up_ptr_list_size() const {
+      return std::distance(bottom_up_ptr_begin(), bottom_up_ptr_end());
+    }
+
     /// Mark this block as being an entry block, which has one path from the
     /// entry by definition.
     void SetAsEntry() { TopDownPathCount = 1; }
@@ -480,6 +493,10 @@ namespace {
     /// A flag indicating whether this optimization pass should run.
     bool Run;
 
+    /// A flag indicating whether the optimization that removes or moves
+    /// retain/release pairs should be performed.
+    bool DisableRetainReleasePairing = false;
+
     /// Flags which determine whether each of the interesting runtime functions
     /// is in fact used in the current function.
     unsigned UsedInThisFunction;
@@ -1272,6 +1289,13 @@ bool ObjCARCOpt::VisitBottomUp(BasicBloc
     LLVM_DEBUG(dbgs() << "    Visiting " << *Inst << "\n");
 
     NestingDetected |= VisitInstructionBottomUp(Inst, BB, Retains, MyStates);
+
+    // Bail out if the number of pointers being tracked becomes too large so
+    // that this pass can complete in a reasonable amount of time.
+    if (MyStates.bottom_up_ptr_list_size() > MaxPtrStates) {
+      DisableRetainReleasePairing = true;
+      return false;
+    }
   }
 
   // If there's a predecessor with an invoke, visit the invoke as if it were
@@ -1394,6 +1418,13 @@ ObjCARCOpt::VisitTopDown(BasicBlock *BB,
     LLVM_DEBUG(dbgs() << "    Visiting " << Inst << "\n");
 
     NestingDetected |= VisitInstructionTopDown(&Inst, Releases, MyStates);
+
+    // Bail out if the number of pointers being tracked becomes too large so
+    // that this pass can complete in a reasonable amount of time.
+    if (MyStates.top_down_ptr_list_size() > MaxPtrStates) {
+      DisableRetainReleasePairing = true;
+      return false;
+    }
   }
 
   LLVM_DEBUG(dbgs() << "\nState Before Checking for CFG Hazards:\n"
@@ -1500,13 +1531,19 @@ bool ObjCARCOpt::Visit(Function &F,
 
   // Use reverse-postorder on the reverse CFG for bottom-up.
   bool BottomUpNestingDetected = false;
-  for (BasicBlock *BB : llvm::reverse(ReverseCFGPostOrder))
+  for (BasicBlock *BB : llvm::reverse(ReverseCFGPostOrder)) {
     BottomUpNestingDetected |= VisitBottomUp(BB, BBStates, Retains);
+    if (DisableRetainReleasePairing)
+      return false;
+  }
 
   // Use reverse-postorder for top-down.
   bool TopDownNestingDetected = false;
-  for (BasicBlock *BB : llvm::reverse(PostOrder))
+  for (BasicBlock *BB : llvm::reverse(PostOrder)) {
     TopDownNestingDetected |= VisitTopDown(BB, BBStates, Releases);
+    if (DisableRetainReleasePairing)
+      return false;
+  }
 
   return TopDownNestingDetected && BottomUpNestingDetected;
 }
@@ -2002,6 +2039,9 @@ bool ObjCARCOpt::OptimizeSequences(Funct
   // Analyze the CFG of the function, and all instructions.
   bool NestingDetected = Visit(F, BBStates, Retains, Releases);
 
+  if (DisableRetainReleasePairing)
+    return false;
+
   // Transform.
   bool AnyPairsCompletelyEliminated = PerformCodePlacement(BBStates, Retains,
                                                            Releases,

Added: llvm/trunk/test/Transforms/ObjCARC/opt-max-ptr-states.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/opt-max-ptr-states.ll?rev=359226&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/opt-max-ptr-states.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/opt-max-ptr-states.ll Thu Apr 25 12:42:55 2019
@@ -0,0 +1,26 @@
+; RUN: opt -objc-arc -S < %s | FileCheck -check-prefix=ENABLE -check-prefix=CHECK %s
+; RUN: opt -objc-arc -arc-opt-max-ptr-states=1 -S < %s | FileCheck -check-prefix=DISABLE -check-prefix=CHECK %s
+
+ at g0 = common global i8* null, align 8
+
+; CHECK: call i8* @llvm.objc.retain
+; ENABLE-NOT: call i8* @llvm.objc.retain
+; DISABLE: call i8* @llvm.objc.retain
+; CHECK: call void @llvm.objc.release
+; ENABLE-NOT: call void @llvm.objc.release
+; DISABLE: call void @llvm.objc.release
+
+define void @foo0(i8* %a) {
+  %1 = tail call i8* @llvm.objc.retain(i8* %a)
+  %2 = tail call i8* @llvm.objc.retain(i8* %a)
+  %3 = load i8*, i8** @g0, align 8
+  store i8* %a, i8** @g0, align 8
+  tail call void @llvm.objc.release(i8* %3)
+  tail call void @llvm.objc.release(i8* %a), !clang.imprecise_release !0
+  ret void
+}
+
+declare i8* @llvm.objc.retain(i8*)
+declare void @llvm.objc.release(i8*)
+
+!0 = !{}




More information about the llvm-commits mailing list