diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -3883,7 +3883,8 @@ Flags |= 0x10; Stream.EmitRecord(bitc::FS_FLAGS, ArrayRef{Flags}); - for (const auto &GVI : valueIds()) { + const std::map &ValueIds = valueIds(); + for (const auto &GVI : ValueIds) { Stream.EmitRecord(bitc::FS_VALUE_GUID, ArrayRef{GVI.second, GVI.first}); } @@ -3962,9 +3963,13 @@ NameVals.clear(); }; + std::set DefOrUseGUIDs; forEachSummary([&](GVInfo I, bool IsAliasee) { GlobalValueSummary *S = I.second; assert(S); + DefOrUseGUIDs.insert(I.first); + for (const ValueInfo &VI : S->refs()) + DefOrUseGUIDs.insert(VI.getGUID()); auto ValueId = getValueId(I.first); assert(ValueId); @@ -4105,20 +4110,30 @@ if (!Index.cfiFunctionDefs().empty()) { for (auto &S : Index.cfiFunctionDefs()) { - NameVals.push_back(StrtabBuilder.add(S)); - NameVals.push_back(S.size()); + if (DefOrUseGUIDs.count( + GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(S)))) { + NameVals.push_back(StrtabBuilder.add(S)); + NameVals.push_back(S.size()); + } + } + if (!NameVals.empty()) { + Stream.EmitRecord(bitc::FS_CFI_FUNCTION_DEFS, NameVals); + NameVals.clear(); } - Stream.EmitRecord(bitc::FS_CFI_FUNCTION_DEFS, NameVals); - NameVals.clear(); } if (!Index.cfiFunctionDecls().empty()) { for (auto &S : Index.cfiFunctionDecls()) { - NameVals.push_back(StrtabBuilder.add(S)); - NameVals.push_back(S.size()); + if (DefOrUseGUIDs.count( + GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(S)))) { + NameVals.push_back(StrtabBuilder.add(S)); + NameVals.push_back(S.size()); + } + } + if (!NameVals.empty()) { + Stream.EmitRecord(bitc::FS_CFI_FUNCTION_DECLS, NameVals); + NameVals.clear(); } - Stream.EmitRecord(bitc::FS_CFI_FUNCTION_DECLS, NameVals); - NameVals.clear(); } // Walk the GUIDs that were referenced, and write the diff --git a/llvm/test/ThinLTO/X86/Inputs/cfi-icall-only-bazqux.ll b/llvm/test/ThinLTO/X86/Inputs/cfi-icall-only-bazqux.ll new file mode 100644 --- /dev/null +++ b/llvm/test/ThinLTO/X86/Inputs/cfi-icall-only-bazqux.ll @@ -0,0 +1,24 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare !type !0 i8 @bar(i8*) +declare i1 @llvm.type.test(i8* %ptr, metadata %type) nounwind readnone + +define i8 @baz(i8* %p) !type !0 { + %x = call i1 @llvm.type.test(i8* %p, metadata !"t1") + %1 = select i1 %x, i8 0, i8 3 + ret i8 %1 +} + +define i8 @qux(i8* %p) !type !0 { + %x = call i1 @llvm.type.test(i8* %p, metadata !"t1") + ret i8 4 +} + +define i8 @g(i1 %i, i8* %p) { + %1 = select i1 %i, i8(i8*)* @bar, i8(i8*)* @qux + %2 = call i8 %1(i8* %p) + ret i8 %2 +} + +!0 = !{i64 0, !"t1"} diff --git a/llvm/test/ThinLTO/X86/cfi-icall-only-defuse.ll b/llvm/test/ThinLTO/X86/cfi-icall-only-defuse.ll new file mode 100644 --- /dev/null +++ b/llvm/test/ThinLTO/X86/cfi-icall-only-defuse.ll @@ -0,0 +1,56 @@ +; Verifies that only functions defined or used by each module make it into the +; CFI functions sets in that module's distributed index. +; RUN: opt -thinlto-bc -thinlto-split-lto-unit %s -o %t1.bc +; RUN: opt -thinlto-bc -thinlto-split-lto-unit %S/Inputs/cfi-icall-only-bazqux.ll -o %t2.bc +; RUN: llvm-lto2 run -thinlto-distributed-indexes %t1.bc %t2.bc -o %t.out \ +; RUN: -r %t1.bc,bar,plx \ +; RUN: -r %t1.bc,baz,x \ +; RUN: -r %t1.bc,f,plx \ +; RUN: -r %t1.bc,foo,plx \ +; RUN: -r %t2.bc,bar,x \ +; RUN: -r %t2.bc,baz,plx \ +; RUN: -r %t2.bc,g,plx \ +; RUN: -r %t2.bc,qux,plx +; RUN: llvm-bcanalyzer -dump %t1.bc.thinlto.bc | FileCheck %s --check-prefix=FOOBAZ +; RUN: llvm-bcanalyzer -dump %t2.bc.thinlto.bc | FileCheck %s --check-prefix=BARQUX + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare !type !0 i8 @baz(i8*) +declare i1 @llvm.type.test(i8* %ptr, metadata %type) nounwind readnone + +define i8 @foo(i8* %p) !type !0 { + %x = call i1 @llvm.type.test(i8* %p, metadata !"t1") + %1 = select i1 %x, i8 0, i8 1 + ret i8 %1 +} + +define i8 @bar(i8* %p) !type !0 { + %x = call i1 @llvm.type.test(i8* %p, metadata !"t1") + ret i8 2 +} + +define i8 @f(i1 %i, i8* %p) { + %1 = select i1 %i, i8(i8*)* @foo, i8(i8*)* @baz + %2 = call i8 %1(i8* %p) + ret i8 %2 +} + +!0 = !{i64 0, !"t1"} + +; FOOBAZ: +; FOOBAZ: +; FOOBAZ: +; FOOBAZ: blob data = 'barbazfoot1' +; FOOBAZ-NEXT: + +; BARQUX: +; BARQUX: +; BARQUX: +; BARQUX: blob data = 'barbazquxt1' +; BARQUX-NEXT: