]> granicus.if.org Git - llvm/commitdiff
[ThinLTO] only emit used or referenced CFI records to index
authorBob Haarman <llvm@inglorion.net>
Tue, 9 Jul 2019 18:50:55 +0000 (18:50 +0000)
committerBob Haarman <llvm@inglorion.net>
Tue, 9 Jul 2019 18:50:55 +0000 (18:50 +0000)
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
test/ThinLTO/X86/Inputs/cfi-icall-only-bazqux.ll [new file with mode: 0644]
test/ThinLTO/X86/cfi-icall-only-defuse.ll [new file with mode: 0644]

index 65b9e0bb6a1bc9d9301d5362e46116fc3d51d5f0..33e28c0ccc5c5ddb0b740dde1367795d837da3b7 100644 (file)
@@ -3973,9 +3973,13 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
     NameVals.clear();
   };
 
+  std::set<GlobalValue::GUID> 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 (file)
index 0000000..06fb015
--- /dev/null
@@ -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 (file)
index 0000000..8424685
--- /dev/null
@@ -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:   <GLOBALVAL_SUMMARY_BLOCK
+; FOOBAZ:     <CFI_FUNCTION_DEFS op0=0 op1=3 op2=3 op3=3 op4=6 op5=3/>
+; FOOBAZ:     <TYPE_ID op0=9 op1=2 op2=4 op3=7 op4=0 op5=0 op6=0 op7=0/>
+; FOOBAZ:   </GLOBALVAL_SUMMARY_BLOCK>
+; FOOBAZ:      <STRTAB_BLOCK
+; FOOBAZ-NEXT:   <BLOB abbrevid=4/> blob data = 'barbazfoot1'
+; FOOBAZ-NEXT: </STRTAB_BLOCK>
+
+; BARQUX:   <GLOBALVAL_SUMMARY_BLOCK
+; BARQUX:     <CFI_FUNCTION_DEFS op0=0 op1=3 op2=3 op3=3 op4=6 op5=3/>
+; BARQUX:     <TYPE_ID op0=9 op1=2 op2=4 op3=7 op4=0 op5=0 op6=0 op7=0/>
+; BARQUX:   </GLOBALVAL_SUMMARY_BLOCK>
+; BARQUX:      <STRTAB_BLOCK
+; BARQUX-NEXT:   <BLOB abbrevid=4/> blob data = 'barbazquxt1'
+; BARQUX-NEXT: </STRTAB_BLOCK>