summaryrefslogtreecommitdiff
path: root/gcc/emit-rtl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/emit-rtl.c')
-rw-r--r--gcc/emit-rtl.c153
1 files changed, 142 insertions, 11 deletions
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 5dd599a8599..5e719ae2ac1 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -157,6 +157,10 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
static GTY ((if_marked ("ggc_marked_p"), param_is (struct mem_attrs)))
htab_t mem_attrs_htab;
+/* A hash table storing register attribute structures. */
+static GTY ((if_marked ("ggc_marked_p"), param_is (struct reg_attrs)))
+ htab_t reg_attrs_htab;
+
/* A hash table storing all CONST_DOUBLEs. */
static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
htab_t const_double_htab;
@@ -190,6 +194,10 @@ static int mem_attrs_htab_eq PARAMS ((const void *,
static mem_attrs *get_mem_attrs PARAMS ((HOST_WIDE_INT, tree, rtx,
rtx, unsigned int,
enum machine_mode));
+static hashval_t reg_attrs_htab_hash PARAMS ((const void *));
+static int reg_attrs_htab_eq PARAMS ((const void *,
+ const void *));
+static reg_attrs *get_reg_attrs PARAMS ((tree, int));
static tree component_ref_for_mem_expr PARAMS ((tree));
static rtx gen_const_vector_0 PARAMS ((enum machine_mode));
@@ -323,6 +331,60 @@ get_mem_attrs (alias, expr, offset, size, align, mode)
return *slot;
}
+/* Returns a hash code for X (which is a really a reg_attrs *). */
+
+static hashval_t
+reg_attrs_htab_hash (x)
+ const void *x;
+{
+ reg_attrs *p = (reg_attrs *) x;
+
+ return ((p->offset * 1000) ^ (long) p->decl);
+}
+
+/* Returns non-zero if the value represented by X (which is really a
+ reg_attrs *) is the same as that given by Y (which is also really a
+ reg_attrs *). */
+
+static int
+reg_attrs_htab_eq (x, y)
+ const void *x;
+ const void *y;
+{
+ reg_attrs *p = (reg_attrs *) x;
+ reg_attrs *q = (reg_attrs *) y;
+
+ return (p->decl == q->decl && p->offset == q->offset);
+}
+/* Allocate a new reg_attrs structure and insert it into the hash table if
+ one identical to it is not already in the table. We are doing this for
+ MEM of mode MODE. */
+
+static reg_attrs *
+get_reg_attrs (decl, offset)
+ tree decl;
+ int offset;
+{
+ reg_attrs attrs;
+ void **slot;
+
+ /* If everything is the default, we can just return zero. */
+ if (decl == 0 && offset == 0)
+ return 0;
+
+ attrs.decl = decl;
+ attrs.offset = offset;
+
+ slot = htab_find_slot (reg_attrs_htab, &attrs, INSERT);
+ if (*slot == 0)
+ {
+ *slot = ggc_alloc (sizeof (reg_attrs));
+ memcpy (*slot, &attrs, sizeof (reg_attrs));
+ }
+
+ return *slot;
+}
+
/* Generate a new REG rtx. Make sure ORIGINAL_REGNO is set properly, and
don't attempt to share with the various global pieces of rtl (such as
frame_pointer_rtx). */
@@ -811,7 +873,7 @@ gen_reg_rtx (mode)
return gen_rtx_CONCAT (mode, realpart, imagpart);
}
- /* Make sure regno_pointer_align, regno_decl, and regno_reg_rtx are large
+ /* Make sure regno_pointer_align, and regno_reg_rtx are large
enough to have an element for this pseudo reg number. */
if (reg_rtx_no == f->emit->regno_pointer_align_length)
@@ -819,7 +881,6 @@ gen_reg_rtx (mode)
int old_size = f->emit->regno_pointer_align_length;
char *new;
rtx *new1;
- tree *new2;
new = ggc_realloc (f->emit->regno_pointer_align, old_size * 2);
memset (new + old_size, 0, old_size);
@@ -830,11 +891,6 @@ gen_reg_rtx (mode)
memset (new1 + old_size, 0, old_size * sizeof (rtx));
regno_reg_rtx = new1;
- new2 = (tree *) ggc_realloc (f->emit->regno_decl,
- old_size * 2 * sizeof (tree));
- memset (new2 + old_size, 0, old_size * sizeof (tree));
- f->emit->regno_decl = new2;
-
f->emit->regno_pointer_align_length = old_size * 2;
}
@@ -843,6 +899,70 @@ gen_reg_rtx (mode)
return val;
}
+/* Generate an register with same attributes as REG,
+ but offsetted by OFFSET. */
+
+rtx
+gen_rtx_REG_offset (reg, mode, regno, offset)
+ enum machine_mode mode;
+ unsigned int regno;
+ int offset;
+ rtx reg;
+{
+ rtx new = gen_rtx_REG (mode, regno);
+ REG_ATTRS (new) = get_reg_attrs (REG_EXPR (reg),
+ REG_OFFSET (reg) + offset);
+ return new;
+}
+
+/* Set the decl for MEM to DECL. */
+
+void
+set_reg_attrs_from_mem (reg, mem)
+ rtx reg;
+ rtx mem;
+{
+ if (MEM_OFFSET (mem) && GET_CODE (MEM_OFFSET (mem)) == CONST_INT)
+ REG_ATTRS (reg)
+ = get_reg_attrs (MEM_EXPR (mem), INTVAL (MEM_OFFSET (mem)));
+}
+
+/* Assign the RTX X to declaration T. */
+void
+set_decl_rtl (t, x)
+ tree t;
+ rtx x;
+{
+ DECL_CHECK (t)->decl.rtl = x;
+
+ if (!x)
+ return;
+ /* For register, we maitain the reverse information too. */
+ if (GET_CODE (x) == REG)
+ REG_ATTRS (x) = get_reg_attrs (t, 0);
+ else if (GET_CODE (x) == SUBREG)
+ REG_ATTRS (SUBREG_REG (x))
+ = get_reg_attrs (t, -SUBREG_BYTE (x));
+ if (GET_CODE (x) == CONCAT)
+ {
+ if (REG_P (XEXP (x, 0)))
+ REG_ATTRS (XEXP (x, 0)) = get_reg_attrs (t, 0);
+ if (REG_P (XEXP (x, 1)))
+ REG_ATTRS (XEXP (x, 1))
+ = get_reg_attrs (t, GET_MODE_UNIT_SIZE (GET_MODE (XEXP (x, 0))));
+ }
+ if (GET_CODE (x) == PARALLEL)
+ {
+ int i;
+ for (i = 0; i < XVECLEN (x, 0); i++)
+ {
+ rtx y = XVECEXP (x, 0, i);
+ if (REG_P (XEXP (y, 0)))
+ REG_ATTRS (XEXP (y, 0)) = get_reg_attrs (t, INTVAL (XEXP (y, 1)));
+ }
+ }
+}
+
/* Identify REG (which may be a CONCAT) as a user register. */
void
@@ -1921,6 +2041,19 @@ set_mem_attributes (ref, t, objectp)
set_mem_attributes_minus_bitpos (ref, t, objectp, 0);
}
+/* Set the decl for MEM to DECL. */
+
+void
+set_mem_attrs_from_reg (mem, reg)
+ rtx mem;
+ rtx reg;
+{
+ MEM_ATTRS (mem)
+ = get_mem_attrs (MEM_ALIAS_SET (mem), REG_EXPR (reg),
+ GEN_INT (REG_OFFSET (reg)),
+ MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem));
+}
+
/* Set the alias set of MEM to SET. */
void
@@ -5216,10 +5349,6 @@ init_emit ()
= (rtx *) ggc_alloc_cleared (f->emit->regno_pointer_align_length
* sizeof (rtx));
- f->emit->regno_decl
- = (tree *) ggc_alloc_cleared (f->emit->regno_pointer_align_length
- * sizeof (tree));
-
/* Put copies of all the hard registers into regno_reg_rtx. */
memcpy (regno_reg_rtx,
static_regno_reg_rtx,
@@ -5323,6 +5452,8 @@ init_emit_once (line_numbers)
mem_attrs_htab = htab_create_ggc (37, mem_attrs_htab_hash,
mem_attrs_htab_eq, NULL);
+ reg_attrs_htab = htab_create_ggc (37, reg_attrs_htab_hash,
+ reg_attrs_htab_eq, NULL);
no_line_numbers = ! line_numbers;