diff mbox series

[v4,2/7] Introduce can_vcond_compare_p function

Message ID 20191001132709.87257-3-iii@linux.ibm.com
State New
Headers show
Series S/390: Use signaling FP comparison instructions | expand

Commit Message

Ilya Leoshkevich Oct. 1, 2019, 1:27 p.m. UTC
z13 supports only non-signaling vector comparisons.  This means we
cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13.
However, we cannot express this restriction today: the code only checks
whether vcond$a$b optab exists, which does not contain information about
the operation.

Introduce a function that checks whether back-end supports vector
comparisons with individual rtx codes by matching vcond expander's third
argument with a fake comparison with the corresponding rtx code.

gcc/ChangeLog:

2019-08-27  Ilya Leoshkevich  <iii@linux.ibm.com>

	PR target/77918
	* optabs-tree.c (vcond_icode_p): New function.
	(vcond_eq_icode_p): New function.
	(expand_vec_cond_expr_p): Use vcond_icode_p and
	vcond_eq_icode_p.
	* optabs.c (can_vcond_compare_p): New function.
	(get_rtx_code): Use get_rtx_code_safe.
	(get_rtx_code_safe): New function.
	* optabs.h (can_vcond_compare_p): New function.
	(get_rtx_code_safe): Likewise.
---
 gcc/optabs-tree.c | 37 +++++++++++++++++++++++++++++++------
 gcc/optabs.c      | 38 ++++++++++++++++++++++++++++++++++----
 gcc/optabs.h      |  7 +++++++
 3 files changed, 72 insertions(+), 10 deletions(-)

Comments

Richard Sandiford Oct. 3, 2019, 12:42 p.m. UTC | #1
Ilya Leoshkevich <iii@linux.ibm.com> writes:
> z13 supports only non-signaling vector comparisons.  This means we
> cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13.
> However, we cannot express this restriction today: the code only checks
> whether vcond$a$b optab exists, which does not contain information about
> the operation.
>
> Introduce a function that checks whether back-end supports vector
> comparisons with individual rtx codes by matching vcond expander's third
> argument with a fake comparison with the corresponding rtx code.
>
> gcc/ChangeLog:
>
> 2019-08-27  Ilya Leoshkevich  <iii@linux.ibm.com>
>
> 	PR target/77918
> 	* optabs-tree.c (vcond_icode_p): New function.
> 	(vcond_eq_icode_p): New function.
> 	(expand_vec_cond_expr_p): Use vcond_icode_p and
> 	vcond_eq_icode_p.
> 	* optabs.c (can_vcond_compare_p): New function.
> 	(get_rtx_code): Use get_rtx_code_safe.
> 	(get_rtx_code_safe): New function.
> 	* optabs.h (can_vcond_compare_p): New function.
> 	(get_rtx_code_safe): Likewise.
> ---
>  gcc/optabs-tree.c | 37 +++++++++++++++++++++++++++++++------
>  gcc/optabs.c      | 38 ++++++++++++++++++++++++++++++++++----
>  gcc/optabs.h      |  7 +++++++
>  3 files changed, 72 insertions(+), 10 deletions(-)
>
> diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
> index 8157798cc71..7f505c9cdee 100644
> --- a/gcc/optabs-tree.c
> +++ b/gcc/optabs-tree.c
> @@ -23,7 +23,10 @@ along with GCC; see the file COPYING3.  If not see
>  #include "coretypes.h"
>  #include "target.h"
>  #include "insn-codes.h"
> +#include "rtl.h"
>  #include "tree.h"
> +#include "memmodel.h"
> +#include "optabs.h"
>  #include "optabs-tree.h"
>  #include "stor-layout.h"
>  
> @@ -329,6 +332,28 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
>    return false;
>  }
>  
> +/* Return true iff vcond_optab/vcondu_optab support the given tree
> +   comparison.  */

Realise it's a bit repetitive in the context of this patch, but...

/* Return true iff vcond_optab/vcondu_optab can handle a vector
   comparison for code CODE, comparing operands of type CMP_OP_TYPE and
   producing a result of type VALUE_TYPE.  */

