[llvm] 8fa16cc - [LTO][lld] Add lto-pgo-warn-mismatch option

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 11 09:46:01 PDT 2021


Author: Yolanda Chen
Date: 2021-08-11T09:45:55-07:00
New Revision: 8fa16cc628cb642798b3c218594cafa7426064e2

URL: https://github.com/llvm/llvm-project/commit/8fa16cc628cb642798b3c218594cafa7426064e2
DIFF: https://github.com/llvm/llvm-project/commit/8fa16cc628cb642798b3c218594cafa7426064e2.diff

LOG: [LTO][lld] Add lto-pgo-warn-mismatch option

When enable CSPGO for ThinLTO, there are profile cfg mismatch warnings that will cause lld-link errors (with /WX)
due to source changes (e.g. `#if` code runs for profile generation but not for profile use)
To disable it we have to use an internal "/mllvm:-no-pgo-warn-mismatch" option.
In contrast clang uses option ”-Wno-backend-plugin“ to avoid such warnings and gcc has an explicit "-Wno-coverage-mismatch" option.

Add "lto-pgo-warn-mismatch" option to lld COFF/ELF to help turn on/off the profile mismatch warnings explicitly when build with ThinLTO and CSPGO.

Differential Revision: https://reviews.llvm.org/D104431

Added: 
    lld/test/COFF/pgo-warn-mismatch.ll
    lld/test/ELF/lto/pgo-warn-mismatch.ll

Modified: 
    lld/COFF/Config.h
    lld/COFF/Driver.cpp
    lld/COFF/LTO.cpp
    lld/COFF/Options.td
    lld/ELF/Config.h
    lld/ELF/Driver.cpp
    lld/ELF/LTO.cpp
    lld/ELF/Options.td
    llvm/include/llvm/LTO/Config.h
    llvm/lib/LTO/CMakeLists.txt
    llvm/lib/LTO/LTOBackend.cpp
    llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp

Removed: 
    


################################################################################
diff  --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index df883b779ee4a..002d128838ce2 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -223,6 +223,9 @@ struct Configuration {
   // Used for /lto-cs-profile-path
   llvm::StringRef ltoCSProfileFile;
 
+  // Used for /lto-pgo-warn-mismatch:
+  bool ltoPGOWarnMismatch = true;
+
   // Used for /call-graph-ordering-file:
   llvm::MapVector<std::pair<const SectionChunk *, const SectionChunk *>,
                   uint64_t>

diff  --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 9ba0db31507f2..5f6bc91c90487 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -1750,6 +1750,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   config->ltoCSProfileGenerate = args.hasArg(OPT_lto_cs_profile_generate);
   config->ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file);
   // Handle miscellaneous boolean flags.
+  config->ltoPGOWarnMismatch = args.hasFlag(OPT_lto_pgo_warn_mismatch,
+                                            OPT_lto_pgo_warn_mismatch_no, true);
   config->allowBind = args.hasFlag(OPT_allowbind, OPT_allowbind_no, true);
   config->allowIsolation =
       args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true);

