Merge "Refactor LTO"

This commit is contained in:
Yi Kong
2023-06-09 03:16:22 +00:00
committed by Gerrit Code Review

View File

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