[clang] Add flag fallow-runtime-check-skip-hot-cutoff (#145999)

Co-authored-by: Kazu Hirata <kazu@google.com>
This commit is contained in:
Florian Mayer 2025-06-27 13:46:54 -07:00 committed by GitHub
parent 23be14b222
commit 8d2034cf68
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 59 additions and 5 deletions

View File

@ -399,6 +399,8 @@ public:
/// with extra debug info.
SanitizerSet SanitizeAnnotateDebugInfo;
std::optional<double> AllowRuntimeCheckSkipHotCutoff;
/// List of backend command-line options for -fembed-bitcode.
std::vector<uint8_t> CmdArgs;

View File

@ -2668,6 +2668,15 @@ def fsanitize_skip_hot_cutoff_EQ
} // end -f[no-]sanitize* flags
def fallow_runtime_check_skip_hot_cutoff_EQ
: Joined<["-"], "fallow-runtime-check-skip-hot-cutoff=">,
Group<f_clang_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Exclude __builtin_allow_runtime_check for the top hottest "
"code responsible for the given fraction of PGO counters "
"(0.0 [default] = skip none; 1.0 = skip all). "
"Argument format: <value>">;
def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">,
Group<f_Group>, Visibility<[ClangOption, CC1Option]>,
HelpText<"Allow unsafe floating-point math optimizations which may decrease precision">,

View File

@ -805,17 +805,21 @@ static void addSanitizers(const Triple &TargetTriple,
// SanitizeSkipHotCutoffs: doubles with range [0, 1]
// Opts.cutoffs: unsigned ints with range [0, 1000000]
auto ScaledCutoffs = CodeGenOpts.SanitizeSkipHotCutoffs.getAllScaled(1000000);
uint64_t AllowRuntimeCheckSkipHotCutoff =
CodeGenOpts.AllowRuntimeCheckSkipHotCutoff.value_or(0.0) * 1000000;
// TODO: remove IsRequested()
if (LowerAllowCheckPass::IsRequested() || ScaledCutoffs.has_value()) {
if (LowerAllowCheckPass::IsRequested() || ScaledCutoffs.has_value() ||
CodeGenOpts.AllowRuntimeCheckSkipHotCutoff.has_value()) {
// We want to call it after inline, which is about OptimizerEarlyEPCallback.
PB.registerOptimizerEarlyEPCallback(
[ScaledCutoffs](ModulePassManager &MPM, OptimizationLevel Level,
ThinOrFullLTOPhase Phase) {
[ScaledCutoffs, AllowRuntimeCheckSkipHotCutoff](
ModulePassManager &MPM, OptimizationLevel Level,
ThinOrFullLTOPhase Phase) {
LowerAllowCheckPass::Options Opts;
// TODO: after removing IsRequested(), make this unconditional
if (ScaledCutoffs.has_value())
Opts.cutoffs = ScaledCutoffs.value();
Opts.runtime_check = AllowRuntimeCheckSkipHotCutoff;
MPM.addPass(
createModuleToFunctionPassAdaptor(LowerAllowCheckPass(Opts)));
});

View File

@ -6028,7 +6028,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
// complicated ways.
auto SanitizeArgs = TC.getSanitizerArgs(Args);
Args.AddLastArg(CmdArgs,
options::OPT_fallow_runtime_check_skip_hot_cutoff_EQ);
bool IsAsyncUnwindTablesDefault =
TC.getDefaultUnwindTableLevel(Args) == ToolChain::UnwindTableLevel::Asynchronous;
bool IsSyncUnwindTablesDefault =

View File

@ -1820,6 +1820,11 @@ void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,
for (std::string Sanitizer : Values)
GenerateArg(Consumer, OPT_fsanitize_skip_hot_cutoff_EQ, Sanitizer);
if (Opts.AllowRuntimeCheckSkipHotCutoff) {
GenerateArg(Consumer, OPT_fallow_runtime_check_skip_hot_cutoff_EQ,
std::to_string(*Opts.AllowRuntimeCheckSkipHotCutoff));
}
for (StringRef Sanitizer :
serializeSanitizerKinds(Opts.SanitizeAnnotateDebugInfo))
GenerateArg(Consumer, OPT_fsanitize_annotate_debug_info_EQ, Sanitizer);
@ -2322,6 +2327,18 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Args.getAllArgValues(OPT_fsanitize_annotate_debug_info_EQ), Diags,
Opts.SanitizeAnnotateDebugInfo);
if (StringRef V =
Args.getLastArgValue(OPT_fallow_runtime_check_skip_hot_cutoff_EQ);
!V.empty()) {
double A;
if (V.getAsDouble(A) || A < 0.0 || A > 1.0) {
Diags.Report(diag::err_drv_invalid_value)
<< "-fallow-runtime-check-skip-hot-cutoff=" << V;
} else {
Opts.AllowRuntimeCheckSkipHotCutoff = A;
}
}
Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
if (!LangOpts->CUDAIsDevice)

View File

@ -0,0 +1,15 @@
// RUN: %clang -fallow-runtime-check-skip-hot-cutoff=1.0 -S -emit-llvm %s -o - -O2 | FileCheck --check-prefix=ONE %s
// RUN: %clang -fallow-runtime-check-skip-hot-cutoff=0.0 -S -emit-llvm %s -o - -O2 | FileCheck --check-prefix=ZERO %s
// RUN: not %clang -fallow-runtime-check-skip-hot-cutoff=6.0 -S -emit-llvm %s -o - -O2 2>&1 | FileCheck --check-prefix=SIX %s
// RUN: not %clang -fallow-runtime-check-skip-hot-cutoff=-1.0 -S -emit-llvm %s -o - -O2 2>&1 | FileCheck --check-prefix=MINUSONE %s
// RUN: not %clang -fallow-runtime-check-skip-hot-cutoff=string -S -emit-llvm %s -o - -O2 2>&1 | FileCheck --check-prefix=STRING %s
// ONE: ret i32 0
// ZERO: ret i32 1
// SIX: invalid value '6.0' in '-fallow-runtime-check-skip-hot-cutoff='
// MINUSONE: invalid value '-1.0' in '-fallow-runtime-check-skip-hot-cutoff='
// STRING: invalid value 'string' in '-fallow-runtime-check-skip-hot-cutoff='
int main(int argc, char** argv) {
return __builtin_allow_runtime_check("foo");
}

View File

@ -0,0 +1,6 @@
// RUN: %clang -### -fallow-runtime-check-skip-hot-cutoff=1.0 %s 2>&1 | FileCheck %s
// CHECK: -fallow-runtime-check-skip-hot-cutoff=1.0
int main(int argc, char** argv) {
return __builtin_allow_runtime_check("foo");
}