diff --git a/cc/Android.bp b/cc/Android.bp index 77e96db35..9496bacfc 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -40,7 +40,6 @@ bootstrap_go_package { "lto.go", "makevars.go", "orderfile.go", - "pgo.go", "prebuilt.go", "proto.go", "rs.go", diff --git a/cc/cc.go b/cc/cc.go index a2cbb3622..74a8d3532 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -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 = <o{} 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{}, <OProperties{}, &AfdoProperties{}, - &PgoProperties{}, &OrderfileProperties{}, &android.ProtoProperties{}, // RustBindgenProperties is included here so that cc_defaults can be used for rust_bindgen modules. diff --git a/cc/lto.go b/cc/lto.go index 30d7b7578..d2a43d27b 100644 --- a/cc/lto.go +++ b/cc/lto.go @@ -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") diff --git a/cc/pgo.go b/cc/pgo.go deleted file mode 100644 index 463e2e623..000000000 --- a/cc/pgo.go +++ /dev/null @@ -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 - // . 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 -}