https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111098

            Bug ID: 111098
           Summary: Missed combine .FMA + .COND_NEG
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: lehua.ding at rivai dot ai
  Target Milestone: ---

For code[1], GCC first combine a[i] + b[i] * c to a .FMA (widening_mul pass)
than fold .FMA + neg to .FNMS. But for code[2], it not fold .FMA + .COND_NEG to
.COND_FNMS. See the codes and dump tree on https://godbolt.org/z/WTKrET4sn.

Can we relax the fold condition after fuse mul+add from neg to neg or COND_NEG?
The simple try is as diff[3].

[1]
r[i] = -(a[i] + b[i] * c);

[2]
r[i] = pred[i] != 1 ? -(a[i] + b[i] * c) : c;

[3]
diff --git a/gcc/match.pd b/gcc/match.pd
index 86fdc606a79..a3719f725ab 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -8020,7 +8020,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (simplify
    (negate (fmas@3 @0 @1 @2))
    (if (single_use (@3))
-    (IFN_FNMS @0 @1 @2))))
+    (IFN_FNMS @0 @1 @2)))
+  (simplify
+   (IFN_COND_NEG @0 (fmas@5 @1 @2 @3) @4)
+   (if (single_use (@5))
+    (IFN_COND_FNMS @0 @1 @2 @3 @4))))

  (simplify
   (IFN_FMS:c (negate @0) @1 @2)
diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
index 712097ac5be..b9f9baba002 100644
--- a/gcc/tree-ssa-math-opts.cc
+++ b/gcc/tree-ssa-math-opts.cc
@@ -3163,8 +3163,10 @@ convert_mult_to_fma_1 (tree mul_result, tree op1, tree
op2)
          && gimple_call_lhs (orig_stmt)
          && TREE_CODE (gimple_call_lhs (orig_stmt)) == SSA_NAME
          && single_imm_use (gimple_call_lhs (orig_stmt), &use_p, &neg_stmt)
-         && is_gimple_assign (neg_stmt)
-         && gimple_assign_rhs_code (neg_stmt) == NEGATE_EXPR
+         && ((is_gimple_assign (neg_stmt)
+              && gimple_assign_rhs_code (neg_stmt) == NEGATE_EXPR)
+             || (gimple_call_internal_p (neg_stmt)
+                 && gimple_call_internal_fn (neg_stmt) == IFN_COND_NEG))
          && !stmt_could_throw_p (cfun, neg_stmt))
        {
          gsi = gsi_for_stmt (neg_stmt);

Reply via email to