diff --git a/llvm/lib/CodeGen/Analysis.cpp b/llvm/lib/CodeGen/Analysis.cpp index af7643d93591f..e693cdbd0ccc1 100644 --- a/llvm/lib/CodeGen/Analysis.cpp +++ b/llvm/lib/CodeGen/Analysis.cpp @@ -593,9 +593,10 @@ 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. - for (const auto &Attr : {Attribute::Alignment, Attribute::Dereferenceable, - Attribute::DereferenceableOrNull, Attribute::NoAlias, - Attribute::NonNull, Attribute::NoUndef}) { + for (const auto &Attr : + {Attribute::Alignment, Attribute::Dereferenceable, + Attribute::DereferenceableOrNull, Attribute::NoAlias, + Attribute::NonNull, Attribute::NoUndef, Attribute::Range}) { CallerAttrs.removeAttribute(Attr); CalleeAttrs.removeAttribute(Attr); } diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 336d89fbcf638..9ec3ac4f99915 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -62,9 +62,10 @@ bool TargetLowering::isInTailCallPosition(SelectionDAG &DAG, SDNode *Node, // the return. Ignore following attributes because they don't affect the // call sequence. AttrBuilder CallerAttrs(F.getContext(), F.getAttributes().getRetAttrs()); - for (const auto &Attr : {Attribute::Alignment, Attribute::Dereferenceable, - Attribute::DereferenceableOrNull, Attribute::NoAlias, - Attribute::NonNull, Attribute::NoUndef}) + for (const auto &Attr : + {Attribute::Alignment, Attribute::Dereferenceable, + Attribute::DereferenceableOrNull, Attribute::NoAlias, + Attribute::NonNull, Attribute::NoUndef, Attribute::Range}) CallerAttrs.removeAttribute(Attr); if (CallerAttrs.hasAttributes()) diff --git a/llvm/test/CodeGen/X86/tailcall-range.ll b/llvm/test/CodeGen/X86/tailcall-range.ll new file mode 100644 index 0000000000000..6ae7405ebc4a9 --- /dev/null +++ b/llvm/test/CodeGen/X86/tailcall-range.ll @@ -0,0 +1,53 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=x86_64-linux < %s | FileCheck %s + +define range(i32 0, 2) i32 @foo(ptr %this) { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movzbl (%rdi), %eax +; CHECK-NEXT: retq +entry: + %call = load volatile i1, ptr %this, align 1 + %spec.select = zext i1 %call to i32 + ret i32 %spec.select +} + +define range(i32 0, 2) i32 @bar(ptr %this) { +; CHECK-LABEL: bar: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xorl %edi, %edi +; CHECK-NEXT: jmp foo@PLT # TAILCALL +entry: + %ret = musttail call i32 @foo(ptr null) + ret i32 %ret +} + +declare i64 @llvm.llround.f32(float) nounwind readnone +define range(i64 0, 8) i64 @testmsxs(float %x) { +; CHECK-LABEL: testmsxs: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: jmp llroundf@PLT # TAILCALL +entry: + %ret = tail call i64 @llvm.llround.f32(float %x) + ret i64 %ret +} + +declare i32 @callee() + +define range(i32 0, 2) i32 @func_with_range_attr() { +; CHECK-LABEL: func_with_range_attr: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: jmp callee@PLT # TAILCALL +entry: + %ret = musttail call i32 @callee() + ret i32 %ret +} + +define i32 @call_with_range_attr() { +; CHECK-LABEL: call_with_range_attr: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: jmp callee@PLT # TAILCALL +entry: + %ret = musttail call range(i32 0, 2) i32 @callee() + ret i32 %ret +}