diff --git a/llvm/lib/CodeGen/Analysis.cpp b/llvm/lib/CodeGen/Analysis.cpp --- a/llvm/lib/CodeGen/Analysis.cpp +++ b/llvm/lib/CodeGen/Analysis.cpp @@ -560,14 +560,12 @@ // 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)) diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -57,18 +57,20 @@ 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. diff --git a/llvm/test/CodeGen/ARM/tail-call.ll b/llvm/test/CodeGen/ARM/tail-call.ll --- a/llvm/test/CodeGen/ARM/tail-call.ll +++ b/llvm/test/CodeGen/ARM/tail-call.ll @@ -99,7 +99,7 @@ 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 @@ %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 +} diff --git a/llvm/test/CodeGen/X86/tail-call-deref.ll b/llvm/test/CodeGen/X86/tail-calls-compatible-attrs.ll rename from llvm/test/CodeGen/X86/tail-call-deref.ll rename to llvm/test/CodeGen/X86/tail-calls-compatible-attrs.ll --- a/llvm/test/CodeGen/X86/tail-call-deref.ll +++ b/llvm/test/CodeGen/X86/tail-calls-compatible-attrs.ll @@ -34,3 +34,19 @@ %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 +}