iamarchit123 created this revision.
Herald added subscribers: mtrofin, ormris, ChuanqiXu, haicheng, hiraditya.
Herald added a project: All.
iamarchit123 requested review of this revision.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.

Test Plan:


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D132186

Files:
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Basic/CodeGenOptions.h
  clang/include/clang/Basic/DiagnosticDriverKinds.td
  clang/include/clang/Basic/DiagnosticFrontendKinds.td
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/BackendUtil.cpp
  clang/lib/CodeGen/CodeGenAction.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  llvm/include/llvm/Analysis/InlineCost.h
  llvm/include/llvm/IR/DiagnosticInfo.h
  llvm/include/llvm/IR/LLVMContext.h
  llvm/include/llvm/Target/TargetOptions.h
  llvm/lib/Analysis/InlineAdvisor.cpp
  llvm/lib/Analysis/InlineCost.cpp
  llvm/lib/IR/DiagnosticInfo.cpp
  llvm/lib/IR/LLVMContext.cpp
  llvm/lib/IR/LLVMContextImpl.h

Index: llvm/lib/IR/LLVMContextImpl.h
===================================================================
--- llvm/lib/IR/LLVMContextImpl.h
+++ llvm/lib/IR/LLVMContextImpl.h
@@ -1391,6 +1391,11 @@
   Optional<uint32_t> DiagnosticsMisExpectTolerance = 0;
   bool MisExpectWarningRequested = false;
 
+  /// The percentile of hotness of a function
+  //  when emiting MisNoInline diagnostics
+  Optional<uint64_t> DiagnosticsMisNoInlinePercentile = 990000;
+  bool MisNoInlineWarningRequested = false;
+
   /// The specialized remark streamer used by LLVM's OptimizationRemarkEmitter.
   std::unique_ptr<LLVMRemarkStreamer> LLVMRS;
 
Index: llvm/lib/IR/LLVMContext.cpp
===================================================================
--- llvm/lib/IR/LLVMContext.cpp
+++ llvm/lib/IR/LLVMContext.cpp
@@ -155,6 +155,19 @@
   return pImpl->DiagnosticsMisExpectTolerance.value_or(0);
 }
 
+void LLVMContext::setMisNoInlineWarningRequested(bool Requested) {
+  pImpl->MisNoInlineWarningRequested = Requested;
+}
+bool LLVMContext::getMisNoInlineWarningRequested() const {
+  return pImpl->MisNoInlineWarningRequested;
+}
+void LLVMContext::setDiagnosticsMisNoInlinePercentileThreshold(
+    Optional<uint64_t> Count) {
+  pImpl->DiagnosticsMisNoInlinePercentile = Count;
+}
+uint64_t LLVMContext::getDiagnosticsMisNoInlinePercentileThreshold() const {
+  return pImpl->DiagnosticsMisNoInlinePercentile.value_or(0);
+}
 bool LLVMContext::isDiagnosticsHotnessThresholdSetFromPSI() const {
   return !pImpl->DiagnosticsHotnessThreshold.has_value();
 }
Index: llvm/lib/IR/DiagnosticInfo.cpp
===================================================================
--- llvm/lib/IR/DiagnosticInfo.cpp
+++ llvm/lib/IR/DiagnosticInfo.cpp
@@ -404,6 +404,19 @@
   DP << getLocationStr() << ": " << getMsg();
 }
 
+DiagnosticInfoMisNoInline::DiagnosticInfoMisNoInline(const Instruction *Inst,
+                                                     const Function &Fn,
+                                                     Twine &Msg)
+    : DiagnosticInfoWithLocationBase(DK_MisNoInline, DS_Warning,
+                                     *Inst->getParent()->getParent(),
+                                     Inst->getDebugLoc()),
+      Fn(Fn), Msg(Msg) {}
+
+void DiagnosticInfoMisNoInline::print(DiagnosticPrinter &DP) const {
+  DP << "Module"
+     << ": " << getFunction().getParent()->getName() << " " << getMsg();
+}
+
 void OptimizationRemarkAnalysisFPCommute::anchor() {}
 void OptimizationRemarkAnalysisAliasing::anchor() {}
 
