diff mbox series

[PR87563,AARCH64-SVE] : Don't keep ifcvt loop when COND_<OP> ifn could not be vectorized.

Message ID 4bf6b224-f0ce-9a1b-adde-ba318cf13f9e@foss.arm.com
State New
Headers show
Series [PR87563,AARCH64-SVE] : Don't keep ifcvt loop when COND_<OP> ifn could not be vectorized. | expand

Commit Message

Renlin Li Oct. 12, 2018, 4:36 p.m. UTC
Hi all,

ifcvt will created versioned loop and it will permissively generate
scalar COND_<OP> ifn.

If in the loop vectorize pass, COND_<OP> could not get vectorized,
the if-converted loop should be abandoned when the target doesn't support
such ifn.

As currently, COND_<OP> is only used by aarch64 sve extension,
I only run the aarch64-sve testsuites, no change to the result.

Okay to commit?

Regards,
Renlin


gcc/ChangeLog:

2018-10-12  Renlin Li  <renlin.li@arm.com>

	PR target/87563
	* tree-vectorizer.c (try_vectorize_loop_1): Don't use
	if-conversioned loop when it contains ifn with types not
	supported by backend.
	* internal-fn.c (expand_direct_optab_fn): Add an assert.
	(direct_internal_fn_supported_p): New helper function.
	* internal-fn.h (direct_internal_fn_supported_p): Declare.

gcc/testsuite/ChangeLog:

2018-10-12  Renlin Li  <renlin.li@arm.com>

	PR target/87563
	* gcc.target/aarch64/sve/pr87563.c: New.

Comments

Richard Biener Oct. 15, 2018, 8:46 a.m. UTC | #1
On Fri, Oct 12, 2018 at 6:36 PM Renlin Li <renlin.li@foss.arm.com> wrote:
>
> Hi all,
>
> ifcvt will created versioned loop and it will permissively generate
> scalar COND_<OP> ifn.
>
> If in the loop vectorize pass, COND_<OP> could not get vectorized,
> the if-converted loop should be abandoned when the target doesn't support
> such ifn.
>
> As currently, COND_<OP> is only used by aarch64 sve extension,
> I only run the aarch64-sve testsuites, no change to the result.
>
> Okay to commit?

OK.

Richard.

> Regards,
> Renlin
>
>
> gcc/ChangeLog:
>
> 2018-10-12  Renlin Li  <renlin.li@arm.com>
>
>         PR target/87563
>         * tree-vectorizer.c (try_vectorize_loop_1): Don't use
>         if-conversioned loop when it contains ifn with types not
>         supported by backend.
>         * internal-fn.c (expand_direct_optab_fn): Add an assert.
>         (direct_internal_fn_supported_p): New helper function.
>         * internal-fn.h (direct_internal_fn_supported_p): Declare.
>
> gcc/testsuite/ChangeLog:
>
> 2018-10-12  Renlin Li  <renlin.li@arm.com>
>
>         PR target/87563
>         * gcc.target/aarch64/sve/pr87563.c: New.
diff mbox series

Patch

diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index 99765cf407acc7d65356b156e91f9dc51f1dba34..ff3bace1ce643ee10e1f776efffa01af31b6bbe7 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -187,6 +187,7 @@  extern bool direct_internal_fn_supported_p (internal_fn, tree_pair,
 					    optimization_type);
 extern bool direct_internal_fn_supported_p (internal_fn, tree,
 					    optimization_type);
