blob: 1e703397907b2b6abb164262f2433e5426670148 [file] [log] [blame]
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -07001// Copyright 2017 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
21 "android/soong/android"
Pirama Arumuga Nainar49b53d52017-10-04 16:47:29 -070022 "android/soong/cc/config"
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -070023)
24
25var (
26 // Add flags to ignore warnings that profiles are old or missing for
27 // some functions
Pirama Arumuga Nainarf4c0baf2017-09-28 14:35:15 -070028 profileUseOtherFlags = []string{"-Wno-backend-plugin"}
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -070029
Pirama Arumuga Nainar49540802018-01-29 23:11:42 -080030 globalPgoProfileProjects = []string{
Pirama Arumuga Nainar64946fe2018-01-17 14:00:53 -080031 "toolchain/pgo-profiles",
32 "vendor/google_data/pgo-profiles",
33 }
34)
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -070035
Pirama Arumuga Nainar49540802018-01-29 23:11:42 -080036const pgoProfileProjectsConfigKey = "PgoProfileProjects"
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -070037const profileInstrumentFlag = "-fprofile-generate=/data/local/tmp"
38const profileSamplingFlag = "-gline-tables-only"
39const profileUseInstrumentFormat = "-fprofile-use=%s"
40const profileUseSamplingFormat = "-fprofile-sample-use=%s"
41
Pirama Arumuga Nainar49540802018-01-29 23:11:42 -080042func getPgoProfileProjects(config android.DeviceConfig) []string {
43 return config.OnceStringSlice(pgoProfileProjectsConfigKey, func() []string {
44 return append(globalPgoProfileProjects, config.PgoAdditionalProfileDirs()...)
45 })
46}
47
Pirama Arumuga Nainar28316d42018-01-29 09:18:45 -080048func recordMissingProfileFile(ctx ModuleContext, missing string) {
49 getNamedMapForConfig(ctx.Config(), modulesMissingProfileFile).Store(missing, true)
50}
51
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -070052type PgoProperties struct {
53 Pgo struct {
Pirama Arumuga Nainar6aeed8b2017-10-16 13:31:40 -070054 Instrumentation *bool
55 Sampling *bool
56 Profile_file *string `android:"arch_variant"`
57 Benchmarks []string
58 Enable_profile_use *bool `android:"arch_variant"`
Pirama Arumuga Nainar690ed552017-12-13 16:48:20 -080059 // Additional compiler flags to use when building this module
60 // for profiling (either instrumentation or sampling).
61 Cflags []string `android:"arch_variant"`
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -070062 } `android:"arch_variant"`
63
64 PgoPresent bool `blueprint:"mutated"`
65 ShouldProfileModule bool `blueprint:"mutated"`
66}
67
68type pgo struct {
69 Properties PgoProperties
70}
71
Pirama Arumuga Nainar49b53d52017-10-04 16:47:29 -070072func (props *PgoProperties) isInstrumentation() bool {
73 return props.Pgo.Instrumentation != nil && *props.Pgo.Instrumentation == true
74}
75
76func (props *PgoProperties) isSampling() bool {
77 return props.Pgo.Sampling != nil && *props.Pgo.Sampling == true
78}
79
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -070080func (pgo *pgo) props() []interface{} {
81 return []interface{}{&pgo.Properties}
82}
83
Pirama Arumuga Nainar3f5bb9c2017-10-10 10:47:41 -070084func (props *PgoProperties) addProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
Pirama Arumuga Nainar690ed552017-12-13 16:48:20 -080085 flags.CFlags = append(flags.CFlags, props.Pgo.Cflags...)
86
Pirama Arumuga Nainar3f5bb9c2017-10-10 10:47:41 -070087 if props.isInstrumentation() {
Pirama Arumuga Nainar49b53d52017-10-04 16:47:29 -070088 flags.CFlags = append(flags.CFlags, profileInstrumentFlag)
89 // The profile runtime is added below in deps(). Add the below
90 // flag, which is the only other link-time action performed by
91 // the Clang driver during link.
92 flags.LdFlags = append(flags.LdFlags, "-u__llvm_profile_runtime")
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -070093 }
Pirama Arumuga Nainar3f5bb9c2017-10-10 10:47:41 -070094 if props.isSampling() {
Pirama Arumuga Nainar49b53d52017-10-04 16:47:29 -070095 flags.CFlags = append(flags.CFlags, profileSamplingFlag)
96 flags.LdFlags = append(flags.LdFlags, profileSamplingFlag)
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -070097 }
Pirama Arumuga Nainar49b53d52017-10-04 16:47:29 -070098 return flags
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -070099}
100
Pirama Arumuga Nainar64946fe2018-01-17 14:00:53 -0800101func (props *PgoProperties) getPgoProfileFile(ctx ModuleContext) android.OptionalPath {
Pirama Arumuga Nainar49540802018-01-29 23:11:42 -0800102 // Test if the profile_file is present in any of the PGO profile projects
103 for _, profileProject := range getPgoProfileProjects(ctx.DeviceConfig()) {
Pirama Arumuga Nainar64946fe2018-01-17 14:00:53 -0800104 path := android.ExistentPathForSource(ctx, "", profileProject, *props.Pgo.Profile_file)
105 if path.Valid() {
106 return path
107 }
108 }
109
Pirama Arumuga Nainar28316d42018-01-29 09:18:45 -0800110 // Record that this module's profile file is absent
111 missing := *props.Pgo.Profile_file + ":" + ctx.ModuleDir() + "/Android.bp:" + ctx.ModuleName()
112 recordMissingProfileFile(ctx, missing)
113
Pirama Arumuga Nainar64946fe2018-01-17 14:00:53 -0800114 return android.OptionalPathForPath(nil)
115}
116
Pirama Arumuga Nainar3f5bb9c2017-10-10 10:47:41 -0700117func (props *PgoProperties) profileUseFlag(ctx ModuleContext, file string) string {
118 if props.isInstrumentation() {
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700119 return fmt.Sprintf(profileUseInstrumentFormat, file)
120 }
Pirama Arumuga Nainar3f5bb9c2017-10-10 10:47:41 -0700121 if props.isSampling() {
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700122 return fmt.Sprintf(profileUseSamplingFormat, file)
123 }
124 return ""
125}
126
Pirama Arumuga Nainar3f5bb9c2017-10-10 10:47:41 -0700127func (props *PgoProperties) profileUseFlags(ctx ModuleContext, file string) []string {
128 flags := []string{props.profileUseFlag(ctx, file)}
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700129 flags = append(flags, profileUseOtherFlags...)
130 return flags
131}
132
Pirama Arumuga Nainar0fdfc452017-10-10 11:00:18 -0700133func (props *PgoProperties) addProfileUseFlags(ctx ModuleContext, flags Flags) Flags {
Pirama Arumuga Nainar64946fe2018-01-17 14:00:53 -0800134 // Return if 'pgo' property is not present in this module.
135 if !props.PgoPresent {
136 return flags
137 }
138
Pirama Arumuga Nainar6aeed8b2017-10-16 13:31:40 -0700139 // Skip -fprofile-use if 'enable_profile_use' property is set
140 if props.Pgo.Enable_profile_use != nil && *props.Pgo.Enable_profile_use == false {
141 return flags
142 }
143
Pirama Arumuga Nainar64946fe2018-01-17 14:00:53 -0800144 // If the profile file is found, add flags to use the profile
145 if profileFile := props.getPgoProfileFile(ctx); profileFile.Valid() {
146 profileFilePath := profileFile.Path()
147 profileUseFlags := props.profileUseFlags(ctx, profileFilePath.String())
Pirama Arumuga Nainar0fdfc452017-10-10 11:00:18 -0700148
149 flags.CFlags = append(flags.CFlags, profileUseFlags...)
150 flags.LdFlags = append(flags.LdFlags, profileUseFlags...)
151
152 // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
153 // if profileFile gets updated
Pirama Arumuga Nainar64946fe2018-01-17 14:00:53 -0800154 flags.CFlagsDeps = append(flags.CFlagsDeps, profileFilePath)
155 flags.LdFlagsDeps = append(flags.LdFlagsDeps, profileFilePath)
Pirama Arumuga Nainar0fdfc452017-10-10 11:00:18 -0700156 }
157 return flags
158}
159
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700160func (props *PgoProperties) isPGO(ctx BaseModuleContext) bool {
Pirama Arumuga Nainar49b53d52017-10-04 16:47:29 -0700161 isInstrumentation := props.isInstrumentation()
162 isSampling := props.isSampling()
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700163
164 profileKindPresent := isInstrumentation || isSampling
165 filePresent := props.Pgo.Profile_file != nil
166 benchmarksPresent := len(props.Pgo.Benchmarks) > 0
167
168 // If all three properties are absent, PGO is OFF for this module
169 if !profileKindPresent && !filePresent && !benchmarksPresent {
170 return false
171 }
172
173 // If at least one property exists, validate that all properties exist
174 if !profileKindPresent || !filePresent || !benchmarksPresent {
175 var missing []string
176 if !profileKindPresent {
177 missing = append(missing, "profile kind (either \"instrumentation\" or \"sampling\" property)")
178 }
179 if !filePresent {
180 missing = append(missing, "profile_file property")
181 }
182 if !benchmarksPresent {
183 missing = append(missing, "non-empty benchmarks property")
184 }
185 missingProps := strings.Join(missing, ", ")
186 ctx.ModuleErrorf("PGO specification is missing properties: " + missingProps)
187 }
188
189 // Sampling not supported yet
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700190 if isSampling {
191 ctx.PropertyErrorf("pgo.sampling", "\"sampling\" is not supported yet)")
192 }
193
Pirama Arumuga Nainar6fc8d912017-10-05 10:25:00 -0700194 if isSampling && isInstrumentation {
195 ctx.PropertyErrorf("pgo", "Exactly one of \"instrumentation\" and \"sampling\" properties must be set")
196 }
197
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700198 return true
199}
200
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700201func (pgo *pgo) begin(ctx BaseModuleContext) {
202 // TODO Evaluate if we need to support PGO for host modules
203 if ctx.Host() {
204 return
205 }
206
207 // Check if PGO is needed for this module
208 pgo.Properties.PgoPresent = pgo.Properties.isPGO(ctx)
209
210 if !pgo.Properties.PgoPresent {
211 return
212 }
213
214 // This module should be instrumented if ANDROID_PGO_INSTRUMENT is set
Pirama Arumuga Nainare236b5a2018-01-22 19:10:19 -0800215 // and includes 'all', 'ALL' or a benchmark listed for this module.
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700216 //
217 // TODO Validate that each benchmark instruments at least one module
218 pgo.Properties.ShouldProfileModule = false
Colin Cross6510f912017-11-29 00:27:14 -0800219 pgoBenchmarks := ctx.Config().Getenv("ANDROID_PGO_INSTRUMENT")
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700220 pgoBenchmarksMap := make(map[string]bool)
221 for _, b := range strings.Split(pgoBenchmarks, ",") {
222 pgoBenchmarksMap[b] = true
223 }
224
Pirama Arumuga Nainare236b5a2018-01-22 19:10:19 -0800225 if pgoBenchmarksMap["all"] == true || pgoBenchmarksMap["ALL"] == true {
226 pgo.Properties.ShouldProfileModule = true
227 } else {
228 for _, b := range pgo.Properties.Pgo.Benchmarks {
229 if pgoBenchmarksMap[b] == true {
230 pgo.Properties.ShouldProfileModule = true
231 break
232 }
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700233 }
234 }
235}
236
Pirama Arumuga Nainar49b53d52017-10-04 16:47:29 -0700237func (pgo *pgo) deps(ctx BaseModuleContext, deps Deps) Deps {
238 if pgo.Properties.ShouldProfileModule {
239 runtimeLibrary := config.ProfileRuntimeLibrary(ctx.toolchain())
240 deps.LateStaticLibs = append(deps.LateStaticLibs, runtimeLibrary)
241 }
242 return deps
243}
244
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700245func (pgo *pgo) flags(ctx ModuleContext, flags Flags) Flags {
246 if ctx.Host() {
247 return flags
248 }
249
250 props := pgo.Properties
251
252 // Add flags to profile this module based on its profile_kind
253 if props.ShouldProfileModule {
Pirama Arumuga Nainar3f5bb9c2017-10-10 10:47:41 -0700254 return props.addProfileGatherFlags(ctx, flags)
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700255 }
256
Colin Cross6510f912017-11-29 00:27:14 -0800257 if !ctx.Config().IsEnvTrue("ANDROID_PGO_NO_PROFILE_USE") {
Pirama Arumuga Nainar0fdfc452017-10-10 11:00:18 -0700258 return props.addProfileUseFlags(ctx, flags)
Pirama Arumuga Nainarada83ec2017-08-31 23:38:27 -0700259 }
260
261 return flags
262}