Hi,

as Juzhe noticed in gcc.dg/pr92301.c there was still something missing in
the last patch.  The attached v2 makes sure we always have a COND_LEN operation
before returning true and initializes len and bias even if they are unused.

Bootstrapped and regtested on aarch64 and x86.

Regards
 Robin

Subject: [PATCH v2] gimple-match: Do not try UNCOND optimization with
 COND_LEN.

On riscv we mis-optimize conditional (length) operations into
unconditional operations e.g. in slp-reduc-7.c and
gcc.dg/pr92301.c.

This patch prevents optimizing e.g.
 COND_LEN_ADD ({-1, ... }, a, 0, c, len, bias)
unconditionally into just "a".

Currently, we assume that COND_LEN operations can be optimized similarly
to COND operations.  As the length is part of the mask (and usually not
compile-time constant), we must not perform any optimization that relies
on just the mask being "true".  This patch ensures that we still have a
COND_LEN pattern after optimization.

gcc/ChangeLog:

        PR target/111311
        * gimple-match-exports.cc (maybe_resimplify_conditional_op):
        Check for length masking.
        (try_conditional_simplification): Check that the result is still
        length masked.
---
 gcc/gimple-match-exports.cc | 38 ++++++++++++++++++++++++++++++-------
 gcc/gimple-match.h          |  3 ++-
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/gcc/gimple-match-exports.cc b/gcc/gimple-match-exports.cc
index b36027b0bad..d41de98a3d3 100644
--- a/gcc/gimple-match-exports.cc
+++ b/gcc/gimple-match-exports.cc
@@ -262,7 +262,8 @@ maybe_resimplify_conditional_op (gimple_seq *seq, 
gimple_match_op *res_op,
   if (!res_op->cond.cond)
     return false;
 
-  if (!res_op->cond.else_value
+  if (!res_op->cond.len
+      && !res_op->cond.else_value
       && res_op->code.is_tree_code ())
     {
       /* The "else" value doesn't matter.  If the "then" value is a
@@ -301,9 +302,12 @@ maybe_resimplify_conditional_op (gimple_seq *seq, 
gimple_match_op *res_op,
 
   /* If the "then" value is a gimple value and the "else" value matters,
      create a VEC_COND_EXPR between them, then see if it can be further
-     simplified.  */
+     simplified.
+     Don't do this if we have a COND_LEN_ as that would make us lose the
+     length masking.  */
   gimple_match_op new_op;
-  if (res_op->cond.else_value
+  if (!res_op->cond.len
+      && res_op->cond.else_value
       && VECTOR_TYPE_P (res_op->type)
       && gimple_simplified_result_is_gimple_val (res_op))
     {
@@ -314,7 +318,7 @@ maybe_resimplify_conditional_op (gimple_seq *seq, 
gimple_match_op *res_op,
       return gimple_resimplify3 (seq, res_op, valueize);
     }
 
-  /* Otherwise try rewriting the operation as an IFN_COND_* call.
+  /* Otherwise try rewriting the operation as an IFN_COND_(LEN_)* call.
      Again, this isn't a simplification in itself, since it's what
      RES_OP already described.  */
   if (convert_conditional_op (res_op, &new_op))
@@ -386,9 +390,29 @@ try_conditional_simplification (internal_fn ifn, 
gimple_match_op *res_op,
     default:
       gcc_unreachable ();
     }
-  *res_op = cond_op;
-  maybe_resimplify_conditional_op (seq, res_op, valueize);
-  return true;
+
+  if (len)
+    {
+      /* If we had a COND_LEN before we need to ensure that it stays that
+        way.  */
+      gimple_match_op old_op = *res_op;
+      *res_op = cond_op;
+      maybe_resimplify_conditional_op (seq, res_op, valueize);
+
+      auto cfn = combined_fn (res_op->code);
+      if (internal_fn_p (cfn)
+         && internal_fn_len_index (as_internal_fn (cfn)) != -1)
+       return true;
+
+      *res_op = old_op;
+      return false;
+    }
+  else
+    {
+      *res_op = cond_op;
+      maybe_resimplify_conditional_op (seq, res_op, valueize);
+      return true;
+    }
 }
 
 /* Helper for the autogenerated code, valueize OP.  */
diff --git a/gcc/gimple-match.h b/gcc/gimple-match.h
index bec3ff42e3e..d192b7dae3e 100644
--- a/gcc/gimple-match.h
+++ b/gcc/gimple-match.h
@@ -56,7 +56,8 @@ public:
 
 inline
 gimple_match_cond::gimple_match_cond (tree cond_in, tree else_value_in)
-  : cond (cond_in), else_value (else_value_in)
+  : cond (cond_in), else_value (else_value_in), len (NULL_TREE),
+    bias (NULL_TREE)
 {
 }
 
-- 
2.41.0


Reply via email to