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...@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...@arm.com> PR target/87563 * gcc.target/aarch64/sve/pr87563.c: New.
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");