weiwang created this revision.
Herald added subscribers: cfe-commits, dexonsmith.
Herald added a project: clang.
weiwang requested review of this revision.

Propagate driver commandline remarks options to link. Pass-through happens when:

1. LTO is enabled;
2. Single arch target is specified;
3. The linker is lld;

This gives novice user a convenient way to collect and filter remarks throughout
a typical toolchain invocation with sample profile and LTO using single switch
from the clang driver.

A typical use of this option from clang command-line:

- Using -Rpass* options to print remarks to screen:

`clang -fuse-ld=lld -flto=thin -fprofile-sample-use=foo_sample.txt

  -Rpass=inline -Rpass-missed=inline -Rpass-analysis=inline
  -fdiagnostics-show-hotness -fdiagnostics-hotness-threshold=100 -o foo foo.cpp`

Remarks will be dumped to screen from both pre-lto and lto compilation.

- Using serialized remarks options

`clang -fuse-ld=lld -flto=thin -fprofile-sample-use=foo_sample.txt

  -fsave-optimization-record
  -fdiagnostics-show-hotness -fdiagnostics-hotness-threshold=100 -o foo foo.cpp`

This will produce multiple yaml files containing optimization remarks:

1. foo.opt.yaml : remarks from pre-lto
2. foo.opt.ld.yaml.thin.1.yaml: remark during lto


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D85810

Files:
  clang/include/clang/Driver/Driver.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChains/CommonArgs.cpp
  clang/test/Driver/remarks-pass-through.c

Index: clang/test/Driver/remarks-pass-through.c
===================================================================
--- /dev/null
+++ clang/test/Driver/remarks-pass-through.c
@@ -0,0 +1,28 @@
+// This test verifies remarks options pass-through into linker(lld)
+
+// no pass-through if lto is disabled
+// RUN: %clang -### -o FOO -fdiagnostics-hotness-threshold=100 -fsave-optimization-record %s 2>&1 | not FileCheck %s
+
+// no pass-through if linker is not lld
+// RUN: %clang -### -o FOO -fuse-ld=gold -fdiagnostics-hotness-threshold=100 -fsave-optimization-record %s 2>&1 | not FileCheck %s
+
+// pass-through cases
+// RUN: %clang -### -o FOO -fuse-ld=lld -flto -fdiagnostics-hotness-threshold=100 -fsave-optimization-record -foptimization-record-passes=inline %s 2>&1 | FileCheck %s
+
+// RUN: %clang -### -o FOO -fuse-ld=lld -flto=thin -fdiagnostics-hotness-threshold=100 -fsave-optimization-record=some-format -foptimization-record-file=FOO.txt %s 2>&1 | FileCheck %s -check-prefix=CHECK-CUSTOM
+//
+// RUN: %clang -### -o FOO -fuse-ld=lld -flto=thin -fdiagnostics-hotness-threshold=100 -Rpass=inline -Rpass-missed=inline -Rpass-analysis=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-RPASS
+//
+// CHECK: "--opt-remarks-filename" "FOO.opt.ld.yaml"
+// CHECK: "--opt-remarks-passes" "inline"
+// CHECK: "--opt-remarks-format" "yaml"
+// CHECK: "--opt-remarks-hotness-threshold=100"
+//
+// CHECK-CUSTOM: "--opt-remarks-filename" "FOO.txt.opt.ld.some-format"
+// CHECK-CUSTOM: "--opt-remarks-format" "some-format"
+// CHECK-CUSTOM: "--opt-remarks-hotness-threshold=100"
+//
+// CHECK-RPASS: "-mllvm" "-pass-remarks=inline"
+// CHECK-RPASS: "-mllvm" "-pass-remarks-missed=inline"
+// CHECK-RPASS: "-mllvm" "-pass-remarks-analysis=inline"
+// CHECK-RPASS: "--opt-remarks-hotness-threshold=100"
Index: clang/lib/Driver/ToolChains/CommonArgs.cpp
===================================================================
--- clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -60,6 +60,95 @@
 using namespace clang;
 using namespace llvm::opt;
 
