Ilya Leoshkevich <i...@linux.ibm.com> writes: >> Am 20.08.2019 um 12:13 schrieb Richard Sandiford <richard.sandif...@arm.com>: >> >> Ilya Leoshkevich <i...@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, which does not contain information about the >>> operation. >>> >>> Introduce a hook that tells whether target supports certain vector >>> comparison operations with certain modes. >>> >>> gcc/ChangeLog: >>> >>> 2019-08-09 Ilya Leoshkevich <i...@linux.ibm.com> >>> >>> * doc/tm.texi (TARGET_VCOND_SUPPORTED_P): Document. >>> * doc/tm.texi.in (TARGET_VCOND_SUPPORTED_P): Document. >>> * optabs-tree.c (expand_vec_cond_expr_p): Use vcond_supported_p >>> in addition to get_vcond_icode. >>> * target.def (vcond_supported_p): New hook. >>> * targhooks.c (default_vcond_supported_p): Likewise. >>> * targhooks.h (default_vcond_supported_p): Likewise. >> >> IMO it'd be cleaner to have a new optabs-query.[hc] helper that uses >> the predicate for operand 3 to test whether a particular comparison >> is supported. I guess this would require a cached rtx to avoid >> generating too much garbage rtl though (via GTY((cache))). > > How can I implement such a predicate? Would calling maybe_gen_insn with > a fake rtx be reasonable? In this case, what would be the best way to > generate fake input operands? The existing code that calls > maybe_gen_insn gets the corresponding rtxes from upper layers.
I was thinking of something like optabs.c:can_compare_p, but with some caching to reduce the overhead, and comparing registers rather than constants. E.g.: static rtx cached_binop GTY ((cached)); rtx get_cached_binop (machine_mode mode, rtx_code code, machine_mode op_mode) { ...create or modify cached_binop, with register operands...; return cached_binop; } /* ...maybe a different name if the overload seems like a bad idea... */ bool vcond_supported_p (machine_mode value_mode, rtx_code cmp, machine_mode cmp_op_mode) { bool unsigned = (cmp == LTU || cmp == LEU || cmp == GTU || cmp == GEU); insn_code icode = get_vcond_icode (value_mode, cmp_op_mode, unsigned); if (icode == CODE_FOR_nothing) return false; if (insn_operand_predicate_fn pred = insn_data[icode].operand[3].predicate) { machine_mode cmp_mode = insn_data[icode].operand[3].mode; rtx cmp = get_cached_binop (cmp_mode, cmp, cmp_op_mode); if (!pred (cmp, cmp_mode)) return false; } return true; } (not attached to the names). Then the target pattern would use a normal match_operator for operand 3, with the predicate on the match_operand only allowing through the comparisons it actually supports. The get_cached_binop stuff makes it a bit cumbersome, but that part would be reusable by other queries in future (and by can_compare_p probably). Thanks, Richard