diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 241c54460f2..b87be58cd43 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2005-03-21 Mostafa Hagog + + PR middle-end/20177 + * ddg.c (create_ddg_dependence): Ignore reg-anti dependency. + * modulo-sched.c (const_iteration_count): Return on NULL + pre-header. + (print_node_sched_params): Return on NULL dump_file. + (generate_reg_moves): Handle reg-anti dependencies and disregard + closing branch when generating register moves. + (sms_schedule): Mark the SMSed block dirty. + * passes.c (rest_of_handle_sms): Call update_life_info for all + basic-blocks. + * testsuite/gcc.dg/20050321-1.c: New test. + 2005-03-21 Bob Wilson * config/xtensa/lib1funcs.asm (__mulsi3): Use symbolic name for ACCLO. diff --git a/gcc/ddg.c b/gcc/ddg.c index a54a87c0744..5a2cbeee109 100644 --- a/gcc/ddg.c +++ b/gcc/ddg.c @@ -187,6 +187,8 @@ create_ddg_dependence (ddg_ptr g, ddg_node_ptr src_node, else free (e); } + else if (t == ANTI_DEP && dt == REG_DEP) + free (e); /* We can fix broken anti register deps using reg-moves. */ else add_edge_to_ddg (g, e); } diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c index 56717279436..86773165dd2 100644 --- a/gcc/modulo-sched.c +++ b/gcc/modulo-sched.c @@ -337,6 +337,10 @@ const_iteration_count (rtx count_reg, basic_block pre_header, { rtx insn; rtx head, tail; + + if (! pre_header) + return NULL_RTX; + get_block_head_tail (pre_header->index, &head, &tail); for (insn = tail; insn != PREV_INSN (head); insn = PREV_INSN (insn)) @@ -399,6 +403,8 @@ print_node_sched_params (FILE * dump_file, int num_nodes) { int i; + if (! dump_file) + return; for (i = 0; i < num_nodes; i++) { node_sched_params_ptr nsp = &node_sched_params[i]; @@ -441,14 +447,17 @@ calculate_maxii (ddg_ptr g) return maxii; } - -/* Given the partial schedule, generate register moves when the length - of the register live range is more than ii; the number of moves is - determined according to the following equation: - SCHED_TIME (use) - SCHED_TIME (def) { 1 broken loop-carried - nreg_moves = ----------------------------------- - { dependence. - ii { 0 if not. - This handles the modulo-variable-expansions (mve's) needed for the ps. */ +/* + Breaking intra-loop register anti-dependences: + Each intra-loop register anti-dependence implies a cross-iteration true + dependence of distance 1. Therefore, we can remove such false dependencies + and figure out if the partial schedule broke them by checking if (for a + true-dependence of distance 1): SCHED_TIME (def) < SCHED_TIME (use) and + if so generate a register move. The number of such moves is equal to: + SCHED_TIME (use) - SCHED_TIME (def) { 0 broken + nreg_moves = ----------------------------------- + 1 - { dependecnce. + ii { 1 if not. +*/ static void generate_reg_moves (partial_schedule_ptr ps) { @@ -472,6 +481,9 @@ generate_reg_moves (partial_schedule_ptr ps) { int nreg_moves4e = (SCHED_TIME (e->dest) - SCHED_TIME (e->src)) / ii; + if (e->distance == 1) + nreg_moves4e = (SCHED_TIME (e->dest) - SCHED_TIME (e->src) + ii) / ii; + /* If dest precedes src in the schedule of the kernel, then dest will read before src writes and we can save one reg_copy. */ if (SCHED_ROW (e->dest) == SCHED_ROW (e->src) @@ -495,6 +507,9 @@ generate_reg_moves (partial_schedule_ptr ps) { int dest_copy = (SCHED_TIME (e->dest) - SCHED_TIME (e->src)) / ii; + if (e->distance == 1) + dest_copy = (SCHED_TIME (e->dest) - SCHED_TIME (e->src) + ii) / ii; + if (SCHED_ROW (e->dest) == SCHED_ROW (e->src) && SCHED_COLUMN (e->dest) < SCHED_COLUMN (e->src)) dest_copy--; @@ -538,7 +553,8 @@ normalize_sched_times (partial_schedule_ptr ps) int amount = PS_MIN_CYCLE (ps); int ii = ps->ii; - for (i = 0; i < g->num_nodes; i++) + /* Don't include the closing branch assuming that it is the last node. */ + for (i = 0; i < g->num_nodes - 1; i++) { ddg_node_ptr u = &g->nodes[i]; int normalized_time = SCHED_TIME (u) - amount; @@ -607,7 +623,7 @@ duplicate_insns_of_cycles (partial_schedule_ptr ps, int from_stage, /* SCHED_STAGE (u_node) >= from_stage == 0. Generate increasing number of reg_moves starting with the second occurrence of u_node, which is generated if its SCHED_STAGE <= to_stage. */ - i_reg_moves = to_stage - SCHED_STAGE (u_node); + i_reg_moves = to_stage - SCHED_STAGE (u_node) + 1; i_reg_moves = MAX (i_reg_moves, 0); i_reg_moves = MIN (i_reg_moves, SCHED_NREG_MOVES (u_node)); @@ -1107,6 +1123,8 @@ sms_schedule (FILE *dump_file) scheduling passes doesn't touch it. */ if (! flag_resched_modulo_sched) g->bb->flags |= BB_DISABLE_SCHEDULE; + /* The life-info is not valid any more. */ + g->bb->flags |= BB_DIRTY; generate_reg_moves (ps); if (dump_file) diff --git a/gcc/passes.c b/gcc/passes.c index 7bb661d0d0e..1121d0c3672 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -575,6 +575,8 @@ rest_of_handle_partition_blocks (void) static void rest_of_handle_sms (void) { + sbitmap blocks; + timevar_push (TV_SMS); open_dump_file (DFI_sms, current_function_decl); @@ -587,10 +589,14 @@ rest_of_handle_sms (void) /* Update the life information, because we add pseudos. */ max_regno = max_reg_num (); allocate_reg_info (max_regno, FALSE, FALSE); - update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES, - (PROP_DEATH_NOTES - | PROP_KILL_DEAD_CODE - | PROP_SCAN_DEAD_CODE)); + blocks = sbitmap_alloc (last_basic_block); + sbitmap_ones (blocks); + update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES, + (PROP_DEATH_NOTES + | PROP_REG_INFO + | PROP_KILL_DEAD_CODE + | PROP_SCAN_DEAD_CODE)); + no_new_pseudos = 1; ggc_collect (); diff --git a/gcc/testsuite/gcc.dg/20050321-1.c b/gcc/testsuite/gcc.dg/20050321-1.c new file mode 100644 index 00000000000..01c68cd5ed9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/20050321-1.c @@ -0,0 +1,26 @@ +/* This caused an ICE on powerpc-linux-gnu due to not + up-to-date life info (PR middle-end/20177). */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fmodulo-sched" } */ +extern void * malloc (long); + +struct s { + int k; +}; + +int n; +struct s *a1, *(*use)[]; +float (*vector)[]; + +void +foo (float *V) +{ + int i, used = 0; + + vector = malloc (i * sizeof (float)); + while ((*use)[used] != a1) + used += 1; + for (i = 0; i < n; i++) + *V += (*vector)[i]; +}