victorkingi updated this revision to Diff 546819.
victorkingi added a comment.

added test file optimization-remark.f90


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156320/new/

https://reviews.llvm.org/D156320

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Basic/DiagnosticIDs.cpp
  clang/lib/CodeGen/CodeGenAction.cpp
  clang/lib/Driver/ToolChains/Flang.cpp
  flang/include/flang/Frontend/CodeGenOptions.h
  flang/lib/Frontend/CompilerInvocation.cpp
  flang/lib/Frontend/FrontendActions.cpp
  flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
  flang/test/Driver/driver-help-hidden.f90
  flang/test/Driver/driver-help.f90
  flang/test/Driver/optimization-remark.f90
  flang/tools/flang-driver/driver.cpp

Index: flang/tools/flang-driver/driver.cpp
===================================================================
--- flang/tools/flang-driver/driver.cpp
+++ flang/tools/flang-driver/driver.cpp
@@ -30,6 +30,7 @@
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/Host.h"
+#include <clang/Basic/DiagnosticFrontend.h>
 #include <stdlib.h>
 
 using llvm::StringRef;
Index: flang/test/Driver/optimization-remark.f90
===================================================================
--- /dev/null
+++ flang/test/Driver/optimization-remark.f90
@@ -0,0 +1,35 @@
+! This file tests the -Rpass family of flags (-Rpass, -Rpass-missed
+! and -Rpass-analysis)
+! loop-delete isn't enabled at O0 so we use at least O1
+
+! Check that we can override -Rpass= with -Rno-pass.
+! RUN: %flang_fc1 %s -O1 -Rpass=loop-delete -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
+! RUN: %flang_fc1 %s -O1 -Rpass=loop-delete -Rno-pass -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-NO-REMARKS
+! RUN: %flang_fc1 %s -O1 -Rpass=loop-delete -Rno-everything -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-NO-REMARKS
+! RUN: %flang_fc1 %s -O1 -Rpass=loop-delete -Rno-everything -Reverything -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
+
+! -Reverything implies -Rpass=.*.
+! RUN: %flang_fc1 %s -O1 -Reverything -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
+
+! -Rpass implies -Rpass=.*
+! RUN: %flang_fc1 %s -O1 -Rpass -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
+
+! Check full -Rpass message is emitted
+! RUN: %flang %s -O1 -Rpass=loop-delete 2>&1 | FileCheck %s
+
+
+! CHECK: remark: Loop deleted because it is invariant
+! CHECK-REMARKS: remark:
+! CHECK-NO-REMARKS-NOT: remark:
+
+
+program forttest
+    implicit none
+    real, dimension(1:50) :: aR1
+    integer :: n
+
+    do n = 1,50
+        aR1(n) = n * 1
+    end do
+
+end program forttest
Index: flang/test/Driver/driver-help.f90
===================================================================
--- flang/test/Driver/driver-help.f90
+++ flang/test/Driver/driver-help.f90
@@ -87,6 +87,10 @@
 ! HELP-NEXT: -print-effective-triple Print the effective target triple
 ! HELP-NEXT: -print-target-triple    Print the normalized target triple
 ! HELP-NEXT: -P                     Disable linemarker output in -E mode
+! HELP-NEXT: -Rpass-analysis=<value> Report transformation analysis from optimization passes whose name matches the given POSIX regular expression
+! HELP-NEXT: -Rpass-missed=<value>   Report missed transformations by optimization passes whose name matches the given POSIX regular expression
+! HELP-NEXT: -Rpass=<value>          Report transformations performed by optimization passes whose name matches the given POSIX regular expression
+! HELP-NEXT: -R<remark>              Enable the specified remark
 ! HELP-NEXT: -save-temps=<value>    Save intermediate compilation results.
 ! HELP-NEXT: -save-temps            Save intermediate compilation results
 ! HELP-NEXT: -std=<value>           Language standard to compile for
@@ -206,6 +210,10 @@
 ! HELP-FC1-NEXT: -pic-level <value>      Value for __PIC__
 ! HELP-FC1-NEXT: -plugin <name>         Use the named plugin action instead of the default action (use "help" to list available options)
 ! HELP-FC1-NEXT: -P                     Disable linemarker output in -E mode