> +
> +static bool
> +vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
> +{
> +  return can_vcond_compare_p (get_rtx_code (code, TYPE_UNSIGNED (cmp_op_type)),
> +			      TYPE_MODE (value_type), TYPE_MODE (cmp_op_type));
> +}
> +
> +/* Return true iff vcondeq_optab supports the given tree comparison.  */

Same idea here.

> +
> +static bool
> +vcond_eq_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
> +{
> +  if (code != EQ_EXPR && code != NE_EXPR)
> +    return false;
> +
> +  return get_vcond_eq_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type))
> +	 != CODE_FOR_nothing;
> +}
> +
>  /* Return TRUE iff, appropriate vector insns are available
>     for vector cond expr with vector type VALUE_TYPE and a comparison
>     with operand vector types in CMP_OP_TYPE.  */
> @@ -347,14 +372,14 @@ expand_vec_cond_expr_p (tree value_type, tree cmp_op_type, enum tree_code code)
>        || maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode)))
>      return false;
>  
> -  if (get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
> -		       TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing
> -      && ((code != EQ_EXPR && code != NE_EXPR)
> -	  || get_vcond_eq_icode (TYPE_MODE (value_type),
> -				 TYPE_MODE (cmp_op_type)) == CODE_FOR_nothing))
> +  if (get_rtx_code_safe (code, TYPE_UNSIGNED (cmp_op_type))
> +      == LAST_AND_UNUSED_RTX_CODE)
> +    /* This may happen, for example, if code == SSA_NAME, in which case we
> +       cannot be certain whether a vector insn is available.  */
>      return false;

I think this should just be:

  if (TREE_CODE_CLASS (tcode) != tcc_comparison)
    return false;

OK with those changes and without the introduction of get_rtx_code_safe.

Thanks,
Richard
Ilya Leoshkevich Oct. 7, 2019, 3:04 p.m. UTC | #2
> Am 03.10.2019 um 14:42 schrieb Richard Sandiford <richard.sandiford@arm.com>:
> 
> Ilya Leoshkevich <iii@linux.ibm.com> writes:
>> z13 supports only non-signaling vector comparisons.  This means we
>> cannot vectorize LT, LE, GT, GE and LTGT when compiling for z13.
>> However, we cannot express this restriction today: the code only checks
>> whether vcond$a$b optab exists, which does not contain information about
>> the operation.
>> 
>> Introduce a function that checks whether back-end supports vector
>> comparisons with individual rtx codes by matching vcond expander's third
>> argument with a fake comparison with the corresponding rtx code.
>> 
>> gcc/ChangeLog:
>> 
>> 2019-08-27  Ilya Leoshkevich  <iii@linux.ibm.com>
>> 
>> 	PR target/77918
>> 	* optabs-tree.c (vcond_icode_p): New function.
>> 	(vcond_eq_icode_p): New function.
>> 	(expand_vec_cond_expr_p): Use vcond_icode_p and
>> 	vcond_eq_icode_p.
>> 	* optabs.c (can_vcond_compare_p): New function.
>> 	(get_rtx_code): Use get_rtx_code_safe.
>> 	(get_rtx_code_safe): New function.
>> 	* optabs.h (can_vcond_compare_p): New function.
>> 	(get_rtx_code_safe): Likewise.
>> ---
>> gcc/optabs-tree.c | 37 +++++++++++++++++++++++++++++++------
>> gcc/optabs.c      | 38 ++++++++++++++++++++++++++++++++++----
>> gcc/optabs.h      |  7 +++++++
>> 3 files changed, 72 insertions(+), 10 deletions(-)
>> 
>> diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
>> index 8157798cc71..7f505c9cdee 100644
>> --- a/gcc/optabs-tree.c
>> +++ b/gcc/optabs-tree.c
>> @@ -23,7 +23,10 @@ along with GCC; see the file COPYING3.  If not see
>> #include "coretypes.h"
>> #include "target.h"
>> #include "insn-codes.h"
>> +#include "rtl.h"
>> #include "tree.h"
>> +#include "memmodel.h"
>> +#include "optabs.h"
>> #include "optabs-tree.h"
>> #include "stor-layout.h"
>> 
>> @@ -329,6 +332,28 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
>>   return false;
>> }
>> 
>> +/* Return true iff vcond_optab/vcondu_optab support the given tree
>> +   comparison.  */
> 
> Realise it's a bit repetitive in the context of this patch, but...
> 
> /* Return true iff vcond_optab/vcondu_optab can handle a vector
>   comparison for code CODE, comparing operands of type CMP_OP_TYPE and
>   producing a result of type VALUE_TYPE.  */
> 
>> +
>> +static bool
>> +vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
>> +{
>> +  return can_vcond_compare_p (get_rtx_code (code, TYPE_UNSIGNED (cmp_op_type)),
>> +			      TYPE_MODE (value_type), TYPE_MODE (cmp_op_type));
>> +}
>> +
>> +/* Return true iff vcondeq_optab supports the given tree comparison.  */
> 
> Same idea here.
> 
>> +
>> +static bool
>> +vcond_eq_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
>> +{
>> +  if (code != EQ_EXPR && code != NE_EXPR)
>> +    return false;
>> +
>> +  return get_vcond_eq_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type))
>> +	 != CODE_FOR_nothing;
>> +}
>> +
>> /* Return TRUE iff, appropriate vector insns are available
>>    for vector cond expr with vector type VALUE_TYPE and a comparison
>>    with operand vector types in CMP_OP_TYPE.  */
>> @@ -347,14 +372,14 @@ expand_vec_cond_expr_p (tree value_type, tree cmp_op_type, enum tree_code code)
>>       || maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode)))
>>     return false;
>> 
>> -  if (get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
>> -		       TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing
>> -      && ((code != EQ_EXPR && code != NE_EXPR)
>> -	  || get_vcond_eq_icode (TYPE_MODE (value_type),
>> -				 TYPE_MODE (cmp_op_type)) == CODE_FOR_nothing))
>> +  if (get_rtx_code_safe (code, TYPE_UNSIGNED (cmp_op_type))
>> +      == LAST_AND_UNUSED_RTX_CODE)
>> +    /* This may happen, for example, if code == SSA_NAME, in which case we
>> +       cannot be certain whether a vector insn is available.  */
>>     return false;
> 
> I think this should just be:
> 
>  if (TREE_CODE_CLASS (tcode) != tcc_comparison)
>    return false;
> 
> OK with those changes and without the introduction of get_rtx_code_safe.

