backport: [multiple changes]
2017-08-28 Richard Biener <rguenther@suse.de> Backport from mainline 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. 2017-05-04 Richard Biener <rguenther@suse.de> * tree.c (array_at_struct_end_p): Handle arrays at struct end with flexarrays more conservatively. Refactor and treat arrays of arrays or aggregates more strict. Fix VIEW_CONVERT_EXPR handling. Remove allow_compref argument. * tree.h (array_at_struct_end_p): Adjust prototype. * gimple-fold.c (get_range_strlen): Likewise. * tree-chkp.c (chkp_may_narrow_to_field): Likewise. From-SVN: r251379
This commit is contained in:
parent
2377f9833d
commit
9563a3d30a
|
@ -1,3 +1,22 @@
|
|||
2017-08-28 Richard Biener <rguenther@suse.de>
|
||||
|
||||
Backport from mainline
|
||||
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.
|
||||
|
||||
2017-05-04 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* tree.c (array_at_struct_end_p): Handle arrays at struct
|
||||
end with flexarrays more conservatively. Refactor and treat
|
||||
arrays of arrays or aggregates more strict. Fix
|
||||
VIEW_CONVERT_EXPR handling. Remove allow_compref argument.
|
||||
* tree.h (array_at_struct_end_p): Adjust prototype.
|
||||
* gimple-fold.c (get_range_strlen): Likewise.
|
||||
* tree-chkp.c (chkp_may_narrow_to_field): Likewise.
|
||||
|
||||
2017-08-28 Richard Biener <rguenther@suse.de>
|
||||
|
||||
Backport from mainline
|
||||
|
|
|
@ -1236,7 +1236,7 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
|
|||
the NUL.
|
||||
Set *FLEXP to true if the array whose bound is being
|
||||
used is at the end of a struct. */
|
||||
if (array_at_struct_end_p (arg, true))
|
||||
if (array_at_struct_end_p (arg))
|
||||
*flexp = true;
|
||||
|
||||
arg = TREE_OPERAND (arg, 1);
|
||||
|
|
|
@ -1,3 +1,29 @@
|
|||
2017-08-28 Richard Biener <rguenther@suse.de>
|
||||
|
||||
Backport from mainline
|
||||
2017-08-21 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR middle-end/81884
|
||||
* g++.dg/torture/pr81884.C: New testcase.
|
||||
|
||||
2017-08-28 Richard Biener <rguenther@suse.de>
|
||||
|
||||
Backport from mainline
|
||||
2017-08-01 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/81181
|
||||
* gcc.dg/torture/pr81181.c: New testcase.
|
||||
|
||||
2017-08-08 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/81723
|
||||
* gfortran.dg/pr81723.f: New testcase.
|
||||
|
||||
2017-08-24 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR target/81921
|
||||
* gcc/testsuite/gcc.target/i386/pr81921.c: New testcase.
|
||||
|
||||
2017-05-19 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
Backport from mainline
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/* { dg-do run } */
|
||||
|
||||
typedef unsigned long uint64_t;
|
||||
|
||||
struct value_t {
|
||||
uint64_t _count;
|
||||
value_t(uint64_t c) : _count(c) {}
|
||||
};
|
||||
|
||||
struct X {
|
||||
value_t eventTime;
|
||||
uint64_t arr[0];
|
||||
};
|
||||
|
||||
X* x;
|
||||
|
||||
__attribute__((noclone, noinline))
|
||||
void initialize()
|
||||
{
|
||||
x->arr[0] = 11;
|
||||
x->arr[1] = 12;
|
||||
x->eventTime = value_t(10);
|
||||
x->arr[2] = 13;
|
||||
x->arr[3] = 14;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
char buffer[sizeof(X) + sizeof(uint64_t)*4];
|
||||
x = (X*)buffer;
|
||||
x->eventTime = value_t(999);
|
||||
x->arr[0] = 1;
|
||||
x->arr[1] = 2;
|
||||
x->arr[2] = 3;
|
||||
x->arr[3] = 4;
|
||||
initialize();
|
||||
if (x->arr[0] != 11 || x->arr[1] != 12 || x->arr[2] != 13 || x->arr[3] != 14)
|
||||
__builtin_abort ();
|
||||
}
|
|
@ -3277,7 +3277,7 @@ chkp_may_narrow_to_field (tree ref, tree field)
|
|||
return DECL_SIZE (field) && TREE_CODE (DECL_SIZE (field)) == INTEGER_CST
|
||||
&& tree_to_uhwi (DECL_SIZE (field)) != 0
|
||||
&& !(flag_chkp_flexible_struct_trailing_arrays
|
||||
&& array_at_struct_end_p (ref, true))
|
||||
&& array_at_struct_end_p (ref))
|
||||
&& (!DECL_FIELD_OFFSET (field)
|
||||
|| TREE_CODE (DECL_FIELD_OFFSET (field)) == INTEGER_CST)
|
||||
&& (!DECL_FIELD_BIT_OFFSET (field)
|
||||
|
|
|
@ -2415,6 +2415,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;
|
||||
|
@ -2434,6 +2435,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;
|
||||
}
|
||||
|
@ -2442,15 +2448,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;
|
||||
}
|
||||
|
||||
|
|
63
gcc/tree.c
63
gcc/tree.c
|
@ -13219,18 +13219,26 @@ array_ref_up_bound (tree exp)
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Returns true if REF is an array reference to an array at the end of
|
||||
a structure. If this is the case, the array may be allocated larger
|
||||
than its upper bound implies. When ALLOW_COMPREF is true considers
|
||||
REF when it's a COMPONENT_REF in addition ARRAY_REF and
|
||||
ARRAY_RANGE_REF. */
|
||||
/* Returns true if REF is an array reference or a component reference
|
||||
to an array at the end of a structure.
|
||||
If this is the case, the array may be allocated larger
|
||||
than its upper bound implies. */
|
||||
|
||||
bool
|
||||
array_at_struct_end_p (tree ref, bool allow_compref)
|
||||
array_at_struct_end_p (tree ref)
|
||||
{
|
||||
if (TREE_CODE (ref) != ARRAY_REF
|
||||
&& TREE_CODE (ref) != ARRAY_RANGE_REF
|
||||
&& (!allow_compref || TREE_CODE (ref) != COMPONENT_REF))
|
||||
tree atype;
|
||||
|
||||
if (TREE_CODE (ref) == ARRAY_REF
|
||||
|| TREE_CODE (ref) == ARRAY_RANGE_REF)
|
||||
{
|
||||
atype = TREE_TYPE (TREE_OPERAND (ref, 0));
|
||||
ref = TREE_OPERAND (ref, 0);
|
||||
}
|
||||
else if (TREE_CODE (ref) == COMPONENT_REF
|
||||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 1))) == ARRAY_TYPE)
|
||||
atype = TREE_TYPE (TREE_OPERAND (ref, 1));
|
||||
else
|
||||
return false;
|
||||
|
||||
while (handled_component_p (ref))
|
||||
|
@ -13238,19 +13246,42 @@ array_at_struct_end_p (tree ref, bool allow_compref)
|
|||
/* If the reference chain contains a component reference to a
|
||||
non-union type and there follows another field the reference
|
||||
is not at the end of a structure. */
|
||||
if (TREE_CODE (ref) == COMPONENT_REF
|
||||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
|
||||
if (TREE_CODE (ref) == COMPONENT_REF)
|
||||
{
|
||||
tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
|
||||
while (nextf && TREE_CODE (nextf) != FIELD_DECL)
|
||||
nextf = DECL_CHAIN (nextf);
|
||||
if (nextf)
|
||||
return false;
|
||||
if (TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
|
||||
{
|
||||
tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
|
||||
while (nextf && TREE_CODE (nextf) != FIELD_DECL)
|
||||
nextf = DECL_CHAIN (nextf);
|
||||
if (nextf)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* If we have a multi-dimensional array we do not consider
|
||||
a non-innermost dimension as flex array if the whole
|
||||
multi-dimensional array is at struct end.
|
||||
Same for an array of aggregates with a trailing array
|
||||
member. */
|
||||
else if (TREE_CODE (ref) == ARRAY_REF)
|
||||
return false;
|
||||
else if (TREE_CODE (ref) == ARRAY_RANGE_REF)
|
||||
;
|
||||
/* If we view an underlying object as sth else then what we
|
||||
gathered up to now is what we have to rely on. */
|
||||
else if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
|
||||
break;
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
ref = TREE_OPERAND (ref, 0);
|
||||
}
|
||||
|
||||
/* The array now is at struct end. Treat flexible arrays as
|
||||
always subject to extend, even into just padding constrained by
|
||||
an underlying decl. */
|
||||
if (! TYPE_SIZE (atype))
|
||||
return true;
|
||||
|
||||
tree size = NULL;
|
||||
|
||||
if (TREE_CODE (ref) == MEM_REF
|
||||
|
|
10
gcc/tree.h
10
gcc/tree.h
|
@ -4870,12 +4870,10 @@ extern tree array_ref_up_bound (tree);
|
|||
EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
|
||||
extern tree array_ref_low_bound (tree);
|
||||
|
||||
/* Returns true if REF is an array reference to an array at the end of
|
||||
a structure. If this is the case, the array may be allocated larger
|
||||
than its upper bound implies. When second argument is true considers
|
||||
REF when it's a COMPONENT_REF in addition ARRAY_REF and
|
||||
ARRAY_RANGE_REF. */
|
||||
extern bool array_at_struct_end_p (tree, bool = false);
|
||||
/* Returns true if REF is an array reference or a component reference
|
||||
to an array at the end of a structure. If this is the case, the array
|
||||
may be allocated larger than its upper bound implies. */
|
||||
extern bool array_at_struct_end_p (tree);
|
||||
|
||||
/* Return a tree representing the offset, in bytes, of the field referenced
|
||||
by EXP. This does not include any offset in DECL_FIELD_BIT_OFFSET. */
|
||||
|
|
Loading…
Reference in New Issue