+! HELP-FC1-NEXT: -Rpass-analysis=<value> Report transformation analysis from optimization passes whose name matches the given POSIX regular expression
+! HELP-FC1-NEXT: -Rpass-missed=<value>   Report missed transformations by optimization passes whose name matches the given POSIX regular expression
+! HELP-FC1-NEXT: -Rpass=<value>          Report transformations performed by optimization passes whose name matches the given POSIX regular expression
+! HELP-FC1-NEXT: -R<remark>              Enable the specified remark
 ! HELP-FC1-NEXT: -save-temps=<value>    Save intermediate compilation results.
 ! HELP-FC1-NEXT: -save-temps            Save intermediate compilation results
 ! HELP-FC1-NEXT: -std=<value>           Language standard to compile for
Index: flang/test/Driver/driver-help-hidden.f90
===================================================================
--- flang/test/Driver/driver-help-hidden.f90
+++ flang/test/Driver/driver-help-hidden.f90
@@ -91,6 +91,10 @@
 ! CHECK-NEXT: -print-effective-triple Print the effective target triple
 ! CHECK-NEXT: -print-target-triple    Print the normalized target triple
 ! CHECK-NEXT: -P                     Disable linemarker output in -E mode
+! CHECK-NEXT: -Rpass-analysis=<value> Report transformation analysis from optimization passes whose name matches the given POSIX regular expression
+! CHECK-NEXT: -Rpass-missed=<value>   Report missed transformations by optimization passes whose name matches the given POSIX regular expression
+! CHECK-NEXT: -Rpass=<value>          Report transformations performed by optimization passes whose name matches the given POSIX regular expression
+! CHECK-NEXT: -R<remark>              Enable the specified remark
 ! CHECK-NEXT: -save-temps=<value>    Save intermediate compilation results.
 ! CHECK-NEXT: -save-temps            Save intermediate compilation results
 ! CHECK-NEXT: -std=<value>           Language standard to compile for
Index: flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
===================================================================
--- flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -27,6 +27,7 @@
 #include "llvm/Option/Option.h"
 #include "llvm/Support/BuryPointer.h"
 #include "llvm/Support/CommandLine.h"
+#include <clang/Basic/DiagnosticFrontend.h>
 
 namespace Fortran::frontend {
 
@@ -100,6 +101,72 @@
   llvm_unreachable("Invalid program action!");
 }
 
