diff --git a/llvm/lib/Linker/LinkModules.cpp b/llvm/lib/Linker/LinkModules.cpp --- a/llvm/lib/Linker/LinkModules.cpp +++ b/llvm/lib/Linker/LinkModules.cpp @@ -379,6 +379,12 @@ GV.hasAvailableExternallyLinkage())) return false; + // Drop nocallback attribute while linking because it is treated as a hint on + // the module level. + if (auto *F = dyn_cast(&GV)) + if (!F->isIntrinsic()) + F->removeFnAttr(llvm::Attribute::NoCallback); + if (GV.isDeclaration()) return false; diff --git a/llvm/test/Linker/Inputs/drop-attribute.ll b/llvm/test/Linker/Inputs/drop-attribute.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Linker/Inputs/drop-attribute.ll @@ -0,0 +1,4 @@ +define void @test_nocallback_declaration_definition_linked_in() { +entry: + ret void +} diff --git a/llvm/test/Linker/drop-attribute.ll b/llvm/test/Linker/drop-attribute.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Linker/drop-attribute.ll @@ -0,0 +1,33 @@ +; RUN: llvm-link %s %p/Inputs/drop-attribute.ll -S -o - | FileCheck %s + +; Test case that checks that nocallback attribute is dropped during linking. + +; CHECK: define i32 @main() +define i32 @main() { +entry: + call void @test_nocallback_definition() + call float @llvm.sqrt.f32(float undef) + call void @test_nocallback_declaration_definition_not_linked_in() + call void @test_nocallback_declaration_definition_linked_in() + ret i32 0 +} + +; Test that checks that nocallback attribute on a definition is dropped. +; CHECK: define void @test_nocallback_definition() +define void @test_nocallback_definition() nocallback { + ret void +} + +; Test that checks that nocallback attribute on an intrinsic is NOT dropped. +; CHECK: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn +; CHECK-NEXT: declare float @llvm.sqrt.f32(float) #0 +declare float @llvm.sqrt.f32(float) nocallback + +; Test that checks that nocallback attribute on a declaration when a definition is not linked in is dropped. +; CHECK: declare void @test_nocallback_declaration_definition_not_linked_in(){{$}} +declare void @test_nocallback_declaration_definition_not_linked_in() nocallback + +; Test that checks that nocallback attribute on a declaration when a definition is linked in is dropped. +declare void @test_nocallback_declaration_definition_linked_in() nocallback + +; CHECK: define void @test_nocallback_declaration_definition_linked_in()