Hi!

If a load or store is in EH tables, but doesn't have EH edges out of it,
e.g. for must-not-throw regions, we weren't cleaning it up and adding
MASK_{LOAD,STORE} into EH region instead.
Similarly, the vectorizer needs to add the vectorized stmts to the same
EH region as the corresponding {,masked} load/store (second hunk).
The rest is just making the compiler more robust and not crash if DCE etc.
decides to remove the lhs of MASK_LOAD.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

P.S.: the patch doesn't fix the old issue that -fnon-call-exceptions
loads are never removed from the vectorized loops, stores aren't actually
removed when transforming the stmt, but later on and handling scalar loads
similarly (turning them into say assignments of zero) didn't look trivial.

2014-02-04  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/60023
        * tree-if-conv.c (predicate_mem_writes): Pass true instead of
        false to gsi_replace.
        * tree-vect-stmts.c (vect_finish_stmt_generation): If stmt
        has been in some EH region and vec_stmt could throw, add
        vec_stmt into the same EH region.
        * tree-data-ref.c (get_references_in_stmt): If IFN_MASK_LOAD
        has no lhs, ignore it.
        * internal-fn.c (expand_MASK_LOAD): Likewise.

        * g++.dg/vect/pr60023.cc: New test.

--- gcc/tree-if-conv.c.jj       2014-01-03 11:40:57.000000000 +0100
+++ gcc/tree-if-conv.c  2014-02-03 16:01:40.250716523 +0100
@@ -1723,7 +1723,7 @@ predicate_mem_writes (loop_p loop)
              new_stmt
                = gimple_build_call_internal (IFN_MASK_STORE, 4, addr, ptr,
                                              mask, rhs);
-           gsi_replace (&gsi, new_stmt, false);
+           gsi_replace (&gsi, new_stmt, true);
          }
        else if (gimple_vdef (stmt))
          {
--- gcc/tree-vect-stmts.c.jj    2014-01-16 20:54:59.000000000 +0100
+++ gcc/tree-vect-stmts.c       2014-02-03 16:29:00.881394627 +0100
@@ -1691,6 +1691,13 @@ vect_finish_stmt_generation (gimple stmt
     }
 
   gimple_set_location (vec_stmt, gimple_location (stmt));
+
+  /* While EH edges will generally prevent vectorization, stmt might
+     e.g. be in a must-not-throw region.  Ensure newly created stmts
+     that could throw are part of the same region.  */
+  int lp_nr = lookup_stmt_eh_lp (stmt);
+  if (lp_nr != 0 && stmt_could_throw_p (vec_stmt))
+    add_stmt_to_eh_lp (vec_stmt, lp_nr);
 }
 
 /* Checks if CALL can be vectorized in type VECTYPE.  Returns
--- gcc/tree-data-ref.c.jj      2014-01-03 11:40:57.000000000 +0100
+++ gcc/tree-data-ref.c 2014-02-03 16:05:42.111480787 +0100
@@ -4401,6 +4401,8 @@ get_references_in_stmt (gimple stmt, vec
        switch (gimple_call_internal_fn (stmt))
          {
          case IFN_MASK_LOAD:
+           if (gimple_call_lhs (stmt) == NULL_TREE)
+             break;
            ref.is_read = true;
          case IFN_MASK_STORE:
            ref.ref = fold_build2 (MEM_REF,
--- gcc/internal-fn.c.jj        2014-02-03 11:48:17.000000000 +0100
+++ gcc/internal-fn.c   2014-02-03 16:08:55.606492962 +0100
@@ -820,6 +820,8 @@ expand_MASK_LOAD (gimple stmt)
 
   maskt = gimple_call_arg (stmt, 2);
   lhs = gimple_call_lhs (stmt);
+  if (lhs == NULL_TREE)
+    return;
   type = TREE_TYPE (lhs);
   rhs = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0),
                     gimple_call_arg (stmt, 1));
--- gcc/testsuite/g++.dg/vect/pr60023.cc.jj     2014-02-03 16:39:17.996271473 
+0100
+++ gcc/testsuite/g++.dg/vect/pr60023.cc        2014-02-03 16:39:36.455176379 
+0100
@@ -0,0 +1,80 @@
+// PR tree-optimization/60023
+// { dg-do compile }
+// { dg-additional-options "-O3 -std=c++11 -fnon-call-exceptions" }
+// { dg-additional-options "-mavx2" { target { i?86-*-* x86_64-*-* } } }
+
+struct A { A (); ~A (); };
+
+void
+f1 (int *p, int *q, int *r) noexcept (true)
+{
+  int i;
+  for (i = 0; i < 1024; i++)
+    if (r[i])
+      p[i] = q[i] + 1;
+}
+
+void
+f2 (int *p, int *q, int *r)
+{
+  int i;
+  for (i = 0; i < 1024; i++)
+    if (r[i])
+      p[i] = q[i] + 1;
+}
+
+void
+f3 (int *p, int *q) noexcept (true)
+{
+  int i;
+  for (i = 0; i < 1024; i++)
+    p[i] = q[i] + 1;
+}
+
+void
+f4 (int *p, int *q)
+{
+  int i;
+  for (i = 0; i < 1024; i++)
+    p[i] = q[i] + 1;
+}
+
+void
+f5 (int *p, int *q, int *r) noexcept (true)
+{
+  int i;
+  A a;
+  for (i = 0; i < 1024; i++)
+    if (r[i])
+      p[i] = q[i] + 1;
+}
+
+void
+f6 (int *p, int *q, int *r)
+{
+  int i;
+  A a;
+  for (i = 0; i < 1024; i++)
+    if (r[i])
+      p[i] = q[i] + 1;
+}
+
+void
+f7 (int *p, int *q) noexcept (true)
+{
+  int i;
+  A a;
+  for (i = 0; i < 1024; i++)
+    p[i] = q[i] + 1;
+}
+
+void
+f8 (int *p, int *q)
+{
+  int i;
+  A a;
+  for (i = 0; i < 1024; i++)
+    p[i] = q[i] + 1;
+}
+
+// { dg-final { cleanup-tree-dump "vect" } }

        Jakub

Reply via email to