aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/Analysis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/Analysis.cpp')
-rw-r--r--llvm/lib/CodeGen/Analysis.cpp44
1 files changed, 28 insertions, 16 deletions
diff --git a/llvm/lib/CodeGen/Analysis.cpp b/llvm/lib/CodeGen/Analysis.cpp
index ebbcaeb..6582d24 100644
--- a/llvm/lib/CodeGen/Analysis.cpp
+++ b/llvm/lib/CodeGen/Analysis.cpp
@@ -525,19 +525,15 @@ bool llvm::isInTailCallPosition(ImmutableCallSite CS, const TargetMachine &TM) {
F, I, Ret, *TM.getSubtargetImpl(*F)->getTargetLowering());
}
-bool llvm::returnTypeIsEligibleForTailCall(const Function *F,
- const Instruction *I,
- const ReturnInst *Ret,
- const TargetLoweringBase &TLI) {
- // If the block ends with a void return or unreachable, it doesn't matter
- // what the call's return type is.
- if (!Ret || Ret->getNumOperands() == 0) return true;
+bool llvm::attributesPermitTailCall(const Function *F, const Instruction *I,
+ const ReturnInst *Ret,
+ const TargetLoweringBase &TLI,
+ bool *AllowDifferingSizes) {
+ // ADS may be null, so don't write to it directly.
+ bool DummyADS;
+ bool &ADS = AllowDifferingSizes ? *AllowDifferingSizes : DummyADS;
+ ADS = true;
- // If the return value is undef, it doesn't matter what the call's
- // return type is.
- if (isa<UndefValue>(Ret->getOperand(0))) return true;
-
- // Make sure the attributes attached to each return are compatible.
AttrBuilder CallerAttrs(F->getAttributes(),
AttributeSet::ReturnIndex);
AttrBuilder CalleeAttrs(cast<CallInst>(I)->getAttributes(),
@@ -548,19 +544,18 @@ bool llvm::returnTypeIsEligibleForTailCall(const Function *F,
CallerAttrs = CallerAttrs.removeAttribute(Attribute::NoAlias);
CalleeAttrs = CalleeAttrs.removeAttribute(Attribute::NoAlias);
- bool AllowDifferingSizes = true;
if (CallerAttrs.contains(Attribute::ZExt)) {
if (!CalleeAttrs.contains(Attribute::ZExt))
return false;
- AllowDifferingSizes = false;
+ ADS = false;
CallerAttrs.removeAttribute(Attribute::ZExt);
CalleeAttrs.removeAttribute(Attribute::ZExt);
} else if (CallerAttrs.contains(Attribute::SExt)) {
if (!CalleeAttrs.contains(Attribute::SExt))
return false;
- AllowDifferingSizes = false;
+ ADS = false;
CallerAttrs.removeAttribute(Attribute::SExt);
CalleeAttrs.removeAttribute(Attribute::SExt);
}
@@ -568,7 +563,24 @@ bool llvm::returnTypeIsEligibleForTailCall(const Function *F,
// 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.
- if (CallerAttrs != CalleeAttrs)
+ return CallerAttrs == CalleeAttrs;
+}
+
+bool llvm::returnTypeIsEligibleForTailCall(const Function *F,
+ const Instruction *I,
+ const ReturnInst *Ret,
+ const TargetLoweringBase &TLI) {
+ // If the block ends with a void return or unreachable, it doesn't matter
+ // what the call's return type is.
+ if (!Ret || Ret->getNumOperands() == 0) return true;
+
+ // If the return value is undef, it doesn't matter what the call's
+ // return type is.
+ if (isa<UndefValue>(Ret->getOperand(0))) return true;
+
+ // Make sure the attributes attached to each return are compatible.
+ bool AllowDifferingSizes;
+ if (!attributesPermitTailCall(F, I, Ret, TLI, &AllowDifferingSizes))
return false;
const Value *RetVal = Ret->getOperand(0), *CallVal = I;