Skip to content

Commit

Permalink
[Analysis] Attribute alignment should not prevent tail call optimization
Browse files Browse the repository at this point in the history
Fixes tail folding issue mentioned in D100879.
Reviewed By: dmgreen
Differential Revision: https://reviews.llvm.org/D101230
  • Loading branch information
davidbolvansky committed Apr 24, 2021
1 parent 0eb3299 commit ef2dc7e
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 17 deletions.
14 changes: 6 additions & 8 deletions llvm/lib/CodeGen/Analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
18 changes: 10 additions & 8 deletions llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
27 changes: 26 additions & 1 deletion llvm/test/CodeGen/ARM/tail-call.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

0 comments on commit ef2dc7e

Please sign in to comment.