On Sun, Jul 17, 2011 at 4:29 PM, Richard Sandiford <rdsandif...@googlemail.com> wrote: > Internally, emit-rtl.c uses the idiom: > > MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), > MEM_OFFSET (mem), size, MEM_ALIGN (mem), > MEM_ADDR_SPACE (mem), GET_MODE (mem)); > > where we're reiterating most of the current information and changing > just one field. Even when we're changing several fields: > > MEM_ATTRS (new_rtx) > = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, > MEM_ADDR_SPACE (memref), mmode); > > it's not immediately obvious what those 0s are. This patch uses > gen_mem_attrs to clean this up a bit (I hope) and make patch 5 > a little easier. > > The patch also changes the way find_mem_attrs (now set_mem_attrs) > handles null sizes. The old code would ignore null sizes when > checking whether a non-BLKmode reference had the default attributes, > but it would otherwise keep the size as unknown. This seems wrong: > the caller should be providing the actual size. The only caller > that didn't was offset_address. > > I was tempted to add: > > struct mem_attrs *defattrs; > > defattrs = mode_mem_attrs[(int) GET_MODE (mem)]; > gcc_assert (!defattrs->size || attrs->size == defattrs->size); > > to assert that, when not using BLKmode, the size should match the mode's > size. Unfortunately, that isn't possible as things stand: callers like > expand_assignment expand the inner part of a reference to rtl, then call > set_mem_attributes_minus_bitpos to set its attributes to those of the > outer reference. At this stage, the memory reference still has its > original (inner) mode. The mode is only corrected later. > > It might be nice to clean that up too, but I'd rather leave it for > another time.
Ok if there are no comments from others. Thanks, Richard. > Richard > > > gcc/ > * emit-rtl.c (mem_attrs_eq_p): New function, split out from... > (mem_attrs_htab_eq): ...here. > (find_mem_attrs): Replace with... > (set_mem_attrs): ...this function. Take a mem_attrs structure > rather than individual fields. > (set_mem_attributes_minus_bitpos, set_mem_alias_set) > (set_mem_addr_space, set_mem_align, set_mem_expr, set_mem_offset) > (set_mem_size, change_address, adjust_address_1, offset_address) > (widen_memory_access, get_spill_slot_decl, set_mem_attrs_for_spill): > Update accordingly. > > Index: gcc/emit-rtl.c > =================================================================== > --- gcc/emit-rtl.c 2011-07-17 10:06:49.000000000 +0100 > +++ gcc/emit-rtl.c 2011-07-17 10:06:53.000000000 +0100 > @@ -261,16 +261,11 @@ mem_attrs_htab_hash (const void *x) > ^ (size_t) iterative_hash_expr (p->expr, 0)); > } > > -/* Returns nonzero if the value represented by X (which is really a > - mem_attrs *) is the same as that given by Y (which is also really a > - mem_attrs *). */ > +/* Return true if the given memory attributes are equal. */ > > -static int > -mem_attrs_htab_eq (const void *x, const void *y) > +static bool > +mem_attrs_eq_p (const struct mem_attrs *p, const struct mem_attrs *q) > { > - const mem_attrs *const p = (const mem_attrs *) x; > - const mem_attrs *const q = (const mem_attrs *) y; > - > return (p->alias == q->alias && p->offset == q->offset > && p->size == q->size && p->align == q->align > && p->addrspace == q->addrspace > @@ -279,43 +274,38 @@ mem_attrs_htab_eq (const void *x, const > && operand_equal_p (p->expr, q->expr, 0)))); > } > > -/* Allocate a new mem_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. */ > +/* Returns nonzero if the value represented by X (which is really a > + mem_attrs *) is the same as that given by Y (which is also really a > + mem_attrs *). */ > > -static mem_attrs * > -find_mem_attrs (alias_set_type alias, tree expr, rtx offset, rtx size, > - unsigned int align, addr_space_t addrspace, > - enum machine_mode mode) > +static int > +mem_attrs_htab_eq (const void *x, const void *y) > { > - mem_attrs attrs; > - void **slot; > + return mem_attrs_eq_p ((const mem_attrs *) x, (const mem_attrs *) y); > +} > > - /* If everything is the default, we can just return zero. > - This must match what the corresponding MEM_* macros return when the > - field is not present. */ > - if (alias == 0 && expr == 0 && offset == 0 && addrspace == 0 > - && (size == 0 > - || (mode != BLKmode && GET_MODE_SIZE (mode) == INTVAL (size))) > - && (STRICT_ALIGNMENT && mode != BLKmode > - ? align == GET_MODE_ALIGNMENT (mode) : align == BITS_PER_UNIT)) > - return 0; > +/* Set MEM's memory attributes so that they are the same as ATTRS. */ > > - attrs.alias = alias; > - attrs.expr = expr; > - attrs.offset = offset; > - attrs.size = size; > - attrs.align = align; > - attrs.addrspace = addrspace; > +static void > +set_mem_attrs (rtx mem, mem_attrs *attrs) > +{ > + void **slot; > + > + /* If everything is the default, we can just clear the attributes. */ > + if (mem_attrs_eq_p (attrs, mode_mem_attrs[(int) GET_MODE (mem)])) > + { > + MEM_ATTRS (mem) = 0; > + return; > + } > > - slot = htab_find_slot (mem_attrs_htab, &attrs, INSERT); > + slot = htab_find_slot (mem_attrs_htab, attrs, INSERT); > if (*slot == 0) > { > *slot = ggc_alloc_mem_attrs (); > - memcpy (*slot, &attrs, sizeof (mem_attrs)); > + memcpy (*slot, attrs, sizeof (mem_attrs)); > } > > - return (mem_attrs *) *slot; > + MEM_ATTRS (mem) = (mem_attrs *) *slot; > } > > /* Returns a hash code for X (which is a really a reg_attrs *). */ > @@ -1553,13 +1543,9 @@ get_mem_align_offset (rtx mem, unsigned > set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, > HOST_WIDE_INT bitpos) > { > - alias_set_type alias; > - tree expr = NULL; > - rtx offset = NULL_RTX; > - rtx size = NULL_RTX; > - unsigned int align = BITS_PER_UNIT; > HOST_WIDE_INT apply_bitpos = 0; > tree type; > + struct mem_attrs attrs, *defattrs, *refattrs; > > /* It can happen that type_for_mode was given a mode for which there > is no language-level type. In which case it returns NULL, which > @@ -1577,9 +1563,11 @@ set_mem_attributes_minus_bitpos (rtx ref > set_mem_attributes. */ > gcc_assert (!DECL_P (t) || ref != DECL_RTL_IF_SET (t)); > > + memset (&attrs, 0, sizeof (attrs)); > + > /* Get the alias set from the expression or type (perhaps using a > front-end routine) and use it. */ > - alias = get_alias_set (t); > + attrs.alias = get_alias_set (t); > > MEM_VOLATILE_P (ref) |= TYPE_VOLATILE (type); > MEM_IN_STRUCT_P (ref) > @@ -1594,28 +1582,35 @@ set_mem_attributes_minus_bitpos (rtx ref > MEM_SCALAR_P (ref) = 1; > > /* Default values from pre-existing memory attributes if present. */ > - if (MEM_ATTRS (ref)) > + refattrs = MEM_ATTRS (ref); > + if (refattrs) > { > /* ??? Can this ever happen? Calling this routine on a MEM that > already carries memory attributes should probably be invalid. */ > - expr = MEM_EXPR (ref); > - offset = MEM_OFFSET (ref); > - size = MEM_SIZE (ref); > - align = MEM_ALIGN (ref); > + attrs.expr = refattrs->expr; > + attrs.offset = refattrs->offset; > + attrs.size = refattrs->size; > + attrs.align = refattrs->align; > } > > /* Otherwise, default values from the mode of the MEM reference. */ > - else if (GET_MODE (ref) != BLKmode) > + else > { > + defattrs = mode_mem_attrs[(int) GET_MODE (ref)]; > + gcc_assert (!defattrs->expr); > + gcc_assert (!defattrs->offset); > + > /* Respect mode size. */ > - size = GEN_INT (GET_MODE_SIZE (GET_MODE (ref))); > + attrs.size = defattrs->size; > /* ??? Is this really necessary? We probably should always get > the size from the type below. */ > > /* Respect mode alignment for STRICT_ALIGNMENT targets if T is a type; > if T is an object, always compute the object alignment below. */ > - if (STRICT_ALIGNMENT && TYPE_P (t)) > - align = GET_MODE_ALIGNMENT (GET_MODE (ref)); > + if (TYPE_P (t)) > + attrs.align = defattrs->align; > + else > + attrs.align = BITS_PER_UNIT; > /* ??? If T is a type, respecting mode alignment may *also* be wrong > e.g. if the type carries an alignment attribute. Should we be > able to simply always use TYPE_ALIGN? */ > @@ -1624,7 +1619,7 @@ set_mem_attributes_minus_bitpos (rtx ref > /* We can set the alignment from the type if we are making an object, > this is an INDIRECT_REF, or if TYPE_ALIGN_OK. */ > if (objectp || TREE_CODE (t) == INDIRECT_REF || TYPE_ALIGN_OK (type)) > - align = MAX (align, TYPE_ALIGN (type)); > + attrs.align = MAX (attrs.align, TYPE_ALIGN (type)); > > else if (TREE_CODE (t) == MEM_REF) > { > @@ -1634,12 +1629,13 @@ set_mem_attributes_minus_bitpos (rtx ref > || CONSTANT_CLASS_P (TREE_OPERAND (op0, 0)))) > { > if (DECL_P (TREE_OPERAND (op0, 0))) > - align = DECL_ALIGN (TREE_OPERAND (op0, 0)); > + attrs.align = DECL_ALIGN (TREE_OPERAND (op0, 0)); > else if (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))) > { > - align = TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (op0, 0))); > + attrs.align = TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (op0, 0))); > #ifdef CONSTANT_ALIGNMENT > - align = CONSTANT_ALIGNMENT (TREE_OPERAND (op0, 0), align); > + attrs.align = CONSTANT_ALIGNMENT (TREE_OPERAND (op0, 0), > + attrs.align); > #endif > } > if (TREE_INT_CST_LOW (TREE_OPERAND (t, 1)) != 0) > @@ -1647,23 +1643,23 @@ set_mem_attributes_minus_bitpos (rtx ref > unsigned HOST_WIDE_INT ioff > = TREE_INT_CST_LOW (TREE_OPERAND (t, 1)); > unsigned HOST_WIDE_INT aoff = (ioff & -ioff) * BITS_PER_UNIT; > - align = MIN (aoff, align); > + attrs.align = MIN (aoff, attrs.align); > } > } > else > /* ??? This isn't fully correct, we can't set the alignment from the > type in all cases. */ > - align = MAX (align, TYPE_ALIGN (type)); > + attrs.align = MAX (attrs.align, TYPE_ALIGN (type)); > } > > else if (TREE_CODE (t) == TARGET_MEM_REF) > /* ??? This isn't fully correct, we can't set the alignment from the > type in all cases. */ > - align = MAX (align, TYPE_ALIGN (type)); > + attrs.align = MAX (attrs.align, TYPE_ALIGN (type)); > > /* If the size is known, we can set that. */ > if (TYPE_SIZE_UNIT (type) && host_integerp (TYPE_SIZE_UNIT (type), 1)) > - size = GEN_INT (tree_low_cst (TYPE_SIZE_UNIT (type), 1)); > + attrs.size = GEN_INT (tree_low_cst (TYPE_SIZE_UNIT (type), 1)); > > /* If T is not a type, we may be able to deduce some more information about > the expression. */ > @@ -1700,22 +1696,22 @@ set_mem_attributes_minus_bitpos (rtx ref > /* If this is a decl, set the attributes of the MEM from it. */ > if (DECL_P (t)) > { > - expr = t; > - offset = const0_rtx; > + attrs.expr = t; > + attrs.offset = const0_rtx; > apply_bitpos = bitpos; > - size = (DECL_SIZE_UNIT (t) > - && host_integerp (DECL_SIZE_UNIT (t), 1) > - ? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0); > - align = DECL_ALIGN (t); > + attrs.size = (DECL_SIZE_UNIT (t) > + && host_integerp (DECL_SIZE_UNIT (t), 1) > + ? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0); > + attrs.align = DECL_ALIGN (t); > align_computed = true; > } > > /* If this is a constant, we know the alignment. */ > else if (CONSTANT_CLASS_P (t)) > { > - align = TYPE_ALIGN (type); > + attrs.align = TYPE_ALIGN (type); > #ifdef CONSTANT_ALIGNMENT > - align = CONSTANT_ALIGNMENT (t, align); > + attrs.align = CONSTANT_ALIGNMENT (t, attrs.align); > #endif > align_computed = true; > } > @@ -1727,8 +1723,8 @@ set_mem_attributes_minus_bitpos (rtx ref > else if (TREE_CODE (t) == COMPONENT_REF > && ! DECL_BIT_FIELD (TREE_OPERAND (t, 1))) > { > - expr = t; > - offset = const0_rtx; > + attrs.expr = t; > + attrs.offset = const0_rtx; > apply_bitpos = bitpos; > /* ??? Any reason the field size would be different than > the size we got from the type? */ > @@ -1768,27 +1764,27 @@ set_mem_attributes_minus_bitpos (rtx ref > > if (DECL_P (t2)) > { > - expr = t2; > - offset = NULL; > + attrs.expr = t2; > + attrs.offset = NULL; > if (host_integerp (off_tree, 1)) > { > HOST_WIDE_INT ioff = tree_low_cst (off_tree, 1); > HOST_WIDE_INT aoff = (ioff & -ioff) * BITS_PER_UNIT; > - align = DECL_ALIGN (t2); > - if (aoff && (unsigned HOST_WIDE_INT) aoff < align) > - align = aoff; > + attrs.align = DECL_ALIGN (t2); > + if (aoff && (unsigned HOST_WIDE_INT) aoff < attrs.align) > + attrs.align = aoff; > align_computed = true; > - offset = GEN_INT (ioff); > + attrs.offset = GEN_INT (ioff); > apply_bitpos = bitpos; > } > } > else if (TREE_CODE (t2) == COMPONENT_REF) > { > - expr = t2; > - offset = NULL; > + attrs.expr = t2; > + attrs.offset = NULL; > if (host_integerp (off_tree, 1)) > { > - offset = GEN_INT (tree_low_cst (off_tree, 1)); > + attrs.offset = GEN_INT (tree_low_cst (off_tree, 1)); > apply_bitpos = bitpos; > } > /* ??? Any reason the field size would be different than > @@ -1798,8 +1794,8 @@ set_mem_attributes_minus_bitpos (rtx ref > /* If this is an indirect reference, record it. */ > else if (TREE_CODE (t) == MEM_REF) > { > - expr = t; > - offset = const0_rtx; > + attrs.expr = t; > + attrs.offset = const0_rtx; > apply_bitpos = bitpos; > } > } > @@ -1808,15 +1804,15 @@ set_mem_attributes_minus_bitpos (rtx ref > else if (TREE_CODE (t) == MEM_REF > || TREE_CODE (t) == TARGET_MEM_REF) > { > - expr = t; > - offset = const0_rtx; > + attrs.expr = t; > + attrs.offset = const0_rtx; > apply_bitpos = bitpos; > } > > if (!align_computed && !INDIRECT_REF_P (t)) > { > unsigned int obj_align = get_object_alignment (t, BIGGEST_ALIGNMENT); > - align = MAX (align, obj_align); > + attrs.align = MAX (attrs.align, obj_align); > } > } > > @@ -1825,15 +1821,14 @@ set_mem_attributes_minus_bitpos (rtx ref > object to contain the negative offset. */ > if (apply_bitpos) > { > - offset = plus_constant (offset, -(apply_bitpos / BITS_PER_UNIT)); > - if (size) > - size = plus_constant (size, apply_bitpos / BITS_PER_UNIT); > + attrs.offset = plus_constant (attrs.offset, > + -(apply_bitpos / BITS_PER_UNIT)); > + if (attrs.size) > + attrs.size = plus_constant (attrs.size, apply_bitpos / BITS_PER_UNIT); > } > > /* Now set the attributes we computed above. */ > - MEM_ATTRS (ref) > - = find_mem_attrs (alias, expr, offset, size, align, > - TYPE_ADDR_SPACE (type), GET_MODE (ref)); > + set_mem_attrs (ref, &attrs); > > /* If this is already known to be a scalar or aggregate, we are done. */ > if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref)) > @@ -1858,12 +1853,13 @@ set_mem_attributes (rtx ref, tree t, int > void > set_mem_alias_set (rtx mem, alias_set_type set) > { > + struct mem_attrs attrs; > + > /* If the new and old alias sets don't conflict, something is wrong. */ > gcc_checking_assert (alias_sets_conflict_p (set, MEM_ALIAS_SET (mem))); > - > - MEM_ATTRS (mem) = find_mem_attrs (set, MEM_EXPR (mem), MEM_OFFSET (mem), > - MEM_SIZE (mem), MEM_ALIGN (mem), > - MEM_ADDR_SPACE (mem), GET_MODE (mem)); > + attrs = *get_mem_attrs (mem); > + attrs.alias = set; > + set_mem_attrs (mem, &attrs); > } > > /* Set the address space of MEM to ADDRSPACE (target-defined). */ > @@ -1871,9 +1867,11 @@ set_mem_alias_set (rtx mem, alias_set_ty > void > set_mem_addr_space (rtx mem, addr_space_t addrspace) > { > - MEM_ATTRS (mem) = find_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), > - MEM_OFFSET (mem), MEM_SIZE (mem), > - MEM_ALIGN (mem), addrspace, GET_MODE > (mem)); > + struct mem_attrs attrs; > + > + attrs = *get_mem_attrs (mem); > + attrs.addrspace = addrspace; > + set_mem_attrs (mem, &attrs); > } > > /* Set the alignment of MEM to ALIGN bits. */ > @@ -1881,9 +1879,11 @@ set_mem_addr_space (rtx mem, addr_space_ > void > set_mem_align (rtx mem, unsigned int align) > { > - MEM_ATTRS (mem) = find_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), > - MEM_OFFSET (mem), MEM_SIZE (mem), align, > - MEM_ADDR_SPACE (mem), GET_MODE (mem)); > + struct mem_attrs attrs; > + > + attrs = *get_mem_attrs (mem); > + attrs.align = align; > + set_mem_attrs (mem, &attrs); > } > > /* Set the expr for MEM to EXPR. */ > @@ -1891,10 +1891,11 @@ set_mem_align (rtx mem, unsigned int ali > void > set_mem_expr (rtx mem, tree expr) > { > - MEM_ATTRS (mem) > - = find_mem_attrs (MEM_ALIAS_SET (mem), expr, MEM_OFFSET (mem), > - MEM_SIZE (mem), MEM_ALIGN (mem), > - MEM_ADDR_SPACE (mem), GET_MODE (mem)); > + struct mem_attrs attrs; > + > + attrs = *get_mem_attrs (mem); > + attrs.expr = expr; > + set_mem_attrs (mem, &attrs); > } > > /* Set the offset of MEM to OFFSET. */ > @@ -1902,9 +1903,11 @@ set_mem_expr (rtx mem, tree expr) > void > set_mem_offset (rtx mem, rtx offset) > { > - MEM_ATTRS (mem) = find_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), > - offset, MEM_SIZE (mem), MEM_ALIGN (mem), > - MEM_ADDR_SPACE (mem), GET_MODE (mem)); > + struct mem_attrs attrs; > + > + attrs = *get_mem_attrs (mem); > + attrs.offset = offset; > + set_mem_attrs (mem, &attrs); > } > > /* Set the size of MEM to SIZE. */ > @@ -1912,9 +1915,11 @@ set_mem_offset (rtx mem, rtx offset) > void > set_mem_size (rtx mem, rtx size) > { > - MEM_ATTRS (mem) = find_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), > - MEM_OFFSET (mem), size, MEM_ALIGN (mem), > - MEM_ADDR_SPACE (mem), GET_MODE (mem)); > + struct mem_attrs attrs; > + > + attrs = *get_mem_attrs (mem); > + attrs.size = size; > + set_mem_attrs (mem, &attrs); > } > > /* Return a memory reference like MEMREF, but with its mode changed to MODE > @@ -1961,31 +1966,28 @@ change_address_1 (rtx memref, enum machi > rtx > change_address (rtx memref, enum machine_mode mode, rtx addr) > { > - rtx new_rtx = change_address_1 (memref, mode, addr, 1), size; > + rtx new_rtx = change_address_1 (memref, mode, addr, 1); > enum machine_mode mmode = GET_MODE (new_rtx); > - unsigned int align; > + struct mem_attrs attrs, *defattrs; > > - size = mmode == BLKmode ? 0 : GEN_INT (GET_MODE_SIZE (mmode)); > - align = mmode == BLKmode ? BITS_PER_UNIT : GET_MODE_ALIGNMENT (mmode); > + attrs = *get_mem_attrs (memref); > + defattrs = mode_mem_attrs[(int) mmode]; > + attrs.expr = defattrs->expr; > + attrs.offset = defattrs->offset; > + attrs.size = defattrs->size; > + attrs.align = defattrs->align; > > /* If there are no changes, just return the original memory reference. */ > if (new_rtx == memref) > { > - if (MEM_ATTRS (memref) == 0 > - || (MEM_EXPR (memref) == NULL > - && MEM_OFFSET (memref) == NULL > - && MEM_SIZE (memref) == size > - && MEM_ALIGN (memref) == align)) > + if (mem_attrs_eq_p (get_mem_attrs (memref), &attrs)) > return new_rtx; > > new_rtx = gen_rtx_MEM (mmode, XEXP (memref, 0)); > MEM_COPY_ATTRIBUTES (new_rtx, memref); > } > > - MEM_ATTRS (new_rtx) > - = find_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, > - MEM_ADDR_SPACE (memref), mmode); > - > + set_mem_attrs (new_rtx, &attrs); > return new_rtx; > } > > @@ -2001,16 +2003,17 @@ adjust_address_1 (rtx memref, enum machi > { > rtx addr = XEXP (memref, 0); > rtx new_rtx; > - rtx memoffset = MEM_OFFSET (memref); > - rtx size = 0; > - unsigned int memalign = MEM_ALIGN (memref); > - addr_space_t as = MEM_ADDR_SPACE (memref); > - enum machine_mode address_mode = targetm.addr_space.address_mode (as); > + enum machine_mode address_mode; > int pbits; > + struct mem_attrs attrs, *defattrs; > + unsigned HOST_WIDE_INT max_align; > + > + attrs = *get_mem_attrs (memref); > > /* If there are no changes, just return the original memory reference. */ > if (mode == GET_MODE (memref) && !offset > - && (!validate || memory_address_addr_space_p (mode, addr, as))) > + && (!validate || memory_address_addr_space_p (mode, addr, > + attrs.addrspace))) > return memref; > > /* ??? Prefer to create garbage instead of creating shared rtl. > @@ -2020,6 +2023,7 @@ adjust_address_1 (rtx memref, enum machi > > /* Convert a possibly large offset to a signed value within the > range of the target address space. */ > + address_mode = targetm.addr_space.address_mode (attrs.addrspace); > pbits = GET_MODE_BITSIZE (address_mode); > if (HOST_BITS_PER_WIDE_INT > pbits) > { > @@ -2051,27 +2055,26 @@ adjust_address_1 (rtx memref, enum machi > > /* Compute the new values of the memory attributes due to this adjustment. > We add the offsets and update the alignment. */ > - if (memoffset) > - memoffset = GEN_INT (offset + INTVAL (memoffset)); > + if (attrs.offset) > + attrs.offset = GEN_INT (offset + INTVAL (attrs.offset)); > > /* Compute the new alignment by taking the MIN of the alignment and the > lowest-order set bit in OFFSET, but don't change the alignment if OFFSET > if zero. */ > if (offset != 0) > - memalign > - = MIN (memalign, > - (unsigned HOST_WIDE_INT) (offset & -offset) * BITS_PER_UNIT); > + { > + max_align = (offset & -offset) * BITS_PER_UNIT; > + attrs.align = MIN (attrs.align, max_align); > + } > > /* We can compute the size in a number of ways. */ > - if (GET_MODE (new_rtx) != BLKmode) > - size = GEN_INT (GET_MODE_SIZE (GET_MODE (new_rtx))); > - else if (MEM_SIZE (memref)) > - size = plus_constant (MEM_SIZE (memref), -offset); > - > - MEM_ATTRS (new_rtx) = find_mem_attrs (MEM_ALIAS_SET (memref), > - MEM_EXPR (memref), > - memoffset, size, memalign, as, > - GET_MODE (new_rtx)); > + defattrs = mode_mem_attrs[(int) GET_MODE (new_rtx)]; > + if (defattrs->size) > + attrs.size = defattrs->size; > + else if (attrs.size) > + attrs.size = plus_constant (attrs.size, -offset); > + > + set_mem_attrs (new_rtx, &attrs); > > /* At some point, we should validate that this offset is within the object, > if all the appropriate values are known. */ > @@ -2099,9 +2102,11 @@ adjust_automodify_address_1 (rtx memref, > offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2) > { > rtx new_rtx, addr = XEXP (memref, 0); > - addr_space_t as = MEM_ADDR_SPACE (memref); > - enum machine_mode address_mode = targetm.addr_space.address_mode (as); > + enum machine_mode address_mode; > + struct mem_attrs attrs; > > + attrs = *get_mem_attrs (memref); > + address_mode = targetm.addr_space.address_mode (attrs.addrspace); > new_rtx = simplify_gen_binary (PLUS, address_mode, addr, offset); > > /* At this point we don't know _why_ the address is invalid. It > @@ -2111,7 +2116,8 @@ offset_address (rtx memref, rtx offset, > being able to recognize the magic around pic_offset_table_rtx. > This stuff is fragile, and is yet another example of why it is > bad to expose PIC machinery too early. */ > - if (! memory_address_addr_space_p (GET_MODE (memref), new_rtx, as) > + if (! memory_address_addr_space_p (GET_MODE (memref), new_rtx, > + attrs.addrspace) > && GET_CODE (addr) == PLUS > && XEXP (addr, 0) == pic_offset_table_rtx) > { > @@ -2128,10 +2134,10 @@ offset_address (rtx memref, rtx offset, > > /* Update the alignment to reflect the offset. Reset the offset, which > we don't know. */ > - MEM_ATTRS (new_rtx) > - = find_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 0, 0, > - MIN (MEM_ALIGN (memref), pow2 * BITS_PER_UNIT), > - as, GET_MODE (new_rtx)); > + attrs.offset = 0; > + attrs.size = mode_mem_attrs[(int) GET_MODE (new_rtx)]->size; > + attrs.align = MIN (attrs.align, pow2 * BITS_PER_UNIT); > + set_mem_attrs (new_rtx, &attrs); > return new_rtx; > } > > @@ -2166,29 +2172,30 @@ replace_equiv_address_nv (rtx memref, rt > widen_memory_access (rtx memref, enum machine_mode mode, HOST_WIDE_INT > offset) > { > rtx new_rtx = adjust_address_1 (memref, mode, offset, 1, 1); > - tree expr = MEM_EXPR (new_rtx); > - rtx memoffset = MEM_OFFSET (new_rtx); > + struct mem_attrs attrs; > unsigned int size = GET_MODE_SIZE (mode); > > /* If there are no changes, just return the original memory reference. */ > if (new_rtx == memref) > return new_rtx; > > + attrs = *get_mem_attrs (new_rtx); > + > /* If we don't know what offset we were at within the expression, then > we can't know if we've overstepped the bounds. */ > - if (! memoffset) > - expr = NULL_TREE; > + if (! attrs.offset) > + attrs.expr = NULL_TREE; > > - while (expr) > + while (attrs.expr) > { > - if (TREE_CODE (expr) == COMPONENT_REF) > + if (TREE_CODE (attrs.expr) == COMPONENT_REF) > { > - tree field = TREE_OPERAND (expr, 1); > - tree offset = component_ref_field_offset (expr); > + tree field = TREE_OPERAND (attrs.expr, 1); > + tree offset = component_ref_field_offset (attrs.expr); > > if (! DECL_SIZE_UNIT (field)) > { > - expr = NULL_TREE; > + attrs.expr = NULL_TREE; > break; > } > > @@ -2196,48 +2203,46 @@ widen_memory_access (rtx memref, enum ma > otherwise strip back to the containing structure. */ > if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST > && compare_tree_int (DECL_SIZE_UNIT (field), size) >= 0 > - && INTVAL (memoffset) >= 0) > + && INTVAL (attrs.offset) >= 0) > break; > > if (! host_integerp (offset, 1)) > { > - expr = NULL_TREE; > + attrs.expr = NULL_TREE; > break; > } > > - expr = TREE_OPERAND (expr, 0); > - memoffset > - = (GEN_INT (INTVAL (memoffset) > + attrs.expr = TREE_OPERAND (attrs.expr, 0); > + attrs.offset > + = (GEN_INT (INTVAL (attrs.offset) > + tree_low_cst (offset, 1) > + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) > / BITS_PER_UNIT))); > } > /* Similarly for the decl. */ > - else if (DECL_P (expr) > - && DECL_SIZE_UNIT (expr) > - && TREE_CODE (DECL_SIZE_UNIT (expr)) == INTEGER_CST > - && compare_tree_int (DECL_SIZE_UNIT (expr), size) >= 0 > - && (! memoffset || INTVAL (memoffset) >= 0)) > + else if (DECL_P (attrs.expr) > + && DECL_SIZE_UNIT (attrs.expr) > + && TREE_CODE (DECL_SIZE_UNIT (attrs.expr)) == INTEGER_CST > + && compare_tree_int (DECL_SIZE_UNIT (attrs.expr), size) >= 0 > + && (! attrs.offset || INTVAL (attrs.offset) >= 0)) > break; > else > { > /* The widened memory access overflows the expression, which means > that it could alias another expression. Zap it. */ > - expr = NULL_TREE; > + attrs.expr = NULL_TREE; > break; > } > } > > - if (! expr) > - memoffset = NULL_RTX; > + if (! attrs.expr) > + attrs.offset = NULL_RTX; > > /* The widened memory may alias other stuff, so zap the alias set. */ > /* ??? Maybe use get_alias_set on any remaining expression. */ > - > - MEM_ATTRS (new_rtx) = find_mem_attrs (0, expr, memoffset, GEN_INT (size), > - MEM_ALIGN (new_rtx), > - MEM_ADDR_SPACE (new_rtx), mode); > - > + attrs.alias = 0; > + attrs.size = GEN_INT (size); > + set_mem_attrs (new_rtx, &attrs); > return new_rtx; > } > > @@ -2249,6 +2254,7 @@ get_spill_slot_decl (bool force_build_p) > { > tree d = spill_slot_decl; > rtx rd; > + struct mem_attrs attrs; > > if (d || !force_build_p) > return d; > @@ -2262,8 +2268,10 @@ get_spill_slot_decl (bool force_build_p) > > rd = gen_rtx_MEM (BLKmode, frame_pointer_rtx); > MEM_NOTRAP_P (rd) = 1; > - MEM_ATTRS (rd) = find_mem_attrs (new_alias_set (), d, const0_rtx, > - NULL_RTX, 0, ADDR_SPACE_GENERIC, BLKmode); > + attrs = *mode_mem_attrs[(int) BLKmode]; > + attrs.alias = new_alias_set (); > + attrs.expr = d; > + set_mem_attrs (rd, &attrs); > SET_DECL_RTL (d, rd); > > return d; > @@ -2278,25 +2286,24 @@ get_spill_slot_decl (bool force_build_p) > void > set_mem_attrs_for_spill (rtx mem) > { > - alias_set_type alias; > - rtx addr, offset; > - tree expr; > + struct mem_attrs attrs; > + rtx addr; > > - expr = get_spill_slot_decl (true); > - alias = MEM_ALIAS_SET (DECL_RTL (expr)); > + attrs = *get_mem_attrs (mem); > + attrs.expr = get_spill_slot_decl (true); > + attrs.alias = MEM_ALIAS_SET (DECL_RTL (attrs.expr)); > + attrs.addrspace = ADDR_SPACE_GENERIC; > > /* We expect the incoming memory to be of the form: > (mem:MODE (plus (reg sfp) (const_int offset))) > with perhaps the plus missing for offset = 0. */ > addr = XEXP (mem, 0); > - offset = const0_rtx; > + attrs.offset = const0_rtx; > if (GET_CODE (addr) == PLUS > && CONST_INT_P (XEXP (addr, 1))) > - offset = XEXP (addr, 1); > + attrs.offset = XEXP (addr, 1); > > - MEM_ATTRS (mem) = find_mem_attrs (alias, expr, offset, > - MEM_SIZE (mem), MEM_ALIGN (mem), > - ADDR_SPACE_GENERIC, GET_MODE (mem)); > + set_mem_attrs (mem, &attrs); > MEM_NOTRAP_P (mem) = 1; > } > >