Hi,

As PR115659 shows, assuming c = x CMP y, there are some
folding chances for patterns r = c ? -1/z : z/0.

For r = c ? -1 : z, it can be folded into:
  - r = c | z (with ior_optab supported)
  - or r = c ? c : z

while for r = c ?  z : 0, it can be foled into:
  - r = c & z (with and_optab supported)
  - or r = c ? z : c

This patch is to teach ISEL to take care of them and also
remove the redundant gsi_replace as the caller of function
gimple_expand_vec_cond_expr will handle it.

Bootstrapped and regtested on x86_64-redhat-linux and
powerpc64{,le}-linux-gnu.

Is it ok for trunk?

BR,
Kewen
-----
        PR tree-optimization/115659

gcc/ChangeLog:

        * gimple-isel.cc (gimple_expand_vec_cond_expr): Add more foldings for
        patterns x CMP y ? -1 : z and x CMP y ? z : 0.
---
 gcc/gimple-isel.cc | 48 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 41 insertions(+), 7 deletions(-)

diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc
index 54c1801038b..71af1a8cd97 100644
--- a/gcc/gimple-isel.cc
+++ b/gcc/gimple-isel.cc
@@ -240,16 +240,50 @@ gimple_expand_vec_cond_expr (struct function *fun, 
gimple_stmt_iterator *gsi,
            can_compute_op0 = expand_vec_cmp_expr_p (op0a_type, op0_type,
                                                     tcode);

-         /* Try to fold x CMP y ? -1 : 0 to x CMP y.  */
          if (can_compute_op0
-             && integer_minus_onep (op1)
-             && integer_zerop (op2)
              && TYPE_MODE (TREE_TYPE (lhs)) == TYPE_MODE (TREE_TYPE (op0)))
            {
-             tree conv_op = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), op0);
-             gassign *new_stmt = gimple_build_assign (lhs, conv_op);
-             gsi_replace (gsi, new_stmt, true);
-             return new_stmt;
+             /* Assuming c = x CMP y.  */
+             bool op1_minus_onep = integer_minus_onep (op1);
+             bool op2_zerop = integer_zerop (op2);
+             tree vtype = TREE_TYPE (lhs);
+             machine_mode vmode = TYPE_MODE (vtype);
+             /* Try to fold r = c ? -1 : 0 to r = c.  */
+             if (op1_minus_onep && op2_zerop)
+               {
+                 tree conv_op = build1 (VIEW_CONVERT_EXPR, vtype, op0);
+                 return gimple_build_assign (lhs, conv_op);
+               }
+             /* Try to fold r = c ? -1 : z to r = c | z, or
+                r = c ? c : z.  */
+             if (op1_minus_onep)
+               {
+                 tree conv_op = build1 (VIEW_CONVERT_EXPR, vtype, op0);
+                 tree new_op0 = make_ssa_name (vtype);
+                 gassign *new_stmt = gimple_build_assign (new_op0, conv_op);
+                 gsi_insert_seq_before (gsi, new_stmt, GSI_SAME_STMT);
+                 if (optab_handler (ior_optab, vmode) != CODE_FOR_nothing)
+                   /* r = c | z */
+                   return gimple_build_assign (lhs, BIT_IOR_EXPR, new_op0,
+                                               op2);
+                 /* r = c ? c : z */
+                 op1 = new_op0;
+               }
+             /* Try to fold r = c ? z : 0 to r = c & z, or
+                r = c ? z : c.  */
+             else if (op2_zerop)
+               {
+                 tree conv_op = build1 (VIEW_CONVERT_EXPR, vtype, op0);
+                 tree new_op0 = make_ssa_name (vtype);
+                 gassign *new_stmt = gimple_build_assign (new_op0, conv_op);
+                 gsi_insert_seq_before (gsi, new_stmt, GSI_SAME_STMT);
+                 if (optab_handler (and_optab, vmode) != CODE_FOR_nothing)
+                   /* r = c | z */
+                   return gimple_build_assign (lhs, BIT_AND_EXPR, new_op0,
+                                               op1);
+                 /* r = c ? z : c */
+                 op2 = new_op0;
+               }
            }

          /* When the compare has EH we do not want to forward it when
--
2.43.0

Reply via email to