summaryrefslogtreecommitdiff
path: root/lib/CodeGen/Analysis.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
commitd8e91e46262bc44006913e6796843909f1ac7bcd (patch)
tree7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/CodeGen/Analysis.cpp
parentb7eb8e35e481a74962664b63dfb09483b200209a (diff)
Notes
Diffstat (limited to 'lib/CodeGen/Analysis.cpp')
-rw-r--r--lib/CodeGen/Analysis.cpp29
1 files changed, 25 insertions, 4 deletions
diff --git a/lib/CodeGen/Analysis.cpp b/lib/CodeGen/Analysis.cpp
index 79f11def38f7..797f05ee5cf3 100644
--- a/lib/CodeGen/Analysis.cpp
+++ b/lib/CodeGen/Analysis.cpp
@@ -471,7 +471,7 @@ static bool nextRealType(SmallVectorImpl<CompositeType *> &SubTypes,
bool llvm::isInTailCallPosition(ImmutableCallSite CS, const TargetMachine &TM) {
const Instruction *I = CS.getInstruction();
const BasicBlock *ExitBB = I->getParent();
- const TerminatorInst *Term = ExitBB->getTerminator();
+ const Instruction *Term = ExitBB->getTerminator();
const ReturnInst *Ret = dyn_cast<ReturnInst>(Term);
// The block must end in a return statement or unreachable.
@@ -496,6 +496,10 @@ bool llvm::isInTailCallPosition(ImmutableCallSite CS, const TargetMachine &TM) {
// Debug info intrinsics do not get in the way of tail call optimization.
if (isa<DbgInfoIntrinsic>(BBI))
continue;
+ // A lifetime end intrinsic should not stop tail call optimization.
+ if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(BBI))
+ if (II->getIntrinsicID() == Intrinsic::lifetime_end)
+ continue;
if (BBI->mayHaveSideEffects() || BBI->mayReadFromMemory() ||
!isSafeToSpeculativelyExecute(&*BBI))
return false;
@@ -519,10 +523,12 @@ bool llvm::attributesPermitTailCall(const Function *F, const Instruction *I,
AttrBuilder CalleeAttrs(cast<CallInst>(I)->getAttributes(),
AttributeList::ReturnIndex);
- // Noalias is completely benign as far as calling convention goes, it
- // shouldn't affect whether the call is a tail call.
+ // NoAlias and NonNull are completely benign as far as calling convention
+ // goes, they shouldn't affect whether the call is a tail call.
CallerAttrs.removeAttribute(Attribute::NoAlias);
CalleeAttrs.removeAttribute(Attribute::NoAlias);
+ CallerAttrs.removeAttribute(Attribute::NonNull);
+ CalleeAttrs.removeAttribute(Attribute::NonNull);
if (CallerAttrs.contains(Attribute::ZExt)) {
if (!CalleeAttrs.contains(Attribute::ZExt))
@@ -540,6 +546,21 @@ bool llvm::attributesPermitTailCall(const Function *F, const Instruction *I,
CalleeAttrs.removeAttribute(Attribute::SExt);
}
+ // Drop sext and zext return attributes if the result is not used.
+ // This enables tail calls for code like:
+ //
+ // define void @caller() {
+ // entry:
+ // %unused_result = tail call zeroext i1 @callee()
+ // br label %retlabel
+ // retlabel:
+ // ret void
+ // }
+ if (I->use_empty()) {
+ CalleeAttrs.removeAttribute(Attribute::SExt);
+ CalleeAttrs.removeAttribute(Attribute::ZExt);
+ }
+
// If they're still different, there's some facet we don't understand
// (currently only "inreg", but in future who knows). It may be OK but the
// only safe option is to reject the tail call.
@@ -650,7 +671,7 @@ static void collectEHScopeMembers(
// Returns are boundaries where scope transfer can occur, don't follow
// successors.
- if (Visiting->isReturnBlock())
+ if (Visiting->isEHScopeReturnBlock())
continue;
for (const MachineBasicBlock *Succ : Visiting->successors())