From d02a8b63e5aef49ab6973c64a2225236895763a1 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 7 Jan 2021 09:57:40 +0100 Subject: [PATCH] bswap: Fix up recent vector CONSTRUCTOR optimization [PR98568] As the testcase shows, bswap can match even byte-swapping or indentity from low part of some wider SSA_NAME. For bswap replacement other than for vector CONSTRUCTOR the code has been using NOP_EXPR casts if the types weren't compatible, but for vectors we need to use VIEW_CONVERT_EXPR. The problem with the latter is that we require that it has the same size, which isn't guaranteed, so this patch in those cases first adds a narrowing NOP_EXPR cast and only afterwards does a VIEW_CONVERT_EXPR. 2021-01-07 Jakub Jelinek PR tree-optimization/98568 * gimple-ssa-store-merging.c (bswap_view_convert): New function. (bswap_replace): Use it. * g++.dg/torture/pr98568.C: New test. --- gcc/gimple-ssa-store-merging.c | 25 ++++++++++++++--- gcc/testsuite/g++.dg/torture/pr98568.C | 37 ++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr98568.C diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index 4577647cbc6..f0f4a068de5 100644 --- a/gcc/gimple-ssa-store-merging.c +++ b/gcc/gimple-ssa-store-merging.c @@ -978,6 +978,25 @@ public: }; // class pass_optimize_bswap +/* Helper function for bswap_replace. Build VIEW_CONVERT_EXPR from + VAL to TYPE. If VAL has different type size, emit a NOP_EXPR cast + first. */ + +static tree +bswap_view_convert (gimple_stmt_iterator *gsi, tree type, tree val) +{ + gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (val))); + if (TYPE_SIZE (type) != TYPE_SIZE (TREE_TYPE (val))) + { + HOST_WIDE_INT prec = TREE_INT_CST_LOW (TYPE_SIZE (type)); + tree itype = build_nonstandard_integer_type (prec, 1); + gimple *g = gimple_build_assign (make_ssa_name (itype), NOP_EXPR, val); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + val = gimple_assign_lhs (g); + } + return build1 (VIEW_CONVERT_EXPR, type, val); +} + /* Perform the bswap optimization: replace the expression computed in the rhs of gsi_stmt (GSI) (or if NULL add instead of replace) by an equivalent bswap, load or load + bswap expression. @@ -1100,7 +1119,7 @@ bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl, gimple_set_vuse (load_stmt, n->vuse); gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT); if (conv_code == VIEW_CONVERT_EXPR) - val_tmp = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (tgt), val_tmp); + val_tmp = bswap_view_convert (&gsi, TREE_TYPE (tgt), val_tmp); gimple_assign_set_rhs_with_ops (&gsi, conv_code, val_tmp); update_stmt (cur_stmt); } @@ -1144,7 +1163,7 @@ bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl, if (!is_gimple_val (src)) return NULL_TREE; if (conv_code == VIEW_CONVERT_EXPR) - src = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (tgt), src); + src = bswap_view_convert (&gsi, TREE_TYPE (tgt), src); g = gimple_build_assign (tgt, conv_code, src); } else if (cur_stmt) @@ -1227,7 +1246,7 @@ bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl, tmp = make_temp_ssa_name (bswap_type, NULL, "bswapdst"); tree atmp = tmp; if (conv_code == VIEW_CONVERT_EXPR) - atmp = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (tgt), tmp); + atmp = bswap_view_convert (&gsi, TREE_TYPE (tgt), tmp); convert_stmt = gimple_build_assign (tgt, conv_code, atmp); gsi_insert_after (&gsi, convert_stmt, GSI_SAME_STMT); } diff --git a/gcc/testsuite/g++.dg/torture/pr98568.C b/gcc/testsuite/g++.dg/torture/pr98568.C new file mode 100644 index 00000000000..5c20223c783 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr98568.C @@ -0,0 +1,37 @@ +// PR tree-optimization/98568 +// { dg-do compile } + +char a[2]; +char b[4]; + +void +foo (int x) +{ + a[1] = x >> 8; + a[0] = x; +} + +void +bar (long long x) +{ + b[3] = x >> 24; + b[2] = x >> 16; + b[1] = x >> 8; + b[0] = x; +} + +void +baz (int x) +{ + a[0] = x >> 8; + a[1] = x; +} + +void +qux (long long x) +{ + b[0] = x >> 24; + b[1] = x >> 16; + b[2] = x >> 8; + b[3] = x; +} -- 2.30.2