--- gcc/rtl.h (/gcc-local/trunk) (revision 30596) +++ gcc/rtl.h (/gcc-local/export-ddg) (revision 30596) @@ -145,6 +145,7 @@ typedef struct mem_attrs GTY(()) rtx offset; /* Offset from start of DECL, as CONST_INT. */ rtx size; /* Size in bytes, as a CONST_INT. */ unsigned int align; /* Alignment of MEM in bits. */ + tree orig_expr; /* Explicit original tree expression. */ } mem_attrs; /* Structure used to describe the attributes of a REG in similar way as @@ -1187,6 +1188,11 @@ do { \ : (STRICT_ALIGNMENT && GET_MODE (RTX) != BLKmode \ ? GET_MODE_ALIGNMENT (GET_MODE (RTX)) : BITS_PER_UNIT)) +/* For a MEM rtx, the decl it is known to refer to, if it is known to + refer to part of a DECL. It may also be a COMPONENT_REF. */ +#define MEM_ORIG_EXPR(RTX) \ +(MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->orig_expr) + /* For a REG rtx, the decl it is known to refer to, if it is known to refer to part of a DECL. */ #define REG_EXPR(RTX) (REG_ATTRS (RTX) == 0 ? 0 : REG_ATTRS (RTX)->decl) --- gcc/emit-rtl.h (/gcc-local/trunk) (revision 30596) +++ gcc/emit-rtl.h (/gcc-local/export-ddg) (revision 30596) @@ -29,6 +29,9 @@ extern void set_mem_align (rtx, unsigned /* Set the expr for MEM to EXPR. */ extern void set_mem_expr (rtx, tree); +/* Set the original expr for MEM to ORIG_EXPR. */ +extern void set_mem_orig_expr (rtx, tree); + /* Set the offset for MEM to OFFSET. */ extern void set_mem_offset (rtx, rtx); --- gcc/emit-rtl.c (/gcc-local/trunk) (revision 30596) +++ gcc/emit-rtl.c (/gcc-local/export-ddg) (revision 30596) @@ -181,8 +181,8 @@ static int const_double_htab_eq (const v static rtx lookup_const_double (rtx); static hashval_t mem_attrs_htab_hash (const void *); static int mem_attrs_htab_eq (const void *, const void *); -static mem_attrs *get_mem_attrs (alias_set_type, tree, rtx, rtx, unsigned int, - enum machine_mode); +static mem_attrs *get_mem_attrs (alias_set_type, tree, tree, rtx, rtx, + unsigned int, enum machine_mode); static hashval_t reg_attrs_htab_hash (const void *); static int reg_attrs_htab_eq (const void *, const void *); static reg_attrs *get_reg_attrs (tree, int); @@ -257,7 +257,8 @@ mem_attrs_htab_hash (const void *x) return (p->alias ^ (p->align * 1000) ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000) ^ ((p->size ? INTVAL (p->size) : 0) * 2500000) - ^ (size_t) iterative_hash_expr (p->expr, 0)); + ^ (size_t) iterative_hash_expr (p->expr, + iterative_hash_expr (p->orig_expr, 0))); } /* Returns nonzero if the value represented by X (which is really a @@ -274,7 +275,12 @@ mem_attrs_htab_eq (const void *x, const && p->size == q->size && p->align == q->align && (p->expr == q->expr || (p->expr != NULL_TREE && q->expr != NULL_TREE - && operand_equal_p (p->expr, q->expr, 0)))); + && operand_equal_p (p->expr, q->expr, 0))) + /* We do not use operand_equal_p for ORIG_EXPRs because we need to + distinguish memory references at different points of the loop (which + would have different indices in SSA form, like a[i_1] and a[i_2], but + were later rewritten to same a[i]). */ + && (p->orig_expr == q->orig_expr)); } /* Allocate a new mem_attrs structure and insert it into the hash table if @@ -282,8 +288,8 @@ mem_attrs_htab_eq (const void *x, const MEM of mode MODE. */ static mem_attrs * -get_mem_attrs (alias_set_type alias, tree expr, rtx offset, rtx size, - unsigned int align, enum machine_mode mode) +get_mem_attrs (alias_set_type alias, tree expr, tree orig_expr, rtx offset, + rtx size, unsigned int align, enum machine_mode mode) { mem_attrs attrs; void **slot; @@ -291,7 +297,7 @@ get_mem_attrs (alias_set_type alias, tre /* 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 + if (alias == 0 && expr == 0 && orig_expr == 0 && offset == 0 && (size == 0 || (mode != BLKmode && GET_MODE_SIZE (mode) == INTVAL (size))) && (STRICT_ALIGNMENT && mode != BLKmode @@ -300,6 +306,7 @@ get_mem_attrs (alias_set_type alias, tre attrs.alias = alias; attrs.expr = expr; + attrs.orig_expr = orig_expr; attrs.offset = offset; attrs.size = size; attrs.align = align; @@ -1413,7 +1420,7 @@ component_ref_for_mem_expr (tree ref) || TREE_CODE (inner) == NON_LVALUE_EXPR || TREE_CODE (inner) == VIEW_CONVERT_EXPR || TREE_CODE (inner) == SAVE_EXPR) - inner = TREE_OPERAND (inner, 0); + inner = TREE_OPERAND (inner, 0); if (! DECL_P (inner)) inner = NULL_TREE; @@ -1471,6 +1478,7 @@ set_mem_attributes_minus_bitpos (rtx ref { alias_set_type alias = MEM_ALIAS_SET (ref); tree expr = MEM_EXPR (ref); + tree orig_expr = NULL; rtx offset = MEM_OFFSET (ref); rtx size = MEM_SIZE (ref); unsigned int align = MEM_ALIGN (ref); @@ -1535,6 +1543,8 @@ set_mem_attributes_minus_bitpos (rtx ref { tree base; + orig_expr = t; + if (TREE_THIS_VOLATILE (t)) MEM_VOLATILE_P (ref) = 1; @@ -1710,11 +1720,13 @@ set_mem_attributes_minus_bitpos (rtx ref we're overlapping. */ offset = NULL; expr = NULL; + orig_expr = NULL; } /* Now set the attributes we computed above. */ MEM_ATTRS (ref) - = get_mem_attrs (alias, expr, offset, size, align, GET_MODE (ref)); + = get_mem_attrs (alias, expr, orig_expr, offset, size, align, + GET_MODE (ref)); /* If this is already known to be a scalar or aggregate, we are done. */ if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref)) @@ -1740,7 +1752,7 @@ void set_mem_attrs_from_reg (rtx mem, rtx reg) { MEM_ATTRS (mem) - = get_mem_attrs (MEM_ALIAS_SET (mem), REG_EXPR (reg), + = get_mem_attrs (MEM_ALIAS_SET (mem), REG_EXPR (reg), NULL_TREE, GEN_INT (REG_OFFSET (reg)), MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem)); } @@ -1755,9 +1767,9 @@ set_mem_alias_set (rtx mem, alias_set_ty gcc_assert (alias_sets_conflict_p (set, MEM_ALIAS_SET (mem))); #endif - MEM_ATTRS (mem) = get_mem_attrs (set, MEM_EXPR (mem), MEM_OFFSET (mem), - MEM_SIZE (mem), MEM_ALIGN (mem), - GET_MODE (mem)); + MEM_ATTRS (mem) = get_mem_attrs (set, MEM_EXPR (mem), MEM_ORIG_EXPR (mem), + MEM_OFFSET (mem), MEM_SIZE (mem), + MEM_ALIGN (mem), GET_MODE (mem)); } /* Set the alignment of MEM to ALIGN bits. */ @@ -1766,8 +1778,8 @@ void set_mem_align (rtx mem, unsigned int align) { MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), - MEM_OFFSET (mem), MEM_SIZE (mem), align, - GET_MODE (mem)); + MEM_ORIG_EXPR (mem), MEM_OFFSET (mem), + MEM_SIZE (mem), align, GET_MODE (mem)); } /* Set the expr for MEM to EXPR. */ @@ -1775,9 +1787,29 @@ set_mem_align (rtx mem, unsigned int ali void set_mem_expr (rtx mem, tree expr) { + tree orig_expr = MEM_ORIG_EXPR (mem); + + /* If MEM_EXPR changes, clear MEM_ORIG_EXPR. If we still can preserve it, + we insert set_mem_orig_expr call right after this function call. */ + if (!expr || !mem_expr_equal_p (MEM_EXPR (mem), expr)) + orig_expr = NULL_TREE; + MEM_ATTRS (mem) - = get_mem_attrs (MEM_ALIAS_SET (mem), expr, MEM_OFFSET (mem), - MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem)); + = get_mem_attrs (MEM_ALIAS_SET (mem), expr, orig_expr, + MEM_OFFSET (mem), MEM_SIZE (mem), MEM_ALIGN (mem), + GET_MODE (mem)); +} + + +/* Set the original expr for MEM to ORIG_EXPR. */ + +void +set_mem_orig_expr (rtx mem, tree orig_expr) +{ + MEM_ATTRS (mem) + = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), orig_expr, + MEM_OFFSET (mem), MEM_SIZE (mem), MEM_ALIGN (mem), + GET_MODE (mem)); } /* Set the offset of MEM to OFFSET. */ @@ -1785,9 +1817,16 @@ set_mem_expr (rtx mem, tree expr) void set_mem_offset (rtx mem, rtx offset) { + tree orig_expr = MEM_ORIG_EXPR (mem); + + /* If MEM_EXPR changes, clear MEM_ORIG_EXPR. If we still can preserve it, + we insert set_mem_orig_expr call right after this function call. */ + if (offset != MEM_OFFSET (mem)) + orig_expr = NULL_TREE; + MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), - offset, MEM_SIZE (mem), MEM_ALIGN (mem), - GET_MODE (mem)); + orig_expr, offset, MEM_SIZE (mem), + MEM_ALIGN (mem), GET_MODE (mem)); } /* Set the size of MEM to SIZE. */ @@ -1796,8 +1835,8 @@ void set_mem_size (rtx mem, rtx size) { MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), - MEM_OFFSET (mem), size, MEM_ALIGN (mem), - GET_MODE (mem)); + MEM_ORIG_EXPR (mem), MEM_OFFSET (mem), + size, MEM_ALIGN (mem), GET_MODE (mem)); } /* Return a memory reference like MEMREF, but with its mode changed to MODE @@ -1864,7 +1903,8 @@ change_address (rtx memref, enum machine } MEM_ATTRS (new) - = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, mmode); + = get_mem_attrs (MEM_ALIAS_SET (memref), NULL_TREE, NULL_TREE, 0, + size, align, mmode); return new; } @@ -1931,7 +1971,8 @@ adjust_address_1 (rtx memref, enum machi size = plus_constant (MEM_SIZE (memref), -offset); MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), - memoffset, size, memalign, GET_MODE (new)); + MEM_ORIG_EXPR (memref), memoffset, size, + memalign, GET_MODE (new)); /* At some point, we should validate that this offset is within the object, if all the appropriate values are known. */ @@ -1987,7 +2028,8 @@ offset_address (rtx memref, rtx offset, /* Update the alignment to reflect the offset. Reset the offset, which we don't know. */ MEM_ATTRS (new) - = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 0, 0, + = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), + MEM_ORIG_EXPR (memref), 0, 0, MIN (MEM_ALIGN (memref), pow2 * BITS_PER_UNIT), GET_MODE (new)); return new; @@ -2027,6 +2069,7 @@ widen_memory_access (rtx memref, enum ma tree expr = MEM_EXPR (new); rtx memoffset = MEM_OFFSET (new); unsigned int size = GET_MODE_SIZE (mode); + tree orig_expr = MEM_ORIG_EXPR (new); /* If there are no changes, just return the original memory reference. */ if (new == memref) @@ -2092,8 +2135,11 @@ widen_memory_access (rtx memref, enum ma /* The widened memory may alias other stuff, so zap the alias set. */ /* ??? Maybe use get_alias_set on any remaining expression. */ - MEM_ATTRS (new) = get_mem_attrs (0, expr, memoffset, GEN_INT (size), - MEM_ALIGN (new), mode); + if (expr != MEM_EXPR (new)) + orig_expr = NULL_TREE; + + MEM_ATTRS (new) = get_mem_attrs (0, expr, orig_expr, memoffset, + GEN_INT (size), MEM_ALIGN (new), mode); return new; } --- gcc/function.c (/gcc-local/trunk) (revision 30596) +++ gcc/function.c (/gcc-local/export-ddg) (revision 30596) @@ -2967,7 +2967,10 @@ assign_parms_unsplit_complex (struct ass /* Set MEM_EXPR to the original decl, i.e. to PARM, instead of the copy of decl, i.e. FNARGS. */ if (DECL_INCOMING_RTL (parm) && MEM_P (DECL_INCOMING_RTL (parm))) - set_mem_expr (DECL_INCOMING_RTL (parm), parm); + { + set_mem_expr (DECL_INCOMING_RTL (parm), parm); + set_mem_orig_expr (DECL_INCOMING_RTL (parm), parm); + } } fnargs = TREE_CHAIN (fnargs);