An issue with a backend patch I've been investigating has revealed
a missed optimization opportunity during GCC's vector lowering pass.
An unrecognized insn for "(set (reg:SI) (not:SI (const_int 0))"
revealed that not only was my expander not expecting a NOT with
a constant operand, but also that veclower was producing the
dubious tree expression ~0.

The attached patch replaces a call to gimple_build_assign with a
call to either gimplify_build1 or gimplify_build2 depending upon
whether the operation takes one or two operands.  The net effect
is that where GCC previously produced the following optimized
gimple for testsuite/c-c++common/Wunused-var-16.c (notice the ~0
and the "& 0"):

void foo ()
{
  V x;
  V y;
  vector(16) unsigned char _1;
  unsigned char _7;
  unsigned char _8;

  y_2 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  x_3 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  _7 = ~0;
  _1 = {_7, _7, _7, _7, _7, _7, _7, _7, _7, _7, _7, _7, _7, _7, _7, _7};
  _8 = 0 & _7;
  y_4 = {_8, _8, _8, _8, _8, _8, _8, _8, _8, _8, _8, _8, _8, _8, _8, _8};
  v = y_4;
  return;
}

With this patch we now generate:

void foo ()
{
  V x;
  V y;
  vector(16) unsigned char _1;

  y_2 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  x_3 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  _1 = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255 };
  y_4 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  v = y_4;
  return;
}

This patch has been tested on x86_64-pc-linux-gnu with "make bootstrap"
and "make -k check".

Ok for mainline?


2021-08-18  Roger Sayle  <ro...@nextmovesoftware.com>

gcc/ChangeLog
        * tree-vect-generic.c (expand_vector_operations_1): Use either
        gimplify_build1 or gimplify_build2 instead of gimple_build_assign
        when constructing scalar splat expressions.

gcc/testsuite/ChangeLog
        * c-c++common/Wununsed-var-16.c: Add extra check for that ~0
        is optimized away.

Roger
--

diff --git a/gcc/testsuite/c-c++-common/Wunused-var-16.c 
b/gcc/testsuite/c-c++-common/Wunused-var-16.c
index 8bdbcd3..31c7db3 100644
--- a/gcc/testsuite/c-c++-common/Wunused-var-16.c
+++ b/gcc/testsuite/c-c++-common/Wunused-var-16.c
@@ -1,6 +1,6 @@
 /* PR c++/78949 */
 /* { dg-do compile } */
-/* { dg-options "-Wunused" } */
+/* { dg-options "-Wunused -fdump-tree-optimized" } */
 /* { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } */
 
 typedef unsigned char V __attribute__((vector_size(16)));
@@ -14,3 +14,5 @@ foo ()
   y &= ~x;
   v = y;
 }
+
+/* { dg-final { scan-tree-dump-not " ~0" "optimized" } } */
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index 2e00b3e..0d7f041 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -2162,9 +2162,10 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi,
       if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
          && optab_handler (op, TYPE_MODE (TREE_TYPE (type))) != 
CODE_FOR_nothing)
        {
-         tree slhs = make_ssa_name (TREE_TYPE (TREE_TYPE (lhs)));
-         gimple *repl = gimple_build_assign (slhs, code, srhs1, srhs2);
-         gsi_insert_before (gsi, repl, GSI_SAME_STMT);
+         tree stype = TREE_TYPE (TREE_TYPE (lhs));
+         tree slhs = (rhs2 != NULL_TREE)
+                     ? gimplify_build2 (gsi, code, stype, srhs1, srhs2)
+                     : gimplify_build1 (gsi, code, stype, srhs1);
          gimple_assign_set_rhs_from_tree (gsi,
                                           build_vector_from_val (type, slhs));
          update_stmt (stmt);

Reply via email to