From e025bc2d09e918e21198d89576a74e1e40679fea Mon Sep 17 00:00:00 2001 From: Bob Haarman Date: Tue, 9 Jul 2019 18:50:55 +0000 Subject: [PATCH] [ThinLTO] only emit used or referenced CFI records to index Summary: We emit CFI_FUNCTION_DEFS and CFI_FUNCTION_DECLS to distributed ThinLTO indices to implement indirect function call checking. This change causes us to only emit entries for functions that are either defined or used by the module we're writing the index for (instead of all functions in the combined index), which can make the indices substantially smaller. Fixes PR42378. Reviewers: pcc, vitalybuka, eugenis Subscribers: mehdi_amini, hiraditya, dexonsmith, arphaman, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63887 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@365537 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Bitcode/Writer/BitcodeWriter.cpp | 30 +++++++--- .../X86/Inputs/cfi-icall-only-bazqux.ll | 24 ++++++++ test/ThinLTO/X86/cfi-icall-only-defuse.ll | 56 +++++++++++++++++++ 3 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 test/ThinLTO/X86/Inputs/cfi-icall-only-bazqux.ll create mode 100644 test/ThinLTO/X86/cfi-icall-only-defuse.ll diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 65b9e0bb6a1..33e28c0ccc5 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -3973,9 +3973,13 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { 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); @@ -4120,20 +4124,30 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { 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/test/ThinLTO/X86/Inputs/cfi-icall-only-bazqux.ll b/test/ThinLTO/X86/Inputs/cfi-icall-only-bazqux.ll new file mode 100644 index 00000000000..06fb015b222 --- /dev/null +++ b/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/test/ThinLTO/X86/cfi-icall-only-defuse.ll b/test/ThinLTO/X86/cfi-icall-only-defuse.ll new file mode 100644 index 00000000000..842468508f5 --- /dev/null +++ b/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: -- 2.50.1