diff options
Diffstat (limited to 'src')
20 files changed, 494 insertions, 90 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/CcRules.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/CcRules.java index b21b211871..be7f016365 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/CcRules.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/CcRules.java @@ -34,6 +34,7 @@ import com.google.devtools.build.lib.rules.cpp.CppConfigurationLoader; import com.google.devtools.build.lib.rules.cpp.CppOptions; import com.google.devtools.build.lib.rules.cpp.CppRuleClasses.CcIncludeScanningRule; import com.google.devtools.build.lib.rules.cpp.CpuTransformer; +import com.google.devtools.build.lib.rules.cpp.FdoPrefetchHintsRule; import com.google.devtools.build.lib.rules.cpp.FdoProfileRule; import com.google.devtools.build.lib.rules.platform.PlatformRules; @@ -73,6 +74,7 @@ public class CcRules implements RuleSet { builder.addRuleDefinition(new BazelCcImportRule()); builder.addRuleDefinition(new CcIncludeScanningRule()); builder.addRuleDefinition(new FdoProfileRule()); + builder.addRuleDefinition(new FdoPrefetchHintsRule()); } @Override diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java index ebf00f8eaf..21ccb4a116 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcCommon.java @@ -843,6 +843,9 @@ public final class CcCommon { allFeatures.add(CppRuleClasses.ENABLE_AFDO_THINLTO); } } + if (cppConfiguration.getFdoPrefetchHintsLabel() != null) { + allRequestedFeaturesBuilder.add(CppRuleClasses.FDO_PREFETCH_HINTS); + } if (cppConfiguration.isLipoOptimizationOrInstrumentation()) { // Map LIPO to ThinLTO for LLVM builds. if (toolchain.isLLVMCompiler() && fdoMode != FdoMode.OFF) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java index 5209e1c230..5dc9e75bf6 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchain.java @@ -182,6 +182,29 @@ public class CcToolchain implements RuleConfiguredTargetFactory { return pathPrefix.getRelative(path); } + private Artifact getPrefetchHintsArtifact( + FdoInputFile prefetchHintsFile, RuleContext ruleContext) { + Artifact prefetchHintsArtifact = null; + if (prefetchHintsFile != null) { + prefetchHintsArtifact = prefetchHintsFile.getArtifact(); + if (prefetchHintsArtifact == null) { + prefetchHintsArtifact = + ruleContext.getUniqueDirectoryArtifact( + "fdo", + prefetchHintsFile.getAbsolutePath().getBaseName(), + ruleContext.getBinOrGenfilesDirectory()); + ruleContext.registerAction( + new SymlinkAction( + ruleContext.getActionOwner(), + PathFragment.create(prefetchHintsFile.getAbsolutePath().getPathString()), + prefetchHintsArtifact, + "Symlinking LLVM Cache Prefetch Hints Profile " + + prefetchHintsFile.getAbsolutePath().getPathString())); + } + } + return prefetchHintsArtifact; + } + /* * This function checks the format of the input profile data and converts it to * the indexed format (.profdata) if necessary. @@ -317,7 +340,14 @@ public class CcToolchain implements RuleConfiguredTargetFactory { CppToolchainInfo toolchainInfo = getCppToolchainInfo(ruleContext, cppConfiguration); PathFragment fdoZip = null; + FdoInputFile prefetchHints = null; if (configuration.getCompilationMode() == CompilationMode.OPT) { + if (cppConfiguration.getFdoPrefetchHintsLabel() != null) { + FdoPrefetchHintsProvider provider = + ruleContext.getPrerequisite( + ":fdo_prefetch_hints", Mode.TARGET, FdoPrefetchHintsProvider.PROVIDER); + prefetchHints = provider.getInputFile(); + } if (cppConfiguration.getFdoPath() != null) { fdoZip = cppConfiguration.getFdoPath(); } else if (cppConfiguration.getFdoOptimizeLabel() != null) { @@ -342,10 +372,11 @@ public class CcToolchain implements RuleConfiguredTargetFactory { FdoProfileProvider fdoProvider = ruleContext.getPrerequisite( CcToolchainRule.FDO_PROFILE_ATTR, Mode.TARGET, FdoProfileProvider.PROVIDER); + FdoInputFile inputFile = fdoProvider.getInputFile(); fdoZip = - fdoProvider.getFdoPath() != null - ? fdoProvider.getFdoPath() - : fdoProvider.getProfileArtifact().getPath().asFragment(); + inputFile.getAbsolutePath() != null + ? inputFile.getAbsolutePath() + : inputFile.getArtifact().getPath().asFragment(); } } @@ -373,7 +404,11 @@ public class CcToolchain implements RuleConfiguredTargetFactory { SkyKey fdoKey = FdoSupportValue.key( - cppConfiguration.getLipoMode(), fdoZip, cppConfiguration.getFdoInstrument(), fdoMode); + cppConfiguration.getLipoMode(), + fdoZip, + prefetchHints, + cppConfiguration.getFdoInstrument(), + fdoMode); SkyFunction.Environment skyframeEnv = ruleContext.getAnalysisEnvironment().getSkyframeEnv(); FdoSupportValue fdoSupport; @@ -527,6 +562,8 @@ public class CcToolchain implements RuleConfiguredTargetFactory { return null; } } + Artifact hintsArtifact = getPrefetchHintsArtifact(prefetchHints, ruleContext); + ProfileArtifacts profileArtifacts = new ProfileArtifacts(profileArtifact, hintsArtifact); reportInvalidOptions(ruleContext, toolchainInfo); @@ -578,7 +615,7 @@ public class CcToolchain implements RuleConfiguredTargetFactory { .addNativeDeclaredProvider(ccProvider) .addNativeDeclaredProvider(templateVariableInfo) .addProvider( - fdoSupport.getFdoSupport().createFdoSupportProvider(ruleContext, profileArtifact)) + fdoSupport.getFdoSupport().createFdoSupportProvider(ruleContext, profileArtifacts)) .setFilesToBuild(crosstool) .addProvider(RunfilesProvider.simple(Runfiles.EMPTY)); diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java index a7bf17bf51..bdba98899c 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CcToolchainRule.java @@ -85,6 +85,12 @@ public final class CcToolchainRule implements RuleDefinition { null, (rule, attributes, cppConfig) -> cppConfig.getFdoProfileLabel()); + private static final LabelLateBoundDefault<?> FDO_PREFETCH_HINTS = + LabelLateBoundDefault.fromTargetConfiguration( + CppConfiguration.class, + null, + (rule, attributes, cppConfig) -> cppConfig.getFdoPrefetchHintsLabel()); + /** * Returns true if zipper should be loaded. We load the zipper executable if FDO optimization is * enabled through --fdo_optimize or --fdo_profile @@ -179,6 +185,11 @@ public final class CcToolchainRule implements RuleDefinition { .mandatoryProviders(ImmutableList.of(FdoProfileProvider.PROVIDER.id())) .value(FDO_PROFILE_VALUE)) .add( + attr(":fdo_prefetch_hints", LABEL) + .allowedRuleClasses("fdo_prefetch_hints") + .mandatoryProviders(ImmutableList.of(FdoPrefetchHintsProvider.PROVIDER.id())) + .value(FDO_PREFETCH_HINTS)) + .add( attr(TransitiveLipoInfoProvider.LIPO_CONTEXT_COLLECTOR, LABEL) .cfg(LipoContextCollectorTransition.INSTANCE) .value(CppRuleClasses.LIPO_CONTEXT_COLLECTOR) diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java index 6b6247eab1..b0938b83af 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CompileBuildVariables.java @@ -94,6 +94,8 @@ public enum CompileBuildVariables { FDO_INSTRUMENT_PATH("fdo_instrument_path"), /** Path to the fdo profile artifact */ FDO_PROFILE_PATH("fdo_profile_path"), + /** Path to the cache prefetch profile artifact */ + FDO_PREFETCH_HINTS_PATH("fdo_prefetch_hints_path"), /** Variable for includes that compiler needs to include into sources. */ INCLUDES("includes"); diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java index f1ec0a19a3..efd741a6c3 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java @@ -31,6 +31,8 @@ public class CppActionConfigs { MAC } + // Note: these configs won't be added to the crosstools that defines no_legacy_features feature + // (e.g. ndk, apple, enclave crosstools). Those need to be modified separately. public static String getCppActionConfigs( CppPlatform platform, ImmutableSet<String> existingFeatureNames, @@ -402,6 +404,21 @@ public class CppActionConfigs { " }", "}"), ifTrue( + !existingFeatureNames.contains(CppRuleClasses.FDO_PREFETCH_HINTS), + "feature {", + " name: 'fdo_prefetch_hints'", + " flag_set {", + " action: 'c-compile'", + " action: 'c++-compile'", + " action: 'lto-backend'", + " expand_if_all_available: 'fdo_prefetch_hints_path'", + " flag_group {", + " flag: '-Xclang-only=-mllvm'", + " flag: '-Xclang-only=-prefetch-hints-file=%{fdo_prefetch_hints_path}'", + " }", + " }", + "}"), + ifTrue( !existingFeatureNames.contains(CppRuleClasses.AUTOFDO), "feature {", " name: 'autofdo'", diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java index 4761c2b6d4..568f418ad5 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppConfiguration.java @@ -1333,6 +1333,10 @@ public final class CppConfiguration extends BuildConfiguration.Fragment { return fdoOptimizeLabel; } + public Label getFdoPrefetchHintsLabel() { + return cppOptions.getFdoPrefetchHintsLabel(); + } + public Label getFdoProfileLabel() { return cppOptions.getFdoProfileLabel(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java index 3192605a04..713dd2b242 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppOptions.java @@ -480,6 +480,24 @@ public class CppOptions extends FragmentOptions { return enableLipoSettings() ? fdoOptimizeForBuild : null; } + @Option( + name = "fdo_prefetch_hints", + defaultValue = "null", + converter = LabelConverter.class, + category = "flags", + documentationCategory = OptionDocumentationCategory.OUTPUT_PARAMETERS, + effectTags = {OptionEffectTag.AFFECTS_OUTPUTS}, + help = "Use cache prefetch hints." + ) + public Label fdoPrefetchHintsLabel; + + /** + * Returns the --fdo_prefetch_hints value. + */ + public Label getFdoPrefetchHintsLabel() { + return fdoPrefetchHintsLabel; + } + /** * Returns the --autofdo_lipo_data value for this configuration. This is false except for data * configurations under LIPO builds. diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java index da10c03d71..2862cbc67e 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java @@ -372,6 +372,11 @@ public class CppRuleClasses { public static final String FDO_OPTIMIZE = "fdo_optimize"; /** + * A string constant for the cache prefetch hints feature. + */ + public static final String FDO_PREFETCH_HINTS = "fdo_prefetch_hints"; + + /** * A string constant for the autofdo feature. */ public static final String AUTOFDO = "autofdo"; diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoInputFile.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoInputFile.java new file mode 100644 index 0000000000..d9644032b6 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoInputFile.java @@ -0,0 +1,103 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.lib.rules.cpp; + +import com.google.common.base.Preconditions; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.vfs.PathFragment; +import java.util.Objects; + +/** + * Value object reused by fdo configurations that may be either an artifact or a path. + */ +@Immutable +public final class FdoInputFile { + + private final Artifact artifact; + private final PathFragment absolutePath; + + private FdoInputFile(Artifact artifact, PathFragment absolutePath) { + Preconditions.checkArgument((artifact == null) != (absolutePath == null)); + Preconditions.checkArgument(absolutePath == null || absolutePath.isAbsolute()); + this.artifact = artifact; + this.absolutePath = absolutePath; + } + + public Artifact getArtifact() { + return artifact; + } + + public PathFragment getAbsolutePath() { + return absolutePath; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (!(o instanceof FdoInputFile)) { + return false; + } + + FdoInputFile that = (FdoInputFile) o; + return Objects.equals(this.artifact, that.artifact) + && Objects.equals(this.absolutePath, that.absolutePath); + } + + @Override + public int hashCode() { + return Objects.hash(artifact, absolutePath); + } + + public static FdoInputFile create(RuleContext ruleContext) { + + boolean isLabel = ruleContext.attributes().isAttributeValueExplicitlySpecified("profile"); + boolean isAbsolutePath = + ruleContext.attributes().isAttributeValueExplicitlySpecified("absolute_path_profile"); + + if (isLabel == isAbsolutePath) { + ruleContext.ruleError("exactly one of profile and absolute_path_profile should be specified"); + return null; + } + + if (isLabel) { + Artifact artifact = ruleContext.getPrerequisiteArtifact("profile", Mode.TARGET); + if (!artifact.isSourceArtifact()) { + ruleContext.attributeError("profile", " the target is not an input file"); + } + return new FdoInputFile(artifact, null); + } else { + if (!ruleContext.getFragment(CppConfiguration.class).isFdoAbsolutePathEnabled()) { + ruleContext.attributeError( + "absolute_path_profile", + "this attribute cannot be used when --enable_fdo_profile_absolute_path is false"); + return null; + } + String pathString = ruleContext.getExpander().expand("absolute_path_profile"); + PathFragment absolutePath = PathFragment.create(pathString); + if (!absolutePath.isAbsolute()) { + ruleContext.attributeError( + "absolute_path_profile", + String.format("%s is not an absolute path", absolutePath.getPathString())); + return null; + } + return new FdoInputFile(null, absolutePath); + } + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoPrefetchHints.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoPrefetchHints.java new file mode 100644 index 0000000000..7dcff8fbc0 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoPrefetchHints.java @@ -0,0 +1,42 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.lib.rules.cpp; + +import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException; +import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; +import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory; +import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.Runfiles; +import com.google.devtools.build.lib.analysis.RunfilesProvider; +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; + +/** Implementation for the {@code fdo_prefetch_hints} rule. */ +@Immutable +public final class FdoPrefetchHints implements RuleConfiguredTargetFactory { + @Override + public ConfiguredTarget create(RuleContext ruleContext) + throws RuleErrorException, ActionConflictException { + + FdoInputFile inputFile = FdoInputFile.create(ruleContext); + if (ruleContext.hasErrors()) { + return null; + } + + return new RuleConfiguredTargetBuilder(ruleContext) + .addNativeDeclaredProvider(new FdoPrefetchHintsProvider(inputFile)) + .addProvider(RunfilesProvider.simple(Runfiles.EMPTY)) + .build(); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoPrefetchHintsProvider.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoPrefetchHintsProvider.java new file mode 100644 index 0000000000..e7a7ebf26e --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoPrefetchHintsProvider.java @@ -0,0 +1,37 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.lib.rules.cpp; + +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.packages.NativeInfo; +import com.google.devtools.build.lib.packages.NativeProvider; + +/** Provider that contains the profile used for prefetch hints. */ +@Immutable +public final class FdoPrefetchHintsProvider extends NativeInfo { + public static final NativeProvider<FdoPrefetchHintsProvider> PROVIDER = + new NativeProvider<FdoPrefetchHintsProvider>( + FdoPrefetchHintsProvider.class, "FdoPrefetchHintsInfo") {}; + + private final FdoInputFile fdoInputFile; + + public FdoPrefetchHintsProvider(FdoInputFile fdoInputFile) { + super(PROVIDER); + this.fdoInputFile = fdoInputFile; + } + + public FdoInputFile getInputFile() { + return fdoInputFile; + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoPrefetchHintsRule.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoPrefetchHintsRule.java new file mode 100644 index 0000000000..c706474f07 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoPrefetchHintsRule.java @@ -0,0 +1,78 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.lib.rules.cpp; + +import static com.google.devtools.build.lib.packages.Attribute.attr; +import static com.google.devtools.build.lib.packages.BuildType.LABEL; + +import com.google.devtools.build.lib.analysis.BaseRuleClasses; +import com.google.devtools.build.lib.analysis.RuleDefinition; +import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; +import com.google.devtools.build.lib.packages.RuleClass; +import com.google.devtools.build.lib.syntax.Type; +import com.google.devtools.build.lib.util.FileType; +import com.google.devtools.build.lib.util.FileTypeSet; + +/** {@code fdo_prefetch_hints} rule class. */ +public final class FdoPrefetchHintsRule implements RuleDefinition { + @Override + public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) { + return builder + .requiresConfigurationFragments(CppConfiguration.class) + /* <!-- #BLAZE_RULE(fdo_prefetch_hints).ATTRIBUTE(profile) --> + Label of the hints profile. The hints file has the .afdo extension + The label can also point to an fdo_absolute_path_profile rule. + <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ + .add( + attr("profile", LABEL) + .allowedFileTypes( + FileTypeSet.of( + FileType.of(".afdo"))) + .singleArtifact()) + /* <!-- #BLAZE_RULE(fdo_profile).ATTRIBUTE(absolute_path_profile) --> + Absolute path to the FDO profile. The FDO file may only have the .afdo extension. + <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ + .add(attr("absolute_path_profile", Type.STRING)) + .advertiseProvider(FdoPrefetchHintsProvider.class) + .build(); + } + + @Override + public Metadata getMetadata() { + return RuleDefinition.Metadata.builder() + .name("fdo_prefetch_hints") + .ancestors(BaseRuleClasses.BaseRule.class) + .factoryClass(FdoPrefetchHints.class) + .build(); + } +} + +/*<!-- #BLAZE_RULE (NAME = fdo_prefetch_hints, TYPE = LIBRARY, FAMILY = Cpp) --> + +<p>Represents an FDO prefetch hints profile that is either in the workspace or at a specified +absolute path. +Examples:</p> + +<pre class="code"> +fdo_prefetch_hints( + name = "hints", + profile = "//path/to/hints:profile.afdo", +) + +fdo_profile( + name = "hints_abs", + absolute_path_profile = "/absolute/path/profile.afdo", +) +</pre> +<!-- #END_BLAZE_RULE -->*/ diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoProfile.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoProfile.java index 2e4131fbc4..0fbfe8593e 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoProfile.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoProfile.java @@ -13,7 +13,6 @@ // limitations under the License. package com.google.devtools.build.lib.rules.cpp; -import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; @@ -21,9 +20,7 @@ import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.Runfiles; import com.google.devtools.build.lib.analysis.RunfilesProvider; -import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; -import com.google.devtools.build.lib.vfs.PathFragment; /** Implementation for the {@code fdo_profile} rule. */ @Immutable @@ -32,42 +29,13 @@ public final class FdoProfile implements RuleConfiguredTargetFactory { public ConfiguredTarget create(RuleContext ruleContext) throws RuleErrorException, ActionConflictException { - FdoProfileProvider provider; - - boolean isLabel = ruleContext.attributes().isAttributeValueExplicitlySpecified("profile"); - boolean isAbsolutePath = - ruleContext.attributes().isAttributeValueExplicitlySpecified("absolute_path_profile"); - - if (isLabel == isAbsolutePath) { - ruleContext.ruleError("exactly one of profile and absolute_path_profile should be specified"); + FdoInputFile inputFile = FdoInputFile.create(ruleContext); + if (ruleContext.hasErrors()) { return null; } - if (isLabel) { - Artifact artifact = ruleContext.getPrerequisiteArtifact("profile", Mode.TARGET); - if (!artifact.isSourceArtifact()) { - ruleContext.attributeError("profile", " the target is not an input file"); - } - provider = FdoProfileProvider.fromArtifact(artifact); - } else { - if (!ruleContext.getFragment(CppConfiguration.class).isFdoAbsolutePathEnabled()) { - ruleContext.attributeError( - "absolute_path_profile", - "this attribute cannot be used when --enable_fdo_profile_absolute_path is false"); - return null; - } - String path = ruleContext.getExpander().expand("absolute_path_profile"); - PathFragment fdoPath = PathFragment.create(path); - if (!fdoPath.isAbsolute()) { - ruleContext.attributeError( - "absolute_path_profile", - String.format("%s is not an absolute path", fdoPath.getPathString())); - } - provider = FdoProfileProvider.fromAbsolutePath(fdoPath); - } - return new RuleConfiguredTargetBuilder(ruleContext) - .addNativeDeclaredProvider(provider) + .addNativeDeclaredProvider(new FdoProfileProvider(inputFile)) .addProvider(RunfilesProvider.simple(Runfiles.EMPTY)) .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoProfileProvider.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoProfileProvider.java index b5c73bdc0c..876d164efa 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoProfileProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoProfileProvider.java @@ -13,11 +13,9 @@ // limitations under the License. package com.google.devtools.build.lib.rules.cpp; -import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.packages.NativeInfo; import com.google.devtools.build.lib.packages.NativeProvider; -import com.google.devtools.build.lib.vfs.PathFragment; /** Provider that contains the profile used for FDO. */ @Immutable @@ -25,28 +23,14 @@ public final class FdoProfileProvider extends NativeInfo { public static final NativeProvider<FdoProfileProvider> PROVIDER = new NativeProvider<FdoProfileProvider>(FdoProfileProvider.class, "FdoProfileInfo") {}; - private final Artifact profileArtifact; - private final PathFragment fdoPath; + private final FdoInputFile fdoInputFile; - private FdoProfileProvider(Artifact profileArtifact, PathFragment fdoPath) { + public FdoProfileProvider(FdoInputFile fdoInputFile) { super(PROVIDER); - this.profileArtifact = profileArtifact; - this.fdoPath = fdoPath; + this.fdoInputFile = fdoInputFile; } - public static FdoProfileProvider fromAbsolutePath(PathFragment fdoPath) { - return new FdoProfileProvider(/* profileArtifact= */ null, fdoPath); - } - - public static FdoProfileProvider fromArtifact(Artifact profileArtifact) { - return new FdoProfileProvider(profileArtifact, /* fdoPath= */ null); - } - - public Artifact getProfileArtifact() { - return profileArtifact; - } - - public PathFragment getFdoPath() { - return fdoPath; + public FdoInputFile getInputFile() { + return fdoInputFile; } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java index e10ca70cd0..f657c0775b 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupport.java @@ -605,13 +605,20 @@ public class FdoSupport { FeatureConfiguration featureConfiguration, FdoSupportProvider fdoSupportProvider) { + ImmutableMap.Builder<String, String> variablesBuilder = ImmutableMap.builder(); + + if ((fdoSupportProvider != null) + && (fdoSupportProvider.getPrefetchHintsArtifact() != null)) { + variablesBuilder.put( + CompileBuildVariables.FDO_PREFETCH_HINTS_PATH.getVariableName(), + fdoSupportProvider.getPrefetchHintsArtifact().getExecPathString()); + } + // FDO is disabled -> do nothing. if ((fdoInstrument == null) && (fdoRoot == null)) { return ImmutableMap.of(); } - ImmutableMap.Builder<String, String> variablesBuilder = ImmutableMap.builder(); - if (featureConfiguration.isEnabled(CppRuleClasses.FDO_INSTRUMENT)) { variablesBuilder.put( CompileBuildVariables.FDO_INSTRUMENT_PATH.getVariableName(), fdoInstrument); @@ -663,19 +670,21 @@ public class FdoSupport { LipoContextProvider lipoContextProvider = toolchain.isLLVMCompiler() ? null : CppHelper.getLipoContextProvider(ruleContext); + ImmutableSet.Builder<Artifact> auxiliaryInputs = ImmutableSet.builder(); + + if (fdoSupportProvider.getPrefetchHintsArtifact() != null) { + auxiliaryInputs.add(fdoSupportProvider.getPrefetchHintsArtifact()); + } // If --fdo_optimize was not specified, we don't have any additional inputs. if (fdoProfile == null) { - return ImmutableSet.of(); + return auxiliaryInputs.build(); } else if (fdoMode == FdoMode.LLVM_FDO || fdoMode == FdoMode.AUTO_FDO) { - ImmutableSet.Builder<Artifact> auxiliaryInputs = ImmutableSet.builder(); auxiliaryInputs.add(fdoSupportProvider.getProfileArtifact()); if (lipoContextProvider != null) { auxiliaryInputs.addAll(getAutoFdoImports(ruleContext, sourceExecPath, lipoContextProvider)); } return auxiliaryInputs.build(); } else { - ImmutableSet.Builder<Artifact> auxiliaryInputs = ImmutableSet.builder(); - PathFragment objectName = FileSystemUtils.appendExtension(outputName, usePic ? ".pic.o" : ".o"); @@ -803,18 +812,22 @@ public class FdoSupport { * AutoFDO is disabled, no build variable is added and returns null. */ @ThreadSafe - public Artifact buildProfileForLtoBackend( + public ProfileArtifacts buildProfileForLtoBackend( FdoSupportProvider fdoSupportProvider, FeatureConfiguration featureConfiguration, CcToolchainVariables.Builder buildVariables, RuleContext ruleContext) { + Artifact prefetch = fdoSupportProvider.getPrefetchHintsArtifact(); + if (prefetch != null) { + buildVariables.addStringVariable("fdo_prefetch_hints_path", prefetch.getExecPathString()); + } if (!featureConfiguration.isEnabled(CppRuleClasses.AUTOFDO)) { - return null; + return new ProfileArtifacts(null, prefetch); } Artifact profile = fdoSupportProvider.getProfileArtifact(); buildVariables.addStringVariable("fdo_profile_path", profile.getExecPathString()); - return profile; + return new ProfileArtifacts(profile, prefetch); } /** @@ -827,20 +840,20 @@ public class FdoSupport { } public FdoSupportProvider createFdoSupportProvider( - RuleContext ruleContext, Artifact profileArtifact) { + RuleContext ruleContext, ProfileArtifacts profiles) { if (fdoRoot == null) { - return new FdoSupportProvider(this, null, null); + return new FdoSupportProvider(this, profiles, null); } if (fdoMode == FdoMode.LLVM_FDO) { - Preconditions.checkState(profileArtifact != null); - return new FdoSupportProvider(this, profileArtifact, null); + Preconditions.checkState(profiles != null && profiles.getProfileArtifact() != null); + return new FdoSupportProvider(this, profiles, null); } Preconditions.checkState(fdoPath != null); PathFragment profileRootRelativePath = getAutoProfileRootRelativePath(fdoProfile); - profileArtifact = + Artifact profileArtifact = ruleContext .getAnalysisEnvironment() .getDerivedArtifact(fdoPath.getRelative(profileRootRelativePath), fdoRoot); @@ -854,7 +867,11 @@ public class FdoSupport { gcdaArtifacts.put(path, gcdaArtifact); } - return new FdoSupportProvider(this, profileArtifact, gcdaArtifacts.build()); + return new FdoSupportProvider( + this, + new ProfileArtifacts( + profileArtifact, profiles == null ? null : profiles.getPrefetchHintsArtifact()), + gcdaArtifacts.build()); } /** diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupportProvider.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupportProvider.java index 72715f02ba..2ff61051b6 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupportProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupportProvider.java @@ -28,14 +28,14 @@ import com.google.devtools.build.lib.vfs.PathFragment; @AutoCodec public class FdoSupportProvider implements TransitiveInfoProvider { private final FdoSupport fdoSupport; - private final Artifact profileArtifact; + private final ProfileArtifacts profileArtifacts; private final ImmutableMap<PathFragment, Artifact> gcdaArtifacts; @AutoCodec.Instantiator - public FdoSupportProvider(FdoSupport fdoSupport, Artifact profileArtifact, + public FdoSupportProvider(FdoSupport fdoSupport, ProfileArtifacts profileArtifacts, ImmutableMap<PathFragment, Artifact> gcdaArtifacts) { this.fdoSupport = fdoSupport; - this.profileArtifact = profileArtifact; + this.profileArtifacts = profileArtifacts; this.gcdaArtifacts = gcdaArtifacts; } @@ -43,7 +43,10 @@ public class FdoSupportProvider implements TransitiveInfoProvider { return fdoSupport; } public Artifact getProfileArtifact() { - return profileArtifact; + return profileArtifacts != null ? profileArtifacts.getProfileArtifact() : null; + } + public Artifact getPrefetchHintsArtifact() { + return profileArtifacts != null ? profileArtifacts.getPrefetchHintsArtifact() : null; } public ImmutableMap<PathFragment, Artifact> getGcdaArtifacts() { return gcdaArtifacts; diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupportValue.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupportValue.java index 83c8173ec6..f6bad1f0b2 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupportValue.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FdoSupportValue.java @@ -47,20 +47,33 @@ public class FdoSupportValue implements SkyValue { private final LipoMode lipoMode; private final PathFragment fdoZip; + private final FdoInputFile fdoPrefetchHintsFile; private final String fdoInstrument; private final FdoMode fdoMode; - private Key(LipoMode lipoMode, PathFragment fdoZip, String fdoInstrument, FdoMode fdoMode) { + private Key( + LipoMode lipoMode, + PathFragment fdoZip, + FdoInputFile fdoPrefetchHintsFile, + String fdoInstrument, + FdoMode fdoMode) { this.lipoMode = lipoMode; this.fdoZip = fdoZip; + this.fdoPrefetchHintsFile = fdoPrefetchHintsFile; this.fdoInstrument = fdoInstrument; this.fdoMode = fdoMode; } @AutoCodec.Instantiator @AutoCodec.VisibleForSerialization - static Key of(LipoMode lipoMode, PathFragment fdoZip, String fdoInstrument, FdoMode fdoMode) { - return interner.intern(new Key(lipoMode, fdoZip, fdoInstrument, fdoMode)); + static Key of( + LipoMode lipoMode, + PathFragment fdoZip, + FdoInputFile fdoPrefetchHintsFile, + String fdoInstrument, + FdoMode fdoMode) { + return interner.intern( + new Key(lipoMode, fdoZip, fdoPrefetchHintsFile, fdoInstrument, fdoMode)); } public LipoMode getLipoMode() { @@ -71,6 +84,10 @@ public class FdoSupportValue implements SkyValue { return fdoZip; } + public FdoInputFile getFdoPrefetchHintsFile() { + return fdoPrefetchHintsFile; + } + public String getFdoInstrument() { return fdoInstrument; } @@ -92,13 +109,14 @@ public class FdoSupportValue implements SkyValue { Key that = (Key) o; return Objects.equals(this.lipoMode, that.lipoMode) && Objects.equals(this.fdoZip, that.fdoZip) + && Objects.equals(this.fdoPrefetchHintsFile, that.fdoPrefetchHintsFile) && Objects.equals(this.fdoMode, that.fdoMode) && Objects.equals(this.fdoInstrument, that.fdoInstrument); } @Override public int hashCode() { - return Objects.hash(lipoMode, fdoZip, fdoInstrument); + return Objects.hash(lipoMode, fdoZip, fdoPrefetchHintsFile, fdoInstrument); } @Override @@ -118,7 +136,11 @@ public class FdoSupportValue implements SkyValue { } public static SkyKey key( - LipoMode lipoMode, PathFragment fdoZip, String fdoInstrument, FdoMode fdoMode) { - return Key.of(lipoMode, fdoZip, fdoInstrument, fdoMode); + LipoMode lipoMode, + PathFragment fdoZip, + FdoInputFile fdoPrefetchHintsFile, + String fdoInstrument, + FdoMode fdoMode) { + return Key.of(lipoMode, fdoZip, fdoPrefetchHintsFile, fdoInstrument, fdoMode); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LtoBackendArtifacts.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LtoBackendArtifacts.java index df6dba73d0..f3e6d688a9 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LtoBackendArtifacts.java +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LtoBackendArtifacts.java @@ -230,10 +230,18 @@ public final class LtoBackendArtifacts { // The input to the LTO backend step is the bitcode file. buildVariablesBuilder.addStringVariable( "thinlto_input_bitcode_file", bitcodeFile.getExecPath().toString()); - Artifact autoFdoProfile = fdoSupport.getFdoSupport().buildProfileForLtoBackend( - fdoSupport, featureConfiguration, buildVariablesBuilder, ruleContext); - if (autoFdoProfile != null) { - builder.addInput(autoFdoProfile); + ProfileArtifacts profileArtifacts = + Preconditions.checkNotNull( + fdoSupport + .getFdoSupport() + .buildProfileForLtoBackend( + fdoSupport, featureConfiguration, buildVariablesBuilder, ruleContext)); + + if (profileArtifacts.getProfileArtifact() != null) { + builder.addInput(profileArtifacts.getProfileArtifact()); + } + if (profileArtifacts.getPrefetchHintsArtifact() != null) { + builder.addInput(profileArtifacts.getPrefetchHintsArtifact()); } if (generateDwo) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/ProfileArtifacts.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/ProfileArtifacts.java new file mode 100644 index 0000000000..1b46d99dba --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/ProfileArtifacts.java @@ -0,0 +1,43 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.devtools.build.lib.rules.cpp; + +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; + +/** + * ProfileArtifacts groups together Artifacts that may be used as inputs for feedback-driven + * optimization. + */ +@Immutable +public class ProfileArtifacts { + private final Artifact profileArtifact; + private final Artifact prefetchHintsArtifact; + + public ProfileArtifacts(Artifact profileArtifact) { + this(profileArtifact, null); + } + public ProfileArtifacts(Artifact profileArtifact, Artifact prefetchHintsArtifact) { + this.profileArtifact = profileArtifact; + this.prefetchHintsArtifact = prefetchHintsArtifact; + } + + public Artifact getProfileArtifact() { + return profileArtifact; + } + public Artifact getPrefetchHintsArtifact() { + return prefetchHintsArtifact; + } +} |