blob: 1e229006991d996124f8c72511dcf635654033dc [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"
Ke-Yu Lu351d3642024-02-06 02:15:03 +000024 "github.com/google/blueprint/proptools"
Yi Kongeb8efc92021-12-09 18:06:29 +080025)
26
Vinh Tran056effb2023-06-27 14:03:25 +000027// This flag needs to be in both CFlags and LdFlags to ensure correct symbol ordering
Yi Kong0880a822023-11-14 23:49:40 +000028const afdoFlagsFormat = "-fprofile-sample-use=%s -fprofile-sample-accurate"
Yi Kongeb8efc92021-12-09 18:06:29 +080029
Yi Kongeb8efc92021-12-09 18:06:29 +080030type AfdoProperties struct {
Alix40216ae2022-04-07 20:47:01 +000031 // Afdo allows developers self-service enroll for
32 // automatic feedback-directed optimization using profile data.
Yi Kongeb8efc92021-12-09 18:06:29 +080033 Afdo bool
34
Ke-Yu Lu351d3642024-02-06 02:15:03 +000035 FdoProfilePath *string `blueprint:"mutated"`
Yi Kongeb8efc92021-12-09 18:06:29 +080036}
37
38type afdo struct {
39 Properties AfdoProperties
40}
41
42func (afdo *afdo) props() []interface{} {
43 return []interface{}{&afdo.Properties}
44}
45
Yi Kong9723e332023-12-04 14:52:53 +090046func (afdo *afdo) begin(ctx BaseModuleContext) {
47 // Disable on eng builds for faster build.
48 if ctx.Config().Eng() {
49 afdo.Properties.Afdo = false
50 }
51}
52
Vinh Tran44cb78c2023-03-09 22:07:19 -050053// afdoEnabled returns true for binaries and shared libraries
54// that set afdo prop to True and there is a profile available
55func (afdo *afdo) afdoEnabled() bool {
Yabin Cui01c44562023-04-20 14:07:29 -070056 return afdo != nil && afdo.Properties.Afdo
Yi Kongeb8efc92021-12-09 18:06:29 +080057}
58
Yi Kongeb8efc92021-12-09 18:06:29 +080059func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags {
Colin Cross15fa8142024-02-07 15:09:08 -080060 if ctx.Host() {
61 return flags
62 }
63
Ke-Yu Lu351d3642024-02-06 02:15:03 +000064 if afdo.Properties.Afdo {
Yabin Cui01c44562023-04-20 14:07:29 -070065 // We use `-funique-internal-linkage-names` to associate profiles to the right internal
66 // functions. This option should be used before generating a profile. Because a profile
67 // generated for a binary without unique names doesn't work well building a binary with
68 // unique names (they have different internal function names).
69 // To avoid a chicken-and-egg problem, we enable `-funique-internal-linkage-names` when
70 // `afdo=true`, whether a profile exists or not.
71 // The profile can take effect in three steps:
72 // 1. Add `afdo: true` in Android.bp, and build the binary.
73 // 2. Collect an AutoFDO profile for the binary.
74 // 3. Make the profile searchable by the build system. So it's used the next time the binary
75 // is built.
76 flags.Local.CFlags = append([]string{"-funique-internal-linkage-names"}, flags.Local.CFlags...)
Yi Kongbc2d02a2023-10-16 16:57:53 +090077 // Flags for Flow Sensitive AutoFDO
Yi Kongb33ced02023-10-10 14:11:50 +090078 flags.Local.CFlags = append([]string{"-mllvm", "-enable-fs-discriminator=true"}, flags.Local.CFlags...)
Yi Kongbc2d02a2023-10-16 16:57:53 +090079 // TODO(b/266595187): Remove the following feature once it is enabled in LLVM by default.
80 flags.Local.CFlags = append([]string{"-mllvm", "-improved-fs-discriminator=true"}, flags.Local.CFlags...)
Yabin Cui01c44562023-04-20 14:07:29 -070081 }
Ke-Yu Lu351d3642024-02-06 02:15:03 +000082 if path := afdo.Properties.FdoProfilePath; path != nil {
83 // The flags are prepended to allow overriding.
84 profileUseFlag := fmt.Sprintf(afdoFlagsFormat, *path)
85 flags.Local.CFlags = append([]string{profileUseFlag}, flags.Local.CFlags...)
86 flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...)
Yi Kongeb8efc92021-12-09 18:06:29 +080087
Ke-Yu Lu351d3642024-02-06 02:15:03 +000088 // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
89 // if profileFile gets updated
90 pathForSrc := android.PathForSource(ctx, *path)
91 flags.CFlagsDeps = append(flags.CFlagsDeps, pathForSrc)
92 flags.LdFlagsDeps = append(flags.LdFlagsDeps, pathForSrc)
Yi Kongeb8efc92021-12-09 18:06:29 +080093 }
94
95 return flags
96}
97
Ke-Yu Lu351d3642024-02-06 02:15:03 +000098// FdoProfileMutator reads the FdoProfileProvider from a direct dep with FdoProfileTag
99// assigns FdoProfileInfo.Path to the FdoProfilePath mutated property
100func (c *Module) fdoProfileMutator(ctx android.BottomUpMutatorContext) {
101 if !c.Enabled() {
102 return
103 }
104
105 if !c.afdo.afdoEnabled() {
106 return
107 }
108
Colin Crossd38feb02024-01-23 16:38:06 -0800109 if c.Host() {
110 return
111 }
112
113 if c.static() && !c.staticBinary() {
114 return
115 }
116
117 if c, ok := ctx.Module().(*Module); ok && c.Enabled() {
118 if fdoProfileName, err := ctx.DeviceConfig().AfdoProfile(ctx.ModuleName()); fdoProfileName != "" && err == nil {
119 deps := ctx.AddFarVariationDependencies(
120 []blueprint.Variation{
121 {Mutator: "arch", Variation: ctx.Target().ArchVariation()},
122 {Mutator: "os", Variation: "android"},
123 },
124 FdoProfileTag,
125 fdoProfileName)
126 if len(deps) > 0 && deps[0] != nil {
127 if info, ok := android.OtherModuleProvider(ctx, deps[0], FdoProfileProvider); ok {
128 c.afdo.Properties.FdoProfilePath = proptools.StringPtr(info.Path.String())
129 }
130 }
Ke-Yu Lu351d3642024-02-06 02:15:03 +0000131 }
Colin Crossd38feb02024-01-23 16:38:06 -0800132 }
Vinh Tran44cb78c2023-03-09 22:07:19 -0500133}
134
Ke-Yu Lu351d3642024-02-06 02:15:03 +0000135var _ FdoProfileMutatorInterface = (*Module)(nil)
136
Colin Crossd38feb02024-01-23 16:38:06 -0800137func afdoPropagateViaDepTag(tag blueprint.DependencyTag) bool {
138 libTag, isLibTag := tag.(libraryDependencyTag)
139 // Do not recurse down non-static dependencies
140 if isLibTag {
141 return libTag.static()
142 } else {
143 return tag == objDepTag || tag == reuseObjTag || tag == staticVariantTag
Ke-Yu Lu0be9d602024-02-06 02:15:03 +0000144 }
145}
146
Colin Crossd38feb02024-01-23 16:38:06 -0800147// afdoTransitionMutator creates afdo variants of cc modules.
148type afdoTransitionMutator struct{}
149
150func (a *afdoTransitionMutator) Split(ctx android.BaseModuleContext) []string {
151 return []string{""}
152}
153
154func (a *afdoTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
155 if ctx.Host() {
156 return ""
157 }
158
159 if m, ok := ctx.Module().(*Module); ok && m.afdo != nil {
160 if !afdoPropagateViaDepTag(ctx.DepTag()) {
161 return ""
162 }
163
164 if sourceVariation != "" {
165 return sourceVariation
166 }
167
168 if !m.afdo.afdoEnabled() {
169 return ""
170 }
171
172 // TODO(b/324141705): this is designed to prevent propagating AFDO from static libraries that have afdo: true set, but
173 // it should be m.static() && !m.staticBinary() so that static binaries use AFDO variants of dependencies.
174 if m.static() {
175 return ""
176 }
177
178 return encodeTarget(ctx.Module().Name())
179 }
180 return ""
181}
182
183func (a *afdoTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
184 if m, ok := ctx.Module().(*Module); ok && m.afdo != nil {
185 return incomingVariation
186 }
187 return ""
188}
189
190func (a *afdoTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
191 if variation == "" {
Colin Cross15fa8142024-02-07 15:09:08 -0800192 return
193 }
194
Colin Crossd38feb02024-01-23 16:38:06 -0800195 if m, ok := ctx.Module().(*Module); ok && m.afdo != nil {
196 m.Properties.PreventInstall = true
197 m.Properties.HideFromMake = true
198 m.afdo.Properties.Afdo = true
199 if fdoProfileName, err := ctx.DeviceConfig().AfdoProfile(decodeTarget(variation)); fdoProfileName != "" && err == nil {
200 deps := ctx.AddFarVariationDependencies(
201 []blueprint.Variation{
202 {Mutator: "arch", Variation: ctx.Target().ArchVariation()},
203 {Mutator: "os", Variation: "android"},
204 },
205 FdoProfileTag,
206 fdoProfileName)
207 if len(deps) > 0 && deps[0] != nil {
208 if info, ok := android.OtherModuleProvider(ctx, deps[0], FdoProfileProvider); ok {
209 m.afdo.Properties.FdoProfilePath = proptools.StringPtr(info.Path.String())
Ke-Yu Lu0be9d602024-02-06 02:15:03 +0000210 }
Yi Kongeb8efc92021-12-09 18:06:29 +0800211 }
Yi Kongeb8efc92021-12-09 18:06:29 +0800212 }
213 }
214}
215
216// Encode target name to variation name.
217func encodeTarget(target string) string {
218 if target == "" {
219 return ""
220 }
221 return "afdo-" + target
222}
223
224// Decode target name from variation name.
225func decodeTarget(variation string) string {
226 if variation == "" {
227 return ""
228 }
229 return strings.TrimPrefix(variation, "afdo-")
230}