+static void EmitUnknownDiagWarning(clang::DiagnosticsEngine &Diags,
+                                   clang::diag::Flavor Flavor,
+                                   llvm::StringRef Prefix,
+                                   llvm::StringRef Opt) {
+  llvm::StringRef Suggestion =
+      clang::DiagnosticIDs::getNearestOption(Flavor, Opt);
+  Diags.Report(clang::diag::warn_unknown_diag_option)
+      << (Flavor == clang::diag::Flavor::WarningOrError ? 0 : 1)
+      << (Prefix.str() += std::string(Opt)) << !Suggestion.empty()
+      << (Prefix.str() += std::string(Suggestion));
+}
+
+static void processWarningOptions(clang::DiagnosticsEngine &Diags,
+                                  const clang::DiagnosticOptions &Opts,
+                                  bool ReportDiags) {
+
+  llvm::SmallVector<clang::diag::kind, 10> _Diags;
+  const llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs =
+      Diags.getDiagnosticIDs();
+  // We parse the warning options twice.  The first pass sets diagnostic state,
+  // while the second pass reports warnings/errors.  This has the effect that
+  // we follow the more canonical "last option wins" paradigm when there are
+  // conflicting options.
+  for (unsigned Report = 0, ReportEnd = 2; Report != ReportEnd; ++Report) {
+    bool SetDiagnostic = (Report == 0);
+
+    // If we've set the diagnostic state and are not reporting diagnostics then
+    // we're done.
+    if (!SetDiagnostic && !ReportDiags)
+      break;
+
+    for (unsigned i = 0, e = Opts.Remarks.size(); i != e; ++i) {
+      llvm::StringRef Opt = Opts.Remarks[i];
+      const auto Flavor = clang::diag::Flavor::Remark;
+
+      // Check to see if this warning starts with "no-", if so, this is a
+      // negative form of the option.
+      bool IsPositive = !Opt.startswith("no-");
+      if (!IsPositive)
+        Opt = Opt.substr(3);
+
+      auto Severity = IsPositive ? clang::diag::Severity::Remark
+                                 : clang::diag::Severity::Ignored;
+
+      // -Reverything sets the state of all remarks. Note that all remarks are
+      // in remark groups, so we don't need a separate 'all remarks enabled'
+      // flag.
+      if (Opt == "everything") {
+        if (SetDiagnostic)
+          Diags.setSeverityForAll(Flavor, Severity);
+        continue;
+      }
+
+      if (Report) {
+        if (DiagIDs->getDiagnosticsInGroup(Flavor, Opt, _Diags))
+          EmitUnknownDiagWarning(Diags, Flavor, IsPositive ? "-R" : "-Rno-",
+                                 Opt);
+      } else {
+        Diags.setSeverityForGroup(Flavor, Opt,
+                                  IsPositive ? clang::diag::Severity::Remark
+                                             : clang::diag::Severity::Ignored);
+      }
+    }
+  }
+}
+
 bool executeCompilerInvocation(CompilerInstance *flang) {
   // Honor -help.
   if (flang->getFrontendOpts().showHelp) {
@@ -166,6 +233,9 @@
   // Honor color diagnostics.
   flang->getDiagnosticOpts().ShowColors = flang->getFrontendOpts().showColors;
 
+  processWarningOptions(flang->getDiagnostics(), flang->getDiagnosticOpts(),
+                        false);
+
   // Create and execute the frontend action.
   std::unique_ptr<FrontendAction> act(createFrontendAction(*flang));
   if (!act)
Index: flang/lib/Frontend/FrontendActions.cpp
===================================================================
--- flang/lib/Frontend/FrontendActions.cpp
+++ flang/lib/Frontend/FrontendActions.cpp
@@ -48,6 +48,8 @@
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Bitcode/BitcodeWriterPass.h"
+#include "llvm/IR/DiagnosticHandler.h"
+#include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/LLVMRemarkStreamer.h"
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Verifier.h"
@@ -67,6 +69,7 @@
 #include "llvm/TargetParser/TargetParser.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <memory>
+#include <string>
 #include <system_error>
 
 using namespace Fortran::frontend;
@@ -923,6 +926,98 @@
   mpm.run(*llvmModule, mam);
 }
 
+class StandaloneBackendConsumer : public llvm::DiagnosticHandler {
+
+  const CodeGenOptions &CodeGenOpts;
+  clang::DiagnosticsEngine &Diags;
+
+public:
+  StandaloneBackendConsumer(clang::DiagnosticsEngine &Diags,
+                            const CodeGenOptions &CodeGenOpts)
+      : CodeGenOpts(CodeGenOpts), Diags(Diags) {}
+
+  bool isAnalysisRemarkEnabled(llvm::StringRef PassName) const override {
+    return CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(PassName);
+  }
+  bool isMissedOptRemarkEnabled(llvm::StringRef PassName) const override {
+    return CodeGenOpts.OptimizationRemarkMissed.patternMatches(PassName);
+  }
+  bool isPassedOptRemarkEnabled(llvm::StringRef PassName) const override {
+    return CodeGenOpts.OptimizationRemark.patternMatches(PassName);
+  }
+
+  bool isAnyRemarkEnabled() const override {
+    return CodeGenOpts.OptimizationRemarkAnalysis.hasValidPattern() ||
+           CodeGenOpts.OptimizationRemarkMissed.hasValidPattern() ||
+           CodeGenOpts.OptimizationRemark.hasValidPattern();
+  }
+
+  void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D,
+                               unsigned DiagID) {
+    // We only support warnings and remarks.
+    assert(D.getSeverity() == llvm::DS_Remark ||
+           D.getSeverity() == llvm::DS_Warning);
+
+    // Render message.
+    std::string Msg;
+    llvm::raw_string_ostream MsgStream(Msg);
+    MsgStream << D.getMsg();
+
+    // Emit message.
+    Diags.Report(DiagID) << clang::AddFlagValue(D.getPassName())
+                         << MsgStream.str();
+  }
+
+  void
+  OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase &D) {
+    if (D.isPassed()) {
+      // Optimization remarks are active only if the -Rpass flag has a regular
+      // expression that matches the name of the pass name in \p D.
+      if (CodeGenOpts.OptimizationRemark.patternMatches(D.getPassName()))
+        EmitOptimizationMessage(
+            D, clang::diag::remark_fe_backend_optimization_remark);
+
+    } else if (D.isMissed()) {
+      // Missed optimization remarks are active only if the -Rpass-missed
+      // flag has a regular expression that matches the name of the pass
+      // name in \p D.
+      if (CodeGenOpts.OptimizationRemarkMissed.patternMatches(D.getPassName()))
+        EmitOptimizationMessage(
+            D, clang::diag::remark_fe_backend_optimization_remark_missed);
+    } else {
+      assert(D.isAnalysis() && "Unknown remark type");
+
+      bool ShouldAlwaysPrint = false;
+      if (auto *ORA = llvm::dyn_cast<llvm::OptimizationRemarkAnalysis>(&D))
+        ShouldAlwaysPrint = ORA->shouldAlwaysPrint();
+
+      if (ShouldAlwaysPrint ||
+          CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(
+              D.getPassName()))
+        EmitOptimizationMessage(
+            D, clang::diag::remark_fe_backend_optimization_remark_analysis);
+    }
+  }
+
+  bool handleDiagnostics(const llvm::DiagnosticInfo &DI) override {
+    switch (DI.getKind()) {
+    case llvm::DK_OptimizationRemark:
+      OptimizationRemarkHandler(llvm::cast<llvm::OptimizationRemark>(DI));
+      break;
+    case llvm::DK_OptimizationRemarkMissed:
+      OptimizationRemarkHandler(llvm::cast<llvm::OptimizationRemarkMissed>(DI));
+      break;
+    case llvm::DK_OptimizationRemarkAnalysis:
+      OptimizationRemarkHandler(
+          llvm::cast<llvm::OptimizationRemarkAnalysis>(DI));
+      break;
+    default:
+      break;
+    }
+    return true;
+  }
+};
+
 void CodeGenAction::embedOffloadObjects() {
   CompilerInstance &ci = this->getInstance();
   const auto &cgOpts = ci.getInvocation().getCodeGenOpts();
@@ -1033,6 +1128,11 @@
   if (!codeGenOpts.OffloadObjects.empty())
     embedOffloadObjects();
 
+  StandaloneBackendConsumer M(diags, codeGenOpts);
+
+  llvmModule->getContext().setDiagnosticHandler(
+      std::make_unique<StandaloneBackendConsumer>(M));
+
   // write optimization-record
   llvm::Expected<std::unique_ptr<llvm::ToolOutputFile>> optRecordFileOrErr =
       setupLLVMOptimizationRemarks(
Index: flang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- flang/lib/Frontend/CompilerInvocation.cpp
+++ flang/lib/Frontend/CompilerInvocation.cpp
@@ -153,6 +153,63 @@
   return true;
 }
 
+/// Parse a remark command line argument. It may be missing, disabled/enabled by
+/// '-R[no-]group' or specified with a regular expression by '-Rgroup=regexp'.
+/// On top of that, it can be disabled/enabled globally by '-R[no-]everything'.
+static CodeGenOptions::OptRemark
+parseOptimizationRemark(clang::DiagnosticsEngine &Diags,
+                        llvm::opt::ArgList &Args, llvm::opt::OptSpecifier OptEQ,
+                        llvm::StringRef Name) {
+  CodeGenOptions::OptRemark Result;
+
+  auto InitializeResultPattern = [&Diags, &Args,
+                                  &Result](const llvm::opt::Arg *A,
+                                           llvm::StringRef Pattern) {
+    Result.Pattern = Pattern.str();
+
+    std::string RegexError;
+    Result.Regex = std::make_shared<llvm::Regex>(Result.Pattern);
+    if (!Result.Regex->isValid(RegexError)) {
+      Diags.Report(clang::diag::err_drv_optimization_remark_pattern)
+          << RegexError << A->getAsString(Args);
+      return false;
+    }
+
+    return true;
+  };
+
+  for (llvm::opt::Arg *A : Args) {
+    if (A->getOption().matches(clang::driver::options::OPT_R_Joined)) {
+      llvm::StringRef Value = A->getValue();
+
+      if (Value == Name)
+        Result.Kind = CodeGenOptions::RK_Enabled;
+      else if (Value == "everything")
+        Result.Kind = CodeGenOptions::RK_EnabledEverything;
+      else if (Value.split('-') == std::make_pair(llvm::StringRef("no"), Name))
+        Result.Kind = CodeGenOptions::RK_Disabled;
+      else if (Value == "no-everything")
+        Result.Kind = CodeGenOptions::RK_DisabledEverything;
+      else
+        continue;
+
+      if (Result.Kind == CodeGenOptions::RK_Disabled ||
+          Result.Kind == CodeGenOptions::RK_DisabledEverything) {
+        Result.Pattern = "";
+        Result.Regex = nullptr;
+      } else {
+        InitializeResultPattern(A, ".*");
+      }
+    } else if (A->getOption().matches(OptEQ)) {
+      Result.Kind = CodeGenOptions::RK_WithPattern;
+      if (!InitializeResultPattern(A, A->getValue()))
+        return CodeGenOptions::OptRemark();
+    }
+  }
+
+  return Result;
+}
+
 static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
                              llvm::opt::ArgList &args,
                              clang::DiagnosticsEngine &diags) {
@@ -194,13 +251,42 @@
           args.getLastArg(clang::driver::options::OPT_opt_record_file))
     opts.OptRecordFile = a->getValue();
 
