diff options
author | Akira Hatanaka <ahatanaka@apple.com> | 2019-04-25 19:42:55 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanaka@apple.com> | 2019-04-25 19:42:55 +0000 |
commit | 8edf8f317b59e9a69823c816e850a04b9b6ae015 (patch) | |
tree | e111cef33d744ad5b5691e61d0b02f508fed915c /llvm/lib/Transforms | |
parent | 2c97ff07bfd94971f6480a686f06292059538632 (diff) | |
download | bcm5719-llvm-8edf8f317b59e9a69823c816e850a04b9b6ae015.tar.gz bcm5719-llvm-8edf8f317b59e9a69823c816e850a04b9b6ae015.zip |
[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
llvm-svn: 359226
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp index 34de66f05fb..fa30ee6f72b 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp @@ -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(BasicBlock *BB, 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(Function &F) { // 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, |