+// Remarks option pass-through only happens when
+// 1). single arch target
+// 2). linker is lld
+static bool checkRemarksOptions(StringRef LinkerPath, const ArgList &Args,
+                                const llvm::Triple &Triple) {
+  bool hasMultipleArchs =
+      Triple.isOSDarwin() && Args.getAllArgValues(options::OPT_arch).size() > 1;
+
+  bool isLLD = llvm::sys::path::filename(LinkerPath) == "ld.lld" ||
+               llvm::sys::path::stem(LinkerPath) != "ld.lld";
+  if (hasMultipleArchs || !isLLD)
+    return false;
+  return true;
+}
+
+static void renderRpassOptions(const ArgList &Args, ArgStringList &CmdArgs) {
+  if (const Arg *A = Args.getLastArg(options::OPT_Rpass_EQ)) {
+    CmdArgs.push_back("-mllvm");
+    std::string Passes = std::string("-pass-remarks=") + A->getValue();
+    CmdArgs.push_back(Args.MakeArgString(Passes));
+  }
+
+  if (const Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ)) {
+    CmdArgs.push_back("-mllvm");
+    std::string Passes = std::string("-pass-remarks-missed=") + A->getValue();
+    CmdArgs.push_back(Args.MakeArgString(Passes));
+  }
+
+  if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ)) {
+    CmdArgs.push_back("-mllvm");
+    std::string Passes = std::string("-pass-remarks-analysis=") + A->getValue();
+    CmdArgs.push_back(Args.MakeArgString(Passes));
+  }
+}
+
+static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
+                                 const llvm::Triple &Triple,
+                                 const InputInfo &Input,
+                                 const InputInfo &Output) {
+  StringRef Format = "yaml";
+  if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
+    Format = A->getValue();
+
+  CmdArgs.push_back("--opt-remarks-filename");
+
+  SmallString<128> F;
+  const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
+  if (A) {
+    F = A->getValue();
+  } else {
+    if (Output.isFilename())
+      F = Output.getFilename();
+
+    if (F.empty()) {
+      // Use the input filename.
+      F = llvm::sys::path::stem(Input.getBaseInput());
+    }
+  }
+  // Append "opt.ld.<format>" to the end of the file name.
+  SmallString<32> Extension;
+  Extension += ".opt.ld.";
+  Extension += Format;
+
+  CmdArgs.push_back(Args.MakeArgString(F + Extension));
+
+  if (const Arg *A =
+          Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
+    CmdArgs.push_back("--opt-remarks-passes");
+    CmdArgs.push_back(A->getValue());
+  }
+
+  CmdArgs.push_back("--opt-remarks-format");
+  CmdArgs.push_back(Format.data());
+}
+
+static void renderRemarksHotnessOptions(const ArgList &Args,
+                                        ArgStringList &CmdArgs) {
+  if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
+                   options::OPT_fno_diagnostics_show_hotness, false))
+    CmdArgs.push_back("--opt-remarks-with-hotness");
+
+  if (const Arg *A =
+          Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
+    std::string Opt =
+        std::string("--opt-remarks-hotness-threshold=") + A->getValue();
+    CmdArgs.push_back(Args.MakeArgString(Opt));
+  }
+}
+
 void tools::addPathIfExists(const Driver &D, const Twine &Path,
                             ToolChain::path_list &Paths) {
   if (D.getVFS().exists(Path))
@@ -531,6 +620,23 @@
         Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile));
 
   addX86AlignBranchArgs(D, Args, CmdArgs, /*IsLTO=*/true);
+
+  if (checkRemarksOptions(Linker, Args, ToolChain.getEffectiveTriple())) {
+    // handle remark diagnostics on screen options: '-Rpass-*'
+    if (hasRpassOptions(Args)) {
+      renderRpassOptions(Args, CmdArgs);
+    }
+
+    // handle serialized remarks options: '-fsave-optimization-record'
+    // and '-foptimization-record-*'
+    if (willEmitRemarks(Args)) {
+      renderRemarksOptions(Args, CmdArgs, ToolChain.getEffectiveTriple(), Input,
+                           Output);
+    }
+
+    // handle remarks hotness/threshold related options
+    renderRemarksHotnessOptions(Args, CmdArgs);
+  }
 }
 
 void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -5214,3 +5214,19 @@
     return true;
   return false;
 }
+
+bool clang::driver::hasRpassOptions(const ArgList &Args) {
+  // -Rpass=<format> enables it.
+  if (Args.getLastArg(options::OPT_Rpass_EQ))
+    return true;
+
+  // -Rpass-missed=<format> alone enables it too.
+  if (Args.getLastArg(options::OPT_Rpass_missed_EQ))
+    return true;
+
+  // -Rpass-analysis=<format> alone enables it too.
+  if (Args.getLastArg(options::OPT_Rpass_analysis_EQ))
+    return true;
+
+  return false;
+}
Index: clang/include/clang/Driver/Driver.h
===================================================================
--- clang/include/clang/Driver/Driver.h
+++ clang/include/clang/Driver/Driver.h
@@ -632,6 +632,11 @@
 /// \return True if the argument combination will end up generating remarks.
 bool willEmitRemarks(const llvm::opt::ArgList &Args);
 
+/// \return True if the argument combination will end up outputing remarks
+/// onto screen.
+/// This checks for clang specific R-value ('-Rpass-*') group.
+bool hasRpassOptions(const llvm::opt::ArgList &Args);
+
 } // end namespace driver
 } // end namespace clang
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to