[llvm-commits] [llvm] r127970 - in /llvm/trunk: lib/Transforms/IPO/GlobalOpt.cpp test/Transforms/GlobalOpt/cxx-dtor.ll

Eli Friedman eli.friedman at gmail.com
Sun Mar 20 12:36:40 PDT 2011


On Sun, Mar 20, 2011 at 11:53 AM, Frits van Bommel <fvbommel at gmail.com> wrote:
> On Sun, Mar 20, 2011 at 6:59 PM, Anders Carlsson <andersca at mac.com> wrote:
>> +static Function *FindCXAAtExit(Module &M) {
>> +  Function *Fn = M.getFunction("__cxa_atexit");
>> +
>> +  if (!Fn)
>> +    return 0;
>> +
>> +  const FunctionType *FTy = Fn->getFunctionType();
>> +
>> +  // Checking that the function has the right number of parameters and that they
>> +  // all have pointer types should be enough.
>> +  if (FTy->getNumParams() != 3 ||
>> +      !FTy->getParamType(0)->isPointerTy() ||
>> +      !FTy->getParamType(1)->isPointerTy() ||
>> +      !FTy->getParamType(2)->isPointerTy())
>> +    return 0;
>
> You're not checking the return type here; see below.
>
>> +
>> +  return Fn;
>> +}
>> +
>> +/// cxxDtorIsEmpty - 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' or 'call' to empty C++ dtor.
>> +static bool cxxDtorIsEmpty(const Function& Fn) {
>> +  if (Fn.empty())
>> +    return true;
>
> Fn.empty() is equivalent to Fn.isDeclaration(). Do you really want to
> allow external destructors to be deleted?
>
> (Note: you can allow them if they're readonly/readnone and nounwind)
>
>> +
>> +  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)) {
>> +      const Function *CalledFn = CI->getCalledFunction();
>> +
>> +      if (!CalledFn)
>> +        return false;
>> +
>> +      if (!cxxDtorIsEmpty(*CalledFn))
>> +        return false;
>
> If the destructor is an infinite recursion at run-time, this turns it
> into an infinite recursion at compile time...
>
>> +    } else if (isa<ReturnInst>(*I))
>> +      return true;
>> +    else
>> +      return false;
>
> I think you could allow arbitrary non-terminator instructions without
> side-effects here too. These could be passed as parameters to the
> calls, for instance.
> In fact, that check could be moved up to filter out side-effect-free
> function calls too.
>
>> +  }
>> +
>> +  return false;
>> +}
>> +
>> +bool GlobalOpt::OptimizeEmptyGlobalCXXDtors(Function *CXAAtExitFn) {
>> +  /// Itanium C++ ABI p3.3.5:
>> +  ///
>> +  ///   After constructing a global (or local static) object, that will require
>> +  ///   destruction on exit, a termination function is registered as follows:
>> +  ///
>> +  ///   extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
>> +  ///
>> +  ///   This registration, e.g. __cxa_atexit(f,p,d), is intended to cause the
>> +  ///   call f(p) when DSO d is unloaded, before all such termination calls
>> +  ///   registered before this one. It returns zero if registration is
>> +  ///    successful, nonzero on failure.
>> +
>> +  // This pass will look for calls to __cxa_atexit where the function is trivial
>> +  // and remove them.
> [snip]
>> +    if (!cxxDtorIsEmpty(*DtorFn))
>> +      continue;
>> +
>> +    // Just remove the call.
>> +    CS.getInstruction()->eraseFromParent();
>> +    ++NumCXXDtorsRemoved;
>
> According to the comment above, __cxa_atexit returns an int. If it has
> any uses, this leaves them dangling.
> Since it should be safe to pretend that registering an empty
> destructor is successful, you should call
> "CS->replaceAllUsesWith(Constant::getNullValue(CS.getType()));" before
> erasing __cxa_atexit calls that have uses.
> You should probably also either check for non-void return type in
> FindCXAAtExit(), or skip the RAUW if the return type is void.

Also worth pointing out that the CS could be an invoke.  (It wouldn't
be very useful because __cxa_atexit can't throw, but not illegal
AFAIK.)

-Eli

> Also, note that 'CS.getInstruction()->' is equivalent to 'CS->' due to
> operator overloading :).
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>




More information about the llvm-commits mailing list