Index: llvm/lib/Analysis/InlineCost.cpp
===================================================================
--- llvm/lib/Analysis/InlineCost.cpp
+++ llvm/lib/Analysis/InlineCost.cpp
@@ -2919,33 +2919,29 @@
     return InlineResult::failure("interposable");
 
   // Don't inline functions marked noinline.
-  if (Callee->hasFnAttribute(Attribute::NoInline))
-    return InlineResult::failure("noinline function attribute");
+  if (Callee->hasFnAttribute(Attribute::NoInline)) {
+    auto IR = InlineResult::failure("noinline function attribute");
+    IR.setIsNoInline();
+    return IR;
+  }
 
   // Don't inline call sites marked noinline.
-  if (Call.isNoInline())
-    return InlineResult::failure("noinline call site attribute");
+  if (Call.isNoInline()) {
+    auto IR = InlineResult::failure("noinline call site attribute");
+    IR.setIsNoInline();
+    return IR;
+  }
 
   return None;
 }
 
-InlineCost llvm::getInlineCost(
+InlineCost llvm::isInlineViableFromCostAnalysis(
     CallBase &Call, Function *Callee, const InlineParams &Params,
     TargetTransformInfo &CalleeTTI,
     function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
     function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
     function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
     ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
-
-  auto UserDecision =
-      llvm::getAttributeBasedInliningDecision(Call, Callee, CalleeTTI, GetTLI);
-
-  if (UserDecision) {
-    if (UserDecision->isSuccess())
-      return llvm::InlineCost::getAlways("always inline attribute");
-    return llvm::InlineCost::getNever(UserDecision->getFailureReason());
-  }
-
   LLVM_DEBUG(llvm::dbgs() << "      Analyzing call of " << Callee->getName()
                           << "... (caller:" << Call.getCaller()->getName()
                           << ")\n");
@@ -2976,6 +2972,29 @@
              : InlineCost::getNever(ShouldInline.getFailureReason());
 }
 
+InlineCost llvm::getInlineCost(
+    CallBase &Call, Function *Callee, const InlineParams &Params,
+    TargetTransformInfo &CalleeTTI,
+    function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
+    function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
+    function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
+    ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
+
+  auto UserDecision =
+      llvm::getAttributeBasedInliningDecision(Call, Callee, CalleeTTI, GetTLI);
+  if (UserDecision) {
+    if (UserDecision->isSuccess())
+      return llvm::InlineCost::getAlways("always inline attribute");
+    auto IC = llvm::InlineCost::getNever(UserDecision->getFailureReason());
+    if (UserDecision->isNoInline())
+      IC.setIsNoInline();
+    return IC;
+  }
+  return llvm::isInlineViableFromCostAnalysis(Call, Callee, Params, CalleeTTI,
+                                              GetAssumptionCache, GetTLI,
+                                              GetBFI, PSI, ORE);
+}
+
 InlineResult llvm::isInlineViable(Function &F) {
   bool ReturnsTwice = F.hasFnAttribute(Attribute::ReturnsTwice);
   for (BasicBlock &BB : F) {
Index: llvm/lib/Analysis/InlineAdvisor.cpp
===================================================================
--- llvm/lib/Analysis/InlineAdvisor.cpp
+++ llvm/lib/Analysis/InlineAdvisor.cpp
@@ -28,6 +28,7 @@
 
 using namespace llvm;
 #define DEBUG_TYPE "inline"
+#define DEBUG_TYPE_WARN "misnoinline"
 #ifdef LLVM_HAVE_TF_AOT_INLINERSIZEMODEL
 #define LLVM_HAVE_TF_AOT
 #endif
@@ -61,6 +62,20 @@
                         cl::desc("If true, annotate inline advisor remarks "
                                  "with LTO and pass information."));
 
+// Command line option to enable/disable the warning when profile data suggests
+// a mismatch with the use of the noinline attribute
+static cl::opt<bool> PGOWarnMisNoInline(
+    "pgo-warn-misnoinline", cl::init(false), cl::Hidden,
+    cl::desc("Use this option to turn on/off "
+             "warnings about usage of noinline function attribute "
+             "which may hurt performance."));
+
+// Command line opt option to noinline count threshold
+static cl::opt<unsigned> MisNoInlinePercent(
+    "misnoinline-percent",
+    cl::desc("Prevents emiting diagnostics when function is colder"
+             "that N percentile of total entry counts."));
+
 extern cl::opt<InlinerFunctionImportStatsOpts> InlinerFunctionImportStats;
 
 namespace {
@@ -128,6 +143,64 @@
                                Advisor->getAnnotatedInlinePassName());
 }
 
+static bool canEmitNoInlineWarning(CallBase *CB, InlineCost &IC,
+                                   FunctionAnalysisManager &FAM) {
+  Function &Callee = *CB->getCalledFunction();
+  LLVMContext &Ctx = Callee.getContext();
+  const char *reason = IC.getReason();
+
+  // Check if pass remarks, Wmisnoinline or pgo-warn-misnoinline said anything
+  // about warning
+  if (!OptimizationRemark(DEBUG_TYPE_WARN, "misnoinline", CB).isEnabled() &&
+      !PGOWarnMisNoInline && !Ctx.getMisNoInlineWarningRequested())
+    return false;
+  // If Callee has no profile data bail out
+  if (!Callee.hasProfileData())
+    return false;
+  // Failiure reason is due to noinline callee/call site attribute
+  if (reason == nullptr)
+    return false;
+  if (!IC.isNoInline())
+    return false;
+  uint64_t Percent_Threshold;
+  if (MisNoInlinePercent)
+    Percent_Threshold = MisNoInlinePercent;
+  else
+    Percent_Threshold = Ctx.getDiagnosticsMisNoInlinePercentileThreshold();
+  ProfileSummaryInfo *PSI =
+      FAM.getResult<ModuleAnalysisManagerFunctionProxy>(Callee)
+          .getCachedResult<ProfileSummaryAnalysis>(*Callee.getParent());
+  if (!PSI)
+    return false;
+  BlockFrequencyInfo &CalleeBFI = FAM.getResult<BlockFrequencyAnalysis>(Callee);
+  if (!PSI->isFunctionHotInCallGraphNthPercentile(Percent_Threshold, &Callee,
+                                                  CalleeBFI))
+    return false;
+  // we have checked all conditions we are safe to
+  // check for cost and emit warning
+  return true;
+}
+
+// Emit a noinline diagnostic if:
+// 1. Function entry is hotter than the supplied thrshold in terms of total
+// entry count
+// 2. The noinline function could have been inlined by cost metric. This part is
+// checked when normal inlining fails due to noinline attribute
+static void emitNoInlineWarning(Function *Callee, Function *Caller,
+                                CallBase *CB) {
+  llvm::LLVMContext &Ctx = Caller->getContext();
+  auto RemStr =
+      formatv("Marking {0} noinline while calling in {1} "
+              "may hurt performance as per inline cost/hotness analysis",
+              Callee->getName(), Caller->getName());
+  Twine Msg(RemStr);
+  if (PGOWarnMisNoInline || Ctx.getMisNoInlineWarningRequested())
+    Ctx.diagnose(DiagnosticInfoMisNoInline(CB, *Callee, Msg));
+  OptimizationRemarkEmitter ORE(CB->getParent()->getParent());
+  ORE.emit(OptimizationRemark(DEBUG_TYPE_WARN, "misnoinline", CB)
+           << RemStr.str());
+}
+
 llvm::Optional<llvm::InlineCost> static getDefaultInlineAdvice(
     CallBase &CB, FunctionAnalysisManager &FAM, const InlineParams &Params) {
   Function &Caller = *CB.getCaller();
@@ -153,9 +226,23 @@
     bool RemarksEnabled =
         Callee.getContext().getDiagHandlerPtr()->isMissedOptRemarkEnabled(
             DEBUG_TYPE);
-    return getInlineCost(CB, Params, CalleeTTI, GetAssumptionCache, GetTLI,
-                         GetBFI, PSI, RemarksEnabled ? &ORE : nullptr);
+    InlineCost IC =
+        getInlineCost(CB, Params, CalleeTTI, GetAssumptionCache, GetTLI, GetBFI,
+                      PSI, RemarksEnabled ? &ORE : nullptr);
+    // Check if we should emit a warning for noinline function
+    if (LLVM_UNLIKELY(canEmitNoInlineWarning(&CB, IC, FAM))) {
+      Function &Callee = *CB.getCalledFunction();
+      auto &CalleeTTI = FAM.getResult<TargetIRAnalysis>(Callee);
+      auto TempIC = llvm::isInlineViableFromCostAnalysis(
+          CB, &Callee, Params, CalleeTTI, GetAssumptionCache, GetTLI, GetBFI,
+          PSI);
+
+      if (TempIC.isAlways() || TempIC)
+        emitNoInlineWarning(&Callee, &Caller, &CB);
+    }
+    return IC;
   };
+
   return llvm::shouldInline(
       CB, GetInlineCost, ORE,
       Params.EnableDeferral.value_or(EnableInlineDeferral));
Index: llvm/include/llvm/Target/TargetOptions.h
===================================================================
--- llvm/include/llvm/Target/TargetOptions.h
+++ llvm/include/llvm/Target/TargetOptions.h
@@ -144,7 +144,7 @@
           ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false),
           XRayOmitFunctionIndex(false), DebugStrictDwarf(false),
           Hotpatch(false), PPCGenScalarMASSEntries(false), JMCInstrument(false),
