Merge "Remove PGO build support" into main am: 33914a613f

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/2845655

Change-Id: I5ee81e0edf10806712cc45b8d7b02a5a3ff215e3
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Yi Kong
2023-11-29 08:16:03 +00:00
committed by Automerger Merge Worker
4 changed files with 1 additions and 320 deletions

View File

@@ -40,7 +40,6 @@ bootstrap_go_package {
"lto.go",
"makevars.go",
"orderfile.go",
"pgo.go",
"prebuilt.go",
"proto.go",
"rs.go",

View File

@@ -531,7 +531,6 @@ type ModuleContextIntf interface {
baseModuleName() string
getVndkExtendsModuleName() string
isAfdoCompile() bool
isPgoCompile() bool
isOrderfileCompile() bool
isCfi() bool
isFuzzer() bool
@@ -895,7 +894,6 @@ type Module struct {
vndkdep *vndkdep
lto *lto
afdo *afdo
pgo *pgo
orderfile *orderfile
library libraryInterface
@@ -1278,9 +1276,6 @@ func (c *Module) Init() android.Module {
if c.afdo != nil {
c.AddProperties(c.afdo.props()...)
}
if c.pgo != nil {
c.AddProperties(c.pgo.props()...)
}
if c.orderfile != nil {
c.AddProperties(c.orderfile.props()...)
}
@@ -1410,13 +1405,6 @@ func (c *Module) isAfdoCompile() bool {
return false
}
func (c *Module) isPgoCompile() bool {
if pgo := c.pgo; pgo != nil {
return pgo.Properties.PgoCompile
}
return false
}
func (c *Module) isOrderfileCompile() bool {
if orderfile := c.orderfile; orderfile != nil {
return orderfile.Properties.OrderfileLoad
@@ -1725,10 +1713,6 @@ func (ctx *moduleContextImpl) isAfdoCompile() bool {
return ctx.mod.isAfdoCompile()
}
func (ctx *moduleContextImpl) isPgoCompile() bool {
return ctx.mod.isPgoCompile()
}
func (ctx *moduleContextImpl) isOrderfileCompile() bool {
return ctx.mod.isOrderfileCompile()
}
@@ -1841,7 +1825,6 @@ func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Mo
module.vndkdep = &vndkdep{}
module.lto = &lto{}
module.afdo = &afdo{}
module.pgo = &pgo{}
module.orderfile = &orderfile{}
return module
}
@@ -2267,9 +2250,6 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
if c.afdo != nil {
flags = c.afdo.flags(ctx, flags)
}
if c.pgo != nil {
flags = c.pgo.flags(ctx, flags)
}
if c.orderfile != nil {
flags = c.orderfile.flags(ctx, flags)
}
@@ -2421,9 +2401,6 @@ func (c *Module) begin(ctx BaseModuleContext) {
if c.orderfile != nil {
c.orderfile.begin(ctx)
}
if c.pgo != nil {
c.pgo.begin(ctx)
}
if ctx.useSdk() && c.IsSdkVariant() {
version, err := nativeApiLevelFromUser(ctx, ctx.sdkVersion())
if err != nil {
@@ -4333,7 +4310,6 @@ func DefaultsFactory(props ...interface{}) android.Module {
&VndkProperties{},
&LTOProperties{},
&AfdoProperties{},
&PgoProperties{},
&OrderfileProperties{},
&android.ProtoProperties{},
// RustBindgenProperties is included here so that cc_defaults can be used for rust_bindgen modules.

View File

@@ -140,7 +140,7 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
// Reduce the inlining threshold for a better balance of binary size and
// performance.
if !ctx.Darwin() {
if ctx.isPgoCompile() || ctx.isAfdoCompile() {
if ctx.isAfdoCompile() {
ltoLdFlags = append(ltoLdFlags, "-Wl,-plugin-opt,-import-instr-limit=40")
} else {
ltoLdFlags = append(ltoLdFlags, "-Wl,-plugin-opt,-import-instr-limit=5")

294
cc/pgo.go
View File

@@ -1,294 +0,0 @@
// Copyright 2017 Google Inc. 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 cc
import (
"fmt"
"path/filepath"
"strings"
"github.com/google/blueprint/proptools"
"android/soong/android"
)
var (
// Add flags to ignore warnings that profiles are old or missing for
// some functions.
profileUseOtherFlags = []string{
"-Wno-backend-plugin",
}
globalPgoProfileProjects = []string{
"toolchain/pgo-profiles/pgo",
"vendor/google_data/pgo_profile/pgo",
}
)
var pgoProfileProjectsConfigKey = android.NewOnceKey("PgoProfileProjects")
const profileInstrumentFlag = "-fprofile-generate=/data/local/tmp"
const profileUseInstrumentFormat = "-fprofile-use=%s"
func getPgoProfileProjects(config android.DeviceConfig) []string {
return config.OnceStringSlice(pgoProfileProjectsConfigKey, func() []string {
return append(globalPgoProfileProjects, config.PgoAdditionalProfileDirs()...)
})
}
func recordMissingProfileFile(ctx BaseModuleContext, missing string) {
getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
}
type PgoProperties struct {
Pgo struct {
Instrumentation *bool
Profile_file *string `android:"arch_variant"`
Benchmarks []string
Enable_profile_use *bool `android:"arch_variant"`
// Additional compiler flags to use when building this module
// for profiling.
Cflags []string `android:"arch_variant"`
} `android:"arch_variant"`
PgoPresent bool `blueprint:"mutated"`
ShouldProfileModule bool `blueprint:"mutated"`
PgoCompile bool `blueprint:"mutated"`
PgoInstrLink bool `blueprint:"mutated"`
}
type pgo struct {
Properties PgoProperties
}
func (props *PgoProperties) isInstrumentation() bool {
return props.Pgo.Instrumentation != nil && *props.Pgo.Instrumentation == true
}
func (pgo *pgo) props() []interface{} {
return []interface{}{&pgo.Properties}
}
func (props *PgoProperties) addInstrumentationProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
// Add to C flags iff PGO is explicitly enabled for this module.
if props.ShouldProfileModule {
flags.Local.CFlags = append(flags.Local.CFlags, props.Pgo.Cflags...)
flags.Local.CFlags = append(flags.Local.CFlags, profileInstrumentFlag)
}
flags.Local.LdFlags = append(flags.Local.LdFlags, profileInstrumentFlag)
return flags
}
func (props *PgoProperties) getPgoProfileFile(ctx BaseModuleContext) android.OptionalPath {
profileFile := *props.Pgo.Profile_file
// Test if the profile_file is present in any of the PGO profile projects
for _, profileProject := range getPgoProfileProjects(ctx.DeviceConfig()) {
// Bug: http://b/74395273 If the profile_file is unavailable,
// use a versioned file named
// <profile_file>.<arbitrary-version> when available. This
// works around an issue where ccache serves stale cache
// entries when the profile file has changed.
globPattern := filepath.Join(profileProject, profileFile+".*")
versionedProfiles, err := ctx.GlobWithDeps(globPattern, nil)
if err != nil {
ctx.ModuleErrorf("glob: %s", err.Error())
}
path := android.ExistentPathForSource(ctx, profileProject, profileFile)
if path.Valid() {
if len(versionedProfiles) != 0 {
ctx.PropertyErrorf("pgo.profile_file", "Profile_file has multiple versions: "+filepath.Join(profileProject, profileFile)+", "+strings.Join(versionedProfiles, ", "))
}
return path
}
if len(versionedProfiles) > 1 {
ctx.PropertyErrorf("pgo.profile_file", "Profile_file has multiple versions: "+strings.Join(versionedProfiles, ", "))
} else if len(versionedProfiles) == 1 {
return android.OptionalPathForPath(android.PathForSource(ctx, versionedProfiles[0]))
}
}
// Record that this module's profile file is absent
missing := *props.Pgo.Profile_file + ":" + ctx.ModuleDir() + "/Android.bp:" + ctx.ModuleName()
recordMissingProfileFile(ctx, missing)
return android.OptionalPathForPath(nil)
}
func (props *PgoProperties) profileUseFlags(ctx ModuleContext, file string) []string {
flags := []string{fmt.Sprintf(profileUseInstrumentFormat, file)}
flags = append(flags, profileUseOtherFlags...)
return flags
}
func (props *PgoProperties) addProfileUseFlags(ctx ModuleContext, flags Flags) Flags {
// Return if 'pgo' property is not present in this module.
if !props.PgoPresent {
return flags
}
if props.PgoCompile {
profileFile := props.getPgoProfileFile(ctx)
profileFilePath := profileFile.Path()
profileUseFlags := props.profileUseFlags(ctx, profileFilePath.String())
flags.Local.CFlags = append(flags.Local.CFlags, profileUseFlags...)
flags.Local.LdFlags = append(flags.Local.LdFlags, profileUseFlags...)
// Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
// if profileFile gets updated
flags.CFlagsDeps = append(flags.CFlagsDeps, profileFilePath)
flags.LdFlagsDeps = append(flags.LdFlagsDeps, profileFilePath)
}
return flags
}
func (props *PgoProperties) isPGO(ctx BaseModuleContext) bool {
isInstrumentation := props.isInstrumentation()
profileKindPresent := isInstrumentation
filePresent := props.Pgo.Profile_file != nil
benchmarksPresent := len(props.Pgo.Benchmarks) > 0
// If all three properties are absent, PGO is OFF for this module
if !profileKindPresent && !filePresent && !benchmarksPresent {
return false
}
// profileKindPresent and filePresent are mandatory properties.
if !profileKindPresent || !filePresent {
var missing []string
if !profileKindPresent {
missing = append(missing, "profile kind")
}
if !filePresent {
missing = append(missing, "profile_file property")
}
missingProps := strings.Join(missing, ", ")
ctx.ModuleErrorf("PGO specification is missing properties: " + missingProps)
}
// Benchmark property is mandatory for instrumentation PGO.
if isInstrumentation && !benchmarksPresent {
ctx.ModuleErrorf("Instrumentation PGO specification is missing benchmark property")
}
return true
}
func (pgo *pgo) begin(ctx BaseModuleContext) {
// TODO Evaluate if we need to support PGO for host modules
if ctx.Host() {
return
}
// Check if PGO is needed for this module
pgo.Properties.PgoPresent = pgo.Properties.isPGO(ctx)
if !pgo.Properties.PgoPresent {
return
}
// This module should be instrumented if ANDROID_PGO_INSTRUMENT is set
// and includes 'all', 'ALL' or a benchmark listed for this module.
//
// TODO Validate that each benchmark instruments at least one module
pgo.Properties.ShouldProfileModule = false
pgoBenchmarks := ctx.Config().Getenv("ANDROID_PGO_INSTRUMENT")
pgoBenchmarksMap := make(map[string]bool)
for _, b := range strings.Split(pgoBenchmarks, ",") {
pgoBenchmarksMap[b] = true
}
if pgoBenchmarksMap["all"] == true || pgoBenchmarksMap["ALL"] == true {
pgo.Properties.ShouldProfileModule = true
pgo.Properties.PgoInstrLink = pgo.Properties.isInstrumentation()
} else {
for _, b := range pgo.Properties.Pgo.Benchmarks {
if pgoBenchmarksMap[b] == true {
pgo.Properties.ShouldProfileModule = true
pgo.Properties.PgoInstrLink = pgo.Properties.isInstrumentation()
break
}
}
}
// PGO profile use is not feasible for a Clang coverage build because
// -fprofile-use and -fprofile-instr-generate are incompatible.
if ctx.DeviceConfig().ClangCoverageEnabled() {
return
}
if !ctx.Config().IsEnvTrue("ANDROID_PGO_NO_PROFILE_USE") &&
proptools.BoolDefault(pgo.Properties.Pgo.Enable_profile_use, true) {
if profileFile := pgo.Properties.getPgoProfileFile(ctx); profileFile.Valid() {
pgo.Properties.PgoCompile = true
}
}
}
func (pgo *pgo) flags(ctx ModuleContext, flags Flags) Flags {
if ctx.Host() {
return flags
}
// Deduce PgoInstrLink property i.e. whether this module needs to be
// linked with profile-generation flags. Here, we're setting it if any
// dependency needs PGO instrumentation. It is initially set in
// begin() if PGO is directly enabled for this module.
if ctx.static() && !ctx.staticBinary() {
// For static libraries, check if any whole_static_libs are
// linked with profile generation
ctx.VisitDirectDeps(func(m android.Module) {
if depTag, ok := ctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok {
if depTag.static() && depTag.wholeStatic {
if cc, ok := m.(*Module); ok {
if cc.pgo.Properties.PgoInstrLink {
pgo.Properties.PgoInstrLink = true
}
}
}
}
})
} else {
// For executables and shared libraries, check all static dependencies.
ctx.VisitDirectDeps(func(m android.Module) {
if depTag, ok := ctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok {
if depTag.static() {
if cc, ok := m.(*Module); ok {
if cc.pgo.Properties.PgoInstrLink {
pgo.Properties.PgoInstrLink = true
}
}
}
}
})
}
props := pgo.Properties
// Add flags to profile this module based on its profile_kind
if (props.ShouldProfileModule && props.isInstrumentation()) || props.PgoInstrLink {
// Instrumentation PGO use and gather flags cannot coexist.
return props.addInstrumentationProfileGatherFlags(ctx, flags)
}
if !ctx.Config().IsEnvTrue("ANDROID_PGO_NO_PROFILE_USE") {
flags = props.addProfileUseFlags(ctx, flags)
}
return flags
}