(Sorry if you received the mail twice because it was not plain text at first and was rejected by @sourceware.org)
We saw bb like this in the IR dump after pass_build_cfg: <bb 21>: [1.cc : 205:45] D.332088 = table->_vptr.Table; [1.cc : 205:45] D.332134 = D.332088 + 104; [1.cc : 205:45] D.332135 = [1.cc : 205] *D.332134; [1.cc : 205:45] D.332092 = [1.cc : 205] &this->cp_stream_; [1.cc : 205:46] OBJ_TYPE_REF(D.332135;(struct Table)table->13) (table, cp_arg, D.332092); // indirect call [1.cc : 179:64] Reader::~Reader (&version); [1.cc : 205:46] Switcher::~Switcher (&tcswr); The indirect call above has the same source lineno with "Switcher::~Switcher (&tcswr);", but they have no discriminator so they cannot be discriminated in autofdo. This causes the problem that autofdo mistakenly regards "Switcher::~Switcher (&tcswr);" as a target of the indirect call above, and makes a wrong promotion. The existing code has the logic to assign different discriminators to calls with the same lineno, but it only works when the lineno in a bb is monotonical. In this case, there is another stmt with lineno 179 between the indirect call and "Switcher::~Switcher (&tcswr);" (both with lineno 205), so existing code will not assign different discriminators for them. The patch is to assign discriminators for calls with the same lineno anyway. regression test is going. internal perf test for autofdo shows a little improvement. Ok for google-4_9 if regression pass? Thanks, Wei. ChangeLog: 2014-08-06 Wei Mi <w...@google.com> * tree-cfg.c (increase_discriminator_for_locus): It was next_discriminator_for_locus. Add a param "return_next". (next_discriminator_for_locus): Renamed. (assign_discriminator): Use the renamed func. (assign_discriminators): Assign different discriminators for calls with the same lineno. Index: tree-cfg.c =================================================================== --- tree-cfg.c (revision 213402) +++ tree-cfg.c (working copy) @@ -914,10 +914,12 @@ make_edges (void) /* Find the next available discriminator value for LOCUS. The discriminator distinguishes among several basic blocks that share a common locus, allowing for more accurate sample-based - profiling. */ + profiling. If RETURN_NEXT is true, return the discriminator + value after the increase, else return the discriminator value + before the increase. */ static int -next_discriminator_for_locus (location_t locus) +increase_discriminator_for_locus (location_t locus, bool return_next) { struct locus_discrim_map item; struct locus_discrim_map **slot; @@ -934,8 +936,10 @@ next_discriminator_for_locus (location_t (*slot)->locus = locus; (*slot)->discriminator = 0; } + (*slot)->discriminator++; - return (*slot)->discriminator; + return return_next ? (*slot)->discriminator + : (*slot)->discriminator - 1; } /* Return TRUE if LOCUS1 and LOCUS2 refer to the same source line. */ @@ -974,7 +978,7 @@ assign_discriminator (location_t locus, if (locus == UNKNOWN_LOCATION) return; - discriminator = next_discriminator_for_locus (locus); + discriminator = increase_discriminator_for_locus (locus, true); for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { @@ -1009,23 +1013,16 @@ assign_discriminators (void) for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); - if (curr_locus == UNKNOWN_LOCATION) - { - curr_locus = gimple_location (stmt); - } - else if (!same_line_p (curr_locus, gimple_location (stmt))) + if (gimple_code (stmt) == GIMPLE_CALL) { curr_locus = gimple_location (stmt); - curr_discr = 0; - } - else if (curr_discr != 0) - { - gimple_set_location (stmt, location_with_discriminator ( - gimple_location (stmt), curr_discr)); + /* return the current discriminator first, then increase the + discriminator for next call. */ + curr_discr = increase_discriminator_for_locus (curr_locus, false); + if (curr_discr != 0) + gimple_set_location (stmt, location_with_discriminator ( + gimple_location (stmt), curr_discr)); } - /* Allocate a new discriminator for CALL stmt. */ - if (gimple_code (stmt) == GIMPLE_CALL) - curr_discr = next_discriminator_for_locus (curr_locus); } if (locus == UNKNOWN_LOCATION)