diff options
| author | Francis Visoiu Mistrih <francisvm@yahoo.com> | 2019-11-06 17:09:55 -0800 |
|---|---|---|
| committer | Francis Visoiu Mistrih <francisvm@yahoo.com> | 2019-11-11 08:30:06 -0800 |
| commit | a9a3781df81a8a630e5d233efbc8b15b24ddd1dd (patch) | |
| tree | 94d8b045db0c77789b2c5a3c01d1d639f42696b4 /llvm/lib/CodeGen | |
| parent | 135a493f34561219d67251b58a482cd3fc6416b9 (diff) | |
| download | bcm5719-llvm-a9a3781df81a8a630e5d233efbc8b15b24ddd1dd.tar.gz bcm5719-llvm-a9a3781df81a8a630e5d233efbc8b15b24ddd1dd.zip | |
[ObjC] Override TailCallKind when lowering objc intrinsics
The tail-call-kind-ness is known by the ObjCARC analysis and can be
enforced while lowering the intrinsics to calls.
This allows us to get the requested tail calls at -O0 without trying to
preserve the attributes throughout passes that change code even at -O0
,like the Always Inliner, where the ObjCOpt pass doesn't run.
Differential Revision: https://reviews.llvm.org/D69980
Diffstat (limited to 'llvm/lib/CodeGen')
| -rw-r--r-- | llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp index 0d2f6f99ca9..79d0c80dd35 100644 --- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/PreISelIntrinsicLowering.h" +#include "llvm/Analysis/ObjCARCInstKind.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/Function.h" #include "llvm/IR/Intrinsics.h" @@ -56,6 +57,17 @@ static bool lowerLoadRelative(Function &F) { return Changed; } +// ObjCARC has knowledge about whether an obj-c runtime function needs to be +// always tail-called or never tail-called. +static CallInst::TailCallKind getOverridingTailCallKind(const Function &F) { + objcarc::ARCInstKind Kind = objcarc::GetFunctionClass(&F); + if (objcarc::IsAlwaysTail(Kind)) + return CallInst::TCK_Tail; + else if (objcarc::IsNeverTail(Kind)) + return CallInst::TCK_NoTail; + return CallInst::TCK_None; +} + static bool lowerObjCCall(Function &F, const char *NewFn, bool setNonLazyBind = false) { if (F.use_empty()) @@ -75,6 +87,8 @@ static bool lowerObjCCall(Function &F, const char *NewFn, } } + CallInst::TailCallKind OverridingTCK = getOverridingTailCallKind(F); + for (auto I = F.use_begin(), E = F.use_end(); I != E;) { auto *CI = cast<CallInst>(I->getUser()); assert(CI->getCalledFunction() && "Cannot lower an indirect call!"); @@ -84,7 +98,17 @@ static bool lowerObjCCall(Function &F, const char *NewFn, SmallVector<Value *, 8> Args(CI->arg_begin(), CI->arg_end()); CallInst *NewCI = Builder.CreateCall(FCache, Args); NewCI->setName(CI->getName()); - NewCI->setTailCallKind(CI->getTailCallKind()); + + // Try to set the most appropriate TailCallKind based on both the current + // attributes and the ones that we could get from ObjCARC's special + // knowledge of the runtime functions. + // + // std::max respects both requirements of notail and tail here: + // * notail on either the call or from ObjCARC becomes notail + // * tail on either side is stronger than none, but not notail + CallInst::TailCallKind TCK = CI->getTailCallKind(); + NewCI->setTailCallKind(std::max(TCK, OverridingTCK)); + if (!CI->use_empty()) CI->replaceAllUsesWith(NewCI); CI->eraseFromParent(); |

