Skip to content

Commit 5b60312

Browse files
committed
Add llvm-profdata action, support env
Having a real action name for llvm-profdata is helpful for fdo and for coverage. This change makes sure if a toolchain provides env for llvm-profdata, it is correctly used in fdo actions. Fixes #640
1 parent 8a95356 commit 5b60312

8 files changed

Lines changed: 182 additions & 2 deletions

File tree

cc/action_names.bzl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ PREPROCESS_ASSEMBLE_ACTION_NAME = "preprocess-assemble"
5252
# Name of the coverage action.
5353
LLVM_COV = "llvm-cov"
5454

55+
# Name of the profile data merging action.
56+
LLVM_PROFDATA = "llvm-profdata"
57+
5558
# Name of the action producing ThinLto index.
5659
LTO_INDEXING_ACTION_NAME = "lto-indexing"
5760

@@ -126,6 +129,7 @@ ACTION_NAMES = struct(
126129
assemble = ASSEMBLE_ACTION_NAME,
127130
preprocess_assemble = PREPROCESS_ASSEMBLE_ACTION_NAME,
128131
llvm_cov = LLVM_COV,
132+
llvm_profdata = LLVM_PROFDATA,
129133
lto_indexing = LTO_INDEXING_ACTION_NAME,
130134
lto_backend = LTO_BACKEND_ACTION_NAME,
131135
cpp_header_analysis = CPP_HEADER_ANALYSIS_ACTION_NAME,

cc/private/rules_impl/cc_toolchain_provider_helper.bzl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,16 @@ def get_cc_toolchain_provider(ctx, attributes):
184184
)
185185
tool_paths = _compute_tool_paths(toolchain_config_info, tools_directory)
186186
toolchain_features = cc_common.cc_toolchain_features(toolchain_config_info = toolchain_config_info, tools_directory = tools_directory)
187+
feature_configuration = toolchain_features.configure_features(
188+
requested_features = toolchain_features.default_features_and_action_configs(),
189+
)
187190
fdo_context = create_fdo_context(
188191
llvm_profdata = tool_paths.get("llvm-profdata"),
189192
all_files = attributes.all_files,
190193
zipper = attributes.zipper,
191194
cc_toolchain_config_info = toolchain_config_info,
192195
coverage_enabled = ctx.configuration.coverage_enabled,
196+
feature_configuration = feature_configuration,
193197
)
194198
if fdo_context == None:
195199
return None

cc/private/rules_impl/fdo/fdo_context.bzl

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"""FDO context describes how C++ FDO compilation should be done."""
1515

