Skip to content

Commit ba12574

Browse files
committed
AutoFDO: Don't try to promote indirect calls that result in recursive direct calls
AutoFDO tries to promote and inline all indirect calls that were promoted and inlined in the original binary and that are still hot. In the included test case, the promotion results in a direct call that is a recursive call. inline_call and optimize_inline_calls can't handle recursive calls at this stage. Currently, inline_call fails with a segmentation fault. This change leaves the indirect call alone if promotion will result in a recursive call. Tested on x86_64-pc-linux-gnu. gcc/ChangeLog: * auto-profile.cc (afdo_indirect_call): Don't attempt to promote indirect calls that will result in direct recursive calls. gcc/testsuite/ChangeLog: * g++.dg/tree-prof/indir-call-recursive-inlining.C : New test.
1 parent 41582f8 commit ba12574

File tree

2 files changed

+78
-16
lines changed

2 files changed

+78
-16
lines changed

gcc/auto-profile.cc

+24-16
Original file line numberDiff line numberDiff line change
@@ -975,20 +975,20 @@ read_profile (void)
975975
* after annotation, we just need to mark, and let follow-up logic to
976976
decide if it needs to promote and inline. */
977977

978-
static void
978+
static bool
979979
afdo_indirect_call (gimple_stmt_iterator *gsi, const icall_target_map &map,
980980
bool transform)
981981
{
982982
gimple *gs = gsi_stmt (*gsi);
983983
tree callee;
984984

985985
if (map.size () == 0)
986-
return;
986+
return false;
987987
gcall *stmt = dyn_cast <gcall *> (gs);
988988
if (!stmt
989989
|| gimple_call_internal_p (stmt)
990990
|| gimple_call_fndecl (stmt) != NULL_TREE)
991-
return;
991+
return false;
992992

993993
gcov_type total = 0;
994994
icall_target_map::const_iterator max_iter = map.end ();
@@ -1003,7 +1003,7 @@ afdo_indirect_call (gimple_stmt_iterator *gsi, const icall_target_map &map,
10031003
struct cgraph_node *direct_call = cgraph_node::get_for_asmname (
10041004
get_identifier (afdo_string_table->get_name (max_iter->first)));
10051005
if (direct_call == NULL || !direct_call->profile_id)
1006-
return;
1006+
return false;
10071007

10081008
callee = gimple_call_fn (stmt);
10091009

@@ -1013,20 +1013,27 @@ afdo_indirect_call (gimple_stmt_iterator *gsi, const icall_target_map &map,
10131013
hist->hvalue.counters = XNEWVEC (gcov_type, hist->n_counters);
10141014
gimple_add_histogram_value (cfun, stmt, hist);
10151015

1016-
// Total counter
1016+
/* Total counter */
10171017
hist->hvalue.counters[0] = total;
1018-
// Number of value/counter pairs
1018+
/* Number of value/counter pairs */
10191019
hist->hvalue.counters[1] = 1;
1020-
// Value
1020+
/* Value */
10211021
hist->hvalue.counters[2] = direct_call->profile_id;
1022-
// Counter
1022+
/* Counter */
10231023
hist->hvalue.counters[3] = max_iter->second;
10241024

10251025
if (!transform)
1026-
return;
1026+
return false;
1027+
1028+
cgraph_node* current_function_node = cgraph_node::get (current_function_decl);
1029+
1030+
/* If the direct call is a recursive call, don't promote it since
1031+
we are not set up to inline recursive calls at this stage. */
1032+
if (direct_call == current_function_node)
1033+
return false;
10271034

10281035
struct cgraph_edge *indirect_edge
1029-
= cgraph_node::get (current_function_decl)->get_edge (stmt);
1036+
= current_function_node->get_edge (stmt);
10301037

10311038
if (dump_file)
10321039
{
@@ -1040,13 +1047,13 @@ afdo_indirect_call (gimple_stmt_iterator *gsi, const icall_target_map &map,
10401047
{
10411048
if (dump_file)
10421049
fprintf (dump_file, " not transforming\n");
1043-
return;
1050+
return false;
10441051
}
10451052
if (DECL_STRUCT_FUNCTION (direct_call->decl) == NULL)
10461053
{
10471054
if (dump_file)
10481055
fprintf (dump_file, " no declaration\n");
1049-
return;
1056+
return false;
10501057
}
10511058

10521059
if (dump_file)
@@ -1063,16 +1070,17 @@ afdo_indirect_call (gimple_stmt_iterator *gsi, const icall_target_map &map,
10631070
cgraph_edge::redirect_call_stmt_to_callee (new_edge);
10641071
gimple_remove_histogram_value (cfun, stmt, hist);
10651072
inline_call (new_edge, true, NULL, NULL, false);
1073+
return true;
10661074
}
10671075

10681076
/* From AutoFDO profiles, find values inside STMT for that we want to measure
10691077
histograms and adds them to list VALUES. */
10701078

1071-
static void
1079+
static bool
10721080
afdo_vpt (gimple_stmt_iterator *gsi, const icall_target_map &map,
10731081
bool transform)
10741082
{
1075-
afdo_indirect_call (gsi, map, transform);
1083+
return afdo_indirect_call (gsi, map, transform);
10761084
}
10771085

10781086
typedef std::set<basic_block> bb_set;
@@ -1498,8 +1506,8 @@ afdo_vpt_for_early_inline (stmt_set *promoted_stmts)
14981506
{
14991507
/* Promote the indirect call and update the promoted_stmts. */
15001508
promoted_stmts->insert (stmt);
1501-
afdo_vpt (&gsi, info.targets, true);
1502-
has_vpt = true;
1509+
if (afdo_vpt (&gsi, info.targets, true))
1510+
has_vpt = true;
15031511
}
15041512
}
15051513
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* { dg-options "-O2 " } */
2+
3+
class Parent
4+
{
5+
public:
6+
Parent *object;
7+
8+
Parent()
9+
{
10+
object = this;
11+
}
12+
13+
virtual void recurse (int t) = 0;
14+
};
15+
16+
class Child : public Parent
17+
{
18+
19+
Parent *
20+
get_object ()
21+
{
22+
return this;
23+
}
24+
25+
public:
26+
virtual void
27+
recurse (int t)
28+
{
29+
if (t != 10)
30+
for (int i = 0; i < 5; ++i)
31+
get_object()->recurse(t + 1);
32+
};
33+
};
34+
35+
Parent *
36+
create_object ()
37+
{
38+
Child *mod = new Child;
39+
return mod;
40+
}
41+
42+
int
43+
main (int argc, char **argv)
44+
{
45+
Parent *parent = create_object ();
46+
47+
for (int i = 0; i < 5; ++i)
48+
{
49+
parent->recurse (0);
50+
}
51+
52+
return 0;
53+
}
54+

0 commit comments

Comments
 (0)