aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-alias.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2017-08-21 07:37:59 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2017-08-21 07:37:59 +0000
commit8322b607d60d721542792af78b84e9069ea1a662 (patch)
treef862273caec95a27fb0f0dffcb2344c356018a6c /gcc/tree-ssa-alias.c
parent5164293abdea95879f97d4ad711aee010cdbbc95 (diff)
downloadgcc-8322b607d60d721542792af78b84e9069ea1a662.zip
gcc-8322b607d60d721542792af78b84e9069ea1a662.tar.gz
gcc-8322b607d60d721542792af78b84e9069ea1a662.tar.bz2
re PR tree-optimization/81884 (Invalid code generation with zero size arrays or flexible array members)
2017-08-21 Richard Biener <rguenther@suse.de> PR middle-end/81884 * tree-ssa-alias.c (stmt_kills_ref_p): Handle array accesses at struct end conservatively when comparing common bases. * g++.dg/torture/pr81884.C: New testcase. From-SVN: r251217
Diffstat (limited to 'gcc/tree-ssa-alias.c')
-rw-r--r--gcc/tree-ssa-alias.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 5794d22..9bbc163 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -2416,6 +2416,7 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref)
if (ref->ref)
{
tree base = ref->ref;
+ tree innermost_dropped_array_ref = NULL_TREE;
if (handled_component_p (base))
{
tree saved_lhs0 = NULL_TREE;
@@ -2435,6 +2436,11 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref)
TREE_OPERAND (base, 0) = saved_base0;
if (res)
break;
+ /* Remember if we drop an array-ref that we need to
+ double-check not being at struct end. */
+ if (TREE_CODE (base) == ARRAY_REF
+ || TREE_CODE (base) == ARRAY_RANGE_REF)
+ innermost_dropped_array_ref = base;
/* Otherwise drop handled components of the access. */
base = saved_base0;
}
@@ -2443,15 +2449,22 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref)
TREE_OPERAND (lhs, 0) = saved_lhs0;
}
/* Finally check if the lhs has the same address and size as the
- base candidate of the access. */
- if (lhs == base
- || (((TYPE_SIZE (TREE_TYPE (lhs))
- == TYPE_SIZE (TREE_TYPE (base)))
- || (TYPE_SIZE (TREE_TYPE (lhs))
- && TYPE_SIZE (TREE_TYPE (base))
- && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)),
- TYPE_SIZE (TREE_TYPE (base)), 0)))
- && operand_equal_p (lhs, base, OEP_ADDRESS_OF)))
+ base candidate of the access. Watch out if we have dropped
+ an array-ref that was at struct end, this means ref->ref may
+ be outside of the TYPE_SIZE of its base. */
+ if ((! innermost_dropped_array_ref
+ || ! array_at_struct_end_p (innermost_dropped_array_ref))
+ && (lhs == base
+ || (((TYPE_SIZE (TREE_TYPE (lhs))
+ == TYPE_SIZE (TREE_TYPE (base)))
+ || (TYPE_SIZE (TREE_TYPE (lhs))
+ && TYPE_SIZE (TREE_TYPE (base))
+ && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)),
+ TYPE_SIZE (TREE_TYPE (base)),
+ 0)))
+ && operand_equal_p (lhs, base,
+ OEP_ADDRESS_OF
+ | OEP_MATCH_SIDE_EFFECTS))))
return true;
}