ok for google branch. David
On Tue, Aug 6, 2013 at 3:41 PM, Dehao Chen <de...@google.com> wrote: > Patch updated. > > http://codereview.appspot.com/12079043 > > Thanks, > Dehao > > > On Fri, Aug 2, 2013 at 11:21 AM, Xinliang David Li <davi...@google.com> wrote: >> More to follow. >> >> David >> >>>>static void >>>> read_profile (void) >>>> { >>>> if (gcov_open (auto_profile_file, 1) == 0) >>>> { >>>> inform (0, "Cannot open profile file %s.", auto_profile_file); >> >> >> Should be at least warning instead -- I think error is probably more >> appropriate -- this is different from regular FDO, where one missing >> gcda might be ok. >> >>>> flag_auto_profile = 0; >>>> return; >>>> } >>>> >>>> if (gcov_read_unsigned () != GCOV_DATA_MAGIC) >>>> { >>>> inform (0, "Magic number does not mathch."); >> >> Should be an error. >> >>>> flag_auto_profile = 0; >>>> return; >>>> } >>>> >>>> >>>> /* function_name_map. */ >>>> afdo_function_name_map = function_name_map::create (); >>>> if (afdo_function_name_map == NULL) >>>> { >>>> inform (0, "Cannot read string table."); >> >> Should be an error unless there is a way to recover. Falling back to >> non-fdo is not the solution. >> >>>> flag_auto_profile = 0; >>>> return; >>>> } >>>> >>>> /* autofdo_source_profile. */ >>>> afdo_source_profile = autofdo_source_profile::create (); >>>> if (afdo_source_profile == NULL) >>>> { >>>> inform (0, "Cannot read function profile."); >> >> An error. >> >>>> flag_auto_profile = 0; >>>> return; >>>> } >>>> >>>> /* autofdo_module_profile. */ >>>> afdo_module_profile = autofdo_module_profile::create (); >>>> if (afdo_module_profile == NULL) >>>> { >>>> inform (0, "Cannot read module profile."); >> >> Should be an error. >> >>>> flag_auto_profile = 0; >>>> return; >>>> } >>>> >>>> /* Read in the working set. */ >>>> if (gcov_read_unsigned () != GCOV_TAG_AFDO_WORKING_SET) >>>> { >>>> inform (0, "Not expected TAG."); >> >> Error. >> >>>> unsigned curr_module = 1, max_group = PARAM_VALUE (PARAM_MAX_LIPO_GROUP); >>>> for (string_vector::const_iterator iter = aux_modules->begin(); >>>> iter != aux_modules->end(); ++iter) >>>> { >>>> gcov_module_info *aux_module = afdo_module_profile->get_module >>>> (*iter); >>>> if (aux_module == module) >>>> continue; >>>> if (aux_module == NULL) >>>> { >>>> inform (0, "aux module %s cannot be found.", *iter); >>>> continue; >>>> } >>>> if ((aux_module->lang & GCOV_MODULE_LANG_MASK) != >>>> (module->lang & GCOV_MODULE_LANG_MASK)) >>>> { >>>> inform (0, "Not importing %s: source language" >>>> " different from primary module's source language", *iter); >> >> >> Should be guarded with -fopt-info -- see similar code in coverage.c. >> >>>> continue; >>>> } >>>> if ((aux_module->lang & GCOV_MODULE_ASM_STMTS) >>>> && flag_ripa_disallow_asm_modules) >>>> { >>>> if (flag_opt_info) >>>> inform (0, "Not importing %s: contains " >>>> "assembler statements", *iter); >> >> Use -fopt-info >> >>>> continue; >>>> } >>>> if (max_group != 0 && curr_module == max_group) >>>> { >>>> if (flag_opt_info) >>>> inform (0, "Not importing %s: maximum group size reached", *iter); >>>> } >>>> if (incompatible_cl_args (module, aux_module)) >>>> { >>>> if (flag_opt_info) >>>> inform (0, "Not importing %s: command-line" >>>> " arguments not compatible with primary module", *iter); >>>> continue; >> >> Use -fopt-info. >> >> >>>> } >>>> module_infos[curr_module++] = aux_module; >>>> add_input_filename (*iter); >>>> } >>>> } >>>> >>>> /* From AutoFDO profiles, find values inside STMT for that we want to >>>> measure >>>> histograms for indirect-call optimization. */ >>>> >>>> { >>>> hist->hvalue.counters[3] = 0; >>>> hist->hvalue.counters[4] = 0; >>>> } >> >> It might be better to create a commmon API to create/update histogram >> entry instead of peeking into the details of the data structure -- to >> avoid future breaks. Such a change can be done as a follow up and >> needs to be in trunk. > > Will update this in a follow-up patch. > >> >>>> } >>>> >>>> /* From AutoFDO profiles, find values inside STMT for that we want to >>>> measure >>>> histograms and adds them to list VALUES. */ >>>> >>>> static void >>>> afdo_vpt (gimple stmt, const icall_target_map &map) >>>> { >>>> afdo_indirect_call (stmt, map); >>>> } >>>> >>>> /* For a given BB, return its execution count, and annotate value profile >>>> on statements. */ >>>> >>>> static gcov_type >>>> afdo_get_bb_count (basic_block bb) >>>> { >>>> gimple_stmt_iterator gsi; >>>> gcov_type max_count = 0; >>>> bool has_annotated = false; >>>> >>>> for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) >>>> { >>>> count_info info; >>>> gimple stmt = gsi_stmt (gsi); >>>> if (afdo_source_profile->get_count_info (stmt, &info)) >>>> { >> >> indentation. > > the tab is not well displayed in the patch... > >> >>>> if (info.first > max_count) >>>> max_count = info.first; >>>> has_annotated = true; >>>> if (info.second.size() > 0) >>>> afdo_vpt (stmt, info.second); >>>> } >>>> } >>>> if (has_annotated) >>>> { >>>> bb->flags |= BB_ANNOTATED; >>>> return max_count; >>>> } >>>> else >>>> return 0; >>>> } >>>> >>>> >>>> static void >>>> afdo_annotate_cfg (void) >>>> { >>>> basic_block bb; >>>> const function_instance *s = >>>> afdo_source_profile->get_function_instance_by_decl ( >>>> current_function_decl); >> >> need a new line after decls. >> >> On Thu, Aug 1, 2013 at 2:49 PM, Dehao Chen <de...@google.com> wrote: >>> On Wed, Jul 31, 2013 at 10:14 AM, Xinliang David Li <davi...@google.com> >>> wrote: >>>> Another round of documentation and naming (not for coding style, but >>>> for clearer semantics) related comments: >>>> >>>> David >>>> >>>>> >>>>> namespace autofdo { >>>>> >>>>> /* Represent a source location: (function_decl, lineno). */ >>>>> typedef std::pair<tree, unsigned> decl_lineno; >>>>> /* Represent an inline stack. vector[0] is the leaf node. */ >>>>> typedef std::vector<decl_lineno> inline_stack; >>>> >>>> leaf or root? >>> >>> leaf >>> >>>> >>>>> /* String array. */ >>>>> typedef std::vector<const char *> string_vector; >>>> >>>> Module name, function name strings or a generic string table?? >>> >>> done >>>> >>>>> /* Map from index in string_map to profile count. */ >>>>> typedef std::map<unsigned, gcov_type> target_map; >>>> >>>> What index? function index? Is profile count function profile count >>>> or target call count? >>> >>> done >>>> >>>> Should it renamed to icall_target_map to be clearer? >>> >>> done >>>> >>>>> /* Represent profile count: (execution_count, value_profile_histogram. */ >>>>> typedef std::pair<gcov_type, target_map> count_info; >>>>> >>>> >>>> The executation count is for what entity? >>> >>> done >>>> >>>>> struct string_compare >>>>> { >>>>> bool operator() (const char *a, const char *b) const >>>>> { return strcmp (a, b) < 0; } >>>>> }; >>>>> >>>>> /* Store a string array, indexed by string position in the array. */ >>>>> class string_map { >>>> >>>> Is it better to rename it to function_name_map ? string_map is too general. >>> >>> done >>>> >>>> >>>>> public: >>>>> static string_map *create (); >>>>> >>>>> /* For a given string, returns its index. */ >>>>> int get_index (const char *name) const; >>>>> /* For a given decl, returns the index of the decl name. */ >>>>> int get_index_by_decl (tree decl) const; >>>>> /* For a given index, returns the string. */ >>>>> const char *get_name (int index) const; >>>>> >>>>> private: >>>>> string_map () {} >>>>> bool read (); >>>>> >>>>> typedef std::map<const char *, unsigned, string_compare> >>>>> string_index_map; >>>>> string_vector vector_; >>>>> string_index_map map_; >>>>> }; >>>>> >>>>> /* Profile of a function copy: >>>>> 1. total_count of the copy. >>>>> 2. head_count of the copy (only valid when the copy is a top-level >>>>> symbol, i.e. it is the original copy instead of the inlined copy). >>>>> 3. map from source location (decl_lineno) to profile (count_info). >>>> >>>> Source location of the inlined callsite? >>> >>> done >>>> >>>>> 4. map from callsite (64 bit integer, higher 32 bit is source >>>>> location >>>>> (decl_lineno), lower 32 bit is callee function name index in >>>>> string_map) to callee symbol. */ >>>>> class symbol { >>>> >>>> >>>> May be rename it to " function_instance" ? >>> >>> done >>>> >>>>> public: >>>>> typedef std::vector<symbol *> symbol_stack; >>>>> >>>>> /* Read the profile and create a symbol with head count as HEAD_COUNT. >>>>> Recursively read callsites to create nested symbols too. STACK is >>>>> used >>>>> to track the recursive creation process. */ >>>>> static const symbol *read_symbol (symbol_stack *stack, gcov_type >>>>> head_count); >>>>> >>>>> /* Recursively deallocate all callsites (nested symbols). */ >>>>> ~symbol (); >>>>> >>>>> /* Accessors. */ >>>>> unsigned name () const { return name_; } >>>>> gcov_type total_count () const { return total_count_; } >>>>> gcov_type head_count () const { return head_count_; } >>>>> >>>>> /* Recursively traverse STACK starting from LEVEL to find the >>>>> corresponding >>>>> symbol. */ >>>>> const symbol *get_symbol (const inline_stack &stack, unsigned level) >>>>> const; >>>>> >>>>> /* Return the profile info for LOC. */ >>>>> bool get_count_info (location_t loc, count_info *info) const; >>>>> >>>>> private: >>>>> symbol (unsigned name, gcov_type head_count) >>>>> : name_(name), total_count_(0), head_count_(head_count) {} >>>>> const symbol *get_symbol_by_decl (unsigned lineno, tree decl) const; >>>>> >>>>> /* Map from callsite (64 bit integer, higher 32 bit is source location >>>>> (decl_lineno), lower 32 bit is callee function name index in >>>>> string_map) to callee symbol. */ >>>>> typedef std::map<gcov_type, const symbol *> callsite_map; >>>> >>>> Why not making a pair and use it as the key? >>> >>> done >>>> >>>>> /* Map from source location (decl_lineno) to profile (count_info). */ >>>>> typedef std::map<unsigned, count_info> position_count_map; >>>>> >>>>> /* symbol name index in the string map. */ >>>> >>>> >>>> Index in string_vector or string_map? >>> >>> done >>>> >>>>> unsigned name_; >>>>> /* The total sampled count. */ >>>>> gcov_type total_count_; >>>>> /* The total sampled count in the head bb. */ >>>>> gcov_type head_count_; >>>>> /* Map from callsite location to callee symbol. */ >>>>> callsite_map callsites; >>>>> /* Map from source location to count and instruction number. */ >>>>> position_count_map pos_counts; >>>>> }; >>>>> >>>>> /* Profile for all functions. */ >>>>> class symbol_map { >>>> >>>> >>>> symbol_map --> program_profiles or afdo_profile ? >>> >>> done >>>> >>>>> public: >>>>> static symbol_map *create () >>>>> { >>>>> symbol_map *map = new symbol_map (); >>>>> if (map->read ()) >>>>> return map; >>>>> delete map; >>>>> return NULL; >>>>> } >>>>> ~symbol_map (); >>>>> /* For a given DECL, returns the top-level symbol. */ >>>>> const symbol *get_symbol_by_decl (tree decl) const; >>>>> /* Find profile info for a given gimple STMT. If found, store the >>>>> profile >>>>> info in INFO, and return true; otherwise return false. */ >>>>> bool get_count_info (gimple stmt, count_info *info) const; >>>>> /* Find total count of the callee of EDGE. */ >>>>> gcov_type get_callsite_total_count (struct cgraph_edge *edge) const; >>>>> >>>>> private: >>>>> /* Map from symbol name index (in string_map) to symbol. */ >>>>> typedef std::map<unsigned, const symbol *> Namesymbol_map; >>>>> >>>>> symbol_map () {} >>>>> bool read (); >>>>> /* Return the symbol in the profile that correspond to the inline >>>>> STACK. */ >>>>> const symbol *get_symbol_by_inline_stack (const inline_stack &stack) >>>>> const; >>>>> >>>>> Namesymbol_map map_; >>>>> }; >>>>> >>>>> /* Module profile. */ >>>>> class module_map { >>>> >>>> afdo_module_profile ? >>> >>> done >>>> >>>>> public: >>>>> static module_map *create () >>>>> { >>>>> module_map *map = new module_map (); >>>>> if (map->read ()) >>>>> return map; >>>>> delete map; >>>>> return NULL; >>>>> } >>>>> >>>>> /* For a given module NAME, returns this module's gcov_m >>>> >>>> On Tue, Jul 30, 2013 at 4:48 PM, Dehao Chen <de...@google.com> wrote: >>>>> Patch updated to fix the code style and documentation. >>>>> >>>>> Thanks, >>>>> Dehao >>>>> >>>>> On Tue, Jul 30, 2013 at 2:24 PM, Xinliang David Li <davi...@google.com> >>>>> wrote: >>>>>> I have some preliminary comments. Mostly just related to code style >>>>>> and missing documentation. >>>>>> >>>>>> David >>>>>> >>>>>>> >>>>>>> #define DEFAULT_AUTO_PROFILE_FILE "fbdata.afdo" >>>>>>> >>>>>>> struct SourceLocation >>>>>> >>>>>> Is using Upper case in struct names allowed? >>>>>> >>>>>>> { >>>>>>> tree func_decl; >>>>>>> unsigned lineno; >>>>>>> }; >>>>>>> >>>>>>> typedef std::vector<const char *> StringVector; >>>>>>> typedef std::vector<SourceLocation> InlineStack; >>>>>>> typedef std::map<unsigned, gcov_type> TargetMap; >>>>>>> >>>>>> >>>>>> Add short description of each new types. >>>>>> >>>>>>> struct ProfileInfo >>>>>>> { >>>>>>> gcov_type count; >>>>>>> TargetMap target_map; >>>>>>> }; >>>>>>> >>>>>>> struct StringCompare >>>>>>> { >>>>>>> bool operator() (const char* a, const char* b) const >>>>>> >>>>>> '*' should bind to name. >>>>>> >>>>>>> { return strcmp (a, b) < 0; } >>>>>>> }; >>>>>>> >>>>>> >>>>>>> class StringMap { >>>>>>> public: >>>>>>> static StringMap *Create(); >>>>>>> int GetIndex (const char *name) const; >>>>>>> int GetIndexByDecl (tree decl) const; >>>>>>> const char *GetName (int index) const; >>>>>>> >>>>>>> private: >>>>>>> StringMap () {} >>>>>>> bool Read (); >>>>>>> >>>>>>> typedef std::map<const char *, unsigned, StringCompare> >>>>>>> StringIndexMap; >>>>>>> StringVector vector_; >>>>>>> StringIndexMap map_; >>>>>>> }; >>>>>> >>>>>> Add some documentation on the new type, indicating what is 'index'. >>>>>> >>>>>>> >>>>>>> class Symbol { >>>>>> >>>>>> The name 'Symbol' is too generic -- can cause conflicts in the future >>>>>> unless namespace is used. ALso missing documentation. >>>>>> >>>>>>> public: >>>>>>> typedef std::vector<Symbol *> SymbolStack; >>>>>> >>>>>> Fix indentation problems. >>>>>> >>>>>> >>>>>>> >>>>>>> /* Read the profile and create a symbol with head count as >>>>>>> HEAD_COUNT. >>>>>>> Recursively read callsites to create nested symbols too. STACK is >>>>>>> used >>>>>>> to track the recursive creation process. */ >>>>>>> static const Symbol *ReadSymbol (SymbolStack *stack, gcov_type >>>>>>> head_count); >>>>>>> >>>>>>> /* Recursively deallocate all callsites (nested symbols). */ >>>>>>> ~Symbol (); >>>>>>> >>>>>>> /* Accessors. */ >>>>>>> unsigned name () const { return name_; } >>>>>>> gcov_type total_count () const { return total_count_; } >>>>>>> gcov_type head_count () const { return head_count_; } >>>>>>> >>>>>>> /* Recursively traverse STACK starting from LEVEL to find the >>>>>>> corresponding >>>>>>> symbol. */ >>>>>>> const Symbol *GetSymbol (const InlineStack &stack, unsigned level) >>>>>>> const; >>>>>>> >>>>>>> /* Return the profile info for LOC. */ >>>>>>> bool GetProfileInfo (location_t loc, ProfileInfo *info) const; >>>>>>> >>>>>>> private: >>>>>>> Symbol (unsigned name, gcov_type head_count) >>>>>>> : name_(name), total_count_(0), head_count_(head_count) {} >>>>>>> const Symbol *GetSymbolByDecl (unsigned lineno, tree decl) const; >>>>>>> >>>>>>> typedef std::map<gcov_type, const Symbol *> CallsiteMap; >>>>>> >>>>>> Need documentation for this map. >>>>>> >>>>>>> typedef std::map<unsigned, ProfileInfo> PositionCountMap; >>>>>> >>>>>> Need documentation. >>>>>> >>>>>>> >>>>>>> /* Symbol name index in the string map. */ >>>>>>> unsigned name_; >>>>>>> /* The total sampled count. */ >>>>>>> gcov_type total_count_; >>>>>>> /* The total sampled count in the head bb. */ >>>>>>> gcov_type head_count_; >>>>>>> /* Map from callsite location to callee symbol. */ >>>>>>> CallsiteMap callsites; >>>>>>> /* Map from source location to count and instruction number. */ >>>>>>> PositionCountMap pos_counts; >>>>>>> }; >>>>>>> >>>>>>> class SymbolMap { >>>>>> >>>>>> Need documentation. >>>>>> >>>>>>> public: >>>>>>> static SymbolMap *Create () >>>>>>> { >>>>>>> SymbolMap *map = new SymbolMap (); >>>>>>> if (map->Read ()) >>>>>>> return map; >>>>>>> delete map; >>>>>>> return NULL; >>>>>>> } >>>>>>> ~SymbolMap (); >>>>>>> const Symbol *GetSymbolByDecl (tree decl) const; >>>>>>> bool GetProfileInfo (gimple stmt, ProfileInfo *info) const; >>>>>>> gcov_type GetCallsiteTotalCount (struct cgraph_edge *edge) const; >>>>>> >>>>>> Missing documentation for the interfaces >>>>>>> >>>>>>> private: >>>>>> >>>>>>> typedef std::map<unsigned, const Symbol *> NameSymbolMap; >>>>>> >>>>>> map from what to symbol? >>>>>> >>>>>>> >>>>>>> SymbolMap () {} >>>>>>> bool Read (); >>>>>>> const Symbol *GetSymbolByInlineStack (const InlineStack &stack) const; >>>>>> >>>>>> Missing documentation for the interfaces >>>>>> >>>>>> >>>>>>> >>>>>>> NameSymbolMap map_; >>>>>>> }; >>>>>>> >>>>>>> class ModuleMap { >>>>>> >>>>>> Need documentation. >>>>>> >>>>>> On Tue, Jul 30, 2013 at 11:03 AM, Dehao Chen <de...@google.com> wrote: >>>>>>> I just rebased the CL to head and updated the patch. >>>>>>> >>>>>>> Thanks, >>>>>>> Dehao >>>>>>> >>>>>>> On Tue, Jul 30, 2013 at 10:09 AM, Xinliang David Li >>>>>>> <davi...@google.com> wrote: >>>>>>>> I can not apply the patch cleanly in my v17 gcc client -- there is >>>>>>>> some problem in auto-profile.c. >>>>>>>> >>>>>>>> David >>>>>>>> >>>>>>>> On Mon, Jul 29, 2013 at 7:52 PM, Dehao Chen <de...@google.com> wrote: >>>>>>>>> This patch refactors AutoFDO to use: >>>>>>>>> >>>>>>>>> 1. C++ to rewrite the whole thing. >>>>>>>>> 2. Use tree instead of hashtable to represent the profile. >>>>>>>>> 3. Make AutoFDO standalone: keep changes to other modules minimum. >>>>>>>>> >>>>>>>>> Bootstrapped and passed regression test and benchmark test. >>>>>>>>> >>>>>>>>> OK for google-4_8 branch? >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> Dehao >>>>>>>>> >>>>>>>>> http://codereview.appspot.com/12079043