Introduce can_vec_cmp_compare_p
This is the same asdcd2ca63ec("Introduce can_vcond_compare_p function"), but for vec_cmp. The reason it's needed is that since5d9ade39b8("IBM Z: Fix PR97326: Enable fp compares in vec_cmp") and4acba48590("IBM Z: Restrict vec_cmp<m><n> on z13") s390's vec_cmp expander advertises that it supports floating point comparisons except signaling ones on z13, but the common code ignores the latter restriction. gcc/ChangeLog: 2020-11-25 Ilya Leoshkevich <iii@linux.ibm.com> * optabs-tree.c (vec_cmp_icode_p): New function. (vec_cmp_eq_icode_p): New function. (expand_vec_cmp_expr_p): Use vec_cmp_icode_p and vec_cmp_eq_icode_p. (vcond_icode_p): Use get_rtx_code_1, just to be uniform with vec_cmp_icode_p. * optabs.c (unsigned_optab_p): New function. (insn_predicate_matches_p): New function. (can_vec_cmp_compare_p): New function. (can_vcond_compare_p): Use unsigned_optab_p and insn_predicate_matches_p. (get_rtx_code): Use get_rtx_code_1. (get_rtx_code_1): Version of get_rtx_code that returns UNKNOWN instead of asserting. * optabs.h (can_vec_cmp_compare_p): New function. (get_rtx_code_1): New function.
This commit is contained in:
parent
0fb378761f
commit
3940daff12
@ -337,6 +337,35 @@ supportable_convert_operation (enum tree_code code,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Return true iff vec_cmp_optab/vec_cmpu_optab can handle a vector comparison
|
||||
for code CODE, comparing operands of type VALUE_TYPE and producing a result
|
||||
of type MASK_TYPE. */
|
||||
|
||||
static bool
|
||||
vec_cmp_icode_p (tree value_type, tree mask_type, enum tree_code code)
|
||||
{
|
||||
enum rtx_code rcode = get_rtx_code_1 (code, TYPE_UNSIGNED (value_type));
|
||||
if (rcode == UNKNOWN)
|
||||
return false;
|
||||
|
||||
return can_vec_cmp_compare_p (rcode, TYPE_MODE (value_type),
|
||||
TYPE_MODE (mask_type));
|
||||
}
|
||||
|
||||
/* Return true iff vec_cmpeq_optab can handle a vector comparison for code
|
||||
CODE, comparing operands of type VALUE_TYPE and producing a result of type
|
||||
MASK_TYPE. */
|
||||
|
||||
static bool
|
||||
vec_cmp_eq_icode_p (tree value_type, tree mask_type, enum tree_code code)
|
||||
{
|
||||
if (code != EQ_EXPR && code != NE_EXPR)
|
||||
return false;
|
||||
|
||||
return get_vec_cmp_eq_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type))
|
||||
!= CODE_FOR_nothing;
|
||||
}
|
||||
|
||||
/* Return TRUE if appropriate vector insn is available
|
||||
for vector comparison expr with vector type VALUE_TYPE
|
||||
and resulting mask with MASK_TYPE. */
|
||||
@ -344,14 +373,8 @@ supportable_convert_operation (enum tree_code code,
|
||||
bool
|
||||
expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
|
||||
{
|
||||
if (get_vec_cmp_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type),
|
||||
TYPE_UNSIGNED (value_type)) != CODE_FOR_nothing)
|
||||
return true;
|
||||
if ((code == EQ_EXPR || code == NE_EXPR)
|
||||
&& (get_vec_cmp_eq_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type))
|
||||
!= CODE_FOR_nothing))
|
||||
return true;
|
||||
return false;
|
||||
return vec_cmp_icode_p (value_type, mask_type, code)
|
||||
|| vec_cmp_eq_icode_p (value_type, mask_type, code);
|
||||
}
|
||||
|
||||
/* Return true iff vcond_optab/vcondu_optab can handle a vector
|
||||
@ -361,8 +384,12 @@ expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
|
||||
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));
|
||||
enum rtx_code rcode = get_rtx_code_1 (code, TYPE_UNSIGNED (cmp_op_type));
|
||||
if (rcode == UNKNOWN)
|
||||
return false;
|
||||
|
||||
return can_vcond_compare_p (rcode, TYPE_MODE (value_type),
|
||||
TYPE_MODE (cmp_op_type));
|
||||
}
|
||||
|
||||
/* Return true iff vcondeq_optab can handle a vector comparison for code CODE,
|
||||
|
||||
76
gcc/optabs.c
76
gcc/optabs.c
@ -4057,23 +4057,59 @@ 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. */
|
||||
/* Return whether RTL code CODE corresponds to an unsigned optab. */
|
||||
|
||||
static bool
|
||||
unsigned_optab_p (enum rtx_code code)
|
||||
{
|
||||
return code == LTU || code == LEU || code == GTU || code == GEU;
|
||||
}
|
||||
|
||||
/* Return whether the backend-emitted comparison for code CODE, comparing
|
||||
operands of mode VALUE_MODE and producing a result with MASK_MODE, matches
|
||||
operand OPNO of pattern ICODE. */
|
||||
|
||||
static bool
|
||||
insn_predicate_matches_p (enum insn_code icode, unsigned int opno,
|
||||
enum rtx_code code, machine_mode mask_mode,
|
||||
machine_mode value_mode)
|
||||
{
|
||||
rtx reg1 = alloca_raw_REG (value_mode, LAST_VIRTUAL_REGISTER + 1);
|
||||
rtx reg2 = alloca_raw_REG (value_mode, LAST_VIRTUAL_REGISTER + 2);
|
||||
rtx test = alloca_rtx_fmt_ee (code, mask_mode, reg1, reg2);
|
||||
return insn_operand_matches (icode, opno, test);
|
||||
}
|
||||
|
||||
/* Return whether the backend can emit a vector comparison (vec_cmp/vec_cmpu)
|
||||
for code CODE, comparing operands of mode VALUE_MODE and producing a result
|
||||
with MASK_MODE. */
|
||||
|
||||
bool
|
||||
can_vec_cmp_compare_p (enum rtx_code code, machine_mode value_mode,
|
||||
machine_mode mask_mode)
|
||||
{
|
||||
enum insn_code icode
|
||||
= get_vec_cmp_icode (value_mode, mask_mode, unsigned_optab_p (code));
|
||||
if (icode == CODE_FOR_nothing)
|
||||
return false;
|
||||
|
||||
return insn_predicate_matches_p (icode, 1, code, mask_mode, value_mode);
|
||||
}
|
||||
|
||||
/* Return whether the backend can emit a vector comparison (vcond/vcondu) 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);
|
||||
enum insn_code icode
|
||||
= get_vcond_icode (value_mode, cmp_op_mode, unsigned_optab_p (code));
|
||||
if (icode == CODE_FOR_nothing)
|
||||
return false;
|
||||
|
||||
return (icode = get_vcond_icode (value_mode, cmp_op_mode, unsigned_p))
|
||||
!= CODE_FOR_nothing
|
||||
&& insn_operand_matches (icode, 3, test);
|
||||
return insn_predicate_matches_p (icode, 3, code, value_mode, cmp_op_mode);
|
||||
}
|
||||
|
||||
/* Return whether the backend can emit vector set instructions for inserting
|
||||
@ -5626,11 +5662,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
|
||||
/* Return rtx code for TCODE or UNKNOWN. Use UNSIGNEDP to select signed
|
||||
or unsigned operation code. */
|
||||
|
||||
enum rtx_code
|
||||
get_rtx_code (enum tree_code tcode, bool unsignedp)
|
||||
get_rtx_code_1 (enum tree_code tcode, bool unsignedp)
|
||||
{
|
||||
enum rtx_code code;
|
||||
switch (tcode)
|
||||
@ -5688,11 +5724,23 @@ get_rtx_code (enum tree_code tcode, bool unsignedp)
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
code = UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
/* Return rtx code for TCODE. Use UNSIGNEDP to select signed
|
||||
or unsigned operation code. */
|
||||
|
||||
enum rtx_code
|
||||
get_rtx_code (enum tree_code tcode, bool unsignedp)
|
||||
{
|
||||
enum rtx_code code = get_rtx_code_1 (tcode, unsignedp);
|
||||
gcc_assert (code != UNKNOWN);
|
||||
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
|
||||
|
||||
12
gcc/optabs.h
12
gcc/optabs.h
@ -244,9 +244,14 @@ enum can_compare_purpose
|
||||
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. */
|
||||
/* Return whether the backend can emit a vector comparison (vec_cmp/vec_cmpu)
|
||||
for code CODE, comparing operands of mode VALUE_MODE and producing a result
|
||||
with MASK_MODE. */
|
||||
extern bool can_vec_cmp_compare_p (enum rtx_code, machine_mode, machine_mode);
|
||||
|
||||
/* Return whether the backend can emit a vector comparison (vcond/vcondu) 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);
|
||||
|
||||
/* Return whether the backend can emit vector set instructions for inserting
|
||||
@ -366,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_1 (enum tree_code tcode, bool unsignedp);
|
||||
extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp);
|
||||
extern rtx vector_compare_rtx (machine_mode cmp_mode, enum tree_code tcode,
|
||||
tree t_op0, tree t_op1, bool unsignedp,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user