This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH v3 3/9] Introduce can_vector_compare_p function
- From: Ilya Leoshkevich <iii at linux dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: richard dot guenther at gmail dot com, richard dot sandiford at arm dot com, segher at kernel dot crashing dot org, joseph at codesourcery dot com, krebbel at linux dot ibm dot com, rdapp at linux dot ibm dot com, Ilya Leoshkevich <iii at linux dot ibm dot com>
- Date: Thu, 5 Sep 2019 13:10:13 +0200
- Subject: [PATCH v3 3/9] Introduce can_vector_compare_p function
- References: <20190905111019.8951-1-iii@linux.ibm.com>
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_vector_compare_p): New function.
(get_rtx_code): Use get_rtx_code_safe.
(get_rtx_code_safe): New function.
* optabs.h (enum can_vector_compare_purpose): New enum.
(can_vector_compare_p): New function.
(get_rtx_code_safe): Likewise.
---
gcc/optabs-tree.c | 41 +++++++++++++++++++++++++++++++++--------
gcc/optabs.c | 43 +++++++++++++++++++++++++++++++++++++++----
gcc/optabs.h | 16 ++++++++++++++++
3 files changed, 88 insertions(+), 12 deletions(-)
diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
index 8157798cc71..ff7237187dd 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,34 @@ 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)
+{
+ enum rtx_code rcode = get_rtx_code_safe (code, TYPE_UNSIGNED (cmp_op_type));
+ if (rcode == 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 can_vector_compare_p (rcode, TYPE_MODE (value_type),
+ TYPE_MODE (cmp_op_type), cvcp_vcond);
+}
+
+/* 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 +378,8 @@ 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))
- 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 cdd07f3e53f..479789570a9 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -3819,6 +3819,30 @@ can_compare_p (enum rtx_code code, machine_mode mode,
return 0;
}
+/* Return whether back-end can emit a vector comparison insn(s) using a given
+ CODE, with operands with CMP_OP_MODE, producing a result with VALUE_MODE,
+ in order to achieve a PURPOSE. */
+
+bool
+can_vector_compare_p (enum rtx_code code, machine_mode value_mode,
+ machine_mode cmp_op_mode,
+ enum can_vector_compare_purpose purpose)
+{
+ 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);
+
+ if (purpose == cvcp_vcond
+ && (icode = get_vcond_icode (value_mode, cmp_op_mode, unsigned_p))
+ != CODE_FOR_nothing
+ && insn_operand_matches (icode, 3, test))
+ return true;
+
+ return false;
+}
+
/* 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 +5372,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 +5434,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..712470a0245 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -242,6 +242,21 @@ enum can_compare_purpose
(without splitting it into pieces). */
extern int can_compare_p (enum rtx_code, machine_mode,
enum can_compare_purpose);
+
+/* The various uses that a vector comparison can have; used by
+ can_vector_compare_p. So far only vcond is defined, vec_cmp is a possible
+ future extension. */
+enum can_vector_compare_purpose
+{
+ cvcp_vcond
+};
+
+/* Return whether back-end can emit a vector comparison insn(s) using a given
+ CODE, with operands with CMP_OP_MODE, producing a result with VALUE_MODE,
+ in order to achieve a PURPOSE. */
+extern bool can_vector_compare_p (enum rtx_code, machine_mode, machine_mode,
+ enum can_vector_compare_purpose);
+
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 +371,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 */
--
2.21.0