re PR middle-end/88963 (gcc generates terrible code for vectors of 64+ length which...
authorRichard Biener <rguenther@suse.de>
Fri, 3 May 2019 10:39:56 +0000 (10:39 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 3 May 2019 10:39:56 +0000 (10:39 +0000)
2019-05-03  Richard Biener  <rguenther@suse.de>

PR tree-optimization/88963
* tree-ssa-forwprop.c (pass_forwprop::execute): Rewrite
vector loads feeding only BIT_FIELD_REFs to component
loads.  Rewrite stores fed by CONSTRUCTORs to component
stores.

* gcc.dg/tree-ssa/ssa-fre-31.c: Disable forwprop.
* gcc.target/i386/pr88963-1.c: New testcase.
* gcc.target/i386/pr88963-2.c: Likewise.

From-SVN: r270844

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c
gcc/testsuite/gcc.target/i386/pr88963-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr88963-2.c [new file with mode: 0644]
gcc/tree-ssa-forwprop.c

index 346cb5f5ad626ecb909079037f448174fd9fa33f..80c34bea46695629a49eaa0813f0ac60ff549e93 100644 (file)
@@ -1,3 +1,11 @@
+2019-05-03  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/88963
+       * tree-ssa-forwprop.c (pass_forwprop::execute): Rewrite
+       vector loads feeding only BIT_FIELD_REFs to component
+       loads.  Rewrite stores fed by CONSTRUCTORs to component
+       stores.
+
 2019-05-03  Jakub Jelinek  <jakub@redhat.com>
 
        * opts.h (finish_options): Remove lang_mask argument.
index 2bb560964026ebd6987318304f17eb81b4f40ec3..57a07d167e55670534b02880bae74bdf25574a5d 100644 (file)
@@ -1,3 +1,10 @@
+2019-05-03  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/88963
+       * gcc.dg/tree-ssa/ssa-fre-31.c: Disable forwprop.
+       * gcc.target/i386/pr88963-1.c: New testcase.
+       * gcc.target/i386/pr88963-2.c: Likewise.
+
 2019-05-03  Dominique d'Humieres  <dominiq@gcc.gnu.org>
 
        PR target/88809
index 6402c81e6ca331f43fd2e64765de2d82a2d388fc..3d429ab1538f4dd55cbf3e2cc3604f0eea8dea05 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-fre1-details" } */
+/* { dg-options "-O -fdump-tree-fre1-details -fno-tree-forwprop" } */
 /* { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } */
 
 typedef double d128 __attribute__((vector_size(16)));
diff --git a/gcc/testsuite/gcc.target/i386/pr88963-1.c b/gcc/testsuite/gcc.target/i386/pr88963-1.c
new file mode 100644 (file)
index 0000000..e6f1525
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64 -mavx2 -fdump-tree-optimized" } */
+
+typedef int VInt __attribute__((vector_size(64)));
+
+void test(VInt*__restrict a, VInt*__restrict b, 
+         VInt*__restrict c)
+{
+  *a = *b + *c;
+}
+
+/* Vector loads and stores should be split.  */
+/* { dg-final { scan-tree-dump-not "vector\\(16\\)" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr88963-2.c b/gcc/testsuite/gcc.target/i386/pr88963-2.c
new file mode 100644 (file)
index 0000000..114f1f5
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64 -msse2 -fdump-tree-optimized" } */
+
+typedef int VInt __attribute__((vector_size(64)));
+
+void test(VInt*__restrict a, VInt*__restrict b, 
+         VInt*__restrict c)
+{
+  *a = *b + *c;
+}
+
+/* Vector loads and stores should be split.  */
+/* { dg-final { scan-tree-dump-not "vector\\(16\\)" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "vector\\(8\\)" "optimized" } } */
index bbfa1bc6fae1f62c5bd45f03187e05f26e3b5d8e..1553c9e70ac1fd51627f351f75ba2d5f01eb719a 100644 (file)
@@ -2400,6 +2400,72 @@ pass_forwprop::execute (function *fun)
              else
                gsi_next (&gsi);
            }
+         else if (TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE
+                  && TYPE_MODE (TREE_TYPE (lhs)) == BLKmode
+                  && gimple_assign_load_p (stmt)
+                  && !gimple_has_volatile_ops (stmt)
+                  && (TREE_CODE (gimple_assign_rhs1 (stmt))
+                      != TARGET_MEM_REF)
+                  && !stmt_can_throw_internal (cfun, stmt))
+           {
+             /* Rewrite loads used only in BIT_FIELD_REF extractions to
+                component-wise loads.  */
+             use_operand_p use_p;
+             imm_use_iterator iter;
+             bool rewrite = true;
+             FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
+               {
+                 gimple *use_stmt = USE_STMT (use_p);
+                 if (is_gimple_debug (use_stmt))
+                   continue;
+                 if (!is_gimple_assign (use_stmt)
+                     || gimple_assign_rhs_code (use_stmt) != BIT_FIELD_REF)
+                   {
+                     rewrite = false;
+                     break;
+                   }
+               }
+             if (rewrite)
+               {
+                 gimple *use_stmt;
+                 FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
+                   {
+                     if (is_gimple_debug (use_stmt))
+                       {
+                         if (gimple_debug_bind_p (use_stmt))
+                           {
+                             gimple_debug_bind_reset_value (use_stmt);
+                             update_stmt (use_stmt);
+                           }
+                         continue;
+                       }
+
+                     tree bfr = gimple_assign_rhs1 (use_stmt);
+                     tree new_rhs = fold_build3 (BIT_FIELD_REF,
+                                                 TREE_TYPE (bfr),
+                                                 unshare_expr (rhs),
+                                                 TREE_OPERAND (bfr, 1),
+                                                 TREE_OPERAND (bfr, 2));
+                     gimple *new_stmt
+                       = gimple_build_assign (gimple_assign_lhs (use_stmt),
+                                              new_rhs);
+
+                     location_t loc = gimple_location (use_stmt);
+                     gimple_set_location (new_stmt, loc);
+                     gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
+                     unlink_stmt_vdef (use_stmt);
+                     gsi_remove (&gsi2, true);
+
+                     gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
+                   }
+
+                 release_defs (stmt);
+                 gsi_remove (&gsi, true);
+               }
+             else
+               gsi_next (&gsi);
+           }
+
          else if (code == COMPLEX_EXPR)
            {
              /* Rewrite stores of a single-use complex build expression
@@ -2440,6 +2506,65 @@ pass_forwprop::execute (function *fun)
              else
                gsi_next (&gsi);
            }
+         else if (code == CONSTRUCTOR
+                  && VECTOR_TYPE_P (TREE_TYPE (rhs))
+                  && TYPE_MODE (TREE_TYPE (rhs)) == BLKmode
+                  && CONSTRUCTOR_NELTS (rhs) > 0
+                  && (!VECTOR_TYPE_P (TREE_TYPE (CONSTRUCTOR_ELT (rhs, 0)->value))
+                      || (TYPE_MODE (TREE_TYPE (CONSTRUCTOR_ELT (rhs, 0)->value))
+                          != BLKmode)))
+           {
+             /* Rewrite stores of a single-use vector constructors
+                to component-wise stores if the mode isn't supported.  */
+             use_operand_p use_p;
+             gimple *use_stmt;
+             if (single_imm_use (lhs, &use_p, &use_stmt)
+                 && gimple_store_p (use_stmt)
+                 && !gimple_has_volatile_ops (use_stmt)
+                 && is_gimple_assign (use_stmt)
+                 && (TREE_CODE (gimple_assign_lhs (use_stmt))
+                     != TARGET_MEM_REF))
+               {
+                 tree elt_t = TREE_TYPE (CONSTRUCTOR_ELT (rhs, 0)->value);
+                 unsigned HOST_WIDE_INT elt_w
+                   = tree_to_uhwi (TYPE_SIZE (elt_t));
+                 unsigned HOST_WIDE_INT n
+                   = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs)));
+                 for (unsigned HOST_WIDE_INT bi = 0; bi < n; bi += elt_w)
+                   {
+                     unsigned HOST_WIDE_INT ci = bi / elt_w;
+                     tree new_rhs;
+                     if (ci < CONSTRUCTOR_NELTS (rhs))
+                       new_rhs = CONSTRUCTOR_ELT (rhs, ci)->value;
+                     else
+                       new_rhs = build_zero_cst (elt_t);
+                     tree use_lhs = gimple_assign_lhs (use_stmt);
+                     tree new_lhs = build3 (BIT_FIELD_REF,
+                                            elt_t,
+                                            unshare_expr (use_lhs),
+                                            bitsize_int (elt_w),
+                                            bitsize_int (bi));
+                     gimple *new_stmt = gimple_build_assign (new_lhs, new_rhs);
+                     location_t loc = gimple_location (use_stmt);
+                     gimple_set_location (new_stmt, loc);
+                     gimple_set_vuse (new_stmt, gimple_vuse (use_stmt));
+                     gimple_set_vdef (new_stmt,
+                                      make_ssa_name (gimple_vop (cfun)));
+                     SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
+                     gimple_set_vuse (use_stmt, gimple_vdef (new_stmt));
+                     gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
+                     gsi_insert_before (&gsi2, new_stmt, GSI_SAME_STMT);
+                   }
+                 gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
+                 unlink_stmt_vdef (use_stmt);
+                 release_defs (use_stmt);
+                 gsi_remove (&gsi2, true);
+                 release_defs (stmt);
+                 gsi_remove (&gsi, true);
+               }
+             else
+               gsi_next (&gsi);
+           }
          else
            gsi_next (&gsi);
        }