Introduce can_vcond_compare_p function

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, but this does not say anything 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-10-07  Ilya Leoshkevich  <iii@linux.ibm.com>

	PR target/77918
	* optabs-tree.c (vcond_icode_p): New function.
	(vcond_eq_icode_p): Likewise.
	(expand_vec_cond_expr_p): Use vcond_icode_p and
	vcond_eq_icode_p.
	* optabs.c (can_vcond_compare_p): New function.
	* optabs.h (can_vcond_compare_p): Likewise.

From-SVN: r276660
This commit is contained in:
Ilya Leoshkevich 2019-10-07 15:01:15 +00:00 committed by Ilya Leoshkevich
parent 70e2a30ac8
commit dcd2ca63ec
4 changed files with 68 additions and 6 deletions

View File

@ -1,3 +1,13 @@
2019-10-07 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/77918
* optabs-tree.c (vcond_icode_p): New function.
(vcond_eq_icode_p): Likewise.
(expand_vec_cond_expr_p): Use vcond_icode_p and
vcond_eq_icode_p.
* optabs.c (can_vcond_compare_p): New function.
* optabs.h (can_vcond_compare_p): Likewise.
2019-10-07 Ilya Leoshkevich <iii@linux.ibm.com>
PR target/77918

View File

@ -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,31 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
return false;
}
/* 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 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_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 +375,13 @@ 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 (TREE_CODE_CLASS (code) != tcc_comparison)
/* 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

View File

@ -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.

View File

@ -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