-          EnableCFIFixup(false), MisExpect(false),
+          EnableCFIFixup(false), MisExpect(false), MisNoInline(false),
           FPDenormalMode(DenormalMode::IEEE, DenormalMode::IEEE) {}
 
     /// DisableFramePointerElim - This returns true if frame pointer elimination
@@ -364,6 +364,10 @@
     /// By default, it is set to false
     unsigned MisExpect : 1;
 
+    /// When set to true, enable MisNoInline Diagnostics
+    /// By default, it is set to false
+    unsigned MisNoInline : 1;
+
     /// Name of the stack usage file (i.e., .su file) if user passes
     /// -fstack-usage. If empty, it can be implied that -fstack-usage is not
     /// passed on the command line.
Index: llvm/include/llvm/IR/LLVMContext.h
===================================================================
--- llvm/include/llvm/IR/LLVMContext.h
+++ llvm/include/llvm/IR/LLVMContext.h
@@ -207,6 +207,14 @@
   void setDiagnosticsMisExpectTolerance(Optional<uint32_t> Tolerance);
   uint32_t getDiagnosticsMisExpectTolerance() const;
 
+  /// Return if a code noinline diagnostic needs to be emitted
+  bool getMisNoInlineWarningRequested() const;
+  /// Set noinline diagnostic
+  void setMisNoInlineWarningRequested(bool Requested);
+  // Get/set for NoInline count threshold
+  void
+  setDiagnosticsMisNoInlinePercentileThreshold(Optional<uint64_t> Threshold);
+  uint64_t getDiagnosticsMisNoInlinePercentileThreshold() const;
   /// Return the minimum hotness value a diagnostic would need in order
   /// to be included in optimization diagnostics.
   ///
