Commit 112333d3 by Bernd Schmidt Committed by Bernd Schmidt

Fix missing barrier problem

From-SVN: r40932
parent 669ff14e
......@@ -2,6 +2,15 @@
* cselib.c (hash_rtx): Don't do tail recursion elimination by hand.
* config/ia64/ia64.c (update_set_flags): New function, broken out of
rtx_needs_barrier.
(set_src_needs_barrier): Likewise.
(rtx_needs_barrier): For SET case, use these two functions. Rework
PARALLEL case to handle all inputs before all outputs.
(emit_insn_group_barriers): Call init_insn_group_barriers only if we
saw a label and no stop bit since then.
(maybe_rotate, process_epilogue): Add prototypes.
2001-03-28 Richard Henderson <rth@redhat.com>
* config/rs6000/rs6000.h (EPILOGUE_USES): Use TARGET_AIX,
......
......@@ -118,6 +118,7 @@ static void ia64_free_machine_status PARAMS ((struct function *));
static void emit_insn_group_barriers PARAMS ((FILE *, rtx));
static void emit_all_insn_group_barriers PARAMS ((FILE *, rtx));
static void emit_predicate_relation_info PARAMS ((void));
static void process_epilogue PARAMS ((void));
static int process_set PARAMS ((FILE *, rtx));
static rtx ia64_expand_fetch_and_op PARAMS ((optab, enum machine_mode,
......@@ -3826,6 +3827,8 @@ static void rws_update PARAMS ((struct reg_write_state *, int,
struct reg_flags, int));
static int rws_access_regno PARAMS ((int, struct reg_flags, int));
static int rws_access_reg PARAMS ((rtx, struct reg_flags, int));
static void update_set_flags PARAMS ((rtx, struct reg_flags *, int *, rtx *));
static int set_src_needs_barrier PARAMS ((rtx, struct reg_flags, int, rtx));
static int rtx_needs_barrier PARAMS ((rtx, struct reg_flags, int));
static void init_insn_group_barriers PARAMS ((void));
static int group_barrier_needed_p PARAMS ((rtx));
......@@ -3994,62 +3997,42 @@ rws_access_reg (reg, flags, pred)
}
}
/* Handle an access to rtx X of type FLAGS using predicate register PRED.
Return 1 is this access creates a dependency with an earlier instruction
in the same group. */
/* Examine X, which is a SET rtx, and update the flags, the predicate, and
the condition, stored in *PFLAGS, *PPRED and *PCOND. */
static int
rtx_needs_barrier (x, flags, pred)
static void
update_set_flags (x, pflags, ppred, pcond)
rtx x;
struct reg_flags flags;
int pred;
struct reg_flags *pflags;
int *ppred;
rtx *pcond;
{
int i, j;
int is_complemented = 0;
int need_barrier = 0;
const char *format_ptr;
struct reg_flags new_flags;
rtx src, dst;
rtx cond = 0;
rtx src = SET_SRC (x);
if (! x)
return 0;
new_flags = flags;
*pcond = 0;
switch (GET_CODE (x))
{
case SET:
src = SET_SRC (x);
switch (GET_CODE (src))
{
case CALL:
/* We don't need to worry about the result registers that
get written by subroutine call. */
need_barrier = rtx_needs_barrier (src, flags, pred);
return need_barrier;
return;
case IF_THEN_ELSE:
if (SET_DEST (x) == pc_rtx)
{
/* X is a conditional branch. */
/* ??? This seems redundant, as the caller sets this bit for
all JUMP_INSNs. */
new_flags.is_branch = 1;
need_barrier = rtx_needs_barrier (src, new_flags, pred);
return need_barrier;
}
return;
else
{
int is_complemented = 0;
/* X is a conditional move. */
cond = XEXP (src, 0);
rtx cond = XEXP (src, 0);
if (GET_CODE (cond) == EQ)
is_complemented = 1;
cond = XEXP (cond, 0);
if (GET_CODE (cond) != REG
&& REGNO_REG_CLASS (REGNO (cond)) != PR_REGS)
abort ();
*pcond = cond;
if (XEXP (src, 1) == SET_DEST (x)
|| XEXP (src, 2) == SET_DEST (x))
{
......@@ -4060,9 +4043,9 @@ rtx_needs_barrier (x, flags, pred)
if (XEXP (src, 1) == SET_DEST (x))
is_complemented = ! is_complemented;
pred = REGNO (cond);
*ppred = REGNO (cond);
if (is_complemented)
++pred;
++*ppred;
}
/* ??? If this is a conditional write to the dest, then this
......@@ -4078,21 +4061,52 @@ rtx_needs_barrier (x, flags, pred)
default:
if (GET_RTX_CLASS (GET_CODE (src)) == '<'
&& GET_MODE_CLASS (GET_MODE (XEXP (src, 0))) == MODE_FLOAT)
/* Set new_flags.is_fp to 1 so that we know we're dealing
/* Set pflags->is_fp to 1 so that we know we're dealing
with a floating point comparison when processing the
destination of the SET. */
new_flags.is_fp = 1;
pflags->is_fp = 1;
/* Discover if this is a parallel comparison. We only handle
and.orcm and or.andcm at present, since we must retain a
strict inverse on the predicate pair. */
else if (GET_CODE (src) == AND)
new_flags.is_and = flags.is_and = 1;
pflags->is_and = 1;
else if (GET_CODE (src) == IOR)
new_flags.is_or = flags.is_or = 1;
pflags->is_or = 1;
break;
}
}
/* Subroutine of rtx_needs_barrier; this function determines whether the
source of a given SET rtx found in X needs a barrier. FLAGS and PRED
are as in rtx_needs_barrier. COND is an rtx that holds the condition
for this insn. */
static int
set_src_needs_barrier (x, flags, pred, cond)
rtx x;
struct reg_flags flags;
int pred;
rtx cond;
{
int need_barrier = 0;
rtx dst;
rtx src = SET_SRC (x);
if (GET_CODE (src) == CALL)
/* We don't need to worry about the result registers that
get written by subroutine call. */
return rtx_needs_barrier (src, flags, pred);
else if (SET_DEST (x) == pc_rtx)
{
/* X is a conditional branch. */
/* ??? This seems redundant, as the caller sets this bit for
all JUMP_INSNs. */
flags.is_branch = 1;
return rtx_needs_barrier (src, flags, pred);
}
need_barrier = rtx_needs_barrier (src, flags, pred);
/* This instruction unconditionally uses a predicate register. */
......@@ -4106,8 +4120,41 @@ rtx_needs_barrier (x, flags, pred)
need_barrier |= rtx_needs_barrier (XEXP (dst, 2), flags, pred);
dst = XEXP (dst, 0);
}
return need_barrier;
}
/* Handle an access to rtx X of type FLAGS using predicate register PRED.
Return 1 is this access creates a dependency with an earlier instruction
in the same group. */
static int
rtx_needs_barrier (x, flags, pred)
rtx x;
struct reg_flags flags;
int pred;
{
int i, j;
int is_complemented = 0;
int need_barrier = 0;
const char *format_ptr;
struct reg_flags new_flags;
rtx cond = 0;
if (! x)
return 0;
new_flags = flags;
switch (GET_CODE (x))
{
case SET:
update_set_flags (x, &new_flags, &pred, &cond);
need_barrier = set_src_needs_barrier (x, new_flags, pred, cond);
if (GET_CODE (SET_SRC (x)) != CALL)
{
new_flags.is_write = 1;
need_barrier |= rtx_needs_barrier (dst, new_flags, pred);
need_barrier |= rtx_needs_barrier (SET_DEST (x), new_flags, pred);
}
break;
case CALL:
......@@ -4180,8 +4227,33 @@ rtx_needs_barrier (x, flags, pred)
case PARALLEL:
for (i = XVECLEN (x, 0) - 1; i >= 0; --i)
if (rtx_needs_barrier (XVECEXP (x, 0, i), flags, pred))
need_barrier = 1;
{
rtx pat = XVECEXP (x, 0, i);
if (GET_CODE (pat) == SET)
{
update_set_flags (pat, &new_flags, &pred, &cond);
need_barrier |= set_src_needs_barrier (pat, new_flags, pred, cond);
}
else if (GET_CODE (pat) == USE || GET_CODE (pat) == CALL)
need_barrier |= rtx_needs_barrier (pat, flags, pred);
else if (GET_CODE (pat) != CLOBBER && GET_CODE (pat) != RETURN)
abort ();
}
for (i = XVECLEN (x, 0) - 1; i >= 0; --i)
{
rtx pat = XVECEXP (x, 0, i);
if (GET_CODE (pat) == SET)
{
if (GET_CODE (SET_SRC (pat)) != CALL)
{
new_flags.is_write = 1;
need_barrier |= rtx_needs_barrier (SET_DEST (pat), new_flags,
pred);
}
}
else if (GET_CODE (pat) == CLOBBER)
need_barrier |= rtx_needs_barrier (pat, flags, pred);
}
break;
case SUBREG:
......@@ -4532,12 +4604,13 @@ emit_insn_group_barriers (dump, insns)
INSN_UID (last_label));
emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), last_label);
insn = last_label;
}
init_insn_group_barriers ();
last_label = 0;
}
}
}
}
}
/* Like emit_insn_group_barriers, but run if no final scheduling pass was run.
......@@ -4783,9 +4856,7 @@ static int itanium_split_issue PARAMS ((const struct ia64_packet *, int));
static rtx ia64_single_set PARAMS ((rtx));
static int insn_matches_slot PARAMS ((const struct ia64_packet *, enum attr_type, int, rtx));
static void ia64_emit_insn_before PARAMS ((rtx, rtx));
#if 0
static rtx gen_nop_type PARAMS ((enum attr_type));
#endif
static void maybe_rotate PARAMS ((FILE *));
static void finish_last_head PARAMS ((FILE *, int));
static void rotate_one_bundle PARAMS ((FILE *));
static void rotate_two_bundles PARAMS ((FILE *));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment