-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[CodeGen] Preserve branch weights from PGO profile during instruction selection at -O0 #161620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
c55f594
6e4ebda
0af0751
67050dd
293b095
a4773d9
b870ddd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
; RUN: llc -mtriple=x86_64-- -O0 -pgo-kind=pgo-sample-use-pipeline -debug-pass=Structure %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=PASSES | ||
; RUN: llc -mtriple=x86_64-- -O0 -pgo-kind=pgo-sample-use-pipeline -debug-only=branch-prob %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=BRANCH_PROB | ||
; RUN: llc -mtriple=x86_64-- -O0 -pgo-kind=pgo-sample-use-pipeline -stop-after=finalize-isel %s -o - | FileCheck %s --check-prefix=MIR | ||
|
||
; REQUIRES: asserts | ||
|
||
; This test verifies that PGO profile information (branch weights) is preserved | ||
; during instruction selection at -O0. | ||
|
||
; Test function with explicit branch weights from PGO. | ||
define i32 @test_pgo_preservation(i32 %x) !prof !15 { | ||
entry: | ||
%cmp = icmp sgt i32 %x, 10 | ||
; This branch has bias: 97 taken vs 3 not taken | ||
br i1 %cmp, label %if.then, label %if.else, !prof !16 | ||
|
||
if.then: | ||
; Hot path - should have high frequency | ||
%add = add nsw i32 %x, 100 | ||
br label %if.end | ||
|
||
if.else: | ||
; Cold path - should have low frequency | ||
%sub = sub nsw i32 %x, 50 | ||
br label %if.end | ||
|
||
if.end: | ||
%result = phi i32 [ %add, %if.then ], [ %sub, %if.else ] | ||
ret i32 %result | ||
} | ||
|
||
; Profile metadata with branch weights 97:3. | ||
!15 = !{!"function_entry_count", i64 100} | ||
!16 = !{!"branch_weights", i32 97, i32 3} | ||
|
||
; Verify that Branch Probability Analysis runs at O0. | ||
; PASSES: Branch Probability Analysis | ||
|
||
; Verify that the branch probabilities reflect the exact profile data. | ||
; BRANCH_PROB: ---- Branch Probability Info : test_pgo_preservation ---- | ||
; BRANCH_PROB: set edge entry -> 0 successor probability to {{.*}} = 97.00% | ||
; BRANCH_PROB: set edge entry -> 1 successor probability to {{.*}} = 3.00% | ||
|
||
; Verify that machine IR preserves the branch probabilities from profile data | ||
; MIR: bb.0.entry: | ||
; MIR-NEXT: successors: %bb.{{[0-9]+}}({{0x03d70a3d|0x7c28f5c3}}), %bb.{{[0-9]+}}({{0x7c28f5c3|0x03d70a3d}}) | ||
; The two successor probability values should be: | ||
; - 0x7c28f5c3: approximately 97% (high probability successor) | ||
; - 0x03d70a3d: approximately 3% (low probability successor) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,6 +44,7 @@ | |
#include "llvm/Support/FileSystem.h" | ||
#include "llvm/Support/FormattedStream.h" | ||
#include "llvm/Support/InitLLVM.h" | ||
#include "llvm/Support/PGOOptions.h" | ||
#include "llvm/Support/PluginLoader.h" | ||
#include "llvm/Support/SourceMgr.h" | ||
#include "llvm/Support/TargetSelect.h" | ||
|
@@ -239,6 +240,38 @@ 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, | ||
SampleUse, | ||
}; | ||
|
||
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(SampleUse, "pgo-sample-use-pipeline", | ||
"Use sampled profile to guide PGO."))); | ||
|
||
// Function to set PGO options on TargetMachine based on command line flags | ||
static void setPGOOptions(TargetMachine &TM) { | ||
std::optional<PGOOptions> PGOOpt; | ||
|
||
switch (PGOKindFlag) { | ||
case SampleUse: | ||
// Use default values for other PGOOptions parameters | ||
|
||
PGOOpt = PGOOptions("", "", "", "", PGOOptions::SampleUse, | ||
PGOOptions::NoCSAction); | ||
break; | ||
case NoPGO: | ||
PGOOpt = std::nullopt; | ||
break; | ||
} | ||
|
||
if (PGOOpt) | ||
TM.setPGOOption(PGOOpt); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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 use a simple flag instead of creating a PGOOption that acts like a boolean switch. In most scenarios, we'd feed cpp source and profile to clang driver, which would set There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 on a simple flag, would it make sense to still use we can pass any of the PGO option.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought it might be useful in the future. There is no way to inject PGOOption into llc. However, there might be logic relying on those parameters in CodeGen in the future that would be easier to test. Maybe I can keep just pgo-kind cmd parameter for now? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with the others. Adding all of this just for a possible future use case seems unreasonable, we can always add more if necessary. Also +1 to using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kept only pgo-kind option with the only value pgo-sample-use-pipeline. |
||
} | ||
|
||
static int compileModule(char **, LLVMContext &); | ||
|
||
[[noreturn]] static void reportError(Twine Msg, StringRef Filename = "") { | ||
|
@@ -554,6 +587,9 @@ static int compileModule(char **argv, LLVMContext &Context) { | |
TheTriple, CPUStr, FeaturesStr, Options, RM, CM, OLvl)); | ||
assert(Target && "Could not allocate target machine!"); | ||
|
||
// Set PGO options based on command line flags | ||
setPGOOptions(*Target); | ||
|
||
return Target->createDataLayout().getStringRepresentation(); | ||
}; | ||
if (InputLanguage == "mir" || | ||
|
@@ -597,6 +633,9 @@ static int compileModule(char **argv, LLVMContext &Context) { | |
TheTriple, CPUStr, FeaturesStr, Options, RM, CM, OLvl)); | ||
assert(Target && "Could not allocate target machine!"); | ||
|
||
// Set PGO options based on command line flags | ||
setPGOOptions(*Target); | ||
|
||
// If we don't have a module then just exit now. We do this down | ||
// here since the CPU/Feature help is underneath the target machine | ||
// creation. | ||
|
Uh oh!
There was an error while loading. Please reload this page.