Index: llvm/include/llvm/IR/DiagnosticInfo.h
===================================================================
--- llvm/include/llvm/IR/DiagnosticInfo.h
+++ llvm/include/llvm/IR/DiagnosticInfo.h
@@ -86,6 +86,7 @@
   DK_SrcMgr,
   DK_DontCall,
   DK_MisExpect,
+  DK_MisNoInline,
   DK_FirstPluginKind // Must be last value to work with
                      // getNextAvailablePluginDiagnosticKind
 };
@@ -397,7 +398,7 @@
 
   /// Return the absolute path tot the file.
   std::string getAbsolutePath() const;
-  
+
   const Function &getFunction() const { return Fn; }
   DiagnosticLocation getLocation() const { return Loc; }
 
@@ -1052,6 +1053,28 @@
   const Twine &Msg;
 };
 
+/// Diagnostic information for MisNoInline analysis.
+/// Diagnostic information for ISel fallback path.
+class DiagnosticInfoMisNoInline : public DiagnosticInfoWithLocationBase {
+  /// The function that is concerned by this diagnostic.
+  /// const Twine &Msg;
+private:
+  const Function &Fn;
+  const Twine &Msg;
+
+public:
+  DiagnosticInfoMisNoInline(const Instruction *Inst, const Function &Fn,
+                            Twine &Msg);
+  const Function &getFunction() const { return Fn; }
+
+  void print(DiagnosticPrinter &DP) const override;
+
+  static bool classof(const DiagnosticInfo *DI) {
+    return DI->getKind() == DK_MisNoInline;
+  }
+  const Twine &getMsg() const { return Msg; }
+};
+
 static DiagnosticSeverity getDiagnosticSeverity(SourceMgr::DiagKind DK) {
   switch (DK) {
   case llvm::SourceMgr::DK_Error:
Index: llvm/include/llvm/Analysis/InlineCost.h
===================================================================
--- llvm/include/llvm/Analysis/InlineCost.h
+++ llvm/include/llvm/Analysis/InlineCost.h
@@ -101,6 +101,8 @@
   /// The cost-benefit pair computed by cost-benefit analysis.
   Optional<CostBenefitPair> CostBenefit = None;
 
+  bool IsNoInline = false;
+
   // Trivial constructor, interesting logic in the factory functions below.
   InlineCost(int Cost, int Threshold, const char *Reason = nullptr,
              Optional<CostBenefitPair> CostBenefit = None)
@@ -159,12 +161,17 @@
   /// Only valid if the cost is of the variable kind. Returns a negative
   /// value if the cost is too high to inline.
   int getCostDelta() const { return Threshold - getCost(); }
+
+  // Set cost is due to function being marked noinline
+  void setIsNoInline() { IsNoInline = true; }
+  bool isNoInline() const { return IsNoInline; }
 };
 
 /// InlineResult is basically true or false. For false results the message
 /// describes a reason.
 class InlineResult {
   const char *Message = nullptr;
+  bool IsNoInline = false;
   InlineResult(const char *Message = nullptr) : Message(Message) {}
 
 public:
@@ -178,6 +185,8 @@
            "getFailureReason should only be called in failure cases");
     return Message;
   }
