summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog20
-rw-r--r--gcc/sched-deps.c20
-rw-r--r--gcc/sched-ebb.c27
-rw-r--r--gcc/sched-int.h5
-rw-r--r--gcc/sched-rgn.c10
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20030715-1.c35
7 files changed, 103 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 788020bb324..7eaa150e028 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,23 @@
+2003-07-15 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ 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 <rsandifo@redhat.com>
* doc/invoke.texi: Resync MIPS -march documentation.
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index cb85feaae38..f2d4fe6cbc6 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 (&reg_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 0e316b51d66..dd9ec63e7b9 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 0ab0d65aee4..8c3a4056342 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 cebb389dd5b..61ab0565dbe 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 90b25d8012a..d13c5707a45 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2003-07-15 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ * gcc.c-torture/execute/20030715-1.c: New test.
+
2003-07-14 Geoffrey Keating <geoffk@apple.com>
* 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 00000000000..a2a28ce962c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20030715-1.c
@@ -0,0 +1,35 @@
+/* PR optimization/11320 */
+/* Origin: Andreas Schwab <schwab@suse.de> */
+
+/* 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;
+}