[llvm] r353603 - [GlobalOpt] Simplify __cxa_atexit elimination
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sat Feb 9 01:18:37 PST 2019
Author: maskray
Date: Sat Feb 9 01:18:37 2019
New Revision: 353603
URL: http://llvm.org/viewvc/llvm-project?rev=353603&view=rev
Log:
[GlobalOpt] Simplify __cxa_atexit elimination
cxxDtorIsEmpty checks callers recursively to determine if the
__cxa_atexit-registered function is empty, and eliminates the
__cxa_atexit call accordingly.
This recursive check is unnecessary as redundant instructions and
function calls can be removed by early-cse and inliner. In addition,
cxxDtorIsEmpty does not mark visited function and it may visit a
function exponential times (multiplication principle).
Modified:
llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
llvm/trunk/test/Transforms/GlobalOpt/cxx-dtor.ll
Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=353603&r1=353602&r2=353603&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Sat Feb 9 01:18:37 2019
@@ -2814,46 +2814,20 @@ static Function *FindCXAAtExit(Module &M
/// Returns whether the given function is an empty C++ destructor and can
/// therefore be eliminated.
/// Note that we assume that other optimization passes have already simplified
-/// the code so we only look for a function with a single basic block, where
-/// the only allowed instructions are 'ret', 'call' to an empty C++ dtor and
-/// other side-effect free instructions.
-static bool cxxDtorIsEmpty(const Function &Fn,
- SmallPtrSet<const Function *, 8> &CalledFunctions) {
+/// the code so we simply check for 'ret'.
+static bool cxxDtorIsEmpty(const Function &Fn) {
// FIXME: We could eliminate C++ destructors if they're readonly/readnone and
// nounwind, but that doesn't seem worth doing.
if (Fn.isDeclaration())
return false;
- if (++Fn.begin() != Fn.end())
- return false;
-
- const BasicBlock &EntryBlock = Fn.getEntryBlock();
- for (BasicBlock::const_iterator I = EntryBlock.begin(), E = EntryBlock.end();
- I != E; ++I) {
- if (const CallInst *CI = dyn_cast<CallInst>(I)) {
- // Ignore debug intrinsics.
- if (isa<DbgInfoIntrinsic>(CI))
- continue;
-
- const Function *CalledFn = CI->getCalledFunction();
-
- if (!CalledFn)
- return false;
-
- SmallPtrSet<const Function *, 8> NewCalledFunctions(CalledFunctions);
-
- // Don't treat recursive functions as empty.
- if (!NewCalledFunctions.insert(CalledFn).second)
- return false;
-
- if (!cxxDtorIsEmpty(*CalledFn, NewCalledFunctions))
- return false;
- } else if (isa<ReturnInst>(*I))
- return true; // We're done.
- else if (I->mayHaveSideEffects())
- return false; // Destructor with side effects, bail.
+ for (auto &I : Fn.getEntryBlock()) {
+ if (isa<DbgInfoIntrinsic>(I))
+ continue;
+ if (isa<ReturnInst>(I))
+ return true;
+ break;
}
-
return false;
}
@@ -2885,11 +2859,7 @@ static bool OptimizeEmptyGlobalCXXDtors(
Function *DtorFn =
dyn_cast<Function>(CI->getArgOperand(0)->stripPointerCasts());
- if (!DtorFn)
- continue;
-
- SmallPtrSet<const Function *, 8> CalledFunctions;
- if (!cxxDtorIsEmpty(*DtorFn, CalledFunctions))
+ if (!DtorFn || !cxxDtorIsEmpty(*DtorFn))
continue;
// Just remove the call.
Modified: llvm/trunk/test/Transforms/GlobalOpt/cxx-dtor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/cxx-dtor.ll?rev=353603&r1=353602&r2=353603&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/GlobalOpt/cxx-dtor.ll (original)
+++ llvm/trunk/test/Transforms/GlobalOpt/cxx-dtor.ll Sat Feb 9 01:18:37 2019
@@ -1,4 +1,4 @@
-; RUN: opt < %s -globalopt -S | FileCheck %s
+; RUN: opt < %s -S -passes='cgscc(inline),function(early-cse),globalopt' | FileCheck %s
%0 = type { i32, void ()* }
%struct.A = type { i8 }
More information about the llvm-commits
mailing list