source: src/CodeTools/DeclStats.cc @ 97d246d

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newwith_gc
Last change on this file since 97d246d was 97d246d, checked in by Aaron Moss <a3moss@…>, 5 years ago

Tweaks to DeclStats?

  • Property mode set to 100644
File size: 10.6 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// DeclStats.cc --
8//
9// Author           : Aaron Moss
10// Created On       : Wed Jan 31 16:40:00 2016
11// Last Modified By : Aaron Moss
12// Last Modified On : Wed Jan 31 16:40:00 2016
13// Update Count     : 1
14//
15
16#include "DeclStats.h"
17
18#include <iostream>
19#include <map>
20#include <sstream>
21#include <string>
22#include <unordered_map>
23#include <unordered_set>
24
25#include "Common/VectorMap.h"
26#include "GenPoly/GenPoly.h"
27#include "Parser/LinkageSpec.h"
28#include "SynTree/Declaration.h"
29#include "SynTree/Visitor.h"
30
31namespace CodeTools {
32       
33        class DeclStats : public Visitor {
34                template<typename T>
35                static void sum(T& a, const T& b) { a += b; }
36
37                static void sum(VectorMap<unsigned>& a, const VectorMap<unsigned>& b) {
38                        a.reserve( b.size() );
39                        for ( unsigned i = 0; i < b.size(); ++i ) {
40                                a[i] += b[i];
41                        }
42                }
43
44                template<typename K>
45                static void sum(std::map<K, unsigned>& a, const std::map<K, unsigned>& b) {
46                        for ( const auto& entry : b ) {
47                                a[ entry.first ] += entry.second;
48                        }
49                }
50
51                template<typename K>
52                static void sum(std::unordered_map<K, unsigned>& a, const std::unordered_map<K, unsigned>& b) {
53                        for ( const auto& entry : b ) {
54                                a[ entry.first ] += entry.second;
55                        }
56                }
57
58                struct ArgPackStats {
59                        VectorMap<unsigned> n;                 ///< Count of decls with each number of elements
60                        VectorMap<unsigned> n_basic;           ///< Count of decls with each number of basic type elements
61                        VectorMap<unsigned> n_poly;            ///< Count of decls with each number of polymorphic elements
62                        std::map<unsigned, unsigned> p_basic;  ///< Count of decls with each percentage of basic type elements
63                        std::map<unsigned, unsigned> p_poly;   ///< Count of decls with each percentage of polymorphic elements
64
65                        ArgPackStats& operator+= (const ArgPackStats& o) {
66                                sum(n, o.n);
67                                sum(n_basic, o.n_basic);
68                                sum(n_poly, o.n_poly);
69                                sum(p_basic, o.p_basic);
70                                sum(p_poly, o.p_poly);
71                               
72                                return *this;
73                        }
74                };
75               
76                struct Stats {
77                        unsigned n_decls;     ///< Total number of declarations
78                        /// Count of declarations with each number of assertion parameters
79                        VectorMap<unsigned> n_type_params;
80                        /// Count of declarations with each name
81                        std::unordered_map<std::string, unsigned> by_name;
82                        /// Count of uses of each basic type
83                        std::unordered_map<std::string, unsigned> basic_type_names;
84                        /// Count of uses of each non-basic type
85                        std::unordered_map<std::string, unsigned> compound_type_names;
86                        /// Stats for the parameter list
87                        ArgPackStats params;
88                        /// Stats for the return list
89                        ArgPackStats returns;
90                       
91                        /// Count of declarations with each number of assertions
92                        std::map<unsigned, unsigned> n_assns;
93                        /// Stats for the assertions' parameters
94                        ArgPackStats assn_params;
95                        /// Stats for the assertions' return types
96                        ArgPackStats assn_returns;
97                       
98                        Stats() : n_decls(0), n_type_params(), by_name(), basic_type_names(), compound_type_names(), params(), returns(), n_assns(), assn_params(), assn_returns() {}
99
100                public:
101                        Stats& operator+= (const Stats& o) {
102                                sum( n_decls, o.n_decls );
103                                sum( n_type_params, o.n_type_params );
104                                sum( by_name, o.by_name );
105                                sum( basic_type_names, o.basic_type_names );
106                                sum( compound_type_names, o.compound_type_names );
107                                sum( params, o.params );
108                                sum( returns, o.returns );
109                                sum( n_assns, o.n_assns );
110                                sum( assn_params, o.assn_params );
111                                sum( assn_returns, o.assn_returns );
112                               
113                                return *this;
114                        }
115                };
116
117                Stats for_linkage[LinkageSpec::NoOfSpecs];   ///< Stores separate stats per linkage
118                std::unordered_set<std::string> seen_names;  ///< Stores manglenames already seen to avoid double-counting
119                Stats total;
120
121                /// Update arg pack stats based on a declaration list
122                void analyze( Stats& stats, ArgPackStats& pstats, std::list<DeclarationWithType*>& decls ) {
123                        unsigned n = 0;
124                        unsigned n_basic = 0;
125                        unsigned n_poly = 0;
126                        for ( auto decl : decls ) {
127                                n += decl->get_type()->size();
128                                if ( BasicType* bt = dynamic_cast<BasicType*>( decl->get_type() ) ) {
129                                        ++n_basic;
130                                        std::stringstream ss;
131                                        bt->print( ss );
132                                        ++stats.basic_type_names[ ss.str() ];
133                                } else if ( GenPoly::hasPolyBase( decl->get_type() ) ) {
134                                        ++n_poly;
135                                } else {
136                                        std::stringstream ss;
137                                        decl->get_type()->print( ss );
138                                        ++stats.compound_type_names[ ss.str() ];
139                                }
140                        }
141                        ++pstats.n.at( n );
142                        ++pstats.n_basic.at( n_basic );
143                        ++pstats.n_poly.at( n_poly );
144                        if ( n > 0 ) {
145                                ++pstats.p_basic[ n_basic*100/n ];
146                                ++pstats.p_poly[ n_poly*100/n ];
147                        }
148                }
149               
150                void analyzeFunc( FunctionType* fnTy, Stats& stats, ArgPackStats& params, ArgPackStats& returns ) {
151                        analyze( stats, params, fnTy->get_parameters() );
152                        analyze( stats, returns, fnTy->get_returnVals() );
153                }
154
155        public:
156                using Visitor::visit;
157
158                virtual void visit( FunctionDecl *decl ) {
159                        // skip if already seen declaration for this function
160                        const std::string& mangleName = decl->get_mangleName().empty() ? decl->get_name() : decl->get_mangleName();
161                        if ( ! seen_names.insert( mangleName ).second ) return;
162                       
163                        Stats& stats = for_linkage[ decl->get_linkage() ];
164
165                        ++stats.n_decls;
166                        FunctionType* fnTy = decl->get_functionType();
167                        const Type::ForallList& forall = fnTy->get_forall();
168                        ++stats.n_type_params.at( forall.size() );
169                        unsigned n_assns = 0;
170                        for ( TypeDecl* fdecl : forall ) {
171                                n_assns += fdecl->get_assertions().size();
172                                for ( DeclarationWithType* assn : fdecl->get_assertions() ) {
173                                        FunctionType *assnTy = 0;
174                                        if ( ObjectDecl *assnObj = dynamic_cast<ObjectDecl*>(assn) ) {
175                                                if ( PointerType *ptrTy = dynamic_cast<PointerType*>(assnObj->get_type()) ) {
176                                                        assnTy = dynamic_cast<FunctionType*>(ptrTy->get_base());
177                                                } else assnTy = dynamic_cast<FunctionType*>(assnObj->get_type());
178                                        } else if ( FunctionDecl *assnDecl = dynamic_cast<FunctionDecl*>(assn) ) {
179                                                assnTy = assnDecl->get_functionType();
180                                        }
181                                        if ( assnTy ) analyzeFunc( assnTy, stats, stats.assn_params, stats.assn_returns );
182                                }
183                        }
184                        ++stats.n_assns[ n_assns ];
185
186                        ++stats.by_name[ decl->get_name() ];
187
188                        analyzeFunc( fnTy, stats, stats.params, stats.returns );
189                }
190
191        private:
192                template<typename F>
193                void printAll( const std::string& name, F extract ) {
194                        std::cout << "\"" << name << "\",";
195                        for ( const auto& stats : for_linkage ) {
196                                std::cout << "," << extract(stats);
197                        }
198                        std::cout << "," << extract(total) << std::endl;
199                }
200
201                template<typename F>
202                void printAllMap( const std::string& name, F extract ) {
203                        for ( const auto& entry : extract(total) ) {
204                                const auto& key = entry.first;
205                                std::cout << "\"" << name << "\"," << key;
206                                for ( const auto& stats : for_linkage ) {
207                                        const auto& map = extract(stats);
208                                        auto it = map.find( key );
209                                        if ( it == map.end() ) std::cout << ",0";
210                                        else std::cout << "," << it->second;
211                                }
212                                std::cout  << "," << entry.second << std::endl;
213                        }
214                }
215
216                template<typename F>
217                void printAllHisto( const std::string& name, F extract ) {
218                        VectorMap<unsigned> histos[LinkageSpec::NoOfSpecs];
219                        VectorMap<unsigned> thisto;
220
221                        for ( const auto& entry : extract(total) ) { ++thisto.at( entry.second ); }
222
223                        for ( unsigned i = 0; i < LinkageSpec::NoOfSpecs; ++i ) {
224                                // can't be a higher count in one of the sub-histograms than the total
225                                histos[i].reserve( thisto.size() );
226
227                                for ( const auto& entry : extract(for_linkage[i]) ) { ++histos[i][entry.second]; }
228                        }
229
230                        for ( unsigned i = 0; i < thisto.size(); ++i ) {
231                                std::cout << "\"" << name << "\"," << i;
232                                for ( const auto& histo : histos ) {
233                                        std::cout << "," << histo[i];
234                                }
235                                std::cout << "," << thisto[i] << std::endl;
236                        }
237                }
238
239                template<typename F>
240                void printAllSparseHisto( const std::string& name, F extract ) {
241                        std::map<unsigned, unsigned> histos[LinkageSpec::NoOfSpecs];
242                        std::map<unsigned, unsigned> thisto;
243
244                        for ( const auto& entry : extract(total) ) { ++thisto[ entry.second ]; }
245
246                        for ( unsigned i = 0; i < LinkageSpec::NoOfSpecs; ++i ) {
247                                for ( const auto& entry : extract(for_linkage[i]) ) { ++histos[i][entry.second]; }
248                        }
249
250                        for ( const auto& entry : thisto ) {
251                                const auto& key = entry.first;
252                                std::cout << "\"" << name << "\"," << key;
253                                for ( unsigned i = 0; i < LinkageSpec::NoOfSpecs; ++i ) {
254                                        auto it = histos[i].find( key );
255                                        if ( it == histos[i].end() ) std::cout << ",0";
256                                        else std::cout << "," << it->second;
257                                }
258                                std::cout << "," << entry.second << std::endl;
259                        }
260                }
261
262                template<typename F>
263                void printAllPack( const std::string& name, F extract ) {
264                        printAllMap("n_basic_" + name, [&extract](const Stats& stats) { return extract(stats).n_basic; });
265                        printAllMap("n_poly_" + name, [&extract](const Stats& stats) { return extract(stats).n_poly; });
266                        printAllMap("n_" + name, [&extract](const Stats& stats) { return extract(stats).n; });
267                        printAllMap("%_basic_" + name, [&extract](const Stats& stats) { return extract(stats).p_basic; });
268                        printAllMap("%_poly_" + name, [&extract](const Stats& stats) { return extract(stats).p_poly; });
269                }
270               
271        public:
272                void print() {
273                        for ( auto& stats : for_linkage ) {
274                                total += stats;
275                        }
276
277                        std::cout << ",,\"intrinsic\",\"Cforall\",\"C\",\"autogen\",\"builtin\",\"TOTAL\"" << std::endl;
278
279                        printAllMap("n_type_params", [](const Stats& stats) { return stats.n_type_params; });
280                        printAll("n_decls", [](const Stats& stats) { return stats.n_decls; });
281                        printAll("unique_names", [](const Stats& stats) { return stats.by_name.size(); });
282                        printAllSparseHisto("overloads", [](const Stats& stats) { return stats.by_name; });
283                        printAll("basic_type_names", [](const Stats& stats) { return stats.basic_type_names.size(); });
284                        printAllSparseHisto("basic_type_uses", [](const Stats& stats) { return stats.basic_type_names; });
285                        printAll("compound_type_names", [](const Stats& stats) { return stats.compound_type_names.size(); });
286                        printAllSparseHisto("compound_type_uses", [](const Stats& stats) { return stats.compound_type_names; });
287                        printAllPack("params", [](const Stats& stats) { return stats.params; });
288                        printAllPack("returns", [](const Stats& stats) { return stats.returns; });
289                        printAllMap("n_assns", [](const Stats& stats) { return stats.n_assns; });
290                        printAllPack("assn_params", [](const Stats& stats) { return stats.assn_params; });
291                        printAllPack("assn_returns", [](const Stats& stats) { return stats.assn_returns; });
292                }
293        };
294
295        void printDeclStats( std::list< Declaration * > &translationUnit ) {
296                DeclStats stats;
297                acceptAll( translationUnit, stats );
298                stats.print();
299        }
300       
301} // namespace CodeTools
302
303// Local Variables: //
304// tab-width: 4 //
305// mode: c++ //
306// compile-command: "make install" //
307// End: //
Note: See TracBrowser for help on using the repository browser.