summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-alias.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-04-02 18:27:45 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-04-02 18:27:45 +0000
commit137eddca1e884c7f157b6ad05c5f68b812ce4a89 (patch)
treed91b288513346f92e0771562d6559092b4173ce6 /gcc/tree-ssa-alias.c
parent9f559b20308d34be446d1ec2072ab6aef74ca9f9 (diff)
downloadgcc-137eddca1e884c7f157b6ad05c5f68b812ce4a89.tar.gz
PR c++/34949
* tree-ssa-alias.c (stmt_kills_ref_p_1): If base != ref->base and both of them are MEM_REFs, just compare first argument for equality and attempt to deal even with differing offsets. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@197370 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-alias.c')
-rw-r--r--gcc/tree-ssa-alias.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index a83e35165d7..968c5054893 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -1889,20 +1889,50 @@ stmt_kills_ref_p_1 (gimple stmt, ao_ref *ref)
&& !stmt_can_throw_internal (stmt))
{
tree base, lhs = gimple_get_lhs (stmt);
- HOST_WIDE_INT size, offset, max_size;
+ HOST_WIDE_INT size, offset, max_size, ref_offset = ref->offset;
base = get_ref_base_and_extent (lhs, &offset, &size, &max_size);
/* We can get MEM[symbol: sZ, index: D.8862_1] here,
so base == ref->base does not always hold. */
- if (base == ref->base)
+ if (base != ref->base)
{
- /* For a must-alias check we need to be able to constrain
- the access properly. */
- if (size != -1 && size == max_size)
+ /* If both base and ref->base are MEM_REFs, only compare the
+ first operand, and if the second operand isn't equal constant,
+ try to add the offsets into offset and ref_offset. */
+ if (TREE_CODE (base) == MEM_REF && TREE_CODE (ref->base) == MEM_REF
+ && TREE_OPERAND (base, 0) == TREE_OPERAND (ref->base, 0))
{
- if (offset <= ref->offset
- && offset + size >= ref->offset + ref->max_size)
- return true;
+ if (!tree_int_cst_equal (TREE_OPERAND (base, 0),
+ TREE_OPERAND (ref->base, 0)))
+ {
+ double_int off1 = mem_ref_offset (base);
+ off1 = off1.alshift (BITS_PER_UNIT == 8
+ ? 3 : exact_log2 (BITS_PER_UNIT),
+ HOST_BITS_PER_DOUBLE_INT);
+ off1 = off1 + double_int::from_shwi (offset);
+ double_int off2 = mem_ref_offset (ref->base);
+ off2 = off2.alshift (BITS_PER_UNIT == 8
+ ? 3 : exact_log2 (BITS_PER_UNIT),
+ HOST_BITS_PER_DOUBLE_INT);
+ off2 = off2 + double_int::from_shwi (ref_offset);
+ if (off1.fits_shwi () && off2.fits_shwi ())
+ {
+ offset = off1.to_shwi ();
+ ref_offset = off2.to_shwi ();
+ }
+ else
+ size = -1;
+ }
}
+ else
+ size = -1;
+ }
+ /* For a must-alias check we need to be able to constrain
+ the access properly. */
+ if (size != -1 && size == max_size)
+ {
+ if (offset <= ref_offset
+ && offset + size >= ref_offset + ref->max_size)
+ return true;
}
}