+  bool isNoInline() const { return IsNoInline; }
+  void setIsNoInline() { IsNoInline = true; }
 };
 
 /// Thresholds to tune inline cost analysis. The inline cost analysis decides
@@ -292,6 +301,16 @@
     CallBase &Call, Function *Callee, TargetTransformInfo &CalleeTTI,
     function_ref<const TargetLibraryInfo &(Function &)> GetTLI);
 
+// Check if a no inline function would have been inlined based on cost decision
+InlineCost isInlineViableFromCostAnalysis(
+    CallBase &Call, Function *Callee, const InlineParams &Params,
+    TargetTransformInfo &CalleeTTI,
+    function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
+    function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
+    function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr,
+    ProfileSummaryInfo *PSI = nullptr,
+    OptimizationRemarkEmitter *ORE = nullptr);
+
 /// Get the cost estimate ignoring thresholds. This is similar to getInlineCost
 /// when passed InlineParams::ComputeFullInlineCost, or a non-null ORE. It
 /// uses default InlineParams otherwise.
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -120,6 +120,14 @@
                                    "Not an integer: %s", Arg.data());
   return Val;
 }
+// Parse misnoinline count value.
+// Valid option values are integers in the range [0, infinity)
+inline Optional<uint64_t> parseCountOption(StringRef Arg) {
+  int64_t Val;
+  if (Arg.getAsInteger(10, Val))
+    return Optional<uint64_t>();
+  return Val;
+}
 
 //===----------------------------------------------------------------------===//
 // Initialization.
@@ -1553,6 +1561,9 @@
   GenerateArg(Args, OPT_fdiagnostics_misexpect_tolerance_EQ,
               Twine(*Opts.DiagnosticsMisExpectTolerance), SA);
 
+  GenerateArg(Args, OPT_fdiagnostics_misnoinline_percentile_EQ,
+              Twine(*Opts.DiagnosticsNoInlinePercentileThreshold), SA);
+
   for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover))
     GenerateArg(Args, OPT_fsanitize_recover_EQ, Sanitizer, SA);
 
@@ -2010,6 +2021,24 @@
     }
   }
 