Thanks! I've made the changes, retested, and committed the result as
https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=276660
alongside
https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=276659
which Richard B. has approved as well.

Now only the main S/390 bits remain..

Best regards,
Ilya
diff mbox series

Patch

diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
index 8157798cc71..7f505c9cdee 100644
--- a/gcc/optabs-tree.c
+++ b/gcc/optabs-tree.c
@@ -23,7 +23,10 @@  along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "target.h"
 #include "insn-codes.h"
+#include "rtl.h"
 #include "tree.h"
+#include "memmodel.h"
+#include "optabs.h"
 #include "optabs-tree.h"
 #include "stor-layout.h"
 
@@ -329,6 +332,28 @@  expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
   return false;
 }
 
+/* Return true iff vcond_optab/vcondu_optab support the given tree
+   comparison.  */
+
+static bool
+vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
+{
+  return can_vcond_compare_p (get_rtx_code (code, TYPE_UNSIGNED (cmp_op_type)),
+			      TYPE_MODE (value_type), TYPE_MODE (cmp_op_type));
+}
+
+/* Return true iff vcondeq_optab supports the given tree comparison.  */
+
+static bool
+vcond_eq_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
+{
+  if (code != EQ_EXPR && code != NE_EXPR)
+    return false;
+
+  return get_vcond_eq_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type))
+	 != CODE_FOR_nothing;
+}
+
 /* Return TRUE iff, appropriate vector insns are available
    for vector cond expr with vector type VALUE_TYPE and a comparison
    with operand vector types in CMP_OP_TYPE.  */
@@ -347,14 +372,14 @@  expand_vec_cond_expr_p (tree value_type, tree cmp_op_type, enum tree_code code)
       || maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode)))
     return false;
 
-  if (get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
-		       TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing
-      && ((code != EQ_EXPR && code != NE_EXPR)
-	  || get_vcond_eq_icode (TYPE_MODE (value_type),
-				 TYPE_MODE (cmp_op_type)) == CODE_FOR_nothing))
+  if (get_rtx_code_safe (code, TYPE_UNSIGNED (cmp_op_type))
+      == LAST_AND_UNUSED_RTX_CODE)
+    /* This may happen, for example, if code == SSA_NAME, in which case we
+       cannot be certain whether a vector insn is available.  */
     return false;
 
