modulo-sched: fix bootstrap compare-debug issue

This patch removes all debug insns from DDG analysis.  It fixes bootstrap
comparison failure on powerpc64le when running with -fmodulo-sched enabled.

	* ddg.c (create_ddg_dep_from_intra_loop_link): Remove assertions.
	(create_ddg_dep_no_link): Likewise.
	(add_cross_iteration_register_deps): Move debug instruction check.
	Other minor refactoring.
	(add_intra_loop_mem_dep): Do not check for debug instructions.
	(add_inter_loop_mem_dep): Likewise.
	(build_intra_loop_deps): Likewise.
	(create_ddg): Do not include debug insns into the graph.
	* ddg.h (struct ddg): Remove num_debug field.
	* modulo-sched.c (doloop_register_get): Adjust condition.
	(res_MII): Remove DDG num_debug field usage.
	(sms_schedule_by_order): Use assertion against debug insns.
	(ps_has_conflicts): Drop debug insn check.

testsuite:

    	* gcc.c-torture/execute/pr70127-debug-sms.c: New test.
    	* gcc.dg/torture/pr87197-debug-sms.c: New test.
This commit is contained in:
Roman Zhuykov 2020-03-27 08:02:56 +03:00
parent 71d69548a1
commit 06d5d63d99
7 changed files with 149 additions and 122 deletions

View File

@ -1,3 +1,19 @@
2020-03-27 Roman Zhuykov <zhroma@ispras.ru>
* ddg.c (create_ddg_dep_from_intra_loop_link): Remove assertions.
(create_ddg_dep_no_link): Likewise.
(add_cross_iteration_register_deps): Move debug instruction check.
Other minor refactoring.
(add_intra_loop_mem_dep): Do not check for debug instructions.
(add_inter_loop_mem_dep): Likewise.
(build_intra_loop_deps): Likewise.
(create_ddg): Do not include debug insns into the graph.
* ddg.h (struct ddg): Remove num_debug field.
* modulo-sched.c (doloop_register_get): Adjust condition.
(res_MII): Remove DDG num_debug field usage.
(sms_schedule_by_order): Use assertion against debug insns.
(ps_has_conflicts): Drop debug insn check.
2020-03-26 Richard Earnshaw <rearnsha@arm.com>
PR target/94220

173
gcc/ddg.c
View File

