aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2020-01-10 22:18:22 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2020-01-10 22:18:22 +0100
commitea69031c5facc70e4a96df83cd58702900fd54b6 (patch)
tree879c6e151d192e9ac99c83999572027edc8d0517 /gcc/gimple-fold.c
parent974bb8a4dcbf51a153ab72da91a7256a296e7fa1 (diff)
downloadgcc-ea69031c5facc70e4a96df83cd58702900fd54b6.zip
gcc-ea69031c5facc70e4a96df83cd58702900fd54b6.tar.gz
gcc-ea69031c5facc70e4a96df83cd58702900fd54b6.tar.bz2
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
Diffstat (limited to 'gcc/gimple-fold.c')
-rw-r--r--gcc/gimple-fold.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index d7c5097..569f91e 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -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);
+
+ /* 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 fold_nonarray_ctor_reference (type, ctor, offset, size,
- from_decl, suboff);
+ 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;
}