-  return true;
+  return vcond_icode_p (value_type, cmp_op_type, code)
+	 || vcond_eq_icode_p (value_type, cmp_op_type, code);
 }
 
 /* Use the current target and options to initialize
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 35921e691f9..d759449846e 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -3819,6 +3819,25 @@  can_compare_p (enum rtx_code code, machine_mode mode,
   return 0;
 }
 
+/* Return whether the backend can emit a vector comparison for code CODE,
+   comparing operands of mode CMP_OP_MODE and producing a result with
+   VALUE_MODE.  */
+
+bool
+can_vcond_compare_p (enum rtx_code code, machine_mode value_mode,
+		     machine_mode cmp_op_mode)
+{
+  enum insn_code icode;
+  bool unsigned_p = (code == LTU || code == LEU || code == GTU || code == GEU);
+  rtx reg1 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 1);
+  rtx reg2 = alloca_raw_REG (cmp_op_mode, LAST_VIRTUAL_REGISTER + 2);
+  rtx test = alloca_rtx_fmt_ee (code, value_mode, reg1, reg2);
+
+  return (icode = get_vcond_icode (value_mode, cmp_op_mode, unsigned_p))
+	 != CODE_FOR_nothing
+	 && insn_operand_matches (icode, 3, test);
+}
+
 /* This function is called when we are going to emit a compare instruction that
    compares the values found in X and Y, using the rtl operator COMPARISON.
 
@@ -5348,11 +5367,11 @@  gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode)
   return insn;
 }
 
-/* Return rtx code for TCODE. Use UNSIGNEDP to select signed
-   or unsigned operation code.  */
+/* Return rtx code for TCODE or LAST_AND_UNUSED_RTX_CODE if it has no RTL
+   counterpart.  Use UNSIGNEDP to select signed or unsigned operation code.  */
 
 enum rtx_code
-get_rtx_code (enum tree_code tcode, bool unsignedp)
+get_rtx_code_safe (enum tree_code tcode, bool unsignedp)
 {
   enum rtx_code code;
   switch (tcode)
@@ -5410,11 +5429,22 @@  get_rtx_code (enum tree_code tcode, bool unsignedp)
       break;
 
     default:
-      gcc_unreachable ();
+      code = LAST_AND_UNUSED_RTX_CODE;
+      break;
     }
   return code;
 }
 
+/* Like get_rtx_code_safe, but asserts when given unsupported tree codes.  */
+
+enum rtx_code
+get_rtx_code (enum tree_code tcode, bool unsignedp)
+{
+  enum rtx_code code = get_rtx_code_safe (tcode, unsignedp);
+  gcc_assert (code != LAST_AND_UNUSED_RTX_CODE);
+  return code;
+}
+
 /* Return a comparison rtx of mode CMP_MODE for COND.  Use UNSIGNEDP to
    select signed or unsigned operators.  OPNO holds the index of the
    first comparison operand for insn ICODE.  Do not generate the
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 897bb5d4443..4cebe231191 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -242,6 +242,12 @@  enum can_compare_purpose
    (without splitting it into pieces).  */
 extern int can_compare_p (enum rtx_code, machine_mode,
 			  enum can_compare_purpose);
+
+/* Return whether the backend can emit a vector comparison for code CODE,
+   comparing operands of mode CMP_OP_MODE and producing a result with
+   VALUE_MODE.  */
+extern bool can_vcond_compare_p (enum rtx_code, machine_mode, machine_mode);
+
 extern rtx prepare_operand (enum insn_code, rtx, int, machine_mode,
 			    machine_mode, int);
 /* Emit a pair of rtl insns to compare two rtx's and to jump
@@ -356,6 +362,7 @@  extern void expand_insn (enum insn_code icode, unsigned int nops,
 extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
 			      class expand_operand *ops);
 
+extern enum rtx_code get_rtx_code_safe (enum tree_code tcode, bool unsignedp);
 extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp);
 
 #endif /* GCC_OPTABS_H */