Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 2a93bda

Browse files
committed
[CGP] Be less conservative about tail-duplicating a ret to allow tail calls
CGP tail-duplicates rets into blocks that end with a call that feed the ret. This puts the call in tail position, potentially allowing the DAG builder to lower it as a tail call. To avoid tail duplication in cases where we won't form the tail call, CGP tried to predict whether this is going to be possible, and avoids doing it when lowering as a tail call will definitely fail. However, it was being too conservative by always throwing away calls to functions with a signext/zeroext attribute on the return type. Instead, we can use the same logic the builder uses to determine whether the attributes work out. Differential Revision: https://reviews.llvm.org/D24315 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@280894 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 6d2157d commit 2a93bda

File tree

4 files changed

+66
-28
lines changed

4 files changed

+66
-28
lines changed

include/llvm/CodeGen/Analysis.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,21 @@ ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred);
105105
/// This function only tests target-independent requirements.
106106
bool isInTailCallPosition(ImmutableCallSite CS, const TargetMachine &TM);
107107

108+
/// Test if given that the input instruction is in the tail call position, if
109+
/// there is an attribute mismatch between the caller and the callee that will
110+
/// inhibit tail call optimizations.
111+
/// \p AllowDifferingSizes is an output parameter which, if forming a tail call
112+
/// is permitted, determines whether it's permitted only if the size of the
113+
/// caller's and callee's return types match exactly.
114+
bool attributesPermitTailCall(const Function *F, const Instruction *I,
115+
const ReturnInst *Ret,
116+
const TargetLoweringBase &TLI,
117+
bool *AllowDifferingSizes = nullptr);
118+
108119
/// Test if given that the input instruction is in the tail call position if the
109120
/// return type or any attributes of the function will inhibit tail call
110121
/// optimization.
111-
bool returnTypeIsEligibleForTailCall(const Function *F,
112-
const Instruction *I,
122+
bool returnTypeIsEligibleForTailCall(const Function *F, const Instruction *I,
113123
const ReturnInst *Ret,
114124
const TargetLoweringBase &TLI);
115125

lib/CodeGen/Analysis.cpp

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -525,19 +525,15 @@ bool llvm::isInTailCallPosition(ImmutableCallSite CS, const TargetMachine &TM) {
525525
F, I, Ret, *TM.getSubtargetImpl(*F)->getTargetLowering());
526526
}
527527

