https://github.com/jdoerfert updated https://github.com/llvm/llvm-project/pull/196234
>From 42f99d61f246b65f5253e10b2b118c62406b174b Mon Sep 17 00:00:00 2001 From: Johannes Doerfert <[email protected]> Date: Mon, 4 May 2026 15:19:00 -0700 Subject: [PATCH] [Instrumentor] Add a global function regexp to limit the instrumentation Only functions that match the "function_regex" will be instrumented, or if they have the instrumentation attribute. --- .../llvm/Transforms/IPO/Instrumentor.h | 8 ++- llvm/lib/Transforms/IPO/Instrumentor.cpp | 22 ++++++- .../Instrumentor/default_config.json | 4 +- .../Instrumentor/function_regex.json | 26 +++++++++ .../Instrumentor/function_regex.ll | 57 +++++++++++++++++++ 5 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 llvm/test/Instrumentation/Instrumentor/function_regex.json create mode 100644 llvm/test/Instrumentation/Instrumentor/function_regex.ll diff --git a/llvm/include/llvm/Transforms/IPO/Instrumentor.h b/llvm/include/llvm/Transforms/IPO/Instrumentor.h index 796104944f7a1..63a37931e98dc 100644 --- a/llvm/include/llvm/Transforms/IPO/Instrumentor.h +++ b/llvm/include/llvm/Transforms/IPO/Instrumentor.h @@ -356,7 +356,12 @@ struct InstrumentationConfig { TargetRegex = BaseConfigurationOption::createStringOption( *this, "target_regex", "Regular expression to be matched against the module target. " - "Only targets that match this regex will be instrumented", + "Only targets that match this regex will be instrumented.", + ""); + FunctionRegex = BaseConfigurationOption::createStringOption( + *this, "function_regex", + "Regular expression to be matched against a function name. " + "Only functions that match this regex will be instrumented.", ""); DemangleFunctionNames = BaseConfigurationOption::createBoolOption( *this, "demangle_function_names", @@ -423,6 +428,7 @@ struct InstrumentationConfig { std::unique_ptr<BaseConfigurationOption> RuntimeStubsFile; std::unique_ptr<BaseConfigurationOption> DemangleFunctionNames; std::unique_ptr<BaseConfigurationOption> TargetRegex; + std::unique_ptr<BaseConfigurationOption> FunctionRegex; std::unique_ptr<BaseConfigurationOption> HostEnabled; std::unique_ptr<BaseConfigurationOption> GPUEnabled; diff --git a/llvm/lib/Transforms/IPO/Instrumentor.cpp b/llvm/lib/Transforms/IPO/Instrumentor.cpp index e42befada5ab2..23fbeb9e7ec33 100644 --- a/llvm/lib/Transforms/IPO/Instrumentor.cpp +++ b/llvm/lib/Transforms/IPO/Instrumentor.cpp @@ -158,6 +158,9 @@ class InstrumentorImpl final { /// The instrumentor configuration. InstrumentationConfig &IConf; + /// The function regex filter, if any. + Regex ParsedFunctionRegex; + /// The underlying module. Module &M; @@ -175,7 +178,7 @@ bool InstrumentorImpl::shouldInstrumentTarget() { bool RegexMatches = true; const auto TargetRegexStr = IConf.TargetRegex->getString(); if (!TargetRegexStr.empty()) { - llvm::Regex TargetRegex(TargetRegexStr); + Regex TargetRegex(TargetRegexStr); std::string ErrMsg; if (!TargetRegex.isValid(ErrMsg)) { IIRB.Ctx.diagnose(DiagnosticInfoInstrumentation( @@ -194,7 +197,11 @@ bool InstrumentorImpl::shouldInstrumentTarget() { bool InstrumentorImpl::shouldInstrumentFunction(Function &Fn) { if (Fn.isDeclaration()) return false; - return !Fn.getName().starts_with(IConf.getRTName()) || + bool RegexMatches = true; + const auto FunctionRegexStr = IConf.FunctionRegex->getString(); + if (!FunctionRegexStr.empty()) + RegexMatches = ParsedFunctionRegex.match(Fn.getName()); + return (RegexMatches && !Fn.getName().starts_with(IConf.getRTName())) || Fn.hasFnAttribute("instrument"); } @@ -279,6 +286,17 @@ bool InstrumentorImpl::instrument() { if (!shouldInstrumentTarget()) return Changed; + const auto FunctionRegexStr = IConf.FunctionRegex->getString(); + if (!FunctionRegexStr.empty()) { + ParsedFunctionRegex = Regex(FunctionRegexStr); + std::string ErrMsg; + if (!ParsedFunctionRegex.isValid(ErrMsg)) { + IIRB.Ctx.diagnose(DiagnosticInfoInstrumentation( + Twine("failed to parse target regex: ") + ErrMsg, DS_Warning)); + return false; + } + } + for (auto &[Name, IO] : IConf.IChoices[InstrumentationLocation::INSTRUCTION_PRE]) if (IO->Enabled) diff --git a/llvm/test/Instrumentation/Instrumentor/default_config.json b/llvm/test/Instrumentation/Instrumentor/default_config.json index 01dd8f8a8f720..c97701d4d84c5 100644 --- a/llvm/test/Instrumentation/Instrumentor/default_config.json +++ b/llvm/test/Instrumentation/Instrumentor/default_config.json @@ -5,7 +5,9 @@ "runtime_stubs_file": "", "runtime_stubs_file.description": "The file into which runtime stubs should be written.", "target_regex": "", - "target_regex.description": "Regular expression to be matched against the module target. Only targets that match this regex will be instrumented", + "target_regex.description": "Regular expression to be matched against the module target. Only targets that match this regex will be instrumented.", + "function_regex": "", + "function_regex.description": "Regular expression to be matched against a function name. Only functions that match this regex will be instrumented.", "demangle_function_names": true, "demangle_function_names.description": "Demangle functions names passed to the runtime.", "host_enabled": true, diff --git a/llvm/test/Instrumentation/Instrumentor/function_regex.json b/llvm/test/Instrumentation/Instrumentor/function_regex.json new file mode 100644 index 0000000000000..91435c73f0f20 --- /dev/null +++ b/llvm/test/Instrumentation/Instrumentor/function_regex.json @@ -0,0 +1,26 @@ +{ + "configuration": { + "runtime_prefix": "__instrumentor_", + "function_regex": "foo|baz" + }, + "instruction_pre": { + "load": { + "enabled": true, + "id": true + }, + "store": { + "enabled": true, + "id": false + } + }, + "instruction_post": { + "load": { + "enabled": true, + "id": true + }, + "store": { + "enabled": true, + "id": true + } + } +} diff --git a/llvm/test/Instrumentation/Instrumentor/function_regex.ll b/llvm/test/Instrumentation/Instrumentor/function_regex.ll new file mode 100644 index 0000000000000..29e28611aa114 --- /dev/null +++ b/llvm/test/Instrumentation/Instrumentor/function_regex.ll @@ -0,0 +1,57 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instrumentor -instrumentor-read-config-file=%S/function_regex.json -S | FileCheck %s + +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + +define i32 @foo() { +; CHECK-LABEL: @foo( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4 +; CHECK-NEXT: call void @__instrumentor_pre_store() #[[ATTR0:[0-9]+]] +; CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4 +; CHECK-NEXT: call void @__instrumentor_post_store(i32 -1) #[[ATTR0]] +; CHECK-NEXT: call void @__instrumentor_pre_load(i32 2) #[[ATTR0]] +; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4 +; CHECK-NEXT: call void @__instrumentor_post_load(i32 -2) #[[ATTR0]] +; CHECK-NEXT: ret i32 [[TMP1]] +; +entry: + %0 = alloca i32, align 4 + store i32 0, ptr %0, align 4 + %2 = load i32, ptr %0, align 4 + ret i32 %2 +} + +define i32 @bar() { +; CHECK-LABEL: @bar( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4 +; CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4 +; CHECK-NEXT: ret i32 [[TMP1]] +; +entry: + %0 = alloca i32, align 4 + store i32 0, ptr %0, align 4 + %2 = load i32, ptr %0, align 4 + ret i32 %2 +} + +define i32 @baz() { +; CHECK-LABEL: @baz( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = alloca i32, align 4 +; CHECK-NEXT: call void @__instrumentor_pre_store() #[[ATTR0]] +; CHECK-NEXT: store i32 0, ptr [[TMP0]], align 4 +; CHECK-NEXT: call void @__instrumentor_post_store(i32 -3) #[[ATTR0]] +; CHECK-NEXT: call void @__instrumentor_pre_load(i32 4) #[[ATTR0]] +; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4 +; CHECK-NEXT: call void @__instrumentor_post_load(i32 -4) #[[ATTR0]] +; CHECK-NEXT: ret i32 [[TMP1]] +; +entry: + %0 = alloca i32, align 4 + store i32 0, ptr %0, align 4 + %2 = load i32, ptr %0, align 4 + ret i32 %2 +} _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
