ia64.c (struct reg_write_state): Change into unsigned short bitfields rather than unsigned int...

* config/ia64/ia64.c (struct reg_write_state): Change into
	unsigned short bitfields rather than unsigned int, decrease
	first_pred to just 10 bits.
	(rws_insn): Change into a bitmap or if not ENABLE_CHECKING
	into two char array.
	(rws_insn_set, rws_insn_test): New functions.
	(in_safe_group_barrier): New variable.
	(rws_update): Remove first argument, always set rws_sum array.
	(rws_access_regno): Use rws_insn_set macro.  Only call rws_update
	or update rws_sum if !in_safe_group_barrier, adjust rws_update
	args.
	(rtx_needs_barrier): Use rws_insn_test macro.
	(safe_group_barrier_needed): Don't save/restore rws_sum array,
	instead set/clear in_safe_group_barrier flag.

From-SVN: r129861
This commit is contained in:
Jakub Jelinek 2007-11-02 21:38:11 +01:00 committed by Jakub Jelinek
parent 7c4b32bcdc
commit 444a356a3b
2 changed files with 91 additions and 31 deletions

View File

@ -1,3 +1,20 @@
2007-11-02 Jakub Jelinek <jakub@redhat.com>
* config/ia64/ia64.c (struct reg_write_state): Change into
unsigned short bitfields rather than unsigned int, decrease
first_pred to just 10 bits.
(rws_insn): Change into a bitmap or if not ENABLE_CHECKING
into two char array.
(rws_insn_set, rws_insn_test): New functions.
(in_safe_group_barrier): New variable.
(rws_update): Remove first argument, always set rws_sum array.
(rws_access_regno): Use rws_insn_set macro. Only call rws_update
or update rws_sum if !in_safe_group_barrier, adjust rws_update
args.
(rtx_needs_barrier): Use rws_insn_test macro.
(safe_group_barrier_needed): Don't save/restore rws_sum array,
instead set/clear in_safe_group_barrier flag.
2007-11-02 Bob Wilson <bob.wilson@acm.org>
* config/xtensa/xtensa.c (xtensa_expand_prologue): Put a

View File