-  if (const llvm::opt::Arg *a =
-          args.getLastArg(clang::driver::options::OPT_opt_record_format))
-    opts.OptRecordFormat = a->getValue();
+  bool needLocTracking = false;
+
+  if (!opts.OptRecordFile.empty())
+    needLocTracking = true;
 
   if (const llvm::opt::Arg *a =
-          args.getLastArg(clang::driver::options::OPT_opt_record_passes))
+          args.getLastArg(clang::driver::options::OPT_opt_record_passes)) {
     opts.OptRecordPasses = a->getValue();
+    needLocTracking = true;
+  }
+
+  if (const llvm::opt::Arg *a =
+          args.getLastArg(clang::driver::options::OPT_opt_record_format)) {
+    opts.OptRecordFormat = a->getValue();
+    needLocTracking = true;
+  }
+
+  opts.OptimizationRemark = parseOptimizationRemark(
+      diags, args, clang::driver::options::OPT_Rpass_EQ, "pass");
+
+  opts.OptimizationRemarkMissed = parseOptimizationRemark(
+      diags, args, clang::driver::options::OPT_Rpass_missed_EQ, "pass-missed");
+
+  opts.OptimizationRemarkAnalysis = parseOptimizationRemark(
+      diags, args, clang::driver::options::OPT_Rpass_analysis_EQ,
+      "pass-analysis");
+
+  needLocTracking |= opts.OptimizationRemark.hasValidPattern() ||
+                     opts.OptimizationRemarkMissed.hasValidPattern() ||
+                     opts.OptimizationRemarkAnalysis.hasValidPattern();
+
+  // If the user requested a flag that requires source locations available in
+  // the backend, make sure that the backend tracks source location information.
+  if (needLocTracking &&
+      opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo)
+    opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly);
 
   if (auto *a = args.getLastArg(clang::driver::options::OPT_save_temps_EQ))
     opts.SaveTempsDir = a->getValue();