1616
load("@bazel_skylib//lib:paths.bzl", "paths")
17+
load("//cc:action_names.bzl", "ACTION_NAMES")
1718
load("//cc/common:cc_common.bzl", "cc_common")
1819
load("//cc/private/rules_impl/fdo:fdo_prefetch_hints.bzl", "FdoPrefetchHintsInfo")
1920
load("//cc/private/rules_impl/fdo:fdo_profile.bzl", "FdoProfileInfo")
@@ -28,6 +29,7 @@ def _create_fdo_context(
2829
zipper,
2930
cc_toolchain_config_info,
3031
coverage_enabled,
32+
feature_configuration,
3133
_fdo_prefetch_hints,
3234
_propeller_optimize,
3335
_memprof_profile,
@@ -48,6 +50,7 @@ def _create_fdo_context(
4850
zipper: (File) zip tool, used to unpact the profiles
4951
cc_toolchain_config_info: (CcToolchainConfigInfo) Used to check CPU value, should be removed
5052
coverage_enabled: (bool) Is code coverage enabled
53+
feature_configuration: (FeatureConfiguration) Used for llvm-profdata action
5154
_fdo_prefetch_hints: (Target) Pointed to by --fdo_prefetch_hints
5255
_propeller_optimize: (Target) Pointed to by --propeller_optimize
5356
_memprof_profile: (Target) Pointed to by --memprof_profile
@@ -70,6 +73,21 @@ def _create_fdo_context(
7073
if cpp_config.compilation_mode() != "opt":
7174
return struct()
7275

76+
llvm_profdata_env = {}
77+
if cc_common.action_is_enabled(
78+
feature_configuration = feature_configuration,
79+
action_name = ACTION_NAMES.llvm_profdata,
80+
):
81+
llvm_profdata = cc_common.get_tool_for_action(
82+
feature_configuration = feature_configuration,
83+
action_name = ACTION_NAMES.llvm_profdata,
84+
)
85+
llvm_profdata_env = cc_common.get_environment_variables(
86+
feature_configuration = feature_configuration,
87+
action_name = ACTION_NAMES.llvm_profdata,
88+
variables = cc_common.empty_variables(),
89+
)
90+
7391
# Propeller optimize cc and ld profiles
7492
cc_profile = _symlink_to(
7593
ctx,
@@ -186,6 +204,7 @@ def _create_fdo_context(
186204
all_files,
187205
zipper,
188206
cc_toolchain_config_info,
207+
llvm_profdata_env,
189208
)
190209
elif branch_fdo_mode in ["auto_fdo", "xbinary_fdo"]:
191210
profile_artifact = _symlink_input(
@@ -203,6 +222,7 @@ def _create_fdo_context(
203222
all_files,
204223
zipper,
205224
cc_toolchain_config_info,
225+
llvm_profdata_env,
206226
)
207227
cs_profile_artifact = _convert_llvm_raw_profile_to_indexed(
208228
ctx,
@@ -212,6 +232,7 @@ def _create_fdo_context(
212232
all_files,
213233
zipper,
214234
cc_toolchain_config_info,
235+
llvm_profdata_env,
215236
)
216237
profile_artifact = _merge_llvm_profiles(
217238
ctx,
@@ -221,6 +242,7 @@ def _create_fdo_context(
221242
non_cs_profile_artifact,
222243
cs_profile_artifact,
223244
"MergedCS.profdata",
245+
llvm_profdata_env,
224246
)
225247

226248
branch_fdo_profile = struct(
@@ -254,7 +276,8 @@ def _convert_llvm_raw_profile_to_indexed(
254276
llvm_profdata,
255277
all_files,
256278
zipper,
257-
cc_toolchain_config_info):
279+
cc_toolchain_config_info,
280+
env):
258281
"""This function checks the input profile format and converts it to the indexed format (.profdata) if necessary."""
259282
basename = _basename(fdo_inputs)
260283
if basename.endswith(".profdata"):
@@ -310,6 +333,7 @@ def _convert_llvm_raw_profile_to_indexed(
310333
arguments = [ctx.actions.args().add("merge").add("-o").add(profile_artifact).add(raw_profile_artifact)],
311334
inputs = [raw_profile_artifact],
312335
outputs = [profile_artifact],
336+
env = env,
313337
use_default_shell_env = True,
314338
progress_message = "LLVMProfDataAction: Generating %{output}",
315339
)
@@ -323,7 +347,8 @@ def _merge_llvm_profiles(
323347
all_files,
324348
profile1,
325349
profile2,
326-
merged_output_name):
350+
merged_output_name,
351+
env):
327352
"""This function merges profile1 and profile2 and generates merged_output."""
328353
profile_artifact = ctx.actions.declare_file(name_prefix + "/" + ctx.label.name + "/" + merged_output_name)
329354

@@ -335,6 +360,7 @@ def _merge_llvm_profiles(
335360
arguments = [ctx.actions.args().add("merge").add("-o").add(profile_artifact).add(profile1).add(profile2)],
336361
inputs = [profile1, profile2],
337362
outputs = [profile_artifact],
363+
env = env,
338364
use_default_shell_env = True,
339365
progress_message = "LLVMProfDataAction: Generating %{output}",
340366
)

cc/toolchains/actions/BUILD

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ cc_action_type(
8888
action_name = ACTION_NAMES.llvm_cov,
8989
)
9090

91+
cc_action_type(
92+
name = "llvm_profdata",
93+
action_name = ACTION_NAMES.llvm_profdata,
94+
)
95+
9196
cc_action_type(
9297
name = "lto_indexing",
9398
action_name = ACTION_NAMES.lto_indexing,
@@ -324,6 +329,7 @@ cc_action_type_set(
324329
":assemble",
325330
":preprocess_assemble",
326331
":llvm_cov",
332+
":llvm_profdata",
327333
":lto_indexing",
328334
":lto_backend",
329335
":lto_index_for_executable",

tests/cc/common/BUILD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
load(":cc_binary_configured_target_tests.bzl", "cc_binary_configured_target_tests")
22
load(":cc_common_test.bzl", "cc_common_tests")
3+
load(":cc_fdo_env_test.bzl", "cc_fdo_env_tests")
34

45
cc_binary_configured_target_tests(name = "cc_binary_configured_target_tests")
56

67
cc_common_tests(name = "cc_common_tests")
8+
9+
cc_fdo_env_tests(name = "cc_fdo_env_tests")
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
"""Tests for FDO action environment variables."""
2+
3+
load("@bazel_features//private:util.bzl", _bazel_version_ge = "ge")
4+
load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite")
5+
load("@rules_testing//lib:util.bzl", "TestingAspectInfo")
6+
load("//cc:action_names.bzl", "ACTION_NAMES")
7+
load("//cc/toolchains:fdo_profile.bzl", "fdo_profile")
8+
load("//tests/cc/testutil/toolchains:features.bzl", "FEATURE_NAMES")
9+
10+
def _test_fdo_profdata_env(name, **kwargs):
11+
native.genrule(
12+
name = name + "_profraw",
13+
outs = [name + "/profile.profraw"],
14+
cmd = "touch $@",
15+
)
16+
17+
fdo_profile(
18+
name = name + "_profile",
19+
profile = name + "_profraw",
20+
)
21+
22+
analysis_test(
23+
name = name,
24+
impl = _test_fdo_profdata_env_impl,
25+
target = "//tests/cc/testutil/toolchains:cc-compiler-k8-compiler",
26+
config_settings = _fdo_config_settings(name),
27+
**kwargs
28+
)
29+
30+
def _fdo_config_settings(name):
31+
return {
32+
str(Label("//tests/cc/testutil/toolchains:with_features")): [
33+
FEATURE_NAMES.fdo_optimize,
34+
FEATURE_NAMES.llvm_profdata_env,
35+
],
36+
str(Label("//tests/cc/testutil/toolchains:with_action_configs")): [
37+
ACTION_NAMES.llvm_profdata,
38+
],
39+
"//command_line_option:fdo_optimize": "//tests/cc/common:" + name + "_profile",
40+
"//command_line_option:compilation_mode": "opt",
41+
}
42+
43+
def _assert_profdata_env(env, target, expected_mnemonics):
44+
profdata_actions = []
45+
seen_mnemonics = {}
46+
for action in target[TestingAspectInfo].actions:
47+
if action.mnemonic in expected_mnemonics:
48+
profdata_actions.append(action)
49+
seen_mnemonics[action.mnemonic] = True
50+
51+
env.expect.that_collection(seen_mnemonics.keys()).contains_at_least(expected_mnemonics)
52+
for action in profdata_actions:
53+
env.expect.where(
54+
detail = "mnemonic: %s" % action.mnemonic,
55+
).that_dict(action.env).contains_at_least({"LLVM_PROFDATA_ENV_KEY": "LLVM_PROFDATA_ENV_VALUE"})
56+
57+
env.expect.where(
58+
detail = "mnemonic: %s" % action.mnemonic,
59+
).that_dict(action.env).keys().contains("PATH")
60+
61+
def _test_fdo_profdata_env_impl(env, target):
62+
_assert_profdata_env(env, target, ["LLVMProfDataAction"])
63+
64+
def _test_csfdo_profdata_merge_env(name, **kwargs):
65+
"""Tests that LLVMProfDataMergeAction gets env vars from the feature configuration.
66+
67+
CS-FDO requires both --fdo_optimize and --cs_fdo_profile, triggering a merge action.
68+
"""
69+
native.genrule(
70+
name = name + "_profraw",
71+
outs = [name + "/profile.profraw"],
72+
cmd = "touch $@",
73+
)
74+
75+
fdo_profile(
76+
name = name + "_profile",
77+
profile = name + "_profraw",
78+
)
79+
80+
config = _fdo_config_settings(name)
81+
config["//command_line_option:cs_fdo_profile"] = str(Label("//tests/cc/common:cs_fdo_profile"))
82+
analysis_test(
83+
name = name,
84+
impl = _test_csfdo_profdata_merge_env_impl,
85+
target = "//tests/cc/testutil/toolchains:cc-compiler-k8-compiler",
86+
config_settings = config,
87+
**kwargs
88+
)
89+
90+
def _test_csfdo_profdata_merge_env_impl(env, target):
91+
_assert_profdata_env(env, target, ["LLVMProfDataMergeAction"])
92+
93+
def cc_fdo_env_tests(name):
94+
"""Creates tests for FDO actions.
95+
96+
Args:
97+
name: The name of the test suite.
98+
"""
99+
native.genrule(
100+
name = "cs_fdo_profraw",
101+
outs = ["cs_profile.profraw"],
102+
cmd = "touch $@",
103+
)
104+
105+
fdo_profile(
106+
name = "cs_fdo_profile",
107+
profile = ":cs_fdo_profraw",
108+
)
109+
110+
tests = []
111+
if _bazel_version_ge("9.0.0"):
112+
tests = [
113+
_test_fdo_profdata_env,
114+
_test_csfdo_profdata_merge_env,
115+
]
116+
test_suite(
117+
name = name,
118+
tests = tests,
119+
)

tests/cc/testutil/toolchains/cc_toolchain_config.bzl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,22 @@ _simple_link_feature = feature(
832832
],
833833
)
834834

835+
_llvm_profdata_env_feature = feature(
836+
name = FEATURE_NAMES.llvm_profdata_env,
837+
enabled = True,
838+
env_sets = [
839+
env_set(
840+
actions = [ACTION_NAMES.llvm_profdata],
841+
env_entries = [
842+
env_entry(
843+
key = "LLVM_PROFDATA_ENV_KEY",
844+
value = "LLVM_PROFDATA_ENV_VALUE",
845+
),
846+
],
847+
),
848+
],
849+
)
850+
835851
_link_env_feature = feature(
836852
name = FEATURE_NAMES.link_env,
837853
env_sets = [
@@ -1341,6 +1357,7 @@ _feature_name_to_feature = {
13411357
FEATURE_NAMES.simple_compile_feature: _simple_compile_feature,
13421358
FEATURE_NAMES.simple_link_feature: _simple_link_feature,
13431359
FEATURE_NAMES.link_env: _link_env_feature,
1360+
FEATURE_NAMES.llvm_profdata_env: _llvm_profdata_env_feature,
13441361
FEATURE_NAMES.static_linking_mode: _static_linking_mode_feature,
13451362
FEATURE_NAMES.dynamic_linking_mode: _dynamic_linking_mode_feature,
13461363
FEATURE_NAMES.objcopy_embed_flags: _objcopy_embed_flags_feature,

tests/cc/testutil/toolchains/features.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,5 @@ FEATURE_NAMES = struct(
9494
no_copts_tokenization = "no_copts_tokenization",
9595
generate_linkmap = "generate_linkmap",
9696
shorten_virtual_includes = "shorten_virtual_includes",
97+
llvm_profdata_env = "llvm_profdata_env",
9798
)

0 commit comments

Comments
 (0)