+  if (auto *arg = Args.getLastArg(
+          options::OPT_fdiagnostics_misnoinline_percentile_EQ)) {
+    auto ResultOrErr = parseCountOption(arg->getValue());
+
+    if (!ResultOrErr) {
+      Diags.Report(diag::err_drv_invalid_diagnotics_misnoinline_threshold)
+          << "-fdiagnostics-misnoinline-percentile-threshold=";
+    } else {
+      Opts.DiagnosticsNoInlinePercentileThreshold = *ResultOrErr;
+      if ((!Opts.DiagnosticsNoInlinePercentileThreshold ||
+           Opts.MisNoInline == 1) &&
+          !UsingProfile) {
+        Diags.Report(diag::warn_drv_diagnostics_misexpect_requires_pgo)
+            << "-fdiagnostics-misnoinline-percentile-threshold=";
+      }
+    }
+  }
+
   // If the user requested to use a sample profile for PGO, then the
   // backend will need to track source location information so the profile
   // can be incorporated into the IR.
@@ -4482,6 +4511,11 @@
         !Diags.isIgnored(diag::warn_profile_data_misexpect, SourceLocation())) {
       Res.getCodeGenOpts().MisExpect = true;
     }
+    if (Warning == "misnoinline" &&
+        !Diags.isIgnored(diag::warn_profile_data_misnoinline,
+                         SourceLocation())) {
+      Res.getCodeGenOpts().MisNoInline = true;
+    }
   }
 
   if (LangOpts.CUDA) {
Index: clang/lib/CodeGen/CodeGenAction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenAction.cpp
+++ clang/lib/CodeGen/CodeGenAction.cpp
@@ -351,6 +351,13 @@
             CodeGenOpts.DiagnosticsMisExpectTolerance);
       }
 
+      if (CodeGenOpts.MisNoInline)
+        Ctx.setMisNoInlineWarningRequested(true);
+
+      if (CodeGenOpts.DiagnosticsNoInlinePercentileThreshold)
+        Ctx.setDiagnosticsMisNoInlinePercentileThreshold(
+            CodeGenOpts.DiagnosticsNoInlinePercentileThreshold);
+
       // Link each LinkModule into our module.
       if (LinkInModules())
         return;
@@ -451,9 +458,10 @@
     void OptimizationFailureHandler(
         const llvm::DiagnosticInfoOptimizationFailure &D);
     void DontCallDiagHandler(const DiagnosticInfoDontCall &D);
-    /// Specialized handler for misexpect warnings.
-    /// Note that misexpect remarks are emitted through ORE
+    /// Specialized handler for misexpect and misnoinline warnings.
+    /// Note that misexpect/misnoinline remarks are emitted through ORE
     void MisExpectDiagHandler(const llvm::DiagnosticInfoMisExpect &D);
+    void MisNoInlineDiagHandler(const llvm::DiagnosticInfoMisNoInline &D);
   };
 
   void BackendConsumer::anchor() {}
@@ -854,6 +862,25 @@
         << Filename << Line << Column;
 }
 
+void BackendConsumer::MisNoInlineDiagHandler(
+    const llvm::DiagnosticInfoMisNoInline &D) {
+  StringRef Filename;
+  unsigned Line, Column;
+  bool BadDebugInfo = false;
+  FullSourceLoc Loc =
+      getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
+  Diags.Report(Loc, diag::warn_profile_data_misnoinline)
+      << D.getFunction().getParent()->getName()
+      << llvm::demangle(D.getFunction().getName().str());
+  if (BadDebugInfo)
+    // If we were not able to translate the file:line:col information
+    // back to a SourceLocation, at least emit a note stating that
+    // we could not translate this location. This can happen in the
+    // case of #line directives.
+    Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
+        << Filename << Line << Column;
+}
+
 /// This function is invoked when the backend needs
 /// to report something to the user.
 void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
@@ -931,6 +958,9 @@
   case llvm::DK_MisExpect:
     MisExpectDiagHandler(cast<DiagnosticInfoMisExpect>(DI));
     return;
+  case llvm::DK_MisNoInline:
+    MisNoInlineDiagHandler(cast<DiagnosticInfoMisNoInline>(DI));
+    return;
   default:
     // Plugin IDs are not bound to any value as they are set dynamically.
     ComputeDiagRemarkID(Severity, backend_plugin, DiagID);