+extern bool direct_internal_fn_supported_p (gcall *, optimization_type);
 
 /* Return true if FN is supported for types TYPE0 and TYPE1 when the
    optimization type is OPT_TYPE.  The types are those associated with
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 34d4f9efab9a45e0a9e3622f37dab0fa417b76f7..d082dd5054fa7175ffd3a53414b1ef42a1fca14e 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2890,6 +2890,7 @@  expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab,
 
   tree_pair types = direct_internal_fn_types (fn, stmt);
   insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
+  gcc_assert (icode != CODE_FOR_nothing);
 
   tree lhs = gimple_call_lhs (stmt);
   rtx lhs_rtx = NULL_RTX;
@@ -3183,6 +3184,17 @@  direct_internal_fn_supported_p (internal_fn fn, tree type,
   return direct_internal_fn_supported_p (fn, tree_pair (type, type), opt_type);
 }
 
+/* Return true if the STMT is supported when the optimization type is OPT_TYPE,
+   given that STMT is a call to a direct internal function.  */
+
+bool
+direct_internal_fn_supported_p (gcall *stmt, optimization_type opt_type)
+{
+  internal_fn fn = gimple_call_internal_fn (stmt);
+  tree_pair types = direct_internal_fn_types (fn, stmt);
+  return direct_internal_fn_supported_p (fn, types, opt_type);
+}
+
 /* If FN is commutative in two consecutive arguments, return the
    index of the first, otherwise return -1.  */
 
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr87563.c b/gcc/testsuite/gcc.target/aarch64/sve/pr87563.c
new file mode 100644
index 0000000000000000000000000000000000000000..83553b7ceea7199b5afb9f5adab50f15f9e41d55
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr87563.c
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-ifcvt-details -fdump-tree-vect" } */
+
+int a, b, c, *e;
+int d[2];
+
+void f ()
+{
+  while (c)
+    {
+      d[0] = 4;
+      d[1] = 4;
+      *e = b == 0 ? 0 : a / b;
+    }
+}
+
+/* { dg-final { scan-tree-dump "COND_DIV" "ifcvt" } } */
+/* { dg-final { scan-tree-dump-not "COND_DIV" "vect" } } */
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 747fb67ba13e80309377e66945a40f5e48f186c5..e70bd60493b22699b6873463281cc337a888f887 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -80,6 +80,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "attribs.h"
 #include "gimple-pretty-print.h"
 #include "opt-problem.h"
+#include "internal-fn.h"
 
 
 /* Loop or bb location, with hotness information.  */
@@ -898,23 +899,30 @@  try_vectorize_loop_1 (hash_table<simduid_to_vf> *&simduid_to_vf_htab,
 	  && ! loop->inner)
 	{
 	  basic_block bb = loop->header;
-	  bool has_mask_load_store = false;
+	  bool require_loop_vectorize = false;
 	  for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
 	       !gsi_end_p (gsi); gsi_next (&gsi))
 	    {
 	      gimple *stmt = gsi_stmt (gsi);
-	      if (is_gimple_call (stmt)
-		  && gimple_call_internal_p (stmt)
-		  && (gimple_call_internal_fn (stmt) == IFN_MASK_LOAD
-		      || gimple_call_internal_fn (stmt) == IFN_MASK_STORE))
+	      gcall *call = dyn_cast <gcall *> (stmt);
+	      if (call && gimple_call_internal_p (call))
 		{
-		  has_mask_load_store = true;
-		  break;
+		  internal_fn ifn = gimple_call_internal_fn (call);
+		  if (ifn == IFN_MASK_LOAD || ifn == IFN_MASK_STORE
+		      /* Don't keep the if-converted parts when the ifn with
+			 specifc type is not supported by the backend.  */
+		      || (direct_internal_fn_p (ifn)
+			  && !direct_internal_fn_supported_p
+			  (call, OPTIMIZE_FOR_SPEED)))
+		    {
+		      require_loop_vectorize = true;
+		      break;
+		    }
 		}
 	      gimple_set_uid (stmt, -1);
 	      gimple_set_visited (stmt, false);
 	    }
-	  if (! has_mask_load_store && vect_slp_bb (bb))
+	  if (!require_loop_vectorize && vect_slp_bb (bb))
 	    {
 	      dump_printf_loc (MSG_NOTE, vect_location,
 			       "basic block vectorized\n");