aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2007-11-02 21:38:11 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2007-11-02 21:38:11 +0100
commit444a356a3bc8de75d802214b2ef110ebec78a72c (patch)
tree9cb08fa7ebf021f07a343dbee0dd920495b48f32 /gcc/config
parent7c4b32bcdc8455d77f73eb56e8fec9ca74fe6be2 (diff)
downloadgcc-444a356a3bc8de75d802214b2ef110ebec78a72c.zip
gcc-444a356a3bc8de75d802214b2ef110ebec78a72c.tar.gz
gcc-444a356a3bc8de75d802214b2ef110ebec78a72c.tar.bz2
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
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/ia64/ia64.c105
1 files changed, 74 insertions, 31 deletions
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 537f9f0..a75e68e 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -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;
}