Index: clang/lib/CodeGen/BackendUtil.cpp
===================================================================
--- clang/lib/CodeGen/BackendUtil.cpp
+++ clang/lib/CodeGen/BackendUtil.cpp
@@ -479,7 +479,7 @@
   Options.MCOptions.Argv0 = CodeGenOpts.Argv0;
   Options.MCOptions.CommandLineArgs = CodeGenOpts.CommandLineArgs;
   Options.MisExpect = CodeGenOpts.MisExpect;
-
+  Options.MisNoInline = CodeGenOpts.MisNoInline;
   return true;
 }
 
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1483,6 +1483,9 @@
 def fdiagnostics_misexpect_tolerance_EQ : Joined<["-"], "fdiagnostics-misexpect-tolerance=">,
     Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<value>">,
     HelpText<"Prevent misexpect diagnostics from being output if the profile counts are within N% of the expected. ">;
+def fdiagnostics_misnoinline_percentile_EQ : Joined<["-"], "fdiagnostics-misnoinline-percentile-threshold=">,
+    Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<value>">,
+    HelpText<"Prevent misnoinline diagnostics from being output if the function is colder than N% of total entry counts. ">;
 defm diagnostics_show_option : BoolFOption<"diagnostics-show-option",
     DiagnosticOpts<"ShowOptionNames">, DefaultTrue,
     NegFlag<SetFalse, [CC1Option]>, PosFlag<SetTrue, [], "Print option name with mappable diagnostics">>;
Index: clang/include/clang/Basic/DiagnosticGroups.td
===================================================================
--- clang/include/clang/Basic/DiagnosticGroups.td
+++ clang/include/clang/Basic/DiagnosticGroups.td
@@ -1272,6 +1272,7 @@
 def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">;
 def ProfileInstrUnprofiled : DiagGroup<"profile-instr-unprofiled">;
 def MisExpect : DiagGroup<"misexpect">;
+def MisNoInline : DiagGroup<"misnoinline">;
 
 // AddressSanitizer frontend instrumentation remarks.
 def SanitizeAddressRemarks : DiagGroup<"sanitize-address">;
Index: clang/include/clang/Basic/DiagnosticFrontendKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -320,6 +320,10 @@
   "Annotation was correct on %0 of profiled executions.">,
   BackendInfo,
   InGroup<MisExpect>;
+def warn_profile_data_misnoinline : Warning<
+  "noinline attribute marking for %0:%1 may hurt performance.">,
+  BackendInfo,
+  InGroup<MisNoInline>;
 } // end of instrumentation issue category
 
 }
Index: clang/include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -148,6 +148,8 @@
   "invalid argument in '%0', only integer or 'auto' is supported">;
 def err_drv_invalid_diagnotics_misexpect_tolerance : Error<
   "invalid argument in '%0', only integers are supported">;
+def err_drv_invalid_diagnotics_misnoinline_threshold : Error<
+  "invalid argument in '%0' only integers are supported">;
 def err_drv_missing_argument : Error<
   "argument to '%0' is missing (expected %1 value%s1)">;
 def err_drv_invalid_Xarch_argument_with_args : Error<
Index: clang/include/clang/Basic/CodeGenOptions.h
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.h
+++ clang/include/clang/Basic/CodeGenOptions.h
@@ -426,6 +426,10 @@
   /// values in order to be included in misexpect diagnostics.
   Optional<uint32_t> DiagnosticsMisExpectTolerance = 0;
 
+  /// The minimum function hotness percentile after which we emit
+  /// a warning to be included in misnoinline diagnostics.
+  Optional<uint64_t> DiagnosticsNoInlinePercentileThreshold = 990000;
+
 public:
   // Define accessors/mutators for code generation options of enumeration type.
 #define CODEGENOPT(Name, Bits, Default)
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -182,6 +182,7 @@
                                      ///< enabled.
 CODEGENOPT(NoWarn            , 1, 0) ///< Set when -Wa,--no-warn is enabled.
 CODEGENOPT(MisExpect         , 1, 0) ///< Set when -Wmisexpect is enabled
+CODEGENOPT(MisNoInline       , 1, 0) ///< Set when -Wmisnoinline is enabled
 CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled.
 CODEGENOPT(NoInlineLineTables, 1, 0) ///< Whether debug info should contain
                                      ///< inline line tables.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D132186: Clang add f... Archit Saxena via Phabricator via cfe-commits

Reply via email to