diff options
author | Manman Ren <mren@apple.com> | 2013-03-16 00:11:09 +0000 |
---|---|---|
committer | Manman Ren <mren@apple.com> | 2013-03-16 00:11:09 +0000 |
commit | 2710ed8fd997be04ff447b8be2190f8fb34ac22b (patch) | |
tree | e16b3753c587ffff6ffeda2e04f35851de6f2d53 /lib/CodeGen/CGCall.cpp | |
parent | 70e82dc7a254054f0de491493489da162e63c364 (diff) |
Exploit this-return of a callsite in a this-return function.
For constructors/desctructors that return 'this', if there exists a callsite
that returns 'this' and is immediately before the return instruction, make
sure we are using the return value from the callsite.
We don't need to keep 'this' alive through the callsite. It also enables
optimizations in the backend, such as tail call optimization.
rdar://12818789
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@177211 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCall.cpp')
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 9e97bce6c3..6438ebf846 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -1705,6 +1705,18 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) { llvm_unreachable("Invalid ABI kind for return argument"); } + // If this function returns 'this' and the last instruction is a CallInst + // that returns 'this', use the return value from the CallInst. We will not + // need to keep 'this' alive through the callsite. It also enables + // optimizations in the backend, such as tail call optimization. + if (CalleeWithThisReturn && CGM.getCXXABI().HasThisReturn(CurGD)) { + llvm::BasicBlock *IP = Builder.GetInsertBlock(); + llvm::CallInst *Callsite; + if (!IP->empty() && (Callsite = dyn_cast<llvm::CallInst>(&IP->back())) && + Callsite->getCalledFunction() == CalleeWithThisReturn) + // Create a bitcast of Callsite. + RV = Builder.CreateBitCast(Callsite, RetAI.getCoerceToType()); + } llvm::Instruction *Ret = RV ? Builder.CreateRet(RV) : Builder.CreateRetVoid(); if (!RetDbgLoc.isUnknown()) Ret->setDebugLoc(RetDbgLoc); |