@ -5308,20 +5308,62 @@ ia64_safe_type (rtx insn)
If a predicate register is written by an AND.ORCM we set WRITTEN_BY_AND
to true; if it was written by an OR.ANDCM we set WRITTEN_BY_OR to true. */
#if GCC_VERSION >= 4000
#define RWS_FIELD_TYPE __extension__ unsigned short
#else
#define RWS_FIELD_TYPE unsigned int
#endif
struct reg_write_state
{
unsigned int write_count : 2;
unsigned int first_pred : 16;
unsigned int written_by_fp : 1;
unsigned int written_by_and : 1;
unsigned int written_by_or : 1;
RWS_FIELD_TYPE write_count : 2;
RWS_FIELD_TYPE first_pred : 10;
RWS_FIELD_TYPE written_by_fp : 1;
RWS_FIELD_TYPE written_by_and : 1;
RWS_FIELD_TYPE written_by_or : 1;
};
/* Cumulative info for the current instruction group. */
struct reg_write_state rws_sum[NUM_REGS];
/* Info for the current instruction. This gets copied to rws_sum after a
stop bit is emitted. */
struct reg_write_state rws_insn[NUM_REGS];
#ifdef ENABLE_CHECKING
/* Bitmap whether a register has been written in the current insn. */
HARD_REG_ELT_TYPE rws_insn[(NUM_REGS + HOST_BITS_PER_WIDEST_FAST_INT - 1)
/ HOST_BITS_PER_WIDEST_FAST_INT];
static inline void
rws_insn_set (int regno)
{
gcc_assert (!TEST_HARD_REG_BIT (rws_insn, regno));
SET_HARD_REG_BIT (rws_insn, regno);
}
static inline int
rws_insn_test (int regno)
{
return TEST_HARD_REG_BIT (rws_insn, regno);
}
#else
/* When not checking, track just REG_AR_CFM and REG_VOLATILE. */
unsigned char rws_insn[2];
static inline void
rws_insn_set (int regno)
{
if (regno == REG_AR_CFM)
rws_insn[0] = 1;
else if (regno == REG_VOLATILE)
rws_insn[1] = 1;
}
static inline int
rws_insn_test (int regno)
{
if (regno == REG_AR_CFM)
return rws_insn[0];
if (regno == REG_VOLATILE)
return rws_insn[1];
return 0;
}
#endif
/* Indicates whether this is the first instruction after a stop bit,
in which case we don't need another stop bit. Without this,
@ -5340,7 +5382,7 @@ struct reg_flags
unsigned int is_sibcall : 1; /* Is this a sibling or normal call? */
};
static void rws_update (struct reg_write_state *, int, struct reg_flags, int);
static void rws_update (int, struct reg_flags, int);
static int rws_access_regno (int, struct reg_flags, int);
static int rws_access_reg (rtx, struct reg_flags, int);
static void update_set_flags (rtx, struct reg_flags *);
@ -5349,26 +5391,27 @@ static int rtx_needs_barrier (rtx, struct reg_flags, int);
static void init_insn_group_barriers (void);
static int group_barrier_needed (rtx);
static int safe_group_barrier_needed (rtx);
static int in_safe_group_barrier;
/* Update *RWS for REGNO, which is being written by the current instruction,
with predicate PRED, and associated register flags in FLAGS. */
static void
rws_update (struct reg_write_state *rws, int regno, struct reg_flags flags, int pred)
rws_update (int regno, struct reg_flags flags, int pred)
{
if (pred)
rws[regno].write_count++;
rws_sum[regno].write_count++;
else
rws[regno].write_count = 2;
rws[regno].written_by_fp |= flags.is_fp;
rws_sum[regno].write_count = 2;
rws_sum[regno].written_by_fp |= flags.is_fp;
/* ??? Not tracking and/or across differing predicates. */
rws[regno].written_by_and = flags.is_and;
rws[regno].written_by_or = flags.is_or;
rws[regno].first_pred = pred;
rws_sum[regno].written_by_and = flags.is_and;
rws_sum[regno].written_by_or = flags.is_or;
rws_sum[regno].first_pred = pred;
}
/* Handle an access to register REGNO of type FLAGS using predicate register
PRED. Update rws_insn and rws_sum arrays. Return 1 if this access creates
PRED. Update rws_sum array. Return 1 if this access creates
a dependency with an earlier instruction in the same group. */
static int
@ -5385,18 +5428,15 @@ rws_access_regno (int regno, struct reg_flags flags, int pred)
{
int write_count;
/* One insn writes same reg multiple times? */
gcc_assert (!rws_insn[regno].write_count);
/* Update info for current instruction. */
rws_update (rws_insn, regno, flags, pred);
rws_insn_set (regno);
write_count = rws_sum[regno].write_count;
switch (write_count)
{
case 0:
/* The register has not been written yet. */
rws_update (rws_sum, regno, flags, pred);
if (!in_safe_group_barrier)
rws_update (regno, flags, pred);
break;
case 1:
@ -5410,7 +5450,8 @@ rws_access_regno (int regno, struct reg_flags flags, int pred)
;
else if ((rws_sum[regno].first_pred ^ 1) != pred)
need_barrier = 1;
rws_update (rws_sum, regno, flags, pred);
if (!in_safe_group_barrier)
rws_update (regno, flags, pred);
break;
case 2:
@ -5422,8 +5463,11 @@ rws_access_regno (int regno, struct reg_flags flags, int pred)
;
else
need_barrier = 1;
rws_sum[regno].written_by_and = flags.is_and;
rws_sum[regno].written_by_or = flags.is_or;
if (!in_safe_group_barrier)
{
rws_sum[regno].written_by_and = flags.is_and;
rws_sum[regno].written_by_or = flags.is_or;
}
break;
default:
@ -5635,7 +5679,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
/* Avoid multiple register writes, in case this is a pattern with
multiple CALL rtx. This avoids a failure in rws_access_reg. */
if (! flags.is_sibcall && ! rws_insn[REG_AR_CFM].write_count)
if (! flags.is_sibcall && ! rws_insn_test (REG_AR_CFM))
{
new_flags.is_write = 1;
need_barrier |= rws_access_regno (REG_RP, new_flags, pred);
@ -5677,7 +5721,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
{
/* Avoid writing the register multiple times if we have multiple
asm outputs. This avoids a failure in rws_access_reg. */
if (! rws_insn[REG_VOLATILE].write_count)
if (! rws_insn_test (REG_VOLATILE))
{
new_flags.is_write = 1;
rws_access_regno (REG_VOLATILE, new_flags, pred);
@ -6071,17 +6115,16 @@ group_barrier_needed (rtx insn)
static int
safe_group_barrier_needed (rtx insn)
{
struct reg_write_state rws_saved[NUM_REGS];
int saved_first_instruction;
int t;
memcpy (rws_saved, rws_sum, NUM_REGS * sizeof *rws_saved);
saved_first_instruction = first_instruction;
in_safe_group_barrier = 1;
t = group_barrier_needed (insn);
memcpy (rws_sum, rws_saved, NUM_REGS * sizeof *rws_saved);
first_instruction = saved_first_instruction;
in_safe_group_barrier = 0;
return t;
}