blob: 1233e332efd9420d27c2e10feba403dbb1f08129 [file] [log] [blame]
Yi Kongeb8efc92021-12-09 18:06:29 +08001// Copyright 2021 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package cc
16
17import (
18 "fmt"
19 "strings"
20
Yi Kongeb8efc92021-12-09 18:06:29 +080021 "android/soong/android"
Vinh Tran44cb78c2023-03-09 22:07:19 -050022
23 "github.com/google/blueprint"
Yi Kongeb8efc92021-12-09 18:06:29 +080024)
25
Vinh Tran056effb2023-06-27 14:03:25 +000026// This flag needs to be in both CFlags and LdFlags to ensure correct symbol ordering
Yi Kong0880a822023-11-14 23:49:40 +000027const afdoFlagsFormat = "-fprofile-sample-use=%s -fprofile-sample-accurate"
Yi Kongeb8efc92021-12-09 18:06:29 +080028
Yi Kongeb8efc92021-12-09 18:06:29 +080029type AfdoProperties struct {
Alix40216ae2022-04-07 20:47:01 +000030 // Afdo allows developers self-service enroll for
31 // automatic feedback-directed optimization using profile data.
Yi Kongeb8efc92021-12-09 18:06:29 +080032 Afdo bool
33
Colin Cross3513fb12024-01-24 14:44:47 -080034 AfdoDep bool `blueprint:"mutated"`
Yi Kongeb8efc92021-12-09 18:06:29 +080035}
36
37type afdo struct {
38 Properties AfdoProperties
39}
40
41func (afdo *afdo) props() []interface{} {
42 return []interface{}{&afdo.Properties}
43}
44
Yi Kong9723e332023-12-04 14:52:53 +090045func (afdo *afdo) begin(ctx BaseModuleContext) {
46 // Disable on eng builds for faster build.
47 if ctx.Config().Eng() {
48 afdo.Properties.Afdo = false
49 }
Yi Kong3d9bed92024-08-05 15:12:57 +090050 // Disable for native coverage builds.
51 if ctx.DeviceConfig().NativeCoverageEnabled() {
52 afdo.Properties.Afdo = false
53 }
Yi Kong9723e332023-12-04 14:52:53 +090054}
55
Vinh Tran44cb78c2023-03-09 22:07:19 -050056// afdoEnabled returns true for binaries and shared libraries
Colin Cross3513fb12024-01-24 14:44:47 -080057// that set afdo prop to True.
Vinh Tran44cb78c2023-03-09 22:07:19 -050058func (afdo *afdo) afdoEnabled() bool {
Yabin Cui01c44562023-04-20 14:07:29 -070059 return afdo != nil && afdo.Properties.Afdo
Yi Kongeb8efc92021-12-09 18:06:29 +080060}
61
Colin Cross3513fb12024-01-24 14:44:47 -080062func (afdo *afdo) isAfdoCompile(ctx ModuleContext) bool {
63 fdoProfilePath := getFdoProfilePathFromDep(ctx)
64 return !ctx.Host() && (afdo.Properties.Afdo || afdo.Properties.AfdoDep) && (fdoProfilePath != "")
65}
66
67func getFdoProfilePathFromDep(ctx ModuleContext) string {
Yu Liuffe86322024-12-18 18:53:12 +000068 fdoProfileDeps := ctx.GetDirectDepsProxyWithTag(FdoProfileTag)
69 if len(fdoProfileDeps) > 0 {
Colin Cross3513fb12024-01-24 14:44:47 -080070 if info, ok := android.OtherModuleProvider(ctx, fdoProfileDeps[0], FdoProfileProvider); ok {
71 return info.Path.String()
72 }
73 }
74 return ""
75}
76
Yi Kongeb8efc92021-12-09 18:06:29 +080077func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags {
Colin Cross15fa8142024-02-07 15:09:08 -080078 if ctx.Host() {
79 return flags
80 }
81
Colin Cross3513fb12024-01-24 14:44:47 -080082 if afdo.Properties.Afdo || afdo.Properties.AfdoDep {
Yi Kong3d9bed92024-08-05 15:12:57 +090083 // Emit additional debug info for AutoFDO
84 flags.Local.CFlags = append([]string{"-fdebug-info-for-profiling"}, flags.Local.CFlags...)
Yabin Cui01c44562023-04-20 14:07:29 -070085 // We use `-funique-internal-linkage-names` to associate profiles to the right internal
86 // functions. This option should be used before generating a profile. Because a profile
87 // generated for a binary without unique names doesn't work well building a binary with
88 // unique names (they have different internal function names).
89 // To avoid a chicken-and-egg problem, we enable `-funique-internal-linkage-names` when
90 // `afdo=true`, whether a profile exists or not.
91 // The profile can take effect in three steps:
92 // 1. Add `afdo: true` in Android.bp, and build the binary.
93 // 2. Collect an AutoFDO profile for the binary.
94 // 3. Make the profile searchable by the build system. So it's used the next time the binary
95 // is built.
96 flags.Local.CFlags = append([]string{"-funique-internal-linkage-names"}, flags.Local.CFlags...)
Yi Kongbc2d02a2023-10-16 16:57:53 +090097 // Flags for Flow Sensitive AutoFDO
Yi Kongb33ced02023-10-10 14:11:50 +090098 flags.Local.CFlags = append([]string{"-mllvm", "-enable-fs-discriminator=true"}, flags.Local.CFlags...)
Yi Kong29501242025-02-19 19:44:36 +090099 flags.Local.LdFlags = append([]string{"-Wl,-mllvm,-enable-fs-discriminator=true"}, flags.Local.LdFlags...)
Yi Kongbc2d02a2023-10-16 16:57:53 +0900100 // TODO(b/266595187): Remove the following feature once it is enabled in LLVM by default.
101 flags.Local.CFlags = append([]string{"-mllvm", "-improved-fs-discriminator=true"}, flags.Local.CFlags...)
Yi Kong29501242025-02-19 19:44:36 +0900102 flags.Local.LdFlags = append([]string{"-Wl,-mllvm,-improved-fs-discriminator=true"}, flags.Local.LdFlags...)
Yabin Cui01c44562023-04-20 14:07:29 -0700103 }
Colin Cross3513fb12024-01-24 14:44:47 -0800104 if fdoProfilePath := getFdoProfilePathFromDep(ctx); fdoProfilePath != "" {
Ke-Yu Lu351d3642024-02-06 02:15:03 +0000105 // The flags are prepended to allow overriding.
Colin Cross3513fb12024-01-24 14:44:47 -0800106 profileUseFlag := fmt.Sprintf(afdoFlagsFormat, fdoProfilePath)
Ke-Yu Lu351d3642024-02-06 02:15:03 +0000107 flags.Local.CFlags = append([]string{profileUseFlag}, flags.Local.CFlags...)
Yi Kongca4d0c92025-03-04 10:37:09 -0800108 // Salvage stale profile by fuzzy matching and use the remapped location for sample profile query.
109 flags.Local.CFlags = append([]string{"-mllvm", "--salvage-stale-profile=true"}, flags.Local.CFlags...)
110 flags.Local.CFlags = append([]string{"-mllvm", "--salvage-stale-profile-max-callsites=2000"}, flags.Local.CFlags...)
Ke-Yu Lu351d3642024-02-06 02:15:03 +0000111 flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...)
Yi Kongeb8efc92021-12-09 18:06:29 +0800112
Ke-Yu Lu351d3642024-02-06 02:15:03 +0000113 // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
114 // if profileFile gets updated
Colin Cross3513fb12024-01-24 14:44:47 -0800115 pathForSrc := android.PathForSource(ctx, fdoProfilePath)
Ke-Yu Lu351d3642024-02-06 02:15:03 +0000116 flags.CFlagsDeps = append(flags.CFlagsDeps, pathForSrc)
117 flags.LdFlagsDeps = append(flags.LdFlagsDeps, pathForSrc)
Yi Kongeb8efc92021-12-09 18:06:29 +0800118 }
119
120 return flags
121}
122
Colin Cross3513fb12024-01-24 14:44:47 -0800123func (a *afdo) addDep(ctx android.BottomUpMutatorContext, fdoProfileTarget string) {
124 if fdoProfileName, err := ctx.DeviceConfig().AfdoProfile(fdoProfileTarget); fdoProfileName != "" && err == nil {
125 ctx.AddFarVariationDependencies(
126 []blueprint.Variation{
127 {Mutator: "arch", Variation: ctx.Target().ArchVariation()},
128 {Mutator: "os", Variation: "android"},
129 },
130 FdoProfileTag,
131 fdoProfileName)
Colin Crossd38feb02024-01-23 16:38:06 -0800132 }
Vinh Tran44cb78c2023-03-09 22:07:19 -0500133}
134
Colin Crossd38feb02024-01-23 16:38:06 -0800135func afdoPropagateViaDepTag(tag blueprint.DependencyTag) bool {
136 libTag, isLibTag := tag.(libraryDependencyTag)
137 // Do not recurse down non-static dependencies
138 if isLibTag {
139 return libTag.static()
140 } else {
141 return tag == objDepTag || tag == reuseObjTag || tag == staticVariantTag
Ke-Yu Lu0be9d602024-02-06 02:15:03 +0000142 }
143}
144
Colin Crossd38feb02024-01-23 16:38:06 -0800145// afdoTransitionMutator creates afdo variants of cc modules.
146type afdoTransitionMutator struct{}
147
148func (a *afdoTransitionMutator) Split(ctx android.BaseModuleContext) []string {
149 return []string{""}
150}
151
152func (a *afdoTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
153 if ctx.Host() {
154 return ""
155 }
156
157 if m, ok := ctx.Module().(*Module); ok && m.afdo != nil {
158 if !afdoPropagateViaDepTag(ctx.DepTag()) {
159 return ""
160 }
161
162 if sourceVariation != "" {
163 return sourceVariation
164 }
165
166 if !m.afdo.afdoEnabled() {
167 return ""
168 }
169
170 // TODO(b/324141705): this is designed to prevent propagating AFDO from static libraries that have afdo: true set, but
Colin Cross6a730042024-12-05 13:53:43 -0800171 // it should be m.staticLibrary() so that static binaries use AFDO variants of dependencies.
Colin Crossd38feb02024-01-23 16:38:06 -0800172 if m.static() {
173 return ""
174 }
175
176 return encodeTarget(ctx.Module().Name())
177 }
178 return ""
179}
180
181func (a *afdoTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
182 if m, ok := ctx.Module().(*Module); ok && m.afdo != nil {
183 return incomingVariation
184 }
185 return ""
186}
187
188func (a *afdoTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
Colin Crossd38feb02024-01-23 16:38:06 -0800189 if m, ok := ctx.Module().(*Module); ok && m.afdo != nil {
Yi Kongf8856892024-07-03 02:02:23 +0900190 if !m.Enabled(ctx) {
191 return
192 }
Colin Cross3513fb12024-01-24 14:44:47 -0800193 if variation == "" {
194 // The empty variation is either a module that has enabled AFDO for itself, or the non-AFDO
195 // variant of a dependency.
Colin Cross6a730042024-12-05 13:53:43 -0800196 if m.afdo.afdoEnabled() && !m.staticLibrary() && !m.Host() {
Colin Cross3513fb12024-01-24 14:44:47 -0800197 m.afdo.addDep(ctx, ctx.ModuleName())
Yi Kongeb8efc92021-12-09 18:06:29 +0800198 }
Colin Cross3513fb12024-01-24 14:44:47 -0800199 } else {
200 // The non-empty variation is the AFDO variant of a dependency of a module that enabled AFDO
201 // for itself.
202 m.Properties.PreventInstall = true
203 m.Properties.HideFromMake = true
204 m.afdo.Properties.AfdoDep = true
205 m.afdo.addDep(ctx, decodeTarget(variation))
Yi Kongeb8efc92021-12-09 18:06:29 +0800206 }
207 }
208}
209
210// Encode target name to variation name.
211func encodeTarget(target string) string {
212 if target == "" {
213 return ""
214 }
215 return "afdo-" + target
216}
217
218// Decode target name from variation name.
219func decodeTarget(variation string) string {
220 if variation == "" {
221 return ""
222 }
223 return strings.TrimPrefix(variation, "afdo-")
224}