Hello, > OK, with the following comments: > > Make sure reg_moves are generated for the correct (result, not addr) > register, in generate_reg_moves(). > > "been">>"being" (multiple appearances). > > Add a note that autoinc_var_is_used_p (rtx def_insn, rtx use_insn) > doesn't need to consider the specific address register; no reg_moves > will be allowed for any life range defined by def_insn and used by > use_insn, if use_insn uses an address register auto-inc'ed by > def_insn.
Attached is the version of the patch which addresses your comments. Currently re-testing on ppc64-redhat-linux (bootstrap and regtest) and arm-linux-gnueabi (bootstrap c). I'll commit it once tesing completes if there if no further changes required. Thanks, Revital * ddg.c (autoinc_var_is_used_p): New function. (create_ddg_dep_from_intra_loop_link, add_cross_iteration_register_deps): Call it. * ddg.h (autoinc_var_is_used_p): Declare. * modulo-sched.c (generate_reg_moves): Call autoinc_var_is_used_p. (sms_schedule): Handle instructions with REG_INC.
Index: ddg.c =================================================================== --- ddg.c (revision 179138) +++ ddg.c (working copy) @@ -145,6 +145,27 @@ mem_access_insn_p (rtx insn) return rtx_mem_access_p (PATTERN (insn)); } +/* Return true if DEF_INSN contains address being auto-inc or auto-dec + which is used in USE_INSN. Otherwise return false. The result is + being used to decide whether to remove the edge between def_insn and + use_insn when -fmodulo-sched-allow-regmoves is set. This function + doesn't need to consider the specific address register; no reg_moves + will be allowed for any life range defined by def_insn and used + by use_insn, if use_insn uses an address register auto-inc'ed by + def_insn. */ +bool +autoinc_var_is_used_p (rtx def_insn, rtx use_insn) +{ + rtx note; + + for (note = REG_NOTES (def_insn); note; note = XEXP (note, 1)) + if (REG_NOTE_KIND (note) == REG_INC + && reg_referenced_p (XEXP (note, 0), PATTERN (use_insn))) + return true; + + return false; +} + /* Computes the dependence parameters (latency, distance etc.), creates a ddg_edge and adds it to the given DDG. */ static void @@ -173,10 +194,15 @@ create_ddg_dep_from_intra_loop_link (ddg compensate for that by generating reg-moves based on the life-range analysis. The anti-deps that will be deleted are the ones which have true-deps edges in the opposite direction (in other words - the kernel has only one def of the relevant register). TODO: - support the removal of all anti-deps edges, i.e. including those + the kernel has only one def of the relevant register). + If the address that is being auto-inc or auto-dec in DEST_NODE + is used in SRC_NODE then do not remove the edge to make sure + reg-moves will not be created for this address. + TODO: support the removal of all anti-deps edges, i.e. including those whose register has multiple defs in the loop. */ - if (flag_modulo_sched_allow_regmoves && (t == ANTI_DEP && dt == REG_DEP)) + if (flag_modulo_sched_allow_regmoves + && (t == ANTI_DEP && dt == REG_DEP) + && !autoinc_var_is_used_p (dest_node->insn, src_node->insn)) { rtx set; @@ -302,10 +328,14 @@ add_cross_iteration_register_deps (ddg_p 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. */ + 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)) + || JUMP_P (use_node->insn) + || autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn)) create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP, REG_DEP, 1); Index: ddg.h =================================================================== --- ddg.h (revision 179138) +++ ddg.h (working copy) @@ -186,4 +186,6 @@ void free_ddg_all_sccs (ddg_all_sccs_ptr int find_nodes_on_paths (sbitmap result, ddg_ptr, sbitmap from, sbitmap to); int longest_simple_path (ddg_ptr, int from, int to, sbitmap via); +bool autoinc_var_is_used_p (rtx, rtx); + #endif /* GCC_DDG_H */ Index: modulo-sched.c =================================================================== --- modulo-sched.c (revision 179138) +++ modulo-sched.c (working copy) @@ -506,6 +506,10 @@ generate_reg_moves (partial_schedule_ptr we assume no regmoves are generated as the doloop instructions are tied to the branch with an edge. */ gcc_assert (set); + /* If the instruction contains auto-inc register then + validate that the regmov is being generated for the + target regsiter rather then the inc'ed register. */ + gcc_assert (!autoinc_var_is_used_p (u->insn, e->dest->insn)); } nreg_moves = MAX (nreg_moves, nreg_moves4e); @@ -1266,12 +1285,10 @@ sms_schedule (void) continue; } - /* Don't handle BBs with calls or barriers or auto-increment insns - (to avoid creating invalid reg-moves for the auto-increment insns), + /* Don't handle BBs with calls or barriers or !single_set with the exception of instructions that include count_reg---these instructions are part of the control part that do-loop recognizes. - ??? Should handle auto-increment insns. ??? Should handle insns defining subregs. */ for (insn = head; insn != NEXT_INSN (tail); insn = NEXT_INSN (insn)) { @@ -1282,7 +1299,6 @@ sms_schedule (void) || (NONDEBUG_INSN_P (insn) && !JUMP_P (insn) && !single_set (insn) && GET_CODE (PATTERN (insn)) != USE && !reg_mentioned_p (count_reg, insn)) - || (FIND_REG_INC_NOTE (insn, NULL_RTX) != 0) || (INSN_P (insn) && (set = single_set (insn)) && GET_CODE (SET_DEST (set)) == SUBREG)) break; @@ -1296,8 +1312,6 @@ sms_schedule (void) fprintf (dump_file, "SMS loop-with-call\n"); else if (BARRIER_P (insn)) fprintf (dump_file, "SMS loop-with-barrier\n"); - else if (FIND_REG_INC_NOTE (insn, NULL_RTX) != 0) - fprintf (dump_file, "SMS reg inc\n"); else if ((NONDEBUG_INSN_P (insn) && !JUMP_P (insn) && !single_set (insn) && GET_CODE (PATTERN (insn)) != USE)) fprintf (dump_file, "SMS loop-with-not-single-set\n");