> But that's what types_compatible_p checks.  What I'd change is to only
> verify this if else_value, not when that was determined by the
> preferred else value hook.


The below has been regtested and bootstrapped on x86, power10, aarch64.  
Regtested on riscv64.

Regards
 Robin


[PATCH v2] match: Check else value compatibility [PR123268].

In PR123268 we transform x * { 0 or 1, 0 or 1, ... } into
x & { 0 or -1, 0 or -1, ...} which is a match.pd pattern.

We start out with
  vect_b_28.48_48 = .COND_LEN_MUL ({ -1, -1, -1, -1 }, a, b, { 0.0, 0.0, 0.0, 
0.0 }, 4, 0);
and simplify to

_67 = .COND_LEN_AND ({ -1, -1, -1, -1 }, _60, { 4294967295, 0, 0, 0 }, { 0.0, 
0.0, 0.0, 0.0 }, 4, 0);

where the operation type is int but the else value (that we just copied
over from the original op) is still float.

In order to catch that, this patch checks if the operation type and the
else value type are compatible while reassembling the conditional
operation.

gcc/ChangeLog:

        * gimple-match-exports.cc (convert_conditional_op): Check if
        orig_op->type and type of else value match.
---
 gcc/gimple-match-exports.cc | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/gcc/gimple-match-exports.cc b/gcc/gimple-match-exports.cc
index 555e8a967a0..cdd9ae552e2 100644
--- a/gcc/gimple-match-exports.cc
+++ b/gcc/gimple-match-exports.cc
@@ -184,6 +184,13 @@ convert_conditional_op (gimple_match_op *orig_op,
   for (unsigned int i = 0; i < num_ops; ++i)
     new_op->ops[i + 1] = orig_op->ops[i];
   tree else_value = orig_op->cond.else_value;
+  /* Some patterns convert operand types, e.g. from float to int.
+     If we had a real else value before (e.g. float) it won't match
+     the type.  Verify that here.  */
+  if (else_value
+      && !types_compatible_p (orig_op->type, TREE_TYPE (else_value)))
+    return false;
+
   if (!else_value)
     else_value = targetm.preferred_else_value (ifn, orig_op->type,
                                               num_ops, orig_op->ops);
-- 
2.52.0

Reply via email to