Merge "Refactor LTO"
diff --git a/cc/lto.go b/cc/lto.go
index 8d6e3e7..878c21f 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -46,12 +46,12 @@
Thin *bool `android:"arch_variant"`
} `android:"arch_variant"`
+ LtoEnabled bool `blueprint:"mutated"`
+
// Dep properties indicate that this module needs to be built with LTO
// since it is an object dependency of an LTO module.
- ThinEnabled bool `blueprint:"mutated"`
- NoLtoEnabled bool `blueprint:"mutated"`
- ThinDep bool `blueprint:"mutated"`
- NoLtoDep bool `blueprint:"mutated"`
+ LtoDep bool `blueprint:"mutated"`
+ NoLtoDep bool `blueprint:"mutated"`
// Use -fwhole-program-vtables cflag.
Whole_program_vtables *bool
@@ -66,19 +66,16 @@
}
func (lto *lto) begin(ctx BaseModuleContext) {
- if ctx.Config().IsEnvTrue("DISABLE_LTO") {
- lto.Properties.NoLtoEnabled = true
- }
+ lto.Properties.LtoEnabled = lto.LTO(ctx)
}
func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
- // TODO(b/131771163): Disable LTO when using explicit fuzzing configurations.
- // LTO breaks fuzzer builds.
- if ctx.isFuzzer() {
+ // TODO(b/131771163): CFI and Fuzzer controls LTO flags by themselves.
+ // This has be checked late because these properties can be mutated.
+ if ctx.isCfi() || ctx.isFuzzer() {
return flags
}
-
- if lto.LTO(ctx) {
+ if lto.Properties.LtoEnabled {
var ltoCFlag string
var ltoLdFlag string
if lto.ThinLTO() {
@@ -97,7 +94,7 @@
flags.Local.CFlags = append(flags.Local.CFlags, "-fwhole-program-vtables")
}
- if (lto.DefaultThinLTO(ctx) || lto.ThinLTO()) && ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") {
+ if ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") {
// Set appropriate ThinLTO cache policy
cacheDirFormat := "-Wl,--thinlto-cache-dir="
cacheDir := android.PathForOutput(ctx, "thinlto-cache").String()
@@ -120,30 +117,40 @@
return flags
}
+// Determine which LTO mode to use for the given module.
func (lto *lto) LTO(ctx BaseModuleContext) bool {
- return lto.ThinLTO() || lto.DefaultThinLTO(ctx)
-}
-
-func (lto *lto) DefaultThinLTO(ctx BaseModuleContext) bool {
+ if lto.Never() {
+ return false
+ }
+ if ctx.Config().IsEnvTrue("DISABLE_LTO") {
+ return false
+ }
+ // Module explicitly requests for LTO.
+ if lto.ThinLTO() {
+ return true
+ }
// LP32 has many subtle issues and less test coverage.
- lib32 := ctx.Arch().ArchType.Multilib == "lib32"
- // CFI adds LTO flags by itself.
- cfi := ctx.isCfi()
+ if ctx.Arch().ArchType.Multilib == "lib32" {
+ return false
+ }
// Performance and binary size are less important for host binaries and tests.
- host := ctx.Host()
- test := ctx.testBinary() || ctx.testLibrary()
+ if ctx.Host() || ctx.testBinary() || ctx.testLibrary() {
+ return false
+ }
// FIXME: ThinLTO for VNDK produces different output.
// b/169217596
- vndk := ctx.isVndk()
- return GlobalThinLTO(ctx) && !lto.Never() && !lib32 && !cfi && !host && !test && !vndk
+ if ctx.isVndk() {
+ return false
+ }
+ return GlobalThinLTO(ctx)
}
func (lto *lto) ThinLTO() bool {
- return lto != nil && (proptools.Bool(lto.Properties.Lto.Thin) || lto.Properties.ThinEnabled)
+ return lto != nil && proptools.Bool(lto.Properties.Lto.Thin)
}
func (lto *lto) Never() bool {
- return lto != nil && (proptools.Bool(lto.Properties.Lto.Never) || lto.Properties.NoLtoEnabled)
+ return lto != nil && proptools.Bool(lto.Properties.Lto.Never)
}
func GlobalThinLTO(ctx android.BaseModuleContext) bool {
@@ -152,11 +159,12 @@
// Propagate lto requirements down from binaries
func ltoDepsMutator(mctx android.TopDownMutatorContext) {
- globalThinLTO := GlobalThinLTO(mctx)
+ defaultLTOMode := GlobalThinLTO(mctx)
if m, ok := mctx.Module().(*Module); ok {
- thin := m.lto.ThinLTO()
- never := m.lto.Never()
+ if m.lto == nil || m.lto.Properties.LtoEnabled == defaultLTOMode {
+ return
+ }
mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
tag := mctx.OtherModuleDependencyTag(dep)
@@ -174,10 +182,9 @@
}
if dep, ok := dep.(*Module); ok {
- if !globalThinLTO && thin && !dep.lto.ThinLTO() {
- dep.lto.Properties.ThinDep = true
- }
- if globalThinLTO && never && !dep.lto.Never() {
+ if m.lto.Properties.LtoEnabled {
+ dep.lto.Properties.LtoDep = true
+ } else {
dep.lto.Properties.NoLtoDep = true
}
}
@@ -196,22 +203,19 @@
// Create variations for LTO types required as static
// dependencies
variationNames := []string{""}
- if !globalThinLTO && m.lto.Properties.ThinDep && !m.lto.ThinLTO() {
+ if m.lto.Properties.LtoDep {
variationNames = append(variationNames, "lto-thin")
}
- if globalThinLTO && m.lto.Properties.NoLtoDep && !m.lto.Never() {
+ if m.lto.Properties.NoLtoDep {
variationNames = append(variationNames, "lto-none")
}
- // Use correct dependencies if LTO property is explicitly set
- // (mutually exclusive)
- if !globalThinLTO && m.lto.ThinLTO() {
- mctx.SetDependencyVariation("lto-thin")
- }
- // Never must be the last, it overrides Thin.
- if globalThinLTO && m.lto.Never() {
+ if globalThinLTO && !m.lto.Properties.LtoEnabled {
mctx.SetDependencyVariation("lto-none")
}
+ if !globalThinLTO && m.lto.Properties.LtoEnabled {
+ mctx.SetDependencyVariation("lto-thin")
+ }
if len(variationNames) > 1 {
modules := mctx.CreateVariations(variationNames...)
@@ -226,14 +230,14 @@
// LTO properties for dependencies
if name == "lto-thin" {
- variation.lto.Properties.ThinEnabled = true
+ variation.lto.Properties.LtoEnabled = true
}
if name == "lto-none" {
- variation.lto.Properties.NoLtoEnabled = true
+ variation.lto.Properties.LtoEnabled = false
}
variation.Properties.PreventInstall = true
variation.Properties.HideFromMake = true
- variation.lto.Properties.ThinDep = false
+ variation.lto.Properties.LtoDep = false
variation.lto.Properties.NoLtoDep = false
}
}