[Bug tree-optimization/99728] code pessimization when using wrapper classes around SIMD types
rguenth at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Wed Jul 14 11:37:40 GMT 2021
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99728
--- Comment #18 from Richard Biener <rguenth at gcc dot gnu.org> ---
OTOH we call is_really_empty_class which for not trivially empty classes ends
up
walking all non-FIELD_DECL fields as well:
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL
&& !DECL_ARTIFICIAL (field)
/* An unnamed bit-field is not a data member. */
&& !DECL_UNNAMED_BIT_FIELD (field)
&& !is_really_empty_class (TREE_TYPE (field), ignore_vptr))
return false;
So the following performs single-member copying optimization (also avoiding
the as-base special-casing when the copy involves a single member). The
copy_single_member function is based on is_really_empty_class which could
be refactored to also compute this as alternate output. In principle the
single member to copy could be inside an aggregate member/base so as-is
this doesn't always avoid an aggregate copy if the single member in 'type'
is an aggregate. It fixes the testcase fully.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index e4df72ec1a3..31eea7c935b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8881,6 +8881,41 @@ immediate_invocation_p (tree fn, int nargs)
&& (nargs > 1 || !source_location_current_p (fn)));
}
+/* Return the FIELD_DECL of the single member of TYPE that needs to be copied
+ by copy assignment if any or NULL_TREE if there are none or multiple. */
+
+static tree
+copy_single_member (tree type)
+{
+ if (!CLASS_TYPE_P (type))
+ return NULL_TREE;
+
+ tree binfo;
+ tree base_binfo;
+ int i;
+ for (binfo = TYPE_BINFO (type), i = 0;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
+ if (!is_really_empty_class (BINFO_TYPE (base_binfo), true))
+ return NULL_TREE;
+
+ tree single_field = NULL_TREE;
+ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+ if (!(!DECL_ARTIFICIAL (field)
+ /* An unnamed bit-field is not a data member. */
+ && !DECL_UNNAMED_BIT_FIELD (field)
+ && !is_really_empty_class (TREE_TYPE (field), true)))
+ continue;
+ if (single_field)
+ return NULL_TREE;
+ single_field = field;
+ }
+
+ return single_field;
+}
+
/* Subroutine of the various build_*_call functions. Overload resolution
has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a
@@ -9501,6 +9536,16 @@ build_over_call (struct z_candidate *cand, int flags,
tsubst_flags_t complain)
val = build2 (COMPOUND_EXPR, type, arg, to);
suppress_warning (val, OPT_Wunused);
}
+ else if (tree field = copy_single_member (type))
+ {
+ arg = cp_build_fold_indirect_ref (arg);
+ tree t = build2 (MODIFY_EXPR, TREE_TYPE (field),
+ build3 (COMPONENT_REF, TREE_TYPE (field),
+ to, field, NULL_TREE),
+ build3 (COMPONENT_REF, TREE_TYPE (field),
+ arg, field, NULL_TREE));
+ val = build2 (COMPOUND_EXPR, type, t, to);
+ suppress_warning (val, OPT_Wunused);
+ }
else if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
{
if (is_std_init_list (type)
More information about the Gcc-bugs
mailing list