From patchwork Sun Jul 17 14:29:02 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 105061 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 67E44B6F7E for ; Mon, 18 Jul 2011 00:29:28 +1000 (EST) Received: (qmail 27669 invoked by alias); 17 Jul 2011 14:29:27 -0000 Received: (qmail 27618 invoked by uid 22791); 17 Jul 2011 14:29:24 -0000 X-SWARE-Spam-Status: No, hits=-0.9 required=5.0 tests=AWL, BAYES_50, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, TW_CP, T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org Received: from mail-wy0-f175.google.com (HELO mail-wy0-f175.google.com) (74.125.82.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 17 Jul 2011 14:29:07 +0000 Received: by wyg30 with SMTP id 30so1964915wyg.20 for ; Sun, 17 Jul 2011 07:29:05 -0700 (PDT) Received: by 10.216.136.160 with SMTP id w32mr2346510wei.30.1310912945357; Sun, 17 Jul 2011 07:29:05 -0700 (PDT) Received: from localhost (rsandifo.gotadsl.co.uk [82.133.89.107]) by mx.google.com with ESMTPS id p14sm2659776wbh.47.2011.07.17.07.29.03 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 17 Jul 2011 07:29:04 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, rdsandiford@googlemail.com Subject: [2/5] Add a set_mem_attrs function References: <87k4bhuh62.fsf@firetop.home> Date: Sun, 17 Jul 2011 15:29:02 +0100 In-Reply-To: <87k4bhuh62.fsf@firetop.home> (Richard Sandiford's message of "Sun, 17 Jul 2011 15:15:49 +0100") Message-ID: <87aacdugk1.fsf@firetop.home> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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. 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; }