From 06d5d63d9944691bb4286e5f6b2422cc97148336 Mon Sep 17 00:00:00 2001 From: Roman Zhuykov Date: Fri, 27 Mar 2020 08:02:56 +0300 Subject: [PATCH] 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. --- gcc/ChangeLog | 16 ++ gcc/ddg.c | 169 +++++++----------- gcc/ddg.h | 3 - gcc/modulo-sched.c | 13 +- gcc/testsuite/ChangeLog | 7 +- .../gcc.c-torture/execute/pr70127-debug-sms.c | 23 +++ .../gcc.dg/torture/pr87197-debug-sms.c | 36 ++++ 7 files changed, 147 insertions(+), 120 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr70127-debug-sms.c create mode 100644 gcc/testsuite/gcc.dg/torture/pr87197-debug-sms.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e81e876bc00..c472a13f5da 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2020-03-27 Roman Zhuykov + + * 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 PR target/94220 diff --git a/gcc/ddg.c b/gcc/ddg.c index ca8cb74823d..3bea4d18ee8 100644 --- a/gcc/ddg.c +++ b/gcc/ddg.c @@ -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); - 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); + 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].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++].insn = insn; + } first_note = NULL; } diff --git a/gcc/ddg.h b/gcc/ddg.h index 32de2b2e0f8..c5fb256cc11 100644 --- a/gcc/ddg.h +++ b/gcc/ddg.h @@ -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; diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c index e16e0232432..77254b31b42 100644 --- a/gcc/modulo-sched.c +++ b/gcc/modulo-sched.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3a1c5e713dc..98f090721d1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,4 +1,9 @@ -2020-03-26 Marek Polacek +2020-03-27 Roman Zhuykov + + * gcc.c-torture/execute/pr70127-debug-sms.c: New test. + * gcc.dg/torture/pr87197-debug-sms.c: New test. + +2020-03-27 Marek Polacek PR c++/94336 - template keyword accepted before destructor names. * g++.dg/template/template-keyword2.C: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr70127-debug-sms.c b/gcc/testsuite/gcc.c-torture/execute/pr70127-debug-sms.c new file mode 100644 index 00000000000..46911789be8 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr70127-debug-sms.c @@ -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; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr87197-debug-sms.c b/gcc/testsuite/gcc.dg/torture/pr87197-debug-sms.c new file mode 100644 index 00000000000..fbbf1b389ea --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr87197-debug-sms.c @@ -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)); + } +} -- 2.30.2