[llvm] [CodeGen] Preserve branch weights from PGO profile during instruction selection at -O0 (PR #161620)

Wei Wang via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 3 10:14:54 PDT 2025


================
@@ -239,6 +240,145 @@ static cl::opt<RunPassOption, true, cl::parser<std::string>> RunPass(
     cl::desc("Run compiler only for specified passes (comma separated list)"),
     cl::value_desc("pass-name"), cl::location(RunPassOpt));
 
+// PGO command line options
+enum PGOKind {
+  NoPGO,
+  InstrGen,
+  InstrUse,
+  SampleUse,
+};
+
+enum CSPGOKind {
+  NoCSPGO,
+  CSInstrGen,
+  CSInstrUse,
+};
+
+static cl::opt<PGOKind>
+    PGOKindFlag("pgo-kind", cl::init(NoPGO), cl::Hidden,
+                cl::desc("The kind of profile guided optimization"),
+                cl::values(clEnumValN(NoPGO, "nopgo", "Do not use PGO."),
+                           clEnumValN(InstrGen, "pgo-instr-gen-pipeline",
+                                      "Instrument the IR to generate profile."),
+                           clEnumValN(InstrUse, "pgo-instr-use-pipeline",
+                                      "Use instrumented profile to guide PGO."),
+                           clEnumValN(SampleUse, "pgo-sample-use-pipeline",
+                                      "Use sampled profile to guide PGO.")));
+
+static cl::opt<std::string>
+    ProfileFile("profile-file", cl::desc("Path to the profile."), cl::Hidden);
+
+static cl::opt<std::string>
+    MemoryProfileFile("memory-profile-file",
+                      cl::desc("Path to the memory profile."), cl::Hidden);
+
+static cl::opt<CSPGOKind> CSPGOKindFlag(
+    "cspgo-kind", cl::init(NoCSPGO), cl::Hidden,
+    cl::desc("The kind of context sensitive profile guided optimization"),
+    cl::values(
+        clEnumValN(NoCSPGO, "nocspgo", "Do not use CSPGO."),
+        clEnumValN(
+            CSInstrGen, "cspgo-instr-gen-pipeline",
+            "Instrument (context sensitive) the IR to generate profile."),
+        clEnumValN(
+            CSInstrUse, "cspgo-instr-use-pipeline",
+            "Use instrumented (context sensitive) profile to guide PGO.")));
+
+static cl::opt<std::string> CSProfileGenFile(
+    "cs-profilegen-file",
+    cl::desc("Path to the instrumented context sensitive profile."),
+    cl::Hidden);
+
+static cl::opt<std::string>
+    ProfileRemappingFile("profile-remapping-file",
+                         cl::desc("Path to the profile remapping file."),
+                         cl::Hidden);
+
+static cl::opt<PGOOptions::ColdFuncOpt> PGOColdFuncAttr(
+    "pgo-cold-func-opt", cl::init(PGOOptions::ColdFuncOpt::Default), cl::Hidden,
+    cl::desc(
+        "Function attribute to apply to cold functions as determined by PGO"),
+    cl::values(clEnumValN(PGOOptions::ColdFuncOpt::Default, "default",
+                          "Default (no attribute)"),
+               clEnumValN(PGOOptions::ColdFuncOpt::OptSize, "optsize",
+                          "Mark cold functions with optsize."),
+               clEnumValN(PGOOptions::ColdFuncOpt::MinSize, "minsize",
+                          "Mark cold functions with minsize."),
+               clEnumValN(PGOOptions::ColdFuncOpt::OptNone, "optnone",
+                          "Mark cold functions with optnone.")));
+
+static cl::opt<bool> DebugInfoForProfiling(
+    "debug-info-for-profiling", cl::init(false), cl::Hidden,
+    cl::desc("Emit special debug info to enable PGO profile generation."));
+
+static cl::opt<bool> PseudoProbeForProfiling(
+    "pseudo-probe-for-profiling", cl::init(false), cl::Hidden,
+    cl::desc("Emit pseudo probes to enable PGO profile generation."));
+
+// Function to set PGO options on TargetMachine based on command line flags
+static void setPGOOptions(TargetMachine &TM) {
+  std::optional<PGOOptions> PGOOpt;
+
+  switch (PGOKindFlag) {
+  case InstrGen:
+    PGOOpt =
+        PGOOptions(ProfileFile, "", "", MemoryProfileFile, PGOOptions::IRInstr,
+                   PGOOptions::NoCSAction, PGOColdFuncAttr);
+    break;
+  case InstrUse:
+    PGOOpt =
+        PGOOptions(ProfileFile, "", ProfileRemappingFile, MemoryProfileFile,
+                   PGOOptions::IRUse, PGOOptions::NoCSAction, PGOColdFuncAttr);
+    break;
+  case SampleUse:
+    PGOOpt = PGOOptions(ProfileFile, "", ProfileRemappingFile,
+                        MemoryProfileFile, PGOOptions::SampleUse,
+                        PGOOptions::NoCSAction, PGOColdFuncAttr);
+    break;
+  case NoPGO:
+    if (DebugInfoForProfiling || PseudoProbeForProfiling ||
+        !MemoryProfileFile.empty())
+      PGOOpt = PGOOptions("", "", "", MemoryProfileFile, PGOOptions::NoAction,
+                          PGOOptions::NoCSAction, PGOColdFuncAttr,
+                          DebugInfoForProfiling, PseudoProbeForProfiling);
+    else
+      PGOOpt = std::nullopt;
+    break;
+  }
+
+  // Handle context-sensitive PGO options
+  if (CSPGOKindFlag != NoCSPGO) {
+    if (PGOOpt && (PGOOpt->Action == PGOOptions::IRInstr ||
+                   PGOOpt->Action == PGOOptions::SampleUse)) {
+      errs() << "CSPGOKind cannot be used with IRInstr or SampleUse";
+      exit(1);
+    }
+    if (CSPGOKindFlag == CSInstrGen) {
+      if (CSProfileGenFile.empty()) {
+        errs() << "CSInstrGen needs to specify CSProfileGenFile";
+        exit(1);
+      }
+      if (PGOOpt) {
+        PGOOpt->CSAction = PGOOptions::CSIRInstr;
+        PGOOpt->CSProfileGenFile = CSProfileGenFile;
+      } else {
+        PGOOpt = PGOOptions("", CSProfileGenFile, ProfileRemappingFile,
+                            /*MemoryProfile=*/"", PGOOptions::NoAction,
+                            PGOOptions::CSIRInstr);
+      }
+    } else /* CSPGOKindFlag == CSInstrUse */ {
+      if (!PGOOpt) {
+        errs() << "CSInstrUse needs to be together with InstrUse";
+        exit(1);
+      }
+      PGOOpt->CSAction = PGOOptions::CSIRUse;
+    }
+  }
+
+  if (PGOOpt)
+    TM.setPGOOption(PGOOpt);
----------------
apolloww wrote:

If the changes here are just to cover the case of directly invoke llc on an IR module with profile information (like the test does), I think we can just use a simple flag instead of creating a PGOOption that acts just like a boolean switch. In most scenarios, we'd feed cpp source and profile to clang driver, which would set `PGOOption` correctly. 

https://github.com/llvm/llvm-project/pull/161620


More information about the llvm-commits mailing list