@ -185,9 +185,6 @@ create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node,
else if (DEP_TYPE (link) == REG_DEP_OUTPUT)
t = OUTPUT_DEP;
gcc_assert (!DEBUG_INSN_P (dest_node->insn) || t == ANTI_DEP);
gcc_assert (!DEBUG_INSN_P (src_node->insn) || t == ANTI_DEP);
/* We currently choose not to create certain anti-deps edges and
compensate for that by generating reg-moves based on the life-range
analysis. The anti-deps that will be deleted are the ones which
@ -222,9 +219,9 @@ create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node,
}
}
latency = dep_cost (link);
e = create_ddg_edge (src_node, dest_node, t, dt, latency, distance);
add_edge_to_ddg (g, e);
latency = dep_cost (link);
e = create_ddg_edge (src_node, dest_node, t, dt, latency, distance);
add_edge_to_ddg (g, e);
}
/* The same as the above function, but it doesn't require a link parameter. */
@ -237,9 +234,6 @@ create_ddg_dep_no_link (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to,
enum reg_note dep_kind;
struct _dep _dep, *dep = &_dep;
gcc_assert (!DEBUG_INSN_P (to->insn) || d_t == ANTI_DEP);
gcc_assert (!DEBUG_INSN_P (from->insn) || d_t == ANTI_DEP);
if (d_t == ANTI_DEP)
dep_kind = REG_DEP_ANTI;
else if (d_t == OUTPUT_DEP)
@ -272,16 +266,15 @@ create_ddg_dep_no_link (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to,
static void
add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
{
int regno = DF_REF_REGNO (last_def);
struct df_link *r_use;
int has_use_in_bb_p = false;
rtx_insn *def_insn = DF_REF_INSN (last_def);
ddg_node_ptr last_def_node = get_node_of_insn (g, def_insn);
ddg_node_ptr use_node;
int regno = DF_REF_REGNO (last_def);
ddg_node_ptr last_def_node = get_node_of_insn (g, DF_REF_INSN (last_def));
df_ref first_def = df_bb_regno_first_def_find (g->bb, regno);
ddg_node_ptr first_def_node = get_node_of_insn (g, DF_REF_INSN (first_def));
ddg_node_ptr use_node;
gcc_assert (last_def_node);
gcc_assert (first_def);
gcc_assert (last_def_node && first_def && first_def_node);
if (flag_checking && DF_REF_ID (last_def) != DF_REF_ID (first_def))
{
@ -300,6 +293,9 @@ add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
rtx_insn *use_insn = DF_REF_INSN (r_use->ref);
if (DEBUG_INSN_P (use_insn))
continue;
/* ??? Do not handle uses with DF_REF_IN_NOTE notes. */
use_node = get_node_of_insn (g, use_insn);
gcc_assert (use_node);
@ -310,35 +306,28 @@ add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
iteration. Any such upwards exposed use appears before
the last_def def. */
create_ddg_dep_no_link (g, last_def_node, use_node,
DEBUG_INSN_P (use_insn) ? ANTI_DEP : TRUE_DEP,
REG_DEP, 1);
TRUE_DEP, REG_DEP, 1);
}
else if (!DEBUG_INSN_P (use_insn))
else
{
/* Add anti deps from last_def's uses in the current iteration
to the first def in the next iteration. We do not add ANTI
dep when there is an intra-loop TRUE dep in the opposite
direction, but use regmoves to fix such disregarded ANTI
deps when broken. If the first_def reaches the USE then
there is such a dep. */
ddg_node_ptr first_def_node = get_node_of_insn (g,
DF_REF_INSN (first_def));
gcc_assert (first_def_node);
/* Always create the edge if the use node is a branch in
order to prevent the creation of reg-moves.
If the address that is being auto-inc or auto-dec in LAST_DEF
is used in USE_INSN then do not remove the edge to make sure
reg-moves will not be created for that address. */
if (DF_REF_ID (last_def) != DF_REF_ID (first_def)
|| !flag_modulo_sched_allow_regmoves
there is such a dep.
Always create the edge if the use node is a branch in
order to prevent the creation of reg-moves.
If the address that is being auto-inc or auto-dec in LAST_DEF
is used in USE_INSN then do not remove the edge to make sure
reg-moves will not be created for that address. */
if (DF_REF_ID (last_def) != DF_REF_ID (first_def)
|| !flag_modulo_sched_allow_regmoves
|| JUMP_P (use_node->insn)
|| autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn)
|| autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn)
|| def_has_ccmode_p (DF_REF_INSN (last_def)))
create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP,
REG_DEP, 1);
create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP,
REG_DEP, 1);
}
}
/* Create an inter-loop output dependence between LAST_DEF (which is the
@ -348,19 +337,11 @@ add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
defs starting with a true dependence to a use which can be in the
next iteration; followed by an anti dependence of that use to the
first def (i.e. if there is a use between the two defs.) */
if (!has_use_in_bb_p)
{
ddg_node_ptr dest_node;
if (DF_REF_ID (last_def) == DF_REF_ID (first_def))
return;
dest_node = get_node_of_insn (g, DF_REF_INSN (first_def));
gcc_assert (dest_node);
create_ddg_dep_no_link (g, last_def_node, dest_node,
OUTPUT_DEP, REG_DEP, 1);
}
if (!has_use_in_bb_p && DF_REF_ID (last_def) != DF_REF_ID (first_def))
create_ddg_dep_no_link (g, last_def_node, first_def_node,
OUTPUT_DEP, REG_DEP, 1);
}
/* Build inter-loop dependencies, by looking at DF analysis backwards. */
static void
build_inter_loop_deps (ddg_ptr g)
@ -417,13 +398,9 @@ add_intra_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
if (mem_write_insn_p (from->insn))
{
if (mem_read_insn_p (to->insn))
create_ddg_dep_no_link (g, from, to,
DEBUG_INSN_P (to->insn)
? ANTI_DEP : TRUE_DEP, MEM_DEP, 0);
create_ddg_dep_no_link (g, from, to, TRUE_DEP, MEM_DEP, 0);
else
create_ddg_dep_no_link (g, from, to,
DEBUG_INSN_P (to->insn)
? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 0);
create_ddg_dep_no_link (g, from, to, OUTPUT_DEP, MEM_DEP, 0);
}
else if (!mem_read_insn_p (to->insn))
create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 0);
@ -441,13 +418,9 @@ add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
if (mem_write_insn_p (from->insn))
{
if (mem_read_insn_p (to->insn))
create_ddg_dep_no_link (g, from, to,
DEBUG_INSN_P (to->insn)
? ANTI_DEP : TRUE_DEP, MEM_DEP, 1);
create_ddg_dep_no_link (g, from, to, TRUE_DEP, MEM_DEP, 1);
else if (from->cuid != to->cuid)
create_ddg_dep_no_link (g, from, to,
DEBUG_INSN_P (to->insn)
? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 1);
create_ddg_dep_no_link (g, from, to, OUTPUT_DEP, MEM_DEP, 1);
}
else
{
@ -456,13 +429,9 @@ add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
else if (from->cuid != to->cuid)
{
create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 1);
if (DEBUG_INSN_P (from->insn) || DEBUG_INSN_P (to->insn))
create_ddg_dep_no_link (g, to, from, ANTI_DEP, MEM_DEP, 1);
else
create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
create_ddg_dep_no_link (g, to, from, TRUE_DEP, MEM_DEP, 1);
}
}
}
/* Perform intra-block Data Dependency analysis and connect the nodes in
@ -491,20 +460,10 @@ build_intra_loop_deps (ddg_ptr g)
sd_iterator_def sd_it;
dep_t dep;
if (! INSN_P (dest_node->insn))
continue;
FOR_EACH_DEP (dest_node->insn, SD_LIST_BACK, sd_it, dep)
{
rtx_insn *src_insn = DEP_PRO (dep);
ddg_node_ptr src_node;
/* Don't add dependencies on debug insns to non-debug insns
to avoid codegen differences between -g and -g0. */
if (DEBUG_INSN_P (src_insn) && !DEBUG_INSN_P (dest_node->insn))
continue;
src_node = get_node_of_insn (g, src_insn);
ddg_node_ptr src_node = get_node_of_insn (g, src_insn);
if (!src_node)
continue;
@ -521,8 +480,7 @@ build_intra_loop_deps (ddg_ptr g)
for (j = 0; j <= i; j++)
{
ddg_node_ptr j_node = &g->nodes[j];
if (DEBUG_INSN_P (j_node->insn))
continue;
if (mem_access_insn_p (j_node->insn))
{
/* Don't bother calculating inter-loop dep if an intra-loop dep
@ -573,23 +531,21 @@ create_ddg (basic_block bb, int closing_branch_deps)
for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
insn = NEXT_INSN (insn))
{
if (! INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
if (!INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
continue;
if (DEBUG_INSN_P (insn))
g->num_debug++;
else
if (NONDEBUG_INSN_P (insn))
{
if (mem_read_insn_p (insn))
g->num_loads++;
if (mem_write_insn_p (insn))
g->num_stores++;
num_nodes++;
}
num_nodes++;
}
/* There is nothing to do for this BB. */
if ((num_nodes - g->num_debug) <= 1)
if (num_nodes <= 1)
{
free (g);
return NULL;
@ -604,38 +560,39 @@ create_ddg (basic_block bb, int closing_branch_deps)
for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
insn = NEXT_INSN (insn))
{
if (! INSN_P (insn))
{
if (! first_note && NOTE_P (insn)
&& NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK)
first_note = insn;
continue;
}
if (LABEL_P (insn) || NOTE_INSN_BASIC_BLOCK_P (insn))
continue;
if (!first_note && (INSN_P (insn) || NOTE_P (insn)))
first_note = insn;
if (!INSN_P (insn) || GET_CODE (PATTERN (insn)) == USE)
continue;
if (JUMP_P (insn))
{
gcc_assert (!g->closing_branch);
g->closing_branch = &g->nodes[i];
}
else if (GET_CODE (PATTERN (insn)) == USE)
if (NONDEBUG_INSN_P (insn))
{
if (! first_note)
first_note = insn;
continue;
g->nodes[i].cuid = i;
g->nodes[i].successors = sbitmap_alloc (num_nodes);
bitmap_clear (g->nodes[i].successors);
g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
bitmap_clear (g->nodes[i].predecessors);
gcc_checking_assert (first_note);
g->nodes[i].first_note = first_note;
g->nodes[i].aux.count = -1;
g->nodes[i].max_dist = XCNEWVEC (int, num_nodes);
for (j = 0; j < num_nodes; j++)
g->nodes[i].max_dist[j] = -1;
g->nodes[i++].insn = insn;
}
g->nodes[i].cuid = i;
g->nodes[i].successors = sbitmap_alloc (num_nodes);
bitmap_clear (g->nodes[i].successors);
g->nodes[i].predecessors = sbitmap_alloc (num_nodes);
bitmap_clear (g->nodes[i].predecessors);
g->nodes[i].first_note = (first_note ? first_note : insn);
g->nodes[i].aux.count = -1;
g->nodes[i].max_dist = XCNEWVEC (int, num_nodes);
for (j = 0; j < num_nodes; j++)
g->nodes[i].max_dist[j] = -1;
g->nodes[i++].insn = insn;
first_note = NULL;
}

View File

@ -116,9 +116,6 @@ struct ddg
int num_loads;
int num_stores;
/* Number of debug instructions in the BB. */
int num_debug;
/* This array holds the nodes in the graph; it is indexed by the node
cuid, which follows the order of the instructions in the BB. */
ddg_node_ptr nodes;

View File

@ -369,7 +369,7 @@ doloop_register_get (rtx_insn *head, rtx_insn *tail)
: prev_nondebug_insn (tail));
for (insn = head; insn != first_insn_not_to_check; insn = NEXT_INSN (insn))
if (!DEBUG_INSN_P (insn) && reg_mentioned_p (reg, insn))
if (NONDEBUG_INSN_P (insn) && reg_mentioned_p (reg, insn))
{
if (dump_file)
{
@ -428,7 +428,7 @@ res_MII (ddg_ptr g)
if (targetm.sched.sms_res_mii)
return targetm.sched.sms_res_mii (g);
return ((g->num_nodes - g->num_debug) / issue_rate);
return g->num_nodes / issue_rate;
}
@ -2152,11 +2152,7 @@ sms_schedule_by_order (ddg_ptr g, int mii, int maxii, int *nodes_order)
ddg_node_ptr u_node = &ps->g->nodes[u];
rtx_insn *insn = u_node->insn;
if (!NONDEBUG_INSN_P (insn))
{
bitmap_clear_bit (tobe_scheduled, u);
continue;
}
gcc_checking_assert (NONDEBUG_INSN_P (insn));
if (bitmap_bit_p (sched_nodes, u))
continue;
@ -3158,9 +3154,6 @@ ps_has_conflicts (partial_schedule_ptr ps, int from, int to)
{
rtx_insn *insn = ps_rtl_insn (ps, crr_insn->id);
if (!NONDEBUG_INSN_P (insn))
continue;
/* Check if there is room for the current insn. */
if (!can_issue_more || state_dead_lock_p (curr_state))
return true;

View File

@ -1,4 +1,9 @@
2020-03-26 Marek Polacek <polacek@redhat.com>
2020-03-27 Roman Zhuykov <zhroma@ispras.ru>
* gcc.c-torture/execute/pr70127-debug-sms.c: New test.
* gcc.dg/torture/pr87197-debug-sms.c: New test.
2020-03-27 Marek Polacek <polacek@redhat.com>
PR c++/94336 - template keyword accepted before destructor names.
* g++.dg/template/template-keyword2.C: New test.

View File

@ -0,0 +1,23 @@
/* { dg-additional-options "-fcompare-debug -fmodulo-sched" } */
struct S { int f; signed int g : 2; } a[1], c = {5, 1}, d;
short b;
__attribute__((noinline, noclone)) void
foo (int x)
{
if (x != 1)
__builtin_abort ();
}
int
main ()
{
while (b++ <= 0)
{
struct S e = {1, 1};
d = e = a[0] = c;
}
foo (a[0].g);
return 0;
}

View File

@ -0,0 +1,36 @@
/* { dg-do compile } */
/* { dg-additional-options "-fcompare-debug -fmodulo-sched --param sms-min-sc=1" } */
int a, c, e, f, g;
void
h (int i)
{
a = i;
}
void
j (char *i, long k)
{
while (k--)
c = *i++;
}
void
l (unsigned char *i, long k)
{
unsigned char *b = i + k;
while (i < b)
{
h (*i);
i++;
}
}
void
m ()
{
while (e)
{
float d = g;
l ((char *) &d, sizeof (g));
if (f)
j ((char *) &d, sizeof (g));
}
}