re PR tree-optimization/93210 (Sub-optimal code optimization on struct/combound constexpr (gcc vs. clang))
PR tree-optimization/93210 * fold-const.h (native_encode_initializer, can_native_interpret_type_p): Declare. * fold-const.c (native_encode_string): Fix up handling with off != -1, simplify. (native_encode_initializer): New function, moved from dwarf2out.c. Adjust to native_encode_expr compatible arguments, including dry-run and partial extraction modes. Don't handle STRING_CST. (can_native_interpret_type_p): No longer static. * gimple-fold.c (fold_ctor_reference): For native_encode_expr, verify offset / BITS_PER_UNIT fits into int and don't call it if can_native_interpret_type_p fails. If suboff is NULL and for CONSTRUCTOR fold_{,non}array_ctor_reference returns NULL, retry with native_encode_initializer. (fold_const_aggregate_ref_1): Formatting fix. * dwarf2out.c (native_encode_initializer): Moved to fold-const.c. (tree_add_const_value_attribute): Adjust caller. * gcc.dg/pr93210.c: New test. * g++.dg/opt/pr93210.C: New test. From-SVN: r280141
This commit is contained in:
parent
974bb8a4dc
commit
ea69031c5f
8 changed files with 373 additions and 158 deletions
|
@ -1,5 +1,23 @@
|
|||
2020-01-10 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/93210
|
||||
* fold-const.h (native_encode_initializer,
|
||||
can_native_interpret_type_p): Declare.
|
||||
* fold-const.c (native_encode_string): Fix up handling with off != -1,
|
||||
simplify.
|
||||
(native_encode_initializer): New function, moved from dwarf2out.c.
|
||||
Adjust to native_encode_expr compatible arguments, including dry-run
|
||||
and partial extraction modes. Don't handle STRING_CST.
|
||||
(can_native_interpret_type_p): No longer static.
|
||||
* gimple-fold.c (fold_ctor_reference): For native_encode_expr, verify
|
||||
offset / BITS_PER_UNIT fits into int and don't call it if
|
||||
can_native_interpret_type_p fails. If suboff is NULL and for
|
||||
CONSTRUCTOR fold_{,non}array_ctor_reference returns NULL, retry with
|
||||
native_encode_initializer.
|
||||
(fold_const_aggregate_ref_1): Formatting fix.
|
||||
* dwarf2out.c (native_encode_initializer): Moved to fold-const.c.
|
||||
(tree_add_const_value_attribute): Adjust caller.
|
||||
|
||||
PR tree-optimization/90838
|
||||
* tree-ssa-forwprop.c (simplify_count_trailing_zeroes): Use
|
||||
SCALAR_INT_TYPE_MODE instead of TYPE_MODE as operand of
|
||||
|
|
146
gcc/dwarf2out.c
146
gcc/dwarf2out.c
|
@ -20258,150 +20258,6 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p)
|
|||
return tree_add_const_value_attribute_for_decl (die, decl);
|
||||
}
|
||||
|
||||
/* Helper function for tree_add_const_value_attribute. Natively encode
|
||||
initializer INIT into an array. Return true if successful. */
|
||||
|
||||
static bool
|
||||
native_encode_initializer (tree init, unsigned char *array, int size)
|
||||
{
|
||||
tree type;
|
||||
|
||||
if (init == NULL_TREE)
|
||||
return false;
|
||||
|
||||
STRIP_NOPS (init);
|
||||
switch (TREE_CODE (init))
|
||||
{
|
||||
case STRING_CST:
|
||||
type = TREE_TYPE (init);
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
{
|
||||
tree enttype = TREE_TYPE (type);
|
||||
scalar_int_mode mode;
|
||||
|
||||
if (!is_int_mode (TYPE_MODE (enttype), &mode)
|
||||
|| GET_MODE_SIZE (mode) != 1)
|
||||
return false;
|
||||
if (int_size_in_bytes (type) != size)
|
||||
return false;
|
||||
if (size > TREE_STRING_LENGTH (init))
|
||||
{
|
||||
memcpy (array, TREE_STRING_POINTER (init),
|
||||
TREE_STRING_LENGTH (init));
|
||||
memset (array + TREE_STRING_LENGTH (init),
|
||||
'\0', size - TREE_STRING_LENGTH (init));
|
||||
}
|
||||
else
|
||||
memcpy (array, TREE_STRING_POINTER (init), size);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case CONSTRUCTOR:
|
||||
type = TREE_TYPE (init);
|
||||
if (int_size_in_bytes (type) != size)
|
||||
return false;
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
{
|
||||
HOST_WIDE_INT min_index;
|
||||
unsigned HOST_WIDE_INT cnt;
|
||||
int curpos = 0, fieldsize;
|
||||
constructor_elt *ce;
|
||||
|
||||
if (TYPE_DOMAIN (type) == NULL_TREE
|
||||
|| !tree_fits_shwi_p (TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
|
||||
return false;
|
||||
|
||||
fieldsize = int_size_in_bytes (TREE_TYPE (type));
|
||||
if (fieldsize <= 0)
|
||||
return false;
|
||||
|
||||
min_index = tree_to_shwi (TYPE_MIN_VALUE (TYPE_DOMAIN (type)));
|
||||
memset (array, '\0', size);
|
||||
FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (init), cnt, ce)
|
||||
{
|
||||
tree val = ce->value;
|
||||
tree index = ce->index;
|
||||
int pos = curpos;
|
||||
if (index && TREE_CODE (index) == RANGE_EXPR)
|
||||
pos = (tree_to_shwi (TREE_OPERAND (index, 0)) - min_index)
|
||||
* fieldsize;
|
||||
else if (index)
|
||||
pos = (tree_to_shwi (index) - min_index) * fieldsize;
|
||||
|
||||
if (val)
|
||||
{
|
||||
STRIP_NOPS (val);
|
||||
if (!native_encode_initializer (val, array + pos, fieldsize))
|
||||
return false;
|
||||
}
|
||||
curpos = pos + fieldsize;
|
||||
if (index && TREE_CODE (index) == RANGE_EXPR)
|
||||
{
|
||||
int count = tree_to_shwi (TREE_OPERAND (index, 1))
|
||||
- tree_to_shwi (TREE_OPERAND (index, 0));
|
||||
while (count-- > 0)
|
||||
{
|
||||
if (val)
|
||||
memcpy (array + curpos, array + pos, fieldsize);
|
||||
curpos += fieldsize;
|
||||
}
|
||||
}
|
||||
gcc_assert (curpos <= size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (TREE_CODE (type) == RECORD_TYPE
|
||||
|| TREE_CODE (type) == UNION_TYPE)
|
||||
{
|
||||
tree field = NULL_TREE;
|
||||
unsigned HOST_WIDE_INT cnt;
|
||||
constructor_elt *ce;
|
||||
|
||||
if (int_size_in_bytes (type) != size)
|
||||
return false;
|
||||
|
||||
if (TREE_CODE (type) == RECORD_TYPE)
|
||||
field = TYPE_FIELDS (type);
|
||||
|
||||
FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (init), cnt, ce)
|
||||
{
|
||||
tree val = ce->value;
|
||||
int pos, fieldsize;
|
||||
|
||||
if (ce->index != 0)
|
||||
field = ce->index;
|
||||
|
||||
if (val)
|
||||
STRIP_NOPS (val);
|
||||
|
||||
if (field == NULL_TREE || DECL_BIT_FIELD (field))
|
||||
return false;
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
|
||||
&& TYPE_DOMAIN (TREE_TYPE (field))
|
||||
&& ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
|
||||
return false;
|
||||
else if (DECL_SIZE_UNIT (field) == NULL_TREE
|
||||
|| !tree_fits_shwi_p (DECL_SIZE_UNIT (field)))
|
||||
return false;
|
||||
fieldsize = tree_to_shwi (DECL_SIZE_UNIT (field));
|
||||
pos = int_byte_position (field);
|
||||
gcc_assert (pos + fieldsize <= size);
|
||||
if (val && fieldsize != 0
|
||||
&& !native_encode_initializer (val, array + pos, fieldsize))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case VIEW_CONVERT_EXPR:
|
||||
case NON_LVALUE_EXPR:
|
||||
return native_encode_initializer (TREE_OPERAND (init, 0), array, size);
|
||||
default:
|
||||
return native_encode_expr (init, array, size) == size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attach a DW_AT_const_value attribute to DIE. The value of the
|
||||
attribute is the const value T. */
|
||||
|
||||
|
@ -20446,7 +20302,7 @@ tree_add_const_value_attribute (dw_die_ref die, tree t)
|
|||
{
|
||||
unsigned char *array = ggc_cleared_vec_alloc<unsigned char> (size);
|
||||
|
||||
if (native_encode_initializer (init, array, size))
|
||||
if (native_encode_initializer (init, array, size) == size)
|
||||
{
|
||||
add_AT_vec (die, DW_AT_const_value, size, 1, array);
|
||||
return true;
|
||||
|
|
219
gcc/fold-const.c
219
gcc/fold-const.c
|
@ -7837,9 +7837,10 @@ native_encode_string (const_tree expr, unsigned char *ptr, int len, int off)
|
|||
return 0;
|
||||
if (off == -1)
|
||||
off = 0;
|
||||
len = MIN (total_bytes - off, len);
|
||||
if (ptr == NULL)
|
||||
/* Dry run. */;
|
||||
else if (TREE_STRING_LENGTH (expr) - off < MIN (total_bytes, len))
|
||||
else
|
||||
{
|
||||
int written = 0;
|
||||
if (off < TREE_STRING_LENGTH (expr))
|
||||
|
@ -7847,12 +7848,9 @@ native_encode_string (const_tree expr, unsigned char *ptr, int len, int off)
|
|||
written = MIN (len, TREE_STRING_LENGTH (expr) - off);
|
||||
memcpy (ptr, TREE_STRING_POINTER (expr) + off, written);
|
||||
}
|
||||
memset (ptr + written, 0,
|
||||
MIN (total_bytes - written, len - written));
|
||||
memset (ptr + written, 0, len - written);
|
||||
}
|
||||
else
|
||||
memcpy (ptr, TREE_STRING_POINTER (expr) + off, MIN (total_bytes, len));
|
||||
return MIN (total_bytes - off, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
@ -7895,6 +7893,213 @@ native_encode_expr (const_tree expr, unsigned char *ptr, int len, int off)
|
|||
}
|
||||
}
|
||||
|
||||
/* Similar to native_encode_expr, but also handle CONSTRUCTORs, VCEs,
|
||||
NON_LVALUE_EXPRs and nops. */
|
||||
|
||||
int
|
||||
native_encode_initializer (tree init, unsigned char *ptr, int len,
|
||||
int off)
|
||||
{
|
||||
/* We don't support starting at negative offset and -1 is special. */
|
||||
if (off < -1 || init == NULL_TREE)
|
||||
return 0;
|
||||
|
||||
STRIP_NOPS (init);
|
||||
switch (TREE_CODE (init))
|
||||
{
|
||||
case VIEW_CONVERT_EXPR:
|
||||
case NON_LVALUE_EXPR:
|
||||
return native_encode_initializer (TREE_OPERAND (init, 0), ptr, len, off);
|
||||
default:
|
||||
return native_encode_expr (init, ptr, len, off);
|
||||
case CONSTRUCTOR:
|
||||
tree type = TREE_TYPE (init);
|
||||
HOST_WIDE_INT total_bytes = int_size_in_bytes (type);
|
||||
if (total_bytes < 0)
|
||||
return 0;
|
||||
if ((off == -1 && total_bytes > len) || off >= total_bytes)
|
||||
return 0;
|
||||
int o = off == -1 ? 0 : off;
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
{
|
||||
HOST_WIDE_INT min_index;
|
||||
unsigned HOST_WIDE_INT cnt;
|
||||
HOST_WIDE_INT curpos = 0, fieldsize;
|
||||
constructor_elt *ce;
|
||||
|
||||
if (TYPE_DOMAIN (type) == NULL_TREE
|
||||
|| !tree_fits_shwi_p (TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
|
||||
return 0;
|
||||
|
||||
fieldsize = int_size_in_bytes (TREE_TYPE (type));
|
||||
if (fieldsize <= 0)
|
||||
return 0;
|
||||
|
||||
min_index = tree_to_shwi (TYPE_MIN_VALUE (TYPE_DOMAIN (type)));
|
||||
if (ptr != NULL)
|
||||
memset (ptr, '\0', MIN (total_bytes - off, len));
|
||||
|
||||
FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (init), cnt, ce)
|
||||
{
|
||||
tree val = ce->value;
|
||||
tree index = ce->index;
|
||||
HOST_WIDE_INT pos = curpos, count = 0;
|
||||
bool full = false;
|
||||
if (index && TREE_CODE (index) == RANGE_EXPR)
|
||||
{
|
||||
if (!tree_fits_shwi_p (TREE_OPERAND (index, 0))
|
||||
|| !tree_fits_shwi_p (TREE_OPERAND (index, 1)))
|
||||
return 0;
|
||||
pos = (tree_to_shwi (TREE_OPERAND (index, 0)) - min_index)
|
||||
* fieldsize;
|
||||
count = (tree_to_shwi (TREE_OPERAND (index, 1))
|
||||
- tree_to_shwi (TREE_OPERAND (index, 0)));
|
||||
}
|
||||
else if (index)
|
||||
{
|
||||
if (!tree_fits_shwi_p (index))
|
||||
return 0;
|
||||
pos = (tree_to_shwi (index) - min_index) * fieldsize;
|
||||
}
|
||||
|
||||
curpos = pos;
|
||||
if (val)
|
||||
do
|
||||
{
|
||||
if (off == -1
|
||||
|| (curpos >= off
|
||||
&& (curpos + fieldsize
|
||||
<= (HOST_WIDE_INT) off + len)))
|
||||
{
|
||||
if (full)
|
||||
{
|
||||
if (ptr)
|
||||
memcpy (ptr + (curpos - o), ptr + (pos - o),
|
||||
fieldsize);
|
||||
}
|
||||
else if (!native_encode_initializer (val,
|
||||
ptr
|
||||
? ptr + curpos - o
|
||||
: NULL,
|
||||
fieldsize,
|
||||
off == -1 ? -1
|
||||
: 0))
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
full = true;
|
||||
pos = curpos;
|
||||
}
|
||||
}
|
||||
else if (curpos + fieldsize > off
|
||||
&& curpos < (HOST_WIDE_INT) off + len)
|
||||
{
|
||||
/* Partial overlap. */
|
||||
unsigned char *p = NULL;
|
||||
int no = 0;
|
||||
int l;
|
||||
if (curpos >= off)
|
||||
{
|
||||
if (ptr)
|
||||
p = ptr + curpos - off;
|
||||
l = MIN ((HOST_WIDE_INT) off + len - curpos,
|
||||
fieldsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = ptr;
|
||||
no = off - curpos;
|
||||
l = len;
|
||||
}
|
||||
if (!native_encode_initializer (val, p, l, no))
|
||||
return 0;
|
||||
}
|
||||
curpos += fieldsize;
|
||||
}
|
||||
while (count-- != 0);
|
||||
}
|
||||
return MIN (total_bytes - off, len);
|
||||
}
|
||||
else if (TREE_CODE (type) == RECORD_TYPE
|
||||
|| TREE_CODE (type) == UNION_TYPE)
|
||||
{
|
||||
unsigned HOST_WIDE_INT cnt;
|
||||
constructor_elt *ce;
|
||||
|
||||
if (ptr != NULL)
|
||||
memset (ptr, '\0', MIN (total_bytes - off, len));
|
||||
FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (init), cnt, ce)
|
||||
{
|
||||
tree field = ce->index;
|
||||
tree val = ce->value;
|
||||
HOST_WIDE_INT pos, fieldsize;
|
||||
|
||||
if (field == NULL_TREE)
|
||||
return 0;
|
||||
|
||||
pos = int_byte_position (field);
|
||||
if (off != -1 && (HOST_WIDE_INT) off + len <= pos)
|
||||
continue;
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
|
||||
&& TYPE_DOMAIN (TREE_TYPE (field))
|
||||
&& ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
|
||||
return 0;
|
||||
if (DECL_SIZE_UNIT (field) == NULL_TREE
|
||||
|| !tree_fits_shwi_p (DECL_SIZE_UNIT (field)))
|
||||
return 0;
|
||||
fieldsize = tree_to_shwi (DECL_SIZE_UNIT (field));
|
||||
if (fieldsize == 0)
|
||||
continue;
|
||||
|
||||
if (off != -1 && pos + fieldsize <= off)
|
||||
continue;
|
||||
|
||||
if (DECL_BIT_FIELD (field))
|
||||
return 0;
|
||||
|
||||
if (val == NULL_TREE)
|
||||
continue;
|
||||
|
||||
if (off == -1
|
||||
|| (pos >= off
|
||||
&& (pos + fieldsize <= (HOST_WIDE_INT) off + len)))
|
||||
{
|
||||
if (!native_encode_initializer (val, ptr ? ptr + pos - o
|
||||
: NULL,
|
||||
fieldsize,
|
||||
off == -1 ? -1 : 0))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Partial overlap. */
|
||||
unsigned char *p = NULL;
|
||||
int no = 0;
|
||||
int l;
|
||||
if (pos >= off)
|
||||
{
|
||||
if (ptr)
|
||||
p = ptr + pos - off;
|
||||
l = MIN ((HOST_WIDE_INT) off + len - pos,
|
||||
fieldsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = ptr;
|
||||
no = off - pos;
|
||||
l = len;
|
||||
}
|
||||
if (!native_encode_initializer (val, p, l, no))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return MIN (total_bytes - off, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Subroutine of native_interpret_expr. Interpret the contents of
|
||||
the buffer PTR of length LEN as an INTEGER_CST of type TYPE.
|
||||
|
@ -8129,7 +8334,7 @@ native_interpret_expr (tree type, const unsigned char *ptr, int len)
|
|||
/* Returns true if we can interpret the contents of a native encoding
|
||||
as TYPE. */
|
||||
|
||||
static bool
|
||||
bool
|
||||
can_native_interpret_type_p (tree type)
|
||||
{
|
||||
switch (TREE_CODE (type))
|
||||
|
|
|
@ -26,7 +26,10 @@ extern int folding_initializer;
|
|||
|
||||
/* Convert between trees and native memory representation. */
|
||||
extern int native_encode_expr (const_tree, unsigned char *, int, int off = -1);
|
||||
extern int native_encode_initializer (tree, unsigned char *, int,
|
||||
int off = -1);
|
||||
extern tree native_interpret_expr (tree, const unsigned char *, int);
|
||||
extern bool can_native_interpret_type_p (tree);
|
||||
|
||||
/* Fold constants as much as possible in an expression.
|
||||
Returns the simplified expression.
|
||||
|
|
|
@ -6919,8 +6919,10 @@ fold_ctor_reference (tree type, tree ctor, const poly_uint64 &poly_offset,
|
|||
if (CONSTANT_CLASS_P (ctor)
|
||||
&& BITS_PER_UNIT == 8
|
||||
&& offset % BITS_PER_UNIT == 0
|
||||
&& offset / BITS_PER_UNIT <= INT_MAX
|
||||
&& size % BITS_PER_UNIT == 0
|
||||
&& size <= MAX_BITSIZE_MODE_ANY_MODE)
|
||||
&& size <= MAX_BITSIZE_MODE_ANY_MODE
|
||||
&& can_native_interpret_type_p (type))
|
||||
{
|
||||
unsigned char buf[MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT];
|
||||
int len = native_encode_expr (ctor, buf, size / BITS_PER_UNIT,
|
||||
|
@ -6934,13 +6936,35 @@ fold_ctor_reference (tree type, tree ctor, const poly_uint64 &poly_offset,
|
|||
if (!suboff)
|
||||
suboff = &dummy;
|
||||
|
||||
tree ret;
|
||||
if (TREE_CODE (TREE_TYPE (ctor)) == ARRAY_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (ctor)) == VECTOR_TYPE)
|
||||
return fold_array_ctor_reference (type, ctor, offset, size,
|
||||
from_decl, suboff);
|
||||
ret = fold_array_ctor_reference (type, ctor, offset, size,
|
||||
from_decl, suboff);
|
||||
else
|
||||
ret = fold_nonarray_ctor_reference (type, ctor, offset, size,
|
||||
from_decl, suboff);
|
||||
|
||||
return fold_nonarray_ctor_reference (type, ctor, offset, size,
|
||||
from_decl, suboff);
|
||||
/* Fall back to native_encode_initializer. Needs to be done
|
||||
only in the outermost fold_ctor_reference call (because it itself
|
||||
recurses into CONSTRUCTORs) and doesn't update suboff. */
|
||||
if (ret == NULL_TREE
|
||||
&& suboff == &dummy
|
||||
&& BITS_PER_UNIT == 8
|
||||
&& offset % BITS_PER_UNIT == 0
|
||||
&& offset / BITS_PER_UNIT <= INT_MAX
|
||||
&& size % BITS_PER_UNIT == 0
|
||||
&& size <= MAX_BITSIZE_MODE_ANY_MODE
|
||||
&& can_native_interpret_type_p (type))
|
||||
{
|
||||
unsigned char buf[MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT];
|
||||
int len = native_encode_initializer (ctor, buf, size / BITS_PER_UNIT,
|
||||
offset / BITS_PER_UNIT);
|
||||
if (len > 0)
|
||||
return native_interpret_expr (type, buf, len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
|
@ -7049,7 +7073,7 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
|
|||
tree c = fold_const_aggregate_ref_1 (TREE_OPERAND (t, 0), valueize);
|
||||
if (c && TREE_CODE (c) == COMPLEX_CST)
|
||||
return fold_build1_loc (EXPR_LOCATION (t),
|
||||
TREE_CODE (t), TREE_TYPE (t), c);
|
||||
TREE_CODE (t), TREE_TYPE (t), c);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2020-01-10 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/93210
|
||||
* gcc.dg/pr93210.c: New test.
|
||||
* g++.dg/opt/pr93210.C: New test.
|
||||
|
||||
2020-01-10 Vladimir Makarov <vmakarov@redhat.com>
|
||||
|
||||
PR inline-asm/93027
|
||||
|
|
37
gcc/testsuite/g++.dg/opt/pr93210.C
Normal file
37
gcc/testsuite/g++.dg/opt/pr93210.C
Normal file
|
@ -0,0 +1,37 @@
|
|||
// PR tree-optimization/93210
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-O2 -fdump-tree-optimized" }
|
||||
// { dg-final { scan-tree-dump-not "static_member\.d" "optimized" } }
|
||||
|
||||
union U { struct { unsigned int a, b; } c; unsigned long long d; };
|
||||
|
||||
inline
|
||||
bool operator == (U const &x, U const &y) noexcept
|
||||
{
|
||||
return x.d == y.d;
|
||||
};
|
||||
|
||||
struct S
|
||||
{
|
||||
static constexpr U static_member = { { 13, 42 } };
|
||||
bool foo (U const &y) const noexcept;
|
||||
bool bar (U const &y) const noexcept;
|
||||
};
|
||||
|
||||
#if __cpp_inline_variables < 201606L
|
||||
constexpr U S::static_member;
|
||||
#endif
|
||||
|
||||
#if __SIZEOF_INT__ * 2 == __SIZEOF_LONG_LONG__
|
||||
bool
|
||||
S::foo (U const &y) const noexcept
|
||||
{
|
||||
return static_member == y;
|
||||
}
|
||||
|
||||
bool
|
||||
S::bar (U const &y) const noexcept
|
||||
{
|
||||
return U (static_member) == y;
|
||||
}
|
||||
#endif
|
66
gcc/testsuite/gcc.dg/pr93210.c
Normal file
66
gcc/testsuite/gcc.dg/pr93210.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* PR tree-optimization/93210 */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -fdump-tree-optimized" } */
|
||||
/* { dg-final { scan-tree-dump-times "return \[0-9]\[0-9a-fA-FxX]*;" 31 "optimized" } } */
|
||||
|
||||
#ifdef __SIZEOF_INT128__
|
||||
typedef unsigned __int128 L;
|
||||
#else
|
||||
typedef unsigned long long L;
|
||||
#endif
|
||||
struct S { signed char a, b; unsigned char c; };
|
||||
struct T { signed char d; struct S e[25]; signed char f; };
|
||||
union U { struct T g; L h[10]; };
|
||||
const union U u = { { 1, { { 2, 3, 4 }, { 5, 6, 7 }, { 8, 9, 10 },
|
||||
{ 12, 13, 14 }, { 15, 16, 17 }, { 18, 19, 20 },
|
||||
{ 22, 23, 24 }, { 25, 26, 27 }, { 28, 29, 30 },
|
||||
{ 32, 33, 34 }, { 35, 36, 37 }, { 38, 39, 40 },
|
||||
{ 42, 43, 44 }, { 45, 46, 47 }, { 48, 49, 50 },
|
||||
{ 52, 53, 54 }, { 55, 56, 57 }, { 58, 59, 60 },
|
||||
{ 62, 63, 64 }, { 65, 66, 67 }, { 68, 69, 70 },
|
||||
{ 72, 73, 74 }, { 75, 76, 77 }, { 78, 79, 80 },
|
||||
{ 82, 83, 84 } }, 85 } };
|
||||
const union U v = { { 1, { { 2, 3, 4 }, [1 ... 23] = { 5, 6, 7 },
|
||||
{ 8, 9, 10 } }, 86 } };
|
||||
struct A { char a[5]; char b[16]; char c[7]; };
|
||||
union V { struct A d; unsigned int e[10]; };
|
||||
const union V w = { { "abcde", "ijkl", "mnopqr" } };
|
||||
#define N(n) __attribute__((noipa)) L foo##n (void) { return u.h[n]; }
|
||||
#define M N(0) N(1) N(2) N(3) N(4) N(5) N(6) N(7) N(8) N(9)
|
||||
M
|
||||
#undef N
|
||||
#define N(n) __attribute__((noipa)) L bar##n (void) { return v.h[n]; }
|
||||
M
|
||||
#undef N
|
||||
#define N(n) __attribute__((noipa)) L baz##n (void) { return w.e[n]; }
|
||||
M
|
||||
|
||||
typedef L (*F) (void);
|
||||
F arr[30] = {
|
||||
#undef N
|
||||
#define N(n) foo##n,
|
||||
M
|
||||
#undef N
|
||||
#define N(n) bar##n,
|
||||
M
|
||||
#undef N
|
||||
#define N(n) baz##n,
|
||||
M
|
||||
};
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
const union U *p = &u;
|
||||
const union U *q = &v;
|
||||
const union V *r = &w;
|
||||
__asm ("" : "+g" (p));
|
||||
__asm ("" : "+g" (q));
|
||||
__asm ("" : "+g" (r));
|
||||
for (int i = 0; i < 10; i++)
|
||||
if (arr[i] () != p->h[i]
|
||||
|| arr[i + 10] () != q->h[i]
|
||||
|| arr[i + 20] () != r->e[i])
|
||||
__builtin_abort ();
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue