forked from OSchip/llvm-project
[Analysis] Attribute alignment should not prevent tail call optimization
Fixes tail folding issue mentioned in D100879. Reviewed By: dmgreen Differential Revision: https://reviews.llvm.org/D101230
This commit is contained in:
parent
0eb3299d28
commit
ef2dc7ed9f
|
@ -560,14 +560,12 @@ bool llvm::attributesPermitTailCall(const Function *F, const Instruction *I,
|
|||
|
||||
// Following attributes 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);
|
||||
CallerAttrs.removeAttribute(Attribute::Dereferenceable);
|
||||
CalleeAttrs.removeAttribute(Attribute::Dereferenceable);
|
||||
CallerAttrs.removeAttribute(Attribute::DereferenceableOrNull);
|
||||
CalleeAttrs.removeAttribute(Attribute::DereferenceableOrNull);
|
||||
for (const auto &Attr : {Attribute::Alignment, Attribute::Dereferenceable,
|
||||
Attribute::DereferenceableOrNull, Attribute::NoAlias,
|
||||
Attribute::NonNull}) {
|
||||
CallerAttrs.removeAttribute(Attr);
|
||||
CalleeAttrs.removeAttribute(Attr);
|
||||
}
|
||||
|
||||
if (CallerAttrs.contains(Attribute::ZExt)) {
|
||||
if (!CalleeAttrs.contains(Attribute::ZExt))
|
||||
|
|
|
@ -57,18 +57,20 @@ bool TargetLowering::isInTailCallPosition(SelectionDAG &DAG, SDNode *Node,
|
|||
return false;
|
||||
|
||||
// Conservatively require the attributes of the call to match those of
|
||||
// the return. Ignore NoAlias and NonNull because they don't affect the
|
||||
// the return. Ignore following attributes because they don't affect the
|
||||
// call sequence.
|
||||
AttributeList CallerAttrs = F.getAttributes();
|
||||
if (AttrBuilder(CallerAttrs, AttributeList::ReturnIndex)
|
||||
.removeAttribute(Attribute::NoAlias)
|
||||
.removeAttribute(Attribute::NonNull)
|
||||
.hasAttributes())
|
||||
AttrBuilder CallerAttrs(F.getAttributes(), AttributeList::ReturnIndex);
|
||||
for (const auto &Attr : {Attribute::Alignment, Attribute::Dereferenceable,
|
||||
Attribute::DereferenceableOrNull, Attribute::NoAlias,
|
||||
Attribute::NonNull})
|
||||
CallerAttrs.removeAttribute(Attr);
|
||||
|
||||
if (CallerAttrs.hasAttributes())
|
||||
return false;
|
||||
|
||||
// It's not safe to eliminate the sign / zero extension of the return value.
|
||||
if (CallerAttrs.hasAttribute(AttributeList::ReturnIndex, Attribute::ZExt) ||
|
||||
CallerAttrs.hasAttribute(AttributeList::ReturnIndex, Attribute::SExt))
|
||||
if (CallerAttrs.contains(Attribute::ZExt) ||
|
||||
CallerAttrs.contains(Attribute::SExt))
|
||||
return false;
|
||||
|
||||
// Check if the only use is a function return node.
|
||||
|
|
|
@ -99,7 +99,7 @@ entry:
|
|||
ret void
|
||||
}
|
||||
|
||||
; Check that NonNull attributes don't inhibit tailcalls.
|
||||
; Check that nonnull attributes don't inhibit tailcalls.
|
||||
|
||||
declare nonnull i8* @nonnull_callee(i8* %p, i32 %val)
|
||||
define i8* @nonnull_caller(i8* %p, i32 %val) {
|
||||
|
@ -110,3 +110,28 @@ entry:
|
|||
%call = tail call i8* @nonnull_callee(i8* %p, i32 %val)
|
||||
ret i8* %call
|
||||
}
|
||||
|
||||
; Check that noalias attributes don't inhibit tailcalls.
|
||||
|
||||
declare noalias i8* @noalias_callee(i8* %p, i32 %val)
|
||||
define i8* @noalias_caller(i8* %p, i32 %val) {
|
||||
; CHECK-LABEL: noalias_caller:
|
||||
; CHECK-TAIL: b noalias_callee
|
||||
; CHECK-NO-TAIL: bl noalias_callee
|
||||
entry:
|
||||
%call = tail call i8* @noalias_callee(i8* %p, i32 %val)
|
||||
ret i8* %call
|
||||
}
|
||||
|
||||
|
||||
; Check that alignment attributes don't inhibit tailcalls.
|
||||
|
||||
declare align 8 i8* @align8_callee(i8* %p, i32 %val)
|
||||
define i8* @align8_caller(i8* %p, i32 %val) {
|
||||
; CHECK-LABEL: align8_caller:
|
||||
; CHECK-TAIL: b align8_callee
|
||||
; CHECK-NO-TAIL: bl align8_callee
|
||||
entry:
|
||||
%call = tail call i8* @align8_callee(i8* %p, i32 %val)
|
||||
ret i8* %call
|
||||
}
|
||||
|
|
|
@ -34,3 +34,19 @@ define i8* @test4() nounwind {
|
|||
%ret = tail call dereferenceable_or_null(8) i8* @foo()
|
||||
ret i8* %ret
|
||||
}
|
||||
|
||||
define align 8 i8* @test5() nounwind {
|
||||
; CHECK-LABEL: test5:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: jmp foo # TAILCALL
|
||||
%ret = tail call i8* @foo()
|
||||
ret i8* %ret
|
||||
}
|
||||
|
||||
define i8* @test6() nounwind {
|
||||
; CHECK-LABEL: test6:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: jmp foo # TAILCALL
|
||||
%ret = tail call align 8 i8* @foo()
|
||||
ret i8* %ret
|
||||
}
|
Loading…
Reference in New Issue