fold-const.h (get_array_ctor_element_at_index): Adjust.
2019-07-12 Richard Biener <rguenther@suse.de> * fold-const.h (get_array_ctor_element_at_index): Adjust. * fold-const.c (get_array_ctor_element_at_index): Add ctor_idx output parameter informing the caller where in the constructor the element was (not) found. Add early exit for when the ctor is sorted. * gimple-fold.c (fold_array_ctor_reference): Support constant folding across multiple array elements. * gcc.dg/tree-ssa/vector-7.c: New testcase. From-SVN: r273435
This commit is contained in:
parent
e067f9924b
commit
831e688af5
6 changed files with 167 additions and 16 deletions
|
@ -1,3 +1,13 @@
|
|||
2019-07-12 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* fold-const.h (get_array_ctor_element_at_index): Adjust.
|
||||
* fold-const.c (get_array_ctor_element_at_index): Add
|
||||
ctor_idx output parameter informing the caller where in
|
||||
the constructor the element was (not) found. Add early exit
|
||||
for when the ctor is sorted.
|
||||
* gimple-fold.c (fold_array_ctor_reference): Support constant
|
||||
folding across multiple array elements.
|
||||
|
||||
2019-07-12 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* cfgexpand.c (expand_gimple_stmt_1) <GIMPLE_RETURN>: If the statement
|
||||
|
|
|
@ -11839,10 +11839,15 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
|
|||
}
|
||||
|
||||
/* Gets the element ACCESS_INDEX from CTOR, which must be a CONSTRUCTOR
|
||||
of an array (or vector). */
|
||||
of an array (or vector). *CTOR_IDX if non-NULL is updated with the
|
||||
constructor element index of the value returned. If the element is
|
||||
not found NULL_TREE is returned and *CTOR_IDX is updated to
|
||||
the index of the element after the ACCESS_INDEX position (which
|
||||
may be outside of the CTOR array). */
|
||||
|
||||
tree
|
||||
get_array_ctor_element_at_index (tree ctor, offset_int access_index)
|
||||
get_array_ctor_element_at_index (tree ctor, offset_int access_index,
|
||||
unsigned *ctor_idx)
|
||||
{
|
||||
tree index_type = NULL_TREE;
|
||||
offset_int low_bound = 0;
|
||||
|
@ -11869,7 +11874,7 @@ get_array_ctor_element_at_index (tree ctor, offset_int access_index)
|
|||
TYPE_SIGN (index_type));
|
||||
|
||||
offset_int max_index;
|
||||
unsigned HOST_WIDE_INT cnt;
|
||||
unsigned cnt;
|
||||
tree cfield, cval;
|
||||
|
||||
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
|
||||
|
@ -11897,11 +11902,26 @@ get_array_ctor_element_at_index (tree ctor, offset_int access_index)
|
|||
max_index = index;
|
||||
}
|
||||
|
||||
/* Do we have match? */
|
||||
if (wi::cmpu (access_index, index) >= 0
|
||||
&& wi::cmpu (access_index, max_index) <= 0)
|
||||
return cval;
|
||||
}
|
||||
/* Do we have match? */
|
||||
if (wi::cmpu (access_index, index) >= 0)
|
||||
{
|
||||
if (wi::cmpu (access_index, max_index) <= 0)
|
||||
{
|
||||
if (ctor_idx)
|
||||
*ctor_idx = cnt;
|
||||
return cval;
|
||||
}
|
||||
}
|
||||
else if (in_gimple_form)
|
||||
/* We're past the element we search for. Note during parsing
|
||||
the elements might not be sorted.
|
||||
??? We should use a binary search and a flag on the
|
||||
CONSTRUCTOR as to whether elements are sorted in declaration
|
||||
order. */
|
||||
break;
|
||||
}
|
||||
if (ctor_idx)
|
||||
*ctor_idx = cnt;
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,8 @@ extern tree fold_build_call_array_loc (location_t, tree, tree, int, tree *);
|
|||
#define fold_build_call_array_initializer(T1,T2,N,T4)\
|
||||
fold_build_call_array_initializer_loc (UNKNOWN_LOCATION, T1, T2, N, T4)
|
||||
extern tree fold_build_call_array_initializer_loc (location_t, tree, tree, int, tree *);
|
||||
extern tree get_array_ctor_element_at_index (tree, offset_int);
|
||||
extern tree get_array_ctor_element_at_index (tree, offset_int,
|
||||
unsigned * = NULL);
|
||||
extern bool fold_convertible_p (const_tree, const_tree);
|
||||
#define fold_convert(T1,T2)\
|
||||
fold_convert_loc (UNKNOWN_LOCATION, T1, T2)
|
||||
|
|
|
@ -6716,14 +6716,13 @@ fold_array_ctor_reference (tree type, tree ctor,
|
|||
elt_size = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ctor))));
|
||||
|
||||
/* When TYPE is non-null, verify that it specifies a constant-sized
|
||||
accessed not larger than size of array element. Avoid division
|
||||
access of a multiple of the array element size. Avoid division
|
||||
by zero below when ELT_SIZE is zero, such as with the result of
|
||||
an initializer for a zero-length array or an empty struct. */
|
||||
if (elt_size == 0
|
||||
|| (type
|
||||
&& (!TYPE_SIZE_UNIT (type)
|
||||
|| TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST
|
||||
|| elt_size < wi::to_offset (TYPE_SIZE_UNIT (type)))))
|
||||
|| TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)))
|
||||
return NULL_TREE;
|
||||
|
||||
/* Compute the array index we look for. */
|
||||
|
@ -6734,10 +6733,88 @@ fold_array_ctor_reference (tree type, tree ctor,
|
|||
/* And offset within the access. */
|
||||
inner_offset = offset % (elt_size.to_uhwi () * BITS_PER_UNIT);
|
||||
|
||||
/* See if the array field is large enough to span whole access. We do not
|
||||
care to fold accesses spanning multiple array indexes. */
|
||||
if (inner_offset + size > elt_size.to_uhwi () * BITS_PER_UNIT)
|
||||
return NULL_TREE;
|
||||
if (size > elt_size.to_uhwi () * BITS_PER_UNIT)
|
||||
{
|
||||
/* native_encode_expr constraints. */
|
||||
if (size > MAX_BITSIZE_MODE_ANY_MODE
|
||||
|| size % BITS_PER_UNIT != 0
|
||||
|| inner_offset % BITS_PER_UNIT != 0)
|
||||
return NULL_TREE;
|
||||
|
||||
unsigned ctor_idx;
|
||||
tree val = get_array_ctor_element_at_index (ctor, access_index,
|
||||
&ctor_idx);
|
||||
if (!val && ctor_idx >= CONSTRUCTOR_NELTS (ctor))
|
||||
return build_zero_cst (type);
|
||||
|
||||
/* native-encode adjacent ctor elements. */
|
||||
unsigned char buf[MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT];
|
||||
unsigned bufoff = 0;
|
||||
offset_int index = 0;
|
||||
offset_int max_index = access_index;
|
||||
constructor_elt *elt = CONSTRUCTOR_ELT (ctor, ctor_idx);
|
||||
if (!val)
|
||||
val = build_zero_cst (TREE_TYPE (TREE_TYPE (ctor)));
|
||||
else if (!CONSTANT_CLASS_P (val))
|
||||
return NULL_TREE;
|
||||
if (!elt->index)
|
||||
;
|
||||
else if (TREE_CODE (elt->index) == RANGE_EXPR)
|
||||
{
|
||||
index = wi::to_offset (TREE_OPERAND (elt->index, 0));
|
||||
max_index = wi::to_offset (TREE_OPERAND (elt->index, 1));
|
||||
}
|
||||
else
|
||||
index = max_index = wi::to_offset (elt->index);
|
||||
index = wi::umax (index, access_index);
|
||||
do
|
||||
{
|
||||
int len = native_encode_expr (val, buf + bufoff,
|
||||
elt_size.to_uhwi (),
|
||||
inner_offset / BITS_PER_UNIT);
|
||||
if (len != elt_size - inner_offset / BITS_PER_UNIT)
|
||||
return NULL_TREE;
|
||||
inner_offset = 0;
|
||||
bufoff += len;
|
||||
|
||||
access_index += 1;
|
||||
if (wi::cmpu (access_index, index) == 0)
|
||||
val = elt->value;
|
||||
else if (wi::cmpu (access_index, max_index) > 0)
|
||||
{
|
||||
ctor_idx++;
|
||||
if (ctor_idx >= CONSTRUCTOR_NELTS (ctor))
|
||||
{
|
||||
val = build_zero_cst (TREE_TYPE (TREE_TYPE (ctor)));
|
||||
++max_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
elt = CONSTRUCTOR_ELT (ctor, ctor_idx);
|
||||
index = 0;
|
||||
max_index = access_index;
|
||||
if (!elt->index)
|
||||
;
|
||||
else if (TREE_CODE (elt->index) == RANGE_EXPR)
|
||||
{
|
||||
index = wi::to_offset (TREE_OPERAND (elt->index, 0));
|
||||
max_index = wi::to_offset (TREE_OPERAND (elt->index, 1));
|
||||
}
|
||||
else
|
||||
index = max_index = wi::to_offset (elt->index);
|
||||
index = wi::umax (index, access_index);
|
||||
if (wi::cmpu (access_index, index) == 0)
|
||||
val = elt->value;
|
||||
else
|
||||
val = build_zero_cst (TREE_TYPE (TREE_TYPE (ctor)));
|
||||
}
|
||||
}
|
||||
}
|
||||
while (bufoff < size / BITS_PER_UNIT);
|
||||
*suboff += size;
|
||||
return native_interpret_expr (type, buf, size / BITS_PER_UNIT);
|
||||
}
|
||||
|
||||
if (tree val = get_array_ctor_element_at_index (ctor, access_index))
|
||||
{
|
||||
if (!size && TREE_CODE (val) != CONSTRUCTOR)
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2019-07-12 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* gcc.dg/tree-ssa/vector-7.c: New testcase.
|
||||
|
||||
2019-07-12 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* c-c++-common/gomp/order-1.c: New test.
|
||||
|
|
39
gcc/testsuite/gcc.dg/tree-ssa/vector-7.c
Normal file
39
gcc/testsuite/gcc.dg/tree-ssa/vector-7.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* { dg-do run } */
|
||||
/* { dg-options "-O3 -fdump-tree-optimized" } */
|
||||
|
||||
typedef __INT8_TYPE__ v16qi __attribute__((vector_size(16),may_alias,aligned(1)));
|
||||
typedef __INT32_TYPE__ v4si __attribute__((vector_size(16),may_alias,aligned(1)));
|
||||
|
||||
const __INT32_TYPE__ x[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
const __INT8_TYPE__ y[32]
|
||||
= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
|
||||
const __INT32_TYPE__ z[8] = { [3] = 3, [1] = 1 };
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
v4si v1 = *(v4si *)(x + 1);
|
||||
for (unsigned i = 0; i < 4; ++i)
|
||||
if (v1[i] != (v4si) { 2, 3, 4, 5 }[i])
|
||||
__builtin_abort ();
|
||||
v4si v2 = *(v4si *)z;
|
||||
for (unsigned i = 0; i < 4; ++i)
|
||||
if (v2[i] != (v4si) { 0, 1, 0, 3 }[i])
|
||||
__builtin_abort ();
|
||||
v4si v3 = *(v4si *)(y + 1);
|
||||
for (unsigned i = 0; i < 4; ++i)
|
||||
if (v3[i] !=
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
(v4si) { 0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f01 }[i]
|
||||
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
(v4si) { 0x04030201, 0x08070605, 0x0c0b0a09, 0x100f0e0d }[i]
|
||||
#else
|
||||
v3[i]
|
||||
#endif
|
||||
)
|
||||
__builtin_abort ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
|
Loading…
Add table
Reference in a new issue