528-
bool llvm::returnTypeIsEligibleForTailCall(const Function *F,
529-
const Instruction *I,
530-
const ReturnInst *Ret,
531-
const TargetLoweringBase &TLI) {
532-
// If the block ends with a void return or unreachable, it doesn't matter
533-
// what the call's return type is.
534-
if (!Ret || Ret->getNumOperands() == 0) return true;
528+
bool llvm::attributesPermitTailCall(const Function *F, const Instruction *I,
529+
const ReturnInst *Ret,
530+
const TargetLoweringBase &TLI,
531+
bool *AllowDifferingSizes) {
532+
// ADS may be null, so don't write to it directly.
533+
bool DummyADS;
534+
bool &ADS = AllowDifferingSizes ? *AllowDifferingSizes : DummyADS;
535+
ADS = true;
535536

536-
// If the return value is undef, it doesn't matter what the call's
537-
// return type is.
538-
if (isa<UndefValue>(Ret->getOperand(0))) return true;
539-
540-
// Make sure the attributes attached to each return are compatible.
541537
AttrBuilder CallerAttrs(F->getAttributes(),
542538
AttributeSet::ReturnIndex);
543539
AttrBuilder CalleeAttrs(cast<CallInst>(I)->getAttributes(),
@@ -548,27 +544,43 @@ bool llvm::returnTypeIsEligibleForTailCall(const Function *F,
548544
CallerAttrs = CallerAttrs.removeAttribute(Attribute::NoAlias);
549545
CalleeAttrs = CalleeAttrs.removeAttribute(Attribute::NoAlias);
550546

551-
bool AllowDifferingSizes = true;
552547
if (CallerAttrs.contains(Attribute::ZExt)) {
553548
if (!CalleeAttrs.contains(Attribute::ZExt))
554549
return false;
555550

556-
AllowDifferingSizes = false;
551+
ADS = false;
557552
CallerAttrs.removeAttribute(Attribute::ZExt);
558553
CalleeAttrs.removeAttribute(Attribute::ZExt);
559554
} else if (CallerAttrs.contains(Attribute::SExt)) {
560555
if (!CalleeAttrs.contains(Attribute::SExt))
561556
return false;
562557

563-
AllowDifferingSizes = false;
558+
ADS = false;
564559
CallerAttrs.removeAttribute(Attribute::SExt);
565560
CalleeAttrs.removeAttribute(Attribute::SExt);
566561
}
567562

568563
// If they're still different, there's some facet we don't understand
569564
// (currently only "inreg", but in future who knows). It may be OK but the
570565
// only safe option is to reject the tail call.
571-
if (CallerAttrs != CalleeAttrs)
566+
return CallerAttrs == CalleeAttrs;
567+
}
568+
569+
bool llvm::returnTypeIsEligibleForTailCall(const Function *F,
570+
const Instruction *I,
571+
const ReturnInst *Ret,
572+
const TargetLoweringBase &TLI) {
573+
// If the block ends with a void return or unreachable, it doesn't matter
574+
// what the call's return type is.
575+
if (!Ret || Ret->getNumOperands() == 0) return true;
576+
577+
// If the return value is undef, it doesn't matter what the call's
578+
// return type is.
579+
if (isa<UndefValue>(Ret->getOperand(0))) return true;
580+
581+
// Make sure the attributes attached to each return are compatible.
582+
bool AllowDifferingSizes;
583+
if (!attributesPermitTailCall(F, I, Ret, TLI, &AllowDifferingSizes))
572584
return false;
573585

574586
const Value *RetVal = Ret->getOperand(0), *CallVal = I;

lib/CodeGen/CodeGenPrepare.cpp

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/Analysis/TargetTransformInfo.h"
2424
#include "llvm/Analysis/ValueTracking.h"
2525
#include "llvm/Analysis/MemoryBuiltins.h"
26+
#include "llvm/CodeGen/Analysis.h"
2627
#include "llvm/IR/CallSite.h"
2728
#include "llvm/IR/Constants.h"
2829
#include "llvm/IR/DataLayout.h"
@@ -1983,14 +1984,6 @@ bool CodeGenPrepare::dupRetToEnableTailCallOpts(BasicBlock *BB) {
19831984
if (PN && PN->getParent() != BB)
19841985
return false;
19851986

1986-
// It's not safe to eliminate the sign / zero extension of the return value.
1987-
// See llvm::isInTailCallPosition().
1988-
const Function *F = BB->getParent();
1989-
AttributeSet CallerAttrs = F->getAttributes();
1990-
if (CallerAttrs.hasAttribute(AttributeSet::ReturnIndex, Attribute::ZExt) ||
1991-
CallerAttrs.hasAttribute(AttributeSet::ReturnIndex, Attribute::SExt))
1992-
return false;
1993-
19941987
// Make sure there are no instructions between the PHI and return, or that the
19951988
// return is the first instruction in the block.
19961989
if (PN) {
@@ -2010,13 +2003,15 @@ bool CodeGenPrepare::dupRetToEnableTailCallOpts(BasicBlock *BB) {
20102003

20112004
/// Only dup the ReturnInst if the CallInst is likely to be emitted as a tail
20122005
/// call.
2006+
const Function *F = BB->getParent();
20132007
SmallVector<CallInst*, 4> TailCalls;
20142008
if (PN) {
20152009
for (unsigned I = 0, E = PN->getNumIncomingValues(); I != E; ++I) {
20162010
CallInst *CI = dyn_cast<CallInst>(PN->getIncomingValue(I));
20172011
// Make sure the phi value is indeed produced by the tail call.
20182012
if (CI && CI->hasOneUse() && CI->getParent() == PN->getIncomingBlock(I) &&
2019-
TLI->mayBeEmittedAsTailCall(CI))
2013+
TLI->mayBeEmittedAsTailCall(CI) &&
2014+
attributesPermitTailCall(F, CI, RetI, *TLI))
20202015
TailCalls.push_back(CI);
20212016
}
20222017
} else {
@@ -2033,7 +2028,8 @@ bool CodeGenPrepare::dupRetToEnableTailCallOpts(BasicBlock *BB) {
20332028
continue;
20342029

20352030
CallInst *CI = dyn_cast<CallInst>(&*RI);
2036-
if (CI && CI->use_empty() && TLI->mayBeEmittedAsTailCall(CI))
2031+
if (CI && CI->use_empty() && TLI->mayBeEmittedAsTailCall(CI) &&
2032+
attributesPermitTailCall(F, CI, RetI, *TLI))
20372033
TailCalls.push_back(CI);
20382034
}
20392035
}

test/CodeGen/X86/tailcall-cgp-dup.ll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,23 @@ someThingWithValue.exit: ; preds = %if.else.i, %if.then
8585
%retval.0.i = bitcast i8* %retval.0.in.i to %0*
8686
ret %0* %retval.0.i
8787
}
88+
89+
90+
; Correctly handle zext returns.
91+
declare zeroext i1 @foo_i1()
92+
93+
; CHECK-LABEL: zext_i1
94+
; CHECK: jmp _foo_i1
95+
define zeroext i1 @zext_i1(i1 %k) {
96+
entry:
97+
br i1 %k, label %land.end, label %land.rhs
98+
99+
land.rhs: ; preds = %entry
100+
%call1 = tail call zeroext i1 @foo_i1()
101+
br label %land.end
102+
103+
land.end: ; preds = %entry, %land.rhs
104+
%0 = phi i1 [ false, %entry ], [ %call1, %land.rhs ]
105+
ret i1 %0
106+
}
107+

0 commit comments

Comments
 (0)