diff  --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp
index d117abf86f79f..6e38f53f21362 100644
--- a/lld/COFF/LTO.cpp
+++ b/lld/COFF/LTO.cpp
@@ -87,6 +87,7 @@ static lto::Config createConfig() {
   c.DebugPassManager = config->ltoDebugPassManager;
   c.CSIRProfile = std::string(config->ltoCSProfileFile);
   c.RunCSIRInstr = config->ltoCSProfileGenerate;
+  c.PGOWarnMismatch = config->ltoPGOWarnMismatch;
 
   if (config->saveTemps)
     checkError(c.addSaveTemps(std::string(config->outputFile) + ".",

diff  --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index 2ce145520ea89..ce3392ce9dcb1 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -244,6 +244,10 @@ def lto_cs_profile_generate: F<"lto-cs-profile-generate">,
     HelpText<"Perform context sensitive PGO instrumentation">;
 def lto_cs_profile_file : P<"lto-cs-profile-file",
     "Context sensitive profile file path">;
+defm lto_pgo_warn_mismatch: B<
+     "lto-pgo-warn-mismatch",
+     "turn on warnings about profile cfg mismatch (default)>",
+     "turn off warnings about profile cfg mismatch">;
 def dash_dash_version : Flag<["--"], "version">,
   HelpText<"Display the version number and exit">;
 def threads

diff  --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index e1abb4dfab36a..a3d28d57d39a0 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -178,6 +178,7 @@ struct Configuration {
   bool ignoreDataAddressEquality;
   bool ignoreFunctionAddressEquality;
   bool ltoCSProfileGenerate;
+  bool ltoPGOWarnMismatch;
   bool ltoDebugPassManager;
   bool ltoEmitAsm;
   bool ltoNewPassManager;

diff  --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 551a3d3c3bb63..dba6f64963904 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1069,6 +1069,8 @@ static void readConfigs(opt::InputArgList &args) {
   config->ltoAAPipeline = args.getLastArgValue(OPT_lto_aa_pipeline);
   config->ltoCSProfileGenerate = args.hasArg(OPT_lto_cs_profile_generate);
   config->ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file);
+  config->ltoPGOWarnMismatch = args.hasFlag(OPT_lto_pgo_warn_mismatch,
+                                            OPT_no_lto_pgo_warn_mismatch, true);
   config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
   config->ltoEmitAsm = args.hasArg(OPT_lto_emit_asm);
   config->ltoNewPassManager =

diff  --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index e8710e3bdb4ff..1f60e1e8a395c 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -163,6 +163,7 @@ static lto::Config createConfig() {
 
   c.CSIRProfile = std::string(config->ltoCSProfileFile);
   c.RunCSIRInstr = config->ltoCSProfileGenerate;
+  c.PGOWarnMismatch = config->ltoPGOWarnMismatch;
 
   if (config->emitLLVM) {
     c.PostInternalizeModuleHook = [](size_t task, const Module &m) {

diff  --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 9667d859a6b42..b5c1be5c600cb 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -563,6 +563,9 @@ def lto_cs_profile_generate: FF<"lto-cs-profile-generate">,
   HelpText<"Perform context sensitive PGO instrumentation">;
 def lto_cs_profile_file: JJ<"lto-cs-profile-file=">,
   HelpText<"Context sensitive profile file path">;
+defm lto_pgo_warn_mismatch: BB<"lto-pgo-warn-mismatch",
+  "turn on warnings about profile cfg mismatch (default)>",
+  "turn off warnings about profile cfg mismatch">;
 def lto_obj_path_eq: JJ<"lto-obj-path=">;
 def lto_sample_profile: JJ<"lto-sample-profile=">,
   HelpText<"Sample profile file path">;

diff  --git a/lld/test/COFF/pgo-warn-mismatch.ll b/lld/test/COFF/pgo-warn-mismatch.ll
new file mode 100644
index 0000000000000..b2e7ad86e844d
--- /dev/null
+++ b/lld/test/COFF/pgo-warn-mismatch.ll
@@ -0,0 +1,70 @@
+; REQUIRES: x86
+
+; RUN: rm -rf %t && split-file %s %t
+; RUN: opt -module-summary %t/a.ll -o %t/a.bc
+; RUN: llvm-profdata merge %t/cs.proftext -o %t/cs.profdata
+
+; Ensure lld generates warnings for profile cfg mismatch.
+; RUN: lld-link /dll /noentry /export:f /lto-cs-profile-file:%t/cs.profdata /lto-pgo-warn-mismatch /opt:lldlto=2 %t/a.bc /out:%t/a.dll 2>&1 | FileCheck %s
+
+; Ensure lld will not generate warnings for profile cfg mismatch.
+; RUN: lld-link /dll /noentry /export:f /lto-cs-profile-file:%t/cs.profdata /lto-pgo-warn-mismatch:no /opt:lldlto=2 %t/a.bc /out:%t/a.dll 2>&1 | count 0
+
+; CHECK: warning: {{.*}} function control flow change detected (hash mismatch) f Hash = [[#]]
+
+;--- a.ll
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define i32 @f(i32 returned %a) #0 {
+entry:
+  ret i32 %a
+}
+
+attributes #0 = { "target-cpu"="x86-64" }
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10, !11, !12}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 2}
+!5 = !{!"MaxCount", i64 1}
+!6 = !{!"MaxInternalCount", i64 0}
+!7 = !{!"MaxFunctionCount", i64 1}
+!8 = !{!"NumCounts", i64 3}
+!9 = !{!"NumFunctions", i64 2}
+!10 = !{!"IsPartialProfile", i64 0}
+!11 = !{!"PartialProfileRatio", double 0.000000e+00}
+!12 = !{!"DetailedSummary", !13}
+!13 = !{!14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29}
+!14 = !{i32 10000, i64 0, i32 0}
+!15 = !{i32 100000, i64 0, i32 0}
+!16 = !{i32 200000, i64 0, i32 0}
+!17 = !{i32 300000, i64 0, i32 0}
+!18 = !{i32 400000, i64 0, i32 0}
+!19 = !{i32 500000, i64 1, i32 2}
+!20 = !{i32 600000, i64 1, i32 2}
+!21 = !{i32 700000, i64 1, i32 2}
+!22 = !{i32 800000, i64 1, i32 2}
+!23 = !{i32 900000, i64 1, i32 2}
+!24 = !{i32 950000, i64 1, i32 2}
+!25 = !{i32 990000, i64 1, i32 2}
+!26 = !{i32 999000, i64 1, i32 2}
+!27 = !{i32 999900, i64 1, i32 2}
+!28 = !{i32 999990, i64 1, i32 2}
+!29 = !{i32 999999, i64 1, i32 2}
+
+;--- cs.proftext
+# CSIR level Instrumentation Flag
+:csir
+f
+# Func Hash:
+1535914979662757887
+# Num Counters:
+2
+# Counter Values:
+1
+0
+

diff  --git a/lld/test/ELF/lto/pgo-warn-mismatch.ll b/lld/test/ELF/lto/pgo-warn-mismatch.ll
new file mode 100644
index 0000000000000..24d1918c123cf
--- /dev/null
+++ b/lld/test/ELF/lto/pgo-warn-mismatch.ll
@@ -0,0 +1,70 @@
+; REQUIRES: x86
+
+; RUN: rm -rf %t && split-file %s %t
+; RUN: opt -module-summary %t/a.ll -o %t/a.bc
+; RUN: llvm-profdata merge %t/cs.proftext -o %t/cs.profdata
+
+;; Ensure lld generates warnings for profile cfg mismatch.
+; RUN: ld.lld --lto-cs-profile-file=%t/cs.profdata --lto-pgo-warn-mismatch -shared %t/a.bc -o /dev/null 2>&1 | FileCheck %s
+
+;; Ensure lld will not generate warnings for profile cfg mismatch.
+; RUN: ld.lld --lto-cs-profile-file=%t/cs.profdata --no-lto-pgo-warn-mismatch -shared --fatal-warnings %t/a.bc -o /dev/null
+
+; CHECK: warning: {{.*}} function control flow change detected (hash mismatch) f Hash = [[#]]
+
+;--- a.ll
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @f(i32 returned %a) #0 {
+entry:
+  ret i32 %a
+}
+
+attributes #0 = { "target-cpu"="x86-64" }
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10, !11, !12}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 2}
+!5 = !{!"MaxCount", i64 1}
+!6 = !{!"MaxInternalCount", i64 0}
+!7 = !{!"MaxFunctionCount", i64 1}
+!8 = !{!"NumCounts", i64 3}
+!9 = !{!"NumFunctions", i64 2}
+!10 = !{!"IsPartialProfile", i64 0}
+!11 = !{!"PartialProfileRatio", double 0.000000e+00}
+!12 = !{!"DetailedSummary", !13}
+!13 = !{!14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29}
+!14 = !{i32 10000, i64 0, i32 0}
+!15 = !{i32 100000, i64 0, i32 0}
+!16 = !{i32 200000, i64 0, i32 0}
+!17 = !{i32 300000, i64 0, i32 0}
+!18 = !{i32 400000, i64 0, i32 0}
+!19 = !{i32 500000, i64 1, i32 2}
+!20 = !{i32 600000, i64 1, i32 2}
+!21 = !{i32 700000, i64 1, i32 2}
+!22 = !{i32 800000, i64 1, i32 2}
+!23 = !{i32 900000, i64 1, i32 2}
+!24 = !{i32 950000, i64 1, i32 2}
+!25 = !{i32 990000, i64 1, i32 2}
+!26 = !{i32 999000, i64 1, i32 2}
+!27 = !{i32 999900, i64 1, i32 2}
+!28 = !{i32 999990, i64 1, i32 2}
+!29 = !{i32 999999, i64 1, i32 2}
+
+;--- cs.proftext
+# CSIR level Instrumentation Flag
+:csir
+f
+# Func Hash:
+1535914979662757887
+# Num Counters:
+2
+# Counter Values:
+1
+0
+

diff  --git a/llvm/include/llvm/LTO/Config.h b/llvm/include/llvm/LTO/Config.h
index 5fd3c9f408f35..eb793d62907e2 100644
--- a/llvm/include/llvm/LTO/Config.h
+++ b/llvm/include/llvm/LTO/Config.h
@@ -70,6 +70,9 @@ struct Config {
   /// Run PGO context sensitive IR instrumentation.
   bool RunCSIRInstr = false;
 
+  /// Turn on/off the warning about a hash mismatch in the PGO profile data.
+  bool PGOWarnMismatch = true;
+
   /// Asserts whether we can assume whole program visibility during the LTO
   /// link.
   bool HasWholeProgramVisibility = false;

diff  --git a/llvm/lib/LTO/CMakeLists.txt b/llvm/lib/LTO/CMakeLists.txt
index e6adfd43e7f98..824e2e4e84c75 100644
--- a/llvm/lib/LTO/CMakeLists.txt
+++ b/llvm/lib/LTO/CMakeLists.txt
@@ -25,6 +25,7 @@ add_llvm_component_library(LLVMLTO
   Extensions
   IPO
   InstCombine
+  Instrumentation
   Linker
   MC
   ObjCARC

diff  --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 5863ec695df0e..6563af0d6c74b 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -74,6 +74,10 @@ static cl::opt<bool> ThinLTOAssumeMerged(
     cl::desc("Assume the input has already undergone ThinLTO function "
              "importing and the other pre-optimization pipeline changes."));
 
+namespace llvm {
+extern cl::opt<bool> NoPGOWarnMismatch;
+}
+
 [[noreturn]] static void reportOpenError(StringRef Path, Twine Msg) {
   errs() << "failed to open " << Path << ": " << Msg << '\n';
   errs().flush();
@@ -221,6 +225,7 @@ static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM,
     PGOOpt = PGOOptions(Conf.CSIRProfile, "", Conf.ProfileRemapping,
                         PGOOptions::IRUse, PGOOptions::CSIRUse,
                         Conf.AddFSDiscriminator);
+    NoPGOWarnMismatch = !Conf.PGOWarnMismatch;
   } else if (Conf.AddFSDiscriminator) {
     PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction,
                         PGOOptions::NoCSAction, true);

diff  --git a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
index 3d9261eb99ba4..152fff9ffce05 100644
--- a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
+++ b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
@@ -198,12 +198,14 @@ static cl::opt<bool>
                             "warnings about missing profile data for "
                             "functions."));
 
+namespace llvm {
 // Command line option to enable/disable the warning about a hash mismatch in
 // the profile data.
-static cl::opt<bool>
+cl::opt<bool>
     NoPGOWarnMismatch("no-pgo-warn-mismatch", cl::init(false), cl::Hidden,
                       cl::desc("Use this option to turn off/on "
                                "warnings about profile cfg mismatch."));
+} // namespace llvm
 
 // Command line option to enable/disable the warning about a hash mismatch in
 // the profile data for Comdat functions, which often turns out to be false


        


More information about the llvm-commits mailing list