@@ -903,6 +989,28 @@
   return true;
 }
 
+static void addDiagnosticArgs(const llvm::opt::ArgList &Args,
+                              llvm::opt::OptSpecifier Group,
+                              llvm::opt::OptSpecifier GroupWithValue,
+                              std::vector<std::string> &Diagnostics) {
+  for (auto *A : Args.filtered(Group)) {
+    if (A->getOption().getKind() == llvm::opt::Option::FlagClass) {
+      // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
+      // its name (minus the "W" or "R" at the beginning) to the diagnostics.
+      Diagnostics.push_back(
+          std::string(A->getOption().getName().drop_front(1)));
+    } else if (A->getOption().matches(GroupWithValue)) {
+      // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic
+      // group. Add only the group name to the diagnostics.
+      Diagnostics.push_back(
+          std::string(A->getOption().getName().drop_front(1).rtrim("=-")));
+    } else {
+      // Otherwise, add its value (for OPT_W_Joined and similar).
+      Diagnostics.push_back(A->getValue());
+    }
+  }
+}
+
 bool CompilerInvocation::createFromArgs(
     CompilerInvocation &res, llvm::ArrayRef<const char *> commandLineArgs,
     clang::DiagnosticsEngine &diags, const char *argv0) {
@@ -954,6 +1062,10 @@
     res.loweringOpts.setPolymorphicTypeImpl(true);
   }
 
