|
@@ -525,19 +525,15 @@ bool llvm::isInTailCallPosition(ImmutableCallSite CS, const TargetMachine &TM) {
|
|
F, I, Ret, *TM.getSubtargetImpl(*F)->getTargetLowering());
|
|
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(),
|
|
AttrBuilder CallerAttrs(F->getAttributes(),
|
|
AttributeSet::ReturnIndex);
|
|
AttributeSet::ReturnIndex);
|
|
AttrBuilder CalleeAttrs(cast<CallInst>(I)->getAttributes(),
|
|
AttrBuilder CalleeAttrs(cast<CallInst>(I)->getAttributes(),
|
|
@@ -548,19 +544,18 @@ bool llvm::returnTypeIsEligibleForTailCall(const Function *F,
|
|
CallerAttrs = CallerAttrs.removeAttribute(Attribute::NoAlias);
|
|
CallerAttrs = CallerAttrs.removeAttribute(Attribute::NoAlias);
|
|
CalleeAttrs = CalleeAttrs.removeAttribute(Attribute::NoAlias);
|
|
CalleeAttrs = CalleeAttrs.removeAttribute(Attribute::NoAlias);
|
|
|
|
|
|
- bool AllowDifferingSizes = true;
|
|
|
|
if (CallerAttrs.contains(Attribute::ZExt)) {
|
|
if (CallerAttrs.contains(Attribute::ZExt)) {
|
|
if (!CalleeAttrs.contains(Attribute::ZExt))
|
|
if (!CalleeAttrs.contains(Attribute::ZExt))
|
|
return false;
|
|
return false;
|
|
|
|
|
|
- AllowDifferingSizes = false;
|
|
|
|
|
|
+ ADS = false;
|
|
CallerAttrs.removeAttribute(Attribute::ZExt);
|
|
CallerAttrs.removeAttribute(Attribute::ZExt);
|
|
CalleeAttrs.removeAttribute(Attribute::ZExt);
|
|
CalleeAttrs.removeAttribute(Attribute::ZExt);
|
|
} else if (CallerAttrs.contains(Attribute::SExt)) {
|
|
} else if (CallerAttrs.contains(Attribute::SExt)) {
|
|
if (!CalleeAttrs.contains(Attribute::SExt))
|
|
if (!CalleeAttrs.contains(Attribute::SExt))
|
|
return false;
|
|
return false;
|
|
|
|
|
|
- AllowDifferingSizes = false;
|
|
|
|
|
|
+ ADS = false;
|
|
CallerAttrs.removeAttribute(Attribute::SExt);
|
|
CallerAttrs.removeAttribute(Attribute::SExt);
|
|
CalleeAttrs.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
|
|
// 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
|
|
// (currently only "inreg", but in future who knows). It may be OK but the
|
|
// only safe option is to reject the tail call.
|
|
// 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;
|
|
return false;
|
|
|
|
|
|
const Value *RetVal = Ret->getOperand(0), *CallVal = I;
|
|
const Value *RetVal = Ret->getOperand(0), *CallVal = I;
|