Re: [mask-load, patch 1/2] Use boolean predicate for masked loads and store

2015-11-03 Thread Richard Biener
On Wed, Oct 28, 2015 at 4:23 PM, Ilya Enkovich  wrote:
> 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

2015-10-28 Thread Ilya Enkovich
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

2015-10-23 Thread Richard Biener
On Thu, Oct 8, 2015 at 5:40 PM, Ilya Enkovich  wrote:
> 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

2015-10-23 Thread 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.

> 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 Thread Ilya Enkovich
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 Thread Ilya Enkovich
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

2015-10-08 Thread Ilya Enkovich
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