llvm.org GIT mirror llvm / 6517c35
Add total function byte size and inline function byte size to "llvm-dwarfdump --statistics" Differential Revision: https://reviews.llvm.org/D54217 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@346531 91177308-0d34-0410-b5e6-96231b3b80d8 Greg Clayton 11 months ago
2 changed file(s) with 39 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
2626 ; CHECK-NOT: "scope bytes covered":0
2727 ; CHECK-NOT "scope bytes covered":[[BYTES]]
2828 ; CHECK: "scope bytes covered":
29 ; CHECK: "total function size":[[FUNCSIZE:[0-9]+]]
30 ; CHECK: "total inlined function size":[[INLINESIZE:[0-9]+]]
31
2932
3033 ; ModuleID = '/tmp/quality.cpp'
3134 source_filename = "/tmp/quality.cpp"
2424 bool IsFunction = false;
2525 };
2626
27 /// Holds accumulated global statistics about local variables.
27 /// Holds accumulated global statistics about DIEs.
2828 struct GlobalStats {
2929 /// Total number of PC range bytes covered by DW_AT_locations.
3030 unsigned ScopeBytesCovered = 0;
3333 unsigned ScopeBytesFromFirstDefinition = 0;
3434 /// Total number of call site entries (DW_TAG_call_site).
3535 unsigned CallSiteEntries = 0;
36 /// Total byte size of concrete functions. This byte size includes
37 /// inline functions contained in the concrete functions.
38 uint64_t FunctionSize = 0;
39 /// Total byte size of inlined functions. This is the total number of bytes
40 /// for the top inline functions within concrete functions. This can help
41 /// tune the inline settings when compiling to match user expectations.
42 uint64_t InlineFunctionSize = 0;
3643 };
3744
3845 /// Extract the low pc from a Die.
5259 static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
5360 std::string VarPrefix, uint64_t ScopeLowPC,
5461 uint64_t BytesInScope,
62 uint32_t InlineDepth,
5563 StringMap &FnStatMap,
5664 GlobalStats &GlobalStats) {
5765 bool HasLoc = false;
136144 static void collectStatsRecursive(DWARFDie Die, std::string FnPrefix,
137145 std::string VarPrefix, uint64_t ScopeLowPC,
138146 uint64_t BytesInScope,
147 uint32_t InlineDepth,
139148 StringMap &FnStatMap,
140149 GlobalStats &GlobalStats) {
141150 // Handle any kind of lexical scope.
142 if (Die.getTag() == dwarf::DW_TAG_subprogram ||
143 Die.getTag() == dwarf::DW_TAG_inlined_subroutine ||
144 Die.getTag() == dwarf::DW_TAG_lexical_block) {
151 const dwarf::Tag Tag = Die.getTag();
152 const bool IsFunction = Tag == dwarf::DW_TAG_subprogram;
153 const bool IsBlock = Tag == dwarf::DW_TAG_lexical_block;
154 const bool IsInlinedFunction = Tag == dwarf::DW_TAG_inlined_subroutine;
155 if (IsFunction || IsInlinedFunction || IsBlock) {
145156
146157 // Reset VarPrefix when entering a new function.
147158 if (Die.getTag() == dwarf::DW_TAG_subprogram ||
148159 Die.getTag() == dwarf::DW_TAG_inlined_subroutine)
149160 VarPrefix = "v";
150
161
151162 // Ignore forward declarations.
152163 if (Die.find(dwarf::DW_AT_declaration))
153164 return;
154165
155166 // Count the function.
156 if (Die.getTag() != dwarf::DW_TAG_lexical_block) {
167 if (!IsBlock) {
157168 StringRef Name = Die.getName(DINameKind::LinkageName);
158169 if (Name.empty())
159170 Name = Die.getName(DINameKind::ShortName);
173184 llvm::consumeError(RangesOrError.takeError());
174185 return;
175186 }
176
187
177188 auto Ranges = RangesOrError.get();
178189 uint64_t BytesInThisScope = 0;
179190 for (auto Range : Ranges)
180191 BytesInThisScope += Range.HighPC - Range.LowPC;
181192 ScopeLowPC = getLowPC(Die);
182193
183 if (BytesInThisScope)
194 if (BytesInThisScope) {
184195 BytesInScope = BytesInThisScope;
196 if (IsFunction)
197 GlobalStats.FunctionSize += BytesInThisScope;
198 else if (IsInlinedFunction && InlineDepth == 0)
199 GlobalStats.InlineFunctionSize += BytesInThisScope;
200 }
185201 } else {
186202 // Not a scope, visit the Die itself. It could be a variable.
187203 collectStatsForDie(Die, FnPrefix, VarPrefix, ScopeLowPC, BytesInScope,
188 FnStatMap, GlobalStats);
189 }
204 InlineDepth, FnStatMap, GlobalStats);
205 }
206
207 // Set InlineDepth correctly for child recursion
208 if (IsFunction)
209 InlineDepth = 0;
210 else if (IsInlinedFunction)
211 ++InlineDepth;
190212
191213 // Traverse children.
192214 unsigned LexicalBlockIndex = 0;
197219 ChildVarPrefix += toHex(LexicalBlockIndex++) + '.';
198220
199221 collectStatsRecursive(Child, FnPrefix, ChildVarPrefix, ScopeLowPC,
200 BytesInScope, FnStatMap, GlobalStats);
222 BytesInScope, InlineDepth, FnStatMap, GlobalStats);
201223 Child = Child.getSibling();
202224 }
203225 }
230252 StringMap Statistics;
231253 for (const auto &CU : static_cast(&DICtx)->compile_units())
232254 if (DWARFDie CUDie = CU->getUnitDIE(false))
233 collectStatsRecursive(CUDie, "/", "g", 0, 0, Statistics, GlobalStats);
255 collectStatsRecursive(CUDie, "/", "g", 0, 0, 0, Statistics, GlobalStats);
234256
235257 /// The version number should be increased every time the algorithm is changed
236258 /// (including bug fixes). New metrics may be added without increasing the
270292 printDatum(OS, "scope bytes total",
271293 GlobalStats.ScopeBytesFromFirstDefinition);
272294 printDatum(OS, "scope bytes covered", GlobalStats.ScopeBytesCovered);
295 printDatum(OS, "total function size", GlobalStats.FunctionSize);
296 printDatum(OS, "total inlined function size", GlobalStats.InlineFunctionSize);
273297 OS << "}\n";
274298 LLVM_DEBUG(
275299 llvm::dbgs() << "Total Availability: "