+  addDiagnosticArgs(args, clang::driver::options::OPT_R_Group,
+                    clang::driver::options::OPT_R_value_Group,
+                    res.getDiagnosticOpts().Remarks);
+
   success &= parseFrontendArgs(res.getFrontendOpts(), args, diags);
   parseTargetArgs(res.getTargetOpts(), args);
   parsePreprocessorArgs(res.getPreprocessorOpts(), args);
Index: flang/include/flang/Frontend/CodeGenOptions.h
===================================================================
--- flang/include/flang/Frontend/CodeGenOptions.h
+++ flang/include/flang/Frontend/CodeGenOptions.h
@@ -69,6 +69,53 @@
   /// The format used for serializing remarks (default: YAML)
   std::string OptRecordFormat;
 
+  enum RemarkKind {
+    RK_Missing,            // Remark argument not present on the command line.
+    RK_Enabled,            // Remark enabled via '-Rgroup'.
+    RK_EnabledEverything,  // Remark enabled via '-Reverything'.
+    RK_Disabled,           // Remark disabled via '-Rno-group'.
+    RK_DisabledEverything, // Remark disabled via '-Rno-everything'.
+    RK_WithPattern,        // Remark pattern specified via '-Rgroup=regexp'.
+  };
+
+  /// Optimization remark with an optional regular expression pattern.
+  struct OptRemark {
+    RemarkKind Kind = RK_Missing;
+    std::string Pattern;
+    std::shared_ptr<llvm::Regex> Regex;
+
+    /// By default, optimization remark is missing.
+    OptRemark() = default;
+
+    /// Returns true iff the optimization remark holds a valid regular
+    /// expression.
+    bool hasValidPattern() const { return Regex != nullptr; }
+
+    /// Matches the given string against the regex, if there is some.
+    bool patternMatches(llvm::StringRef String) const {
+      return hasValidPattern() && Regex->match(String);
+    }
+  };
+
+  /// Selected optimizations for which we should enable optimization remarks.
+  /// Transformation passes whose name matches the contained (optional) regular
+  /// expression (and support this feature), will emit a diagnostic whenever
+  /// they perform a transformation.
+  OptRemark OptimizationRemark;
+
+  /// Selected optimizations for which we should enable missed optimization
+  /// remarks. Transformation passes whose name matches the contained (optional)
+  /// regular expression (and support this feature), will emit a diagnostic
+  /// whenever they tried but failed to perform a transformation.
+  OptRemark OptimizationRemarkMissed;
+
+  /// Selected optimizations for which we should enable optimization analyses.
+  /// Transformation passes whose name matches the contained (optional) regular
+  /// expression (and support this feature), will emit a diagnostic whenever
+  /// they want to explain why they decided to apply or not apply a given
+  /// transformation.
+  OptRemark OptimizationRemarkAnalysis;
+
   // Define accessors/mutators for code generation options of enumeration type.
 #define CODEGENOPT(Name, Bits, Default)
 #define ENUM_CODEGENOPT(Name, Type, Bits, Default)                             \
