Re: [mask-load, patch 1/2] Use boolean predicate for masked loads and store
On Wed, Oct 28, 2015 at 4:23 PM, Ilya Enkovichwrote: > On 23 Oct 13:36, Ilya Enkovich wrote: >> 2015-10-23 13:32 GMT+03:00 Richard Biener : >> > >> > No, we'd get >> > >> > mask_1 = bool != 1; >> > >> > and the 'mask' variable should have been simplified to 'bool' >> > (yes, we'd insert a dead stmt). gimple_build simplifies >> > stmts via the match-and-simplify machinery and match.pd >> > knows how to invert conditions. >> > >> >> Thanks! I'll try it. >> >> Ilya > > Hi, > > Here is a new version. Changes you suggested cause BIT_NOT_EXPR used for > generated mask (instead of != 1 used before). It required a small fix to get > it vectorized to avoid regressions. Is this version OK? Ok. Thanks, Richard. > Thanks, > Ilya > -- > gcc/ > > 2015-10-28 Ilya Enkovich > > * internal-fn.c (expand_MASK_LOAD): Adjust to maskload optab changes. > (expand_MASK_STORE): Adjust to maskstore optab changes. > * optabs-query.c (can_vec_mask_load_store_p): Add MASK_MODE arg. > Adjust to maskload, maskstore optab changes. > * optabs-query.h (can_vec_mask_load_store_p): Add MASK_MODE arg. > * optabs.def (maskload_optab): Transform into convert optab. > (maskstore_optab): Likewise. > * tree-if-conv.c (ifcvt_can_use_mask_load_store): Adjust to > can_vec_mask_load_store_p signature change. > (predicate_mem_writes): Use boolean mask. > * tree-vect-stmts.c (vectorizable_mask_load_store): Adjust to > can_vec_mask_load_store_p signature change. Allow invariant masks. > (vectorizable_operation): Ignore type precision for boolean vectors. > > gcc/testsuite/ > > 2015-10-28 Ilya Enkovich > > * gcc.target/i386/avx2-vec-mask-bit-not.c: New test. > > > diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c > index f12d3af..2317e20 100644 > --- a/gcc/internal-fn.c > +++ b/gcc/internal-fn.c > @@ -1901,7 +1901,9 @@ expand_MASK_LOAD (gcall *stmt) >create_output_operand ([0], target, TYPE_MODE (type)); >create_fixed_operand ([1], mem); >create_input_operand ([2], mask, TYPE_MODE (TREE_TYPE (maskt))); > - expand_insn (optab_handler (maskload_optab, TYPE_MODE (type)), 3, ops); > + expand_insn (convert_optab_handler (maskload_optab, TYPE_MODE (type), > + TYPE_MODE (TREE_TYPE (maskt))), > + 3, ops); > } > > static void > @@ -1924,7 +1926,9 @@ expand_MASK_STORE (gcall *stmt) >create_fixed_operand ([0], mem); >create_input_operand ([1], reg, TYPE_MODE (type)); >create_input_operand ([2], mask, TYPE_MODE (TREE_TYPE (maskt))); > - expand_insn (optab_handler (maskstore_optab, TYPE_MODE (type)), 3, ops); > + expand_insn (convert_optab_handler (maskstore_optab, TYPE_MODE (type), > + TYPE_MODE (TREE_TYPE (maskt))), > + 3, ops); > } > > static void > diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c > index 254089f..c20597c 100644 > --- a/gcc/optabs-query.c > +++ b/gcc/optabs-query.c > @@ -466,7 +466,9 @@ can_mult_highpart_p (machine_mode mode, bool uns_p) > /* Return true if target supports vector masked load/store for mode. */ > > bool > -can_vec_mask_load_store_p (machine_mode mode, bool is_load) > +can_vec_mask_load_store_p (machine_mode mode, > + machine_mode mask_mode, > + bool is_load) > { >optab op = is_load ? maskload_optab : maskstore_optab; >machine_mode vmode; > @@ -474,7 +476,7 @@ can_vec_mask_load_store_p (machine_mode mode, bool > is_load) > >/* If mode is vector mode, check it directly. */ >if (VECTOR_MODE_P (mode)) > -return optab_handler (op, mode) != CODE_FOR_nothing; > +return convert_optab_handler (op, mode, mask_mode) != CODE_FOR_nothing; > >/* Otherwise, return true if there is some vector mode with > the mask load/store supported. */ > @@ -485,7 +487,12 @@ can_vec_mask_load_store_p (machine_mode mode, bool > is_load) >if (!VECTOR_MODE_P (vmode)) > return false; > > - if (optab_handler (op, vmode) != CODE_FOR_nothing) > + mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode), > + GET_MODE_SIZE (vmode)); > + if (mask_mode == VOIDmode) > +return false; > + > + if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) > return true; > >vector_sizes = targetm.vectorize.autovectorize_vector_sizes (); > @@ -496,8 +503,10 @@ can_vec_mask_load_store_p (machine_mode mode, bool > is_load) >if (cur <= GET_MODE_SIZE (mode)) > continue; >vmode = mode_for_vector (mode, cur / GET_MODE_SIZE (mode)); > + mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode), > + cur); >if (VECTOR_MODE_P (vmode) > - &&
Re: [mask-load, patch 1/2] Use boolean predicate for masked loads and store
On 23 Oct 13:36, Ilya Enkovich wrote: > 2015-10-23 13:32 GMT+03:00 Richard Biener: > > > > No, we'd get > > > > mask_1 = bool != 1; > > > > and the 'mask' variable should have been simplified to 'bool' > > (yes, we'd insert a dead stmt). gimple_build simplifies > > stmts via the match-and-simplify machinery and match.pd > > knows how to invert conditions. > > > > Thanks! I'll try it. > > Ilya Hi, Here is a new version. Changes you suggested cause BIT_NOT_EXPR used for generated mask (instead of != 1 used before). It required a small fix to get it vectorized to avoid regressions. Is this version OK? Thanks, Ilya -- gcc/ 2015-10-28 Ilya Enkovich * internal-fn.c (expand_MASK_LOAD): Adjust to maskload optab changes. (expand_MASK_STORE): Adjust to maskstore optab changes. * optabs-query.c (can_vec_mask_load_store_p): Add MASK_MODE arg. Adjust to maskload, maskstore optab changes. * optabs-query.h (can_vec_mask_load_store_p): Add MASK_MODE arg. * optabs.def (maskload_optab): Transform into convert optab. (maskstore_optab): Likewise. * tree-if-conv.c (ifcvt_can_use_mask_load_store): Adjust to can_vec_mask_load_store_p signature change. (predicate_mem_writes): Use boolean mask. * tree-vect-stmts.c (vectorizable_mask_load_store): Adjust to can_vec_mask_load_store_p signature change. Allow invariant masks. (vectorizable_operation): Ignore type precision for boolean vectors. gcc/testsuite/ 2015-10-28 Ilya Enkovich * gcc.target/i386/avx2-vec-mask-bit-not.c: New test. diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index f12d3af..2317e20 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -1901,7 +1901,9 @@ expand_MASK_LOAD (gcall *stmt) create_output_operand ([0], target, TYPE_MODE (type)); create_fixed_operand ([1], mem); create_input_operand ([2], mask, TYPE_MODE (TREE_TYPE (maskt))); - expand_insn (optab_handler (maskload_optab, TYPE_MODE (type)), 3, ops); + expand_insn (convert_optab_handler (maskload_optab, TYPE_MODE (type), + TYPE_MODE (TREE_TYPE (maskt))), + 3, ops); } static void @@ -1924,7 +1926,9 @@ expand_MASK_STORE (gcall *stmt) create_fixed_operand ([0], mem); create_input_operand ([1], reg, TYPE_MODE (type)); create_input_operand ([2], mask, TYPE_MODE (TREE_TYPE (maskt))); - expand_insn (optab_handler (maskstore_optab, TYPE_MODE (type)), 3, ops); + expand_insn (convert_optab_handler (maskstore_optab, TYPE_MODE (type), + TYPE_MODE (TREE_TYPE (maskt))), + 3, ops); } static void diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c index 254089f..c20597c 100644 --- a/gcc/optabs-query.c +++ b/gcc/optabs-query.c @@ -466,7 +466,9 @@ can_mult_highpart_p (machine_mode mode, bool uns_p) /* Return true if target supports vector masked load/store for mode. */ bool -can_vec_mask_load_store_p (machine_mode mode, bool is_load) +can_vec_mask_load_store_p (machine_mode mode, + machine_mode mask_mode, + bool is_load) { optab op = is_load ? maskload_optab : maskstore_optab; machine_mode vmode; @@ -474,7 +476,7 @@ can_vec_mask_load_store_p (machine_mode mode, bool is_load) /* If mode is vector mode, check it directly. */ if (VECTOR_MODE_P (mode)) -return optab_handler (op, mode) != CODE_FOR_nothing; +return convert_optab_handler (op, mode, mask_mode) != CODE_FOR_nothing; /* Otherwise, return true if there is some vector mode with the mask load/store supported. */ @@ -485,7 +487,12 @@ can_vec_mask_load_store_p (machine_mode mode, bool is_load) if (!VECTOR_MODE_P (vmode)) return false; - if (optab_handler (op, vmode) != CODE_FOR_nothing) + mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode), + GET_MODE_SIZE (vmode)); + if (mask_mode == VOIDmode) +return false; + + if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) return true; vector_sizes = targetm.vectorize.autovectorize_vector_sizes (); @@ -496,8 +503,10 @@ can_vec_mask_load_store_p (machine_mode mode, bool is_load) if (cur <= GET_MODE_SIZE (mode)) continue; vmode = mode_for_vector (mode, cur / GET_MODE_SIZE (mode)); + mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode), + cur); if (VECTOR_MODE_P (vmode) - && optab_handler (op, vmode) != CODE_FOR_nothing) + && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) return true; } return false; diff --git a/gcc/optabs-query.h b/gcc/optabs-query.h index 81ac362..162d2e9 100644 --- a/gcc/optabs-query.h +++ b/gcc/optabs-query.h @@ -140,7
Re: [mask-load, patch 1/2] Use boolean predicate for masked loads and store
On Thu, Oct 8, 2015 at 5:40 PM, Ilya Enkovichwrote: > Hi, > > This patch replaces integer mask argument for MASK_LOAD ans MASK_STORE calls > with a boolean one. To allow various boolean vector modes assigned by a > target maskload and maskstore optabs were transformed into convert_optab to > get mask mode as a second operand. Patch applies on top of boolean vector > patch series. > > Thanks, > Ilya > -- > gcc/ > > 2015-10-08 Ilya Enkovich > > * internal-fn.c (expand_MASK_LOAD): Adjust to maskload optab changes. > (expand_MASK_STORE): Adjust to maskstore optab changes. > * optabs-query.c (can_vec_mask_load_store_p): Add MASK_MODE arg. > Adjust to maskload, maskstore optab changes. > * optabs-query.h (can_vec_mask_load_store_p): Add MASK_MODE arg. > * optabs.def (maskload_optab): Transform into convert optab. > (maskstore_optab): Likewise. > * tree-if-conv.c (ifcvt_can_use_mask_load_store): Adjust to > can_vec_mask_load_store_p signature change. > (predicate_mem_writes): Use boolean mask. > * tree-vect-stmts.c (vectorizable_mask_load_store): Adjust to > can_vec_mask_load_store_p signature change. Allow invariant masks. > > > diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c > index 71f811c..5ea3c0d 100644 > --- a/gcc/internal-fn.c > +++ b/gcc/internal-fn.c > @@ -1885,7 +1885,9 @@ expand_MASK_LOAD (gcall *stmt) >create_output_operand ([0], target, TYPE_MODE (type)); >create_fixed_operand ([1], mem); >create_input_operand ([2], mask, TYPE_MODE (TREE_TYPE (maskt))); > - expand_insn (optab_handler (maskload_optab, TYPE_MODE (type)), 3, ops); > + expand_insn (convert_optab_handler (maskload_optab, TYPE_MODE (type), > + TYPE_MODE (TREE_TYPE (maskt))), > + 3, ops); > } > > static void > @@ -1908,7 +1910,9 @@ expand_MASK_STORE (gcall *stmt) >create_fixed_operand ([0], mem); >create_input_operand ([1], reg, TYPE_MODE (type)); >create_input_operand ([2], mask, TYPE_MODE (TREE_TYPE (maskt))); > - expand_insn (optab_handler (maskstore_optab, TYPE_MODE (type)), 3, ops); > + expand_insn (convert_optab_handler (maskstore_optab, TYPE_MODE (type), > + TYPE_MODE (TREE_TYPE (maskt))), > + 3, ops); > } > > static void > diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c > index 254089f..c20597c 100644 > --- a/gcc/optabs-query.c > +++ b/gcc/optabs-query.c > @@ -466,7 +466,9 @@ can_mult_highpart_p (machine_mode mode, bool uns_p) > /* Return true if target supports vector masked load/store for mode. */ > > bool > -can_vec_mask_load_store_p (machine_mode mode, bool is_load) > +can_vec_mask_load_store_p (machine_mode mode, > + machine_mode mask_mode, > + bool is_load) > { >optab op = is_load ? maskload_optab : maskstore_optab; >machine_mode vmode; > @@ -474,7 +476,7 @@ can_vec_mask_load_store_p (machine_mode mode, bool > is_load) > >/* If mode is vector mode, check it directly. */ >if (VECTOR_MODE_P (mode)) > -return optab_handler (op, mode) != CODE_FOR_nothing; > +return convert_optab_handler (op, mode, mask_mode) != CODE_FOR_nothing; > >/* Otherwise, return true if there is some vector mode with > the mask load/store supported. */ > @@ -485,7 +487,12 @@ can_vec_mask_load_store_p (machine_mode mode, bool > is_load) >if (!VECTOR_MODE_P (vmode)) > return false; > > - if (optab_handler (op, vmode) != CODE_FOR_nothing) > + mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode), > + GET_MODE_SIZE (vmode)); > + if (mask_mode == VOIDmode) > +return false; > + > + if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) > return true; > >vector_sizes = targetm.vectorize.autovectorize_vector_sizes (); > @@ -496,8 +503,10 @@ can_vec_mask_load_store_p (machine_mode mode, bool > is_load) >if (cur <= GET_MODE_SIZE (mode)) > continue; >vmode = mode_for_vector (mode, cur / GET_MODE_SIZE (mode)); > + mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode), > + cur); >if (VECTOR_MODE_P (vmode) > - && optab_handler (op, vmode) != CODE_FOR_nothing) > + && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) > return true; > } >return false; > diff --git a/gcc/optabs-query.h b/gcc/optabs-query.h > index 81ac362..162d2e9 100644 > --- a/gcc/optabs-query.h > +++ b/gcc/optabs-query.h > @@ -140,7 +140,7 @@ enum insn_code find_widening_optab_handler_and_mode > (optab, machine_mode, > machine_mode, int, > machine_mode *); > int
Re: [mask-load, patch 1/2] Use boolean predicate for masked loads and store
On Fri, Oct 23, 2015 at 12:23 PM, Ilya Enkovichwrote: > 2015-10-23 12:59 GMT+03:00 Richard Biener : >> >> ICK. So what does the above do? It basically preserves the boolean >> condition >> as "mask" unless ... we ought to swap it (formerly easy, just swap arguments >> of the cond_expr, now a bit harder, we need to invert the condition). But I >> don't understand the 'negate' dance. It looks like you want to have mask >> not be bool != 0 or bool == 1 but just bool in this case. I suggest you >> rework this to do sth like > > That's right, I want to avoid ==,!= comparisons with 0 and 1 by either > using compared SSA_NAME > or SSA_NAME != 0 (negate case). > >> >>gimple_seq stmts = NULL; >>gcc_assert (types_compatible_p (TREE_TYPE (cond), boolean_type_node)); > > Is it really valid assert? Compiling fortran test with LTO I may have > logical(kind=4) [aka 32bit boolean] > type for cond and single bit _Bool for boolean_type_node. I put it there to make sure it is because otherwise the use of boolean_type_node below needs adjustment (boolean_true_node as well). TREE_TYPE (cond) would work and constant_boolean_node (true, TREE_TYPE (cond)) for boolean_type_node. Yes, you are right. >>if (TREE_CODE (cond) == SSA_NAME) >> ; >>else if (COMPARISON_CLASS_P (cond)) >> mask = gimple_build (, TREE_CODE (cond), boolean_type_node, >> TREE_OPERAND (cond, 0), TREE_OPERAND (cond, 1)); >>else >> gcc_unreachable (); >>if (swap) >> mask = gimple_build (, BIT_XOR_EXPR, boolean_type_node, >> mask, boolean_true_node); >>gsi_insert_seq_before (, stmts, GSI_SAME_STMT); >> >> which should do all of the above. > > Thus we would get smth like > > mask_1 = bool != 1 > mask_2 = mask_1 XOR 1 > _ifc_ = mask_2 No, we'd get mask_1 = bool != 1; and the 'mask' variable should have been simplified to 'bool' (yes, we'd insert a dead stmt). gimple_build simplifies stmts via the match-and-simplify machinery and match.pd knows how to invert conditions. > instead of > > _ifc_ = bool > > Note that cond is built to be used as a condition in COND_EXPR > prepared for vectorization, i.e. it is always a comparison, thus > comparison with 0 and 1 is quite a common case. > > Thanks, > Ilya > >> >> The rest of the changes look good to me. >> >> Thanks, >> Richard. >> >>> /* Save mask and its size for further use. */ >>> vect_sizes.safe_push (bitsize); >>> vect_masks.safe_push (mask); >>> diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c >>> index 337ea7b..d6819ec 100644 >>> --- a/gcc/tree-vect-stmts.c >>> +++ b/gcc/tree-vect-stmts.c >>> @@ -1800,6 +1800,7 @@ vectorizable_mask_load_store (gimple *stmt, >>> gimple_stmt_iterator *gsi, >>>bool nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt); >>>struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info); >>>tree vectype = STMT_VINFO_VECTYPE (stmt_info); >>> + tree mask_vectype; >>>tree elem_type; >>>gimple *new_stmt; >>>tree dummy; >>> @@ -1827,8 +1828,8 @@ vectorizable_mask_load_store (gimple *stmt, >>> gimple_stmt_iterator *gsi, >>> >>>is_store = gimple_call_internal_fn (stmt) == IFN_MASK_STORE; >>>mask = gimple_call_arg (stmt, 2); >>> - if (TYPE_PRECISION (TREE_TYPE (mask)) >>> - != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (vectype >>> + >>> + if (TREE_CODE (TREE_TYPE (mask)) != BOOLEAN_TYPE) >>> return false; >>> >>>/* FORNOW. This restriction should be relaxed. */ >>> @@ -1857,6 +1858,19 @@ vectorizable_mask_load_store (gimple *stmt, >>> gimple_stmt_iterator *gsi, >>>if (STMT_VINFO_STRIDED_P (stmt_info)) >>> return false; >>> >>> + if (TREE_CODE (mask) != SSA_NAME) >>> +return false; >>> + >>> + if (!vect_is_simple_use_1 (mask, stmt, loop_vinfo, NULL, >>> +_stmt, , , _vectype)) >>> +return false; >>> + >>> + if (!mask_vectype) >>> +mask_vectype = get_mask_type_for_scalar_type (TREE_TYPE (vectype)); >>> + >>> + if (!mask_vectype) >>> +return false; >>> + >>>if (STMT_VINFO_GATHER_SCATTER_P (stmt_info)) >>> { >>>gimple *def_stmt; >>> @@ -1890,14 +1904,9 @@ vectorizable_mask_load_store (gimple *stmt, >>> gimple_stmt_iterator *gsi, >>> : DR_STEP (dr), size_zero_node) <= 0) >>> return false; >>>else if (!VECTOR_MODE_P (TYPE_MODE (vectype)) >>> - || !can_vec_mask_load_store_p (TYPE_MODE (vectype), !is_store)) >>> -return false; >>> - >>> - if (TREE_CODE (mask) != SSA_NAME) >>> -return false; >>> - >>> - if (!vect_is_simple_use (mask, stmt, loop_vinfo, NULL, >>> - _stmt, , )) >>> + || !can_vec_mask_load_store_p (TYPE_MODE (vectype), >>> + TYPE_MODE (mask_vectype), >>> + !is_store)) >>> return false; >>> >>>if (is_store)
Re: [mask-load, patch 1/2] Use boolean predicate for masked loads and store
2015-10-23 12:59 GMT+03:00 Richard Biener: > > ICK. So what does the above do? It basically preserves the boolean condition > as "mask" unless ... we ought to swap it (formerly easy, just swap arguments > of the cond_expr, now a bit harder, we need to invert the condition). But I > don't understand the 'negate' dance. It looks like you want to have mask > not be bool != 0 or bool == 1 but just bool in this case. I suggest you > rework this to do sth like That's right, I want to avoid ==,!= comparisons with 0 and 1 by either using compared SSA_NAME or SSA_NAME != 0 (negate case). > >gimple_seq stmts = NULL; >gcc_assert (types_compatible_p (TREE_TYPE (cond), boolean_type_node)); Is it really valid assert? Compiling fortran test with LTO I may have logical(kind=4) [aka 32bit boolean] type for cond and single bit _Bool for boolean_type_node. >if (TREE_CODE (cond) == SSA_NAME) > ; >else if (COMPARISON_CLASS_P (cond)) > mask = gimple_build (, TREE_CODE (cond), boolean_type_node, > TREE_OPERAND (cond, 0), TREE_OPERAND (cond, 1)); >else > gcc_unreachable (); >if (swap) > mask = gimple_build (, BIT_XOR_EXPR, boolean_type_node, > mask, boolean_true_node); >gsi_insert_seq_before (, stmts, GSI_SAME_STMT); > > which should do all of the above. Thus we would get smth like mask_1 = bool != 1 mask_2 = mask_1 XOR 1 _ifc_ = mask_2 instead of _ifc_ = bool Note that cond is built to be used as a condition in COND_EXPR prepared for vectorization, i.e. it is always a comparison, thus comparison with 0 and 1 is quite a common case. Thanks, Ilya > > The rest of the changes look good to me. > > Thanks, > Richard. > >> /* Save mask and its size for further use. */ >> vect_sizes.safe_push (bitsize); >> vect_masks.safe_push (mask); >> diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c >> index 337ea7b..d6819ec 100644 >> --- a/gcc/tree-vect-stmts.c >> +++ b/gcc/tree-vect-stmts.c >> @@ -1800,6 +1800,7 @@ vectorizable_mask_load_store (gimple *stmt, >> gimple_stmt_iterator *gsi, >>bool nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt); >>struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info); >>tree vectype = STMT_VINFO_VECTYPE (stmt_info); >> + tree mask_vectype; >>tree elem_type; >>gimple *new_stmt; >>tree dummy; >> @@ -1827,8 +1828,8 @@ vectorizable_mask_load_store (gimple *stmt, >> gimple_stmt_iterator *gsi, >> >>is_store = gimple_call_internal_fn (stmt) == IFN_MASK_STORE; >>mask = gimple_call_arg (stmt, 2); >> - if (TYPE_PRECISION (TREE_TYPE (mask)) >> - != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (vectype >> + >> + if (TREE_CODE (TREE_TYPE (mask)) != BOOLEAN_TYPE) >> return false; >> >>/* FORNOW. This restriction should be relaxed. */ >> @@ -1857,6 +1858,19 @@ vectorizable_mask_load_store (gimple *stmt, >> gimple_stmt_iterator *gsi, >>if (STMT_VINFO_STRIDED_P (stmt_info)) >> return false; >> >> + if (TREE_CODE (mask) != SSA_NAME) >> +return false; >> + >> + if (!vect_is_simple_use_1 (mask, stmt, loop_vinfo, NULL, >> +_stmt, , , _vectype)) >> +return false; >> + >> + if (!mask_vectype) >> +mask_vectype = get_mask_type_for_scalar_type (TREE_TYPE (vectype)); >> + >> + if (!mask_vectype) >> +return false; >> + >>if (STMT_VINFO_GATHER_SCATTER_P (stmt_info)) >> { >>gimple *def_stmt; >> @@ -1890,14 +1904,9 @@ vectorizable_mask_load_store (gimple *stmt, >> gimple_stmt_iterator *gsi, >> : DR_STEP (dr), size_zero_node) <= 0) >> return false; >>else if (!VECTOR_MODE_P (TYPE_MODE (vectype)) >> - || !can_vec_mask_load_store_p (TYPE_MODE (vectype), !is_store)) >> -return false; >> - >> - if (TREE_CODE (mask) != SSA_NAME) >> -return false; >> - >> - if (!vect_is_simple_use (mask, stmt, loop_vinfo, NULL, >> - _stmt, , )) >> + || !can_vec_mask_load_store_p (TYPE_MODE (vectype), >> + TYPE_MODE (mask_vectype), >> + !is_store)) >> return false; >> >>if (is_store)
Re: [mask-load, patch 1/2] Use boolean predicate for masked loads and store
2015-10-23 13:32 GMT+03:00 Richard Biener: > On Fri, Oct 23, 2015 at 12:23 PM, Ilya Enkovich > wrote: >> 2015-10-23 12:59 GMT+03:00 Richard Biener : >>> >>> ICK. So what does the above do? It basically preserves the boolean >>> condition >>> as "mask" unless ... we ought to swap it (formerly easy, just swap arguments >>> of the cond_expr, now a bit harder, we need to invert the condition). But I >>> don't understand the 'negate' dance. It looks like you want to have mask >>> not be bool != 0 or bool == 1 but just bool in this case. I suggest you >>> rework this to do sth like >> >> That's right, I want to avoid ==,!= comparisons with 0 and 1 by either >> using compared SSA_NAME >> or SSA_NAME != 0 (negate case). >> >>> >>>gimple_seq stmts = NULL; >>>gcc_assert (types_compatible_p (TREE_TYPE (cond), boolean_type_node)); >> >> Is it really valid assert? Compiling fortran test with LTO I may have >> logical(kind=4) [aka 32bit boolean] >> type for cond and single bit _Bool for boolean_type_node. > > I put it there to make sure it is because otherwise the use of > boolean_type_node > below needs adjustment (boolean_true_node as well). TREE_TYPE (cond) > would work and constant_boolean_node (true, TREE_TYPE (cond)) for > boolean_type_node. > > Yes, you are right. > >>>if (TREE_CODE (cond) == SSA_NAME) >>> ; >>>else if (COMPARISON_CLASS_P (cond)) >>> mask = gimple_build (, TREE_CODE (cond), boolean_type_node, >>> TREE_OPERAND (cond, 0), TREE_OPERAND (cond, 1)); >>>else >>> gcc_unreachable (); >>>if (swap) >>> mask = gimple_build (, BIT_XOR_EXPR, boolean_type_node, >>> mask, boolean_true_node); >>>gsi_insert_seq_before (, stmts, GSI_SAME_STMT); >>> >>> which should do all of the above. >> >> Thus we would get smth like >> >> mask_1 = bool != 1 >> mask_2 = mask_1 XOR 1 >> _ifc_ = mask_2 > > No, we'd get > > mask_1 = bool != 1; > > and the 'mask' variable should have been simplified to 'bool' > (yes, we'd insert a dead stmt). gimple_build simplifies > stmts via the match-and-simplify machinery and match.pd > knows how to invert conditions. > Thanks! I'll try it. Ilya
[mask-load, patch 1/2] Use boolean predicate for masked loads and store
Hi, This patch replaces integer mask argument for MASK_LOAD ans MASK_STORE calls with a boolean one. To allow various boolean vector modes assigned by a target maskload and maskstore optabs were transformed into convert_optab to get mask mode as a second operand. Patch applies on top of boolean vector patch series. Thanks, Ilya -- gcc/ 2015-10-08 Ilya Enkovich* internal-fn.c (expand_MASK_LOAD): Adjust to maskload optab changes. (expand_MASK_STORE): Adjust to maskstore optab changes. * optabs-query.c (can_vec_mask_load_store_p): Add MASK_MODE arg. Adjust to maskload, maskstore optab changes. * optabs-query.h (can_vec_mask_load_store_p): Add MASK_MODE arg. * optabs.def (maskload_optab): Transform into convert optab. (maskstore_optab): Likewise. * tree-if-conv.c (ifcvt_can_use_mask_load_store): Adjust to can_vec_mask_load_store_p signature change. (predicate_mem_writes): Use boolean mask. * tree-vect-stmts.c (vectorizable_mask_load_store): Adjust to can_vec_mask_load_store_p signature change. Allow invariant masks. diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index 71f811c..5ea3c0d 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -1885,7 +1885,9 @@ expand_MASK_LOAD (gcall *stmt) create_output_operand ([0], target, TYPE_MODE (type)); create_fixed_operand ([1], mem); create_input_operand ([2], mask, TYPE_MODE (TREE_TYPE (maskt))); - expand_insn (optab_handler (maskload_optab, TYPE_MODE (type)), 3, ops); + expand_insn (convert_optab_handler (maskload_optab, TYPE_MODE (type), + TYPE_MODE (TREE_TYPE (maskt))), + 3, ops); } static void @@ -1908,7 +1910,9 @@ expand_MASK_STORE (gcall *stmt) create_fixed_operand ([0], mem); create_input_operand ([1], reg, TYPE_MODE (type)); create_input_operand ([2], mask, TYPE_MODE (TREE_TYPE (maskt))); - expand_insn (optab_handler (maskstore_optab, TYPE_MODE (type)), 3, ops); + expand_insn (convert_optab_handler (maskstore_optab, TYPE_MODE (type), + TYPE_MODE (TREE_TYPE (maskt))), + 3, ops); } static void diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c index 254089f..c20597c 100644 --- a/gcc/optabs-query.c +++ b/gcc/optabs-query.c @@ -466,7 +466,9 @@ can_mult_highpart_p (machine_mode mode, bool uns_p) /* Return true if target supports vector masked load/store for mode. */ bool -can_vec_mask_load_store_p (machine_mode mode, bool is_load) +can_vec_mask_load_store_p (machine_mode mode, + machine_mode mask_mode, + bool is_load) { optab op = is_load ? maskload_optab : maskstore_optab; machine_mode vmode; @@ -474,7 +476,7 @@ can_vec_mask_load_store_p (machine_mode mode, bool is_load) /* If mode is vector mode, check it directly. */ if (VECTOR_MODE_P (mode)) -return optab_handler (op, mode) != CODE_FOR_nothing; +return convert_optab_handler (op, mode, mask_mode) != CODE_FOR_nothing; /* Otherwise, return true if there is some vector mode with the mask load/store supported. */ @@ -485,7 +487,12 @@ can_vec_mask_load_store_p (machine_mode mode, bool is_load) if (!VECTOR_MODE_P (vmode)) return false; - if (optab_handler (op, vmode) != CODE_FOR_nothing) + mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode), + GET_MODE_SIZE (vmode)); + if (mask_mode == VOIDmode) +return false; + + if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) return true; vector_sizes = targetm.vectorize.autovectorize_vector_sizes (); @@ -496,8 +503,10 @@ can_vec_mask_load_store_p (machine_mode mode, bool is_load) if (cur <= GET_MODE_SIZE (mode)) continue; vmode = mode_for_vector (mode, cur / GET_MODE_SIZE (mode)); + mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode), + cur); if (VECTOR_MODE_P (vmode) - && optab_handler (op, vmode) != CODE_FOR_nothing) + && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) return true; } return false; diff --git a/gcc/optabs-query.h b/gcc/optabs-query.h index 81ac362..162d2e9 100644 --- a/gcc/optabs-query.h +++ b/gcc/optabs-query.h @@ -140,7 +140,7 @@ enum insn_code find_widening_optab_handler_and_mode (optab, machine_mode, machine_mode, int, machine_mode *); int can_mult_highpart_p (machine_mode, bool); -bool can_vec_mask_load_store_p (machine_mode, bool); +bool can_vec_mask_load_store_p (machine_mode, machine_mode, bool); bool can_compare_and_swap_p (machine_mode, bool); bool can_atomic_exchange_p (machine_mode, bool); bool lshift_cheap_p (bool); diff --git