blob: 00b22456f0b68580b09f9296517c62370ae23ffe [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 }
50}
51
Vinh Tran44cb78c2023-03-09 22:07:19 -050052// afdoEnabled returns true for binaries and shared libraries
Colin Cross3513fb12024-01-24 14:44:47 -080053// that set afdo prop to True.
Vinh Tran44cb78c2023-03-09 22:07:19 -050054func (afdo *afdo) afdoEnabled() bool {
Yabin Cui01c44562023-04-20 14:07:29 -070055 return afdo != nil && afdo.Properties.Afdo
Yi Kongeb8efc92021-12-09 18:06:29 +080056}
57
Colin Cross3513fb12024-01-24 14:44:47 -080058func (afdo *afdo) isAfdoCompile(ctx ModuleContext) bool {
59 fdoProfilePath := getFdoProfilePathFromDep(ctx)
60 return !ctx.Host() && (afdo.Properties.Afdo || afdo.Properties.AfdoDep) && (fdoProfilePath != "")
61}
62
63func getFdoProfilePathFromDep(ctx ModuleContext) string {
64 fdoProfileDeps := ctx.GetDirectDepsWithTag(FdoProfileTag)
65 if len(fdoProfileDeps) > 0 && fdoProfileDeps[0] != nil {
66 if info, ok := android.OtherModuleProvider(ctx, fdoProfileDeps[0], FdoProfileProvider); ok {
67 return info.Path.String()
68 }
69 }
70 return ""
71}
72
Yi Kongeb8efc92021-12-09 18:06:29 +080073func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags {
Colin Cross15fa8142024-02-07 15:09:08 -080074 if ctx.Host() {
75 return flags
76 }
77
Colin Cross3513fb12024-01-24 14:44:47 -080078 if afdo.Properties.Afdo || afdo.Properties.AfdoDep {
Yabin Cui01c44562023-04-20 14:07:29 -070079 // We use `-funique-internal-linkage-names` to associate profiles to the right internal
80 // functions. This option should be used before generating a profile. Because a profile
81 // generated for a binary without unique names doesn't work well building a binary with
82 // unique names (they have different internal function names).
83 // To avoid a chicken-and-egg problem, we enable `-funique-internal-linkage-names` when
84 // `afdo=true`, whether a profile exists or not.
85 // The profile can take effect in three steps:
86 // 1. Add `afdo: true` in Android.bp, and build the binary.
87 // 2. Collect an AutoFDO profile for the binary.
88 // 3. Make the profile searchable by the build system. So it's used the next time the binary
89 // is built.
90 flags.Local.CFlags = append([]string{"-funique-internal-linkage-names"}, flags.Local.CFlags...)
Yi Kongbc2d02a2023-10-16 16:57:53 +090091 // Flags for Flow Sensitive AutoFDO
Yi Kongb33ced02023-10-10 14:11:50 +090092 flags.Local.CFlags = append([]string{"-mllvm", "-enable-fs-discriminator=true"}, flags.Local.CFlags...)
Yi Kongbc2d02a2023-10-16 16:57:53 +090093 // TODO(b/266595187): Remove the following feature once it is enabled in LLVM by default.
94 flags.Local.CFlags = append([]string{"-mllvm", "-improved-fs-discriminator=true"}, flags.Local.CFlags...)
Yabin Cui01c44562023-04-20 14:07:29 -070095 }
Colin Cross3513fb12024-01-24 14:44:47 -080096 if fdoProfilePath := getFdoProfilePathFromDep(ctx); fdoProfilePath != "" {
Ke-Yu Lu351d3642024-02-06 02:15:03 +000097 // The flags are prepended to allow overriding.
Colin Cross3513fb12024-01-24 14:44:47 -080098 profileUseFlag := fmt.Sprintf(afdoFlagsFormat, fdoProfilePath)
Ke-Yu Lu351d3642024-02-06 02:15:03 +000099 flags.Local.CFlags = append([]string{profileUseFlag}, flags.Local.CFlags...)
100 flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...)
Yi Kongeb8efc92021-12-09 18:06:29 +0800101
Ke-Yu Lu351d3642024-02-06 02:15:03 +0000102 // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
103 // if profileFile gets updated
Colin Cross3513fb12024-01-24 14:44:47 -0800104 pathForSrc := android.PathForSource(ctx, fdoProfilePath)
Ke-Yu Lu351d3642024-02-06 02:15:03 +0000105 flags.CFlagsDeps = append(flags.CFlagsDeps, pathForSrc)
106 flags.LdFlagsDeps = append(flags.LdFlagsDeps, pathForSrc)
Yi Kongeb8efc92021-12-09 18:06:29 +0800107 }
108
109 return flags
110}
111
Colin Cross3513fb12024-01-24 14:44:47 -0800112func (a *afdo) addDep(ctx android.BottomUpMutatorContext, fdoProfileTarget string) {
113 if fdoProfileName, err := ctx.DeviceConfig().AfdoProfile(fdoProfileTarget); fdoProfileName != "" && err == nil {
114 ctx.AddFarVariationDependencies(
115 []blueprint.Variation{
116 {Mutator: "arch", Variation: ctx.Target().ArchVariation()},
117 {Mutator: "os", Variation: "android"},
118 },
119 FdoProfileTag,
120 fdoProfileName)
Colin Crossd38feb02024-01-23 16:38:06 -0800121 }
Vinh Tran44cb78c2023-03-09 22:07:19 -0500122}
123
Colin Crossd38feb02024-01-23 16:38:06 -0800124func afdoPropagateViaDepTag(tag blueprint.DependencyTag) bool {
125 libTag, isLibTag := tag.(libraryDependencyTag)
126 // Do not recurse down non-static dependencies
127 if isLibTag {
128 return libTag.static()
129 } else {
130 return tag == objDepTag || tag == reuseObjTag || tag == staticVariantTag
Ke-Yu Lu0be9d602024-02-06 02:15:03 +0000131 }
132}
133
Colin Crossd38feb02024-01-23 16:38:06 -0800134// afdoTransitionMutator creates afdo variants of cc modules.
135type afdoTransitionMutator struct{}
136
137func (a *afdoTransitionMutator) Split(ctx android.BaseModuleContext) []string {
138 return []string{""}
139}
140
141func (a *afdoTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
142 if ctx.Host() {
143 return ""
144 }
145
146 if m, ok := ctx.Module().(*Module); ok && m.afdo != nil {
147 if !afdoPropagateViaDepTag(ctx.DepTag()) {
148 return ""
149 }
150
151 if sourceVariation != "" {
152 return sourceVariation
153 }
154
155 if !m.afdo.afdoEnabled() {
156 return ""
157 }
158
159 // TODO(b/324141705): this is designed to prevent propagating AFDO from static libraries that have afdo: true set, but
160 // it should be m.static() && !m.staticBinary() so that static binaries use AFDO variants of dependencies.
161 if m.static() {
162 return ""
163 }
164
165 return encodeTarget(ctx.Module().Name())
166 }
167 return ""
168}
169
170func (a *afdoTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
171 if m, ok := ctx.Module().(*Module); ok && m.afdo != nil {
172 return incomingVariation
173 }
174 return ""
175}
176
177func (a *afdoTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
Colin Crossd38feb02024-01-23 16:38:06 -0800178 if m, ok := ctx.Module().(*Module); ok && m.afdo != nil {
Colin Cross3513fb12024-01-24 14:44:47 -0800179 if variation == "" {
180 // The empty variation is either a module that has enabled AFDO for itself, or the non-AFDO
181 // variant of a dependency.
182 if m.afdo.afdoEnabled() && !(m.static() && !m.staticBinary()) && !m.Host() {
183 m.afdo.addDep(ctx, ctx.ModuleName())
Yi Kongeb8efc92021-12-09 18:06:29 +0800184 }
Colin Cross3513fb12024-01-24 14:44:47 -0800185 } else {
186 // The non-empty variation is the AFDO variant of a dependency of a module that enabled AFDO
187 // for itself.
188 m.Properties.PreventInstall = true
189 m.Properties.HideFromMake = true
190 m.afdo.Properties.AfdoDep = true
191 m.afdo.addDep(ctx, decodeTarget(variation))
Yi Kongeb8efc92021-12-09 18:06:29 +0800192 }
193 }
194}
195
196// Encode target name to variation name.
197func encodeTarget(target string) string {
198 if target == "" {
199 return ""
200 }
201 return "afdo-" + target
202}
203
204// Decode target name from variation name.
205func decodeTarget(variation string) string {
206 if variation == "" {
207 return ""
208 }
209 return strings.TrimPrefix(variation, "afdo-")
210}