diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 788020bb324e..7eaa150e0284 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2003-07-15 Eric Botcazou + + PR optimization/11320 + * sched-int.h (struct deps) [reg_conditional_sets]: New field. + (struct sched_info) [compute_jump_reg_dependencies]: New prototype. + * sched-deps.c (sched_analyze_insn) [JUMP_INSN]: Update call to + current_sched_info->compute_jump_reg_dependencies. Record which + registers are used and which registers are set by the jump. + Clear deps->reg_conditional_sets after a barrier. + Set deps->reg_conditional_sets if the insn is a COND_EXEC. + Clear deps->reg_conditional_sets if the insn is not a COND_EXEC. + (init_deps): Initialize reg_conditional_sets. + (free_deps): Clear reg_conditional_sets. + * sched-ebb.c (compute_jump_reg_dependencies): New prototype. + Mark registers live on entry of the fallthrough block and conditionally + set as set by the jump. Mark registers live on entry of non-fallthrough + blocks as used by the jump. + * sched-rgn.c (compute_jump_reg_dependencies): New prototype. + Mark new parameters as unused. + 2003-07-15 Richard Sandiford * doc/invoke.texi: Resync MIPS -march documentation. diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c index cb85feaae387..f2d4fe6cbc6f 100644 --- a/gcc/sched-deps.c +++ b/gcc/sched-deps.c @@ -864,12 +864,14 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn, rtx loop_notes) else { rtx pending, pending_mem; - regset_head tmp; - INIT_REG_SET (&tmp); + regset_head tmp_uses, tmp_sets; + INIT_REG_SET (&tmp_uses); + INIT_REG_SET (&tmp_sets); - (*current_sched_info->compute_jump_reg_dependencies) (insn, &tmp); + (*current_sched_info->compute_jump_reg_dependencies) + (insn, &deps->reg_conditional_sets, &tmp_uses, &tmp_sets); /* Make latency of jump equal to 0 by using anti-dependence. */ - EXECUTE_IF_SET_IN_REG_SET (&tmp, 0, i, + EXECUTE_IF_SET_IN_REG_SET (&tmp_uses, 0, i, { struct deps_reg *reg_last = &deps->reg_last[i]; add_dependence_list (insn, reg_last->sets, REG_DEP_ANTI); @@ -877,7 +879,10 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn, rtx loop_notes) reg_last->uses_length++; reg_last->uses = alloc_INSN_LIST (insn, reg_last->uses); }); - CLEAR_REG_SET (&tmp); + IOR_REG_SET (reg_pending_sets, &tmp_sets); + + CLEAR_REG_SET (&tmp_uses); + CLEAR_REG_SET (&tmp_sets); /* All memory writes and volatile reads must happen before the jump. Non-volatile reads must happen before the jump iff @@ -984,6 +989,7 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn, rtx loop_notes) } flush_pending_lists (deps, insn, true, true); + CLEAR_REG_SET (&deps->reg_conditional_sets); reg_pending_barrier = NOT_A_BARRIER; } else @@ -1015,6 +1021,7 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn, rtx loop_notes) add_dependence_list (insn, reg_last->clobbers, REG_DEP_OUTPUT); add_dependence_list (insn, reg_last->uses, REG_DEP_ANTI); reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets); + SET_REGNO_REG_SET (&deps->reg_conditional_sets, i); }); } else @@ -1063,6 +1070,7 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn, rtx loop_notes) reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets); reg_last->uses_length = 0; reg_last->clobbers_length = 0; + CLEAR_REGNO_REG_SET (&deps->reg_conditional_sets, i); }); } @@ -1385,6 +1393,7 @@ init_deps (struct deps *deps) deps->reg_last = (struct deps_reg *) xcalloc (max_reg, sizeof (struct deps_reg)); INIT_REG_SET (&deps->reg_last_in_use); + INIT_REG_SET (&deps->reg_conditional_sets); deps->pending_read_insns = 0; deps->pending_read_mems = 0; @@ -1426,6 +1435,7 @@ free_deps (struct deps *deps) free_INSN_LIST_list (®_last->clobbers); }); CLEAR_REG_SET (&deps->reg_last_in_use); + CLEAR_REG_SET (&deps->reg_conditional_sets); free (deps->reg_last); } diff --git a/gcc/sched-ebb.c b/gcc/sched-ebb.c index 0e316b51d661..dd9ec63e7b9b 100644 --- a/gcc/sched-ebb.c +++ b/gcc/sched-ebb.c @@ -55,7 +55,7 @@ static int schedule_more_p (void); static const char *ebb_print_insn (rtx, int); static int rank (rtx, rtx); static int contributes_to_priority (rtx, rtx); -static void compute_jump_reg_dependencies (rtx, regset); +static void compute_jump_reg_dependencies (rtx, regset, regset, regset); static basic_block earliest_block_with_similiar_load (basic_block, rtx); static void add_deps_for_risky_insns (rtx, rtx); static basic_block schedule_ebb (rtx, rtx); @@ -163,20 +163,29 @@ contributes_to_priority (rtx next ATTRIBUTE_UNUSED, return 1; } -/* INSN is a JUMP_INSN. Store the set of registers that must be considered - to be set by this jump in SET. */ + /* INSN is a JUMP_INSN, COND_SET is the set of registers that are + conditionally set before INSN. Store the set of registers that + must be considered as used by this jump in USED and that of + registers that must be considered as set in SET. */ static void -compute_jump_reg_dependencies (rtx insn, regset set) +compute_jump_reg_dependencies (rtx insn, regset cond_set, regset used, + regset set) { basic_block b = BLOCK_FOR_INSN (insn); edge e; for (e = b->succ; e; e = e->succ_next) - if ((e->flags & EDGE_FALLTHRU) == 0) - { - bitmap_operation (set, set, e->dest->global_live_at_start, - BITMAP_IOR); - } + if (e->flags & EDGE_FALLTHRU) + /* The jump may be a by-product of a branch that has been merged + in the main codepath after being conditionalized. Therefore + it may guard the fallthrough block from using a value that has + conditionally overwritten that of the main codepath. So we + consider that it restores the value of the main codepath. */ + bitmap_operation (set, e->dest->global_live_at_start, cond_set, + BITMAP_AND); + else + bitmap_operation (used, used, e->dest->global_live_at_start, + BITMAP_IOR); } /* Used in schedule_insns to initialize current_sched_info for scheduling diff --git a/gcc/sched-int.h b/gcc/sched-int.h index 0ab0d65aee4e..8c3a4056342a 100644 --- a/gcc/sched-int.h +++ b/gcc/sched-int.h @@ -112,6 +112,9 @@ struct deps /* Element N is set for each register that has any nonzero element in reg_last[N].{uses,sets,clobbers}. */ regset_head reg_last_in_use; + + /* Element N is set for each register that is conditionally set. */ + regset_head reg_conditional_sets; }; /* This structure holds some state of the current scheduling pass, and @@ -148,7 +151,7 @@ struct sched_info /* Called when computing dependencies for a JUMP_INSN. This function should store the set of registers that must be considered as set by the jump in the regset. */ - void (*compute_jump_reg_dependencies) (rtx, regset); + void (*compute_jump_reg_dependencies) (rtx, regset, regset, regset); /* The boundaries of the set of insns to be scheduled. */ rtx prev_head, next_tail; diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c index cebb389dd5bb..61ab0565dbe2 100644 --- a/gcc/sched-rgn.c +++ b/gcc/sched-rgn.c @@ -1701,7 +1701,7 @@ static int schedule_more_p (void); static const char *rgn_print_insn (rtx, int); static int rgn_rank (rtx, rtx); static int contributes_to_priority (rtx, rtx); -static void compute_jump_reg_dependencies (rtx, regset); +static void compute_jump_reg_dependencies (rtx, regset, regset, regset); /* Return nonzero if there are more insns that should be scheduled. */ @@ -1951,11 +1951,15 @@ contributes_to_priority (rtx next, rtx insn) return BLOCK_NUM (next) == BLOCK_NUM (insn); } -/* INSN is a JUMP_INSN. Store the set of registers that must be considered - to be set by this jump in SET. */ +/* INSN is a JUMP_INSN, COND_SET is the set of registers that are + conditionally set before INSN. Store the set of registers that + must be considered as used by this jump in USED and that of + registers that must be considered as set in SET. */ static void compute_jump_reg_dependencies (rtx insn ATTRIBUTE_UNUSED, + regset cond_exec ATTRIBUTE_UNUSED, + regset used ATTRIBUTE_UNUSED, regset set ATTRIBUTE_UNUSED) { /* Nothing to do here, since we postprocess jumps in diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 90b25d8012a2..d13c5707a45e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-07-15 Eric Botcazou + + * gcc.c-torture/execute/20030715-1.c: New test. + 2003-07-14 Geoffrey Keating * gcc.dg/pch/inline-3.c: New file. diff --git a/gcc/testsuite/gcc.c-torture/execute/20030715-1.c b/gcc/testsuite/gcc.c-torture/execute/20030715-1.c new file mode 100644 index 000000000000..a2a28ce962c8 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20030715-1.c @@ -0,0 +1,35 @@ +/* PR optimization/11320 */ +/* Origin: Andreas Schwab */ + +/* Verify that the scheduler correctly computes the dependencies + in the presence of conditional instructions. */ + +int strcmp (const char *, const char *); +int ap_standalone; + +const char *ap_check_cmd_context (void *a, int b) +{ + return 0; +} + +const char *server_type (void *a, void *b, char *arg) +{ + const char *err = ap_check_cmd_context (a, 0x01|0x02|0x04|0x08|0x10); + if (err) + return err; + + if (!strcmp (arg, "inetd")) + ap_standalone = 0; + else if (!strcmp (arg, "standalone")) + ap_standalone = 1; + else + return "ServerType must be either 'inetd' or 'standalone'"; + + return 0; +} + +int main () +{ + server_type (0, 0, "standalone"); + return 0; +}