blob: 61550845d42427c0b7ea5e56122590031fecd83e [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 {
Ke-Yu Lu351d3642024-02-06 02:15:03 +000060 if afdo.Properties.Afdo {
Yabin Cui01c44562023-04-20 14:07:29 -070061 // We use `-funique-internal-linkage-names` to associate profiles to the right internal
62 // functions. This option should be used before generating a profile. Because a profile
63 // generated for a binary without unique names doesn't work well building a binary with
64 // unique names (they have different internal function names).
65 // To avoid a chicken-and-egg problem, we enable `-funique-internal-linkage-names` when
66 // `afdo=true`, whether a profile exists or not.
67 // The profile can take effect in three steps:
68 // 1. Add `afdo: true` in Android.bp, and build the binary.
69 // 2. Collect an AutoFDO profile for the binary.
70 // 3. Make the profile searchable by the build system. So it's used the next time the binary
71 // is built.
72 flags.Local.CFlags = append([]string{"-funique-internal-linkage-names"}, flags.Local.CFlags...)
Yi Kongbc2d02a2023-10-16 16:57:53 +090073 // Flags for Flow Sensitive AutoFDO
Yi Kongb33ced02023-10-10 14:11:50 +090074 flags.Local.CFlags = append([]string{"-mllvm", "-enable-fs-discriminator=true"}, flags.Local.CFlags...)
Yi Kongbc2d02a2023-10-16 16:57:53 +090075 // TODO(b/266595187): Remove the following feature once it is enabled in LLVM by default.
76 flags.Local.CFlags = append([]string{"-mllvm", "-improved-fs-discriminator=true"}, flags.Local.CFlags...)
Yabin Cui01c44562023-04-20 14:07:29 -070077 }
Ke-Yu Lu351d3642024-02-06 02:15:03 +000078 if path := afdo.Properties.FdoProfilePath; path != nil {
79 // The flags are prepended to allow overriding.
80 profileUseFlag := fmt.Sprintf(afdoFlagsFormat, *path)
81 flags.Local.CFlags = append([]string{profileUseFlag}, flags.Local.CFlags...)
82 flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...)
Yi Kongeb8efc92021-12-09 18:06:29 +080083
Ke-Yu Lu351d3642024-02-06 02:15:03 +000084 // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
85 // if profileFile gets updated
86 pathForSrc := android.PathForSource(ctx, *path)
87 flags.CFlagsDeps = append(flags.CFlagsDeps, pathForSrc)
88 flags.LdFlagsDeps = append(flags.LdFlagsDeps, pathForSrc)
Yi Kongeb8efc92021-12-09 18:06:29 +080089 }
90
91 return flags
92}
93
Ke-Yu Lu351d3642024-02-06 02:15:03 +000094// FdoProfileMutator reads the FdoProfileProvider from a direct dep with FdoProfileTag
95// assigns FdoProfileInfo.Path to the FdoProfilePath mutated property
96func (c *Module) fdoProfileMutator(ctx android.BottomUpMutatorContext) {
97 if !c.Enabled() {
98 return
99 }
100
101 if !c.afdo.afdoEnabled() {
102 return
103 }
104
105 if c.Host() {
106 return
107 }
108
109 if c.static() && !c.staticBinary() {
110 return
111 }
112
113 if c, ok := ctx.Module().(*Module); ok && c.Enabled() {
114 if fdoProfileName, err := ctx.DeviceConfig().AfdoProfile(ctx.ModuleName()); fdoProfileName != "" && err == nil {
115 deps := ctx.AddFarVariationDependencies(
116 []blueprint.Variation{
117 {Mutator: "arch", Variation: ctx.Target().ArchVariation()},
118 {Mutator: "os", Variation: "android"},
119 },
120 FdoProfileTag,
121 fdoProfileName)
122 if len(deps) > 0 && deps[0] != nil {
123 if info, ok := android.OtherModuleProvider(ctx, deps[0], FdoProfileProvider); ok {
124 c.afdo.Properties.FdoProfilePath = proptools.StringPtr(info.Path.String())
125 }
126 }
127 }
Colin Crossa6b407f2024-01-23 16:38:06 -0800128 }
Vinh Tran44cb78c2023-03-09 22:07:19 -0500129}
130
Ke-Yu Lu351d3642024-02-06 02:15:03 +0000131var _ FdoProfileMutatorInterface = (*Module)(nil)
132
Colin Crossa6b407f2024-01-23 16:38:06 -0800133func afdoPropagateViaDepTag(tag blueprint.DependencyTag) bool {
134 libTag, isLibTag := tag.(libraryDependencyTag)
135 // Do not recurse down non-static dependencies
136 if isLibTag {
137 return libTag.static()
138 } else {
139 return tag == objDepTag || tag == reuseObjTag || tag == staticVariantTag
Yi Kongeb8efc92021-12-09 18:06:29 +0800140 }
141}
142
Colin Crossa6b407f2024-01-23 16:38:06 -0800143// afdoTransitionMutator creates afdo variants of cc modules.
144type afdoTransitionMutator struct{}
145
146func (a *afdoTransitionMutator) Split(ctx android.BaseModuleContext) []string {
147 return []string{""}
148}
149
150func (a *afdoTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
151 if m, ok := ctx.Module().(*Module); ok && m.afdo != nil {
152 if !afdoPropagateViaDepTag(ctx.DepTag()) {
153 return ""
Yi Kongeb8efc92021-12-09 18:06:29 +0800154 }
155
Colin Crossa6b407f2024-01-23 16:38:06 -0800156 if sourceVariation != "" {
157 return sourceVariation
Yi Kongeb8efc92021-12-09 18:06:29 +0800158 }
Vinh Tran44cb78c2023-03-09 22:07:19 -0500159
Colin Crossa6b407f2024-01-23 16:38:06 -0800160 if m.afdo.afdoEnabled() && !(m.static() && !m.staticBinary()) && !m.Host() {
161 return encodeTarget(ctx.Module().Name())
162 }
163 }
164 return ""
165}
166
167func (a *afdoTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
168 if m, ok := ctx.Module().(*Module); ok && m.afdo != nil {
169 return incomingVariation
170 }
171 return ""
172}
173
174func (a *afdoTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
Ke-Yu Lu351d3642024-02-06 02:15:03 +0000175 if variation == "" {
176 return
177 }
178
Colin Crossa6b407f2024-01-23 16:38:06 -0800179 if m, ok := ctx.Module().(*Module); ok && m.afdo != nil {
Ke-Yu Lu351d3642024-02-06 02:15:03 +0000180 m.Properties.PreventInstall = true
181 m.Properties.HideFromMake = true
182 m.afdo.Properties.Afdo = true
183 if fdoProfileName, err := ctx.DeviceConfig().AfdoProfile(decodeTarget(variation)); fdoProfileName != "" && err == nil {
184 deps := ctx.AddFarVariationDependencies(
185 []blueprint.Variation{
186 {Mutator: "arch", Variation: ctx.Target().ArchVariation()},
187 {Mutator: "os", Variation: "android"},
188 },
189 FdoProfileTag,
190 fdoProfileName)
191 if len(deps) > 0 && deps[0] != nil {
192 if info, ok := android.OtherModuleProvider(ctx, deps[0], FdoProfileProvider); ok {
193 m.afdo.Properties.FdoProfilePath = proptools.StringPtr(info.Path.String())
194 }
Yi Kongeb8efc92021-12-09 18:06:29 +0800195 }
Yi Kongeb8efc92021-12-09 18:06:29 +0800196 }
197 }
198}
199
200// Encode target name to variation name.
201func encodeTarget(target string) string {
202 if target == "" {
203 return ""
204 }
205 return "afdo-" + target
206}
207
208// Decode target name from variation name.
209func decodeTarget(variation string) string {
210 if variation == "" {
211 return ""
212 }
213 return strings.TrimPrefix(variation, "afdo-")
214}