Index: clang/lib/Driver/ToolChains/Flang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Flang.cpp
+++ clang/lib/Driver/ToolChains/Flang.cpp
@@ -516,6 +516,9 @@
   // Add Codegen options
   addCodegenOptions(Args, CmdArgs);
 
+  // -rpass flags
+  Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
+
   // Remarks can be enabled with any of the `-f.*optimization-record.*` flags.
   if (willEmitRemarks(Args))
     renderRemarksOptions(Args, CmdArgs, Input);
Index: clang/lib/CodeGen/CodeGenAction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenAction.cpp
+++ clang/lib/CodeGen/CodeGenAction.cpp
@@ -769,9 +769,7 @@
   if (D.getHotness())
     MsgStream << " (hotness: " << *D.getHotness() << ")";
 
-  Diags.Report(Loc, DiagID)
-      << AddFlagValue(D.getPassName())
-      << MsgStream.str();
+  Diags.Report(Loc, DiagID) << AddFlagValue(D.getPassName()) << MsgStream.str();
 
   if (BadDebugInfo)
     // If we were not able to translate the file:line:col information
Index: clang/lib/Basic/DiagnosticIDs.cpp
===================================================================
--- clang/lib/Basic/DiagnosticIDs.cpp
+++ clang/lib/Basic/DiagnosticIDs.cpp
@@ -771,9 +771,8 @@
   // diagnostics.
   if (Diag.FatalErrorOccurred) {
     if (DiagLevel >= DiagnosticIDs::Error &&
-        Diag.Client->IncludeInDiagnosticCounts()) {
+        Diag.Client->IncludeInDiagnosticCounts())
       ++Diag.NumErrors;
-    }
 
     return false;
   }
@@ -794,9 +793,8 @@
       Diag.UncompilableErrorOccurred = true;
 
     Diag.ErrorOccurred = true;
-    if (Diag.Client->IncludeInDiagnosticCounts()) {
+    if (Diag.Client->IncludeInDiagnosticCounts())
       ++Diag.NumErrors;
-    }
 
     // If we've emitted a lot of errors, emit a fatal error instead of it to
     // stop a flood of bogus errors.
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -806,18 +806,18 @@
 def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[NoXarchOption, CoreOption]>,
   HelpText<"Don't emit warning for unused driver arguments">;
 def Q : Flag<["-"], "Q">, IgnoredGCCCompat;
-def Rpass_EQ : Joined<["-"], "Rpass=">, Group<R_value_Group>, Flags<[CC1Option]>,
+def Rpass_EQ : Joined<["-"], "Rpass=">, Group<R_value_Group>, Flags<[CC1Option, FlangOption, FC1Option]>,
   HelpText<"Report transformations performed by optimization passes whose "
            "name matches the given POSIX regular expression">;
 def Rpass_missed_EQ : Joined<["-"], "Rpass-missed=">, Group<R_value_Group>,
-  Flags<[CC1Option]>,
+  Flags<[CC1Option, FlangOption, FC1Option]>,
   HelpText<"Report missed transformations by optimization passes whose "
            "name matches the given POSIX regular expression">;
 def Rpass_analysis_EQ : Joined<["-"], "Rpass-analysis=">, Group<R_value_Group>,
-  Flags<[CC1Option]>,
+  Flags<[CC1Option, FlangOption, FC1Option]>,
   HelpText<"Report transformation analysis from optimization passes whose "
            "name matches the given POSIX regular expression">;
-def R_Joined : Joined<["-"], "R">, Group<R_Group>, Flags<[CC1Option, CoreOption]>,
+def R_Joined : Joined<["-"], "R">, Group<R_Group>, Flags<[CC1Option, CoreOption, FlangOption, FC1Option]>,
   MetaVarName<"<remark>">, HelpText<"Enable the specified remark">;
 def S : Flag<["-"], "S">, Flags<[NoXarchOption,CC1Option,FlangOption,FC1Option]>, Group<Action_Group>,
   HelpText<"Only run preprocess and compilation steps">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to