public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-2023] c-family: implement -ffp-contract=on
@ 2023-06-21 18:31 Alexander Monakov
  0 siblings, 0 replies; only message in thread
From: Alexander Monakov @ 2023-06-21 18:31 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:1c1dd39625719d92b0ab7afc690f0aada5951072

commit r14-2023-g1c1dd39625719d92b0ab7afc690f0aada5951072
Author: Alexander Monakov <amonakov@ispras.ru>
Date:   Thu May 18 23:47:47 2023 +0300

    c-family: implement -ffp-contract=on
    
    Implement -ffp-contract=on for C and C++ without changing default
    behavior (=off for -std=cNN, =fast for C++ and -std=gnuNN).
    
    gcc/c-family/ChangeLog:
    
            * c-gimplify.cc (fma_supported_p): New helper.
            (c_gimplify_expr) [PLUS_EXPR, MINUS_EXPR]: Implement FMA
            contraction.
    
    gcc/ChangeLog:
    
            * common.opt (fp_contract_mode) [on]: Remove fallback.
            * config/sh/sh.md (*fmasf4): Correct flag_fp_contract_mode test.
            * doc/invoke.texi (-ffp-contract): Update.
            * trans-mem.cc (diagnose_tm_1): Skip internal function calls.

Diff:
---
 gcc/c-family/c-gimplify.cc | 79 ++++++++++++++++++++++++++++++++++++++++++++++
 gcc/common.opt             |  3 +-
 gcc/config/sh/sh.md        |  2 +-
 gcc/doc/invoke.texi        |  8 +++--
 gcc/trans-mem.cc           |  3 ++
 5 files changed, 89 insertions(+), 6 deletions(-)

diff --git a/gcc/c-family/c-gimplify.cc b/gcc/c-family/c-gimplify.cc
index ef5c7d919fc..17b0610a89f 100644
--- a/gcc/c-family/c-gimplify.cc
+++ b/gcc/c-family/c-gimplify.cc
@@ -41,6 +41,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-ubsan.h"
 #include "tree-nested.h"
 #include "context.h"
+#include "tree-pass.h"
+#include "internal-fn.h"
 
 /*  The gimplification pass converts the language-dependent trees
     (ld-trees) emitted by the parser into language-independent trees
@@ -686,6 +688,14 @@ c_build_bind_expr (location_t loc, tree block, tree body)
   return bind;
 }
 
+/* Helper for c_gimplify_expr: test if target supports fma-like FN.  */
+
+static bool
+fma_supported_p (enum internal_fn fn, tree type)
+{
+  return direct_internal_fn_supported_p (fn, type, OPTIMIZE_FOR_BOTH);
+}
+
 /* Gimplification of expression trees.  */
 
 /* Do C-specific gimplification on *EXPR_P.  PRE_P and POST_P are as in
@@ -739,6 +749,75 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
 	break;
       }
 
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+      {
+	tree type = TREE_TYPE (*expr_p);
+	/* For -ffp-contract=on we need to attempt FMA contraction only
+	   during initial gimplification.  Late contraction across statement
+	   boundaries would violate language semantics.  */
+	if (SCALAR_FLOAT_TYPE_P (type)
+	    && flag_fp_contract_mode == FP_CONTRACT_ON
+	    && cfun && !(cfun->curr_properties & PROP_gimple_any)
+	    && fma_supported_p (IFN_FMA, type))
+	  {
+	    bool neg_mul = false, neg_add = code == MINUS_EXPR;
+
+	    tree *op0_p = &TREE_OPERAND (*expr_p, 0);
+	    tree *op1_p = &TREE_OPERAND (*expr_p, 1);
+
+	    /* Look for ±(x * y) ± z, swapping operands if necessary.  */
+	    if (TREE_CODE (*op0_p) == NEGATE_EXPR
+		&& TREE_CODE (TREE_OPERAND (*op0_p, 0)) == MULT_EXPR)
+	      /* '*EXPR_P' is '-(x * y) ± z'.  This is fine.  */;
+	    else if (TREE_CODE (*op0_p) != MULT_EXPR)
+	      {
+		std::swap (op0_p, op1_p);
+		std::swap (neg_mul, neg_add);
+	      }
+	    if (TREE_CODE (*op0_p) == NEGATE_EXPR)
+	      {
+		op0_p = &TREE_OPERAND (*op0_p, 0);
+		neg_mul = !neg_mul;
+	      }
+	    if (TREE_CODE (*op0_p) != MULT_EXPR)
+	      break;
+	    auto_vec<tree, 3> ops (3);
+	    ops.quick_push (TREE_OPERAND (*op0_p, 0));
+	    ops.quick_push (TREE_OPERAND (*op0_p, 1));
+	    ops.quick_push (*op1_p);
+
+	    enum internal_fn ifn = IFN_FMA;
+	    if (neg_mul)
+	      {
+		if (fma_supported_p (IFN_FNMA, type))
+		  ifn = IFN_FNMA;
+		else
+		  ops[0] = build1 (NEGATE_EXPR, type, ops[0]);
+	      }
+	    if (neg_add)
+	      {
+		enum internal_fn ifn2 = ifn == IFN_FMA ? IFN_FMS : IFN_FNMS;
+		if (fma_supported_p (ifn2, type))
+		  ifn = ifn2;
+		else
+		  ops[2] = build1 (NEGATE_EXPR, type, ops[2]);
+	      }
+	    /* Avoid gimplify_arg: it emits all side effects into *PRE_P.  */
+	    for (auto &&op : ops)
+	      if (gimplify_expr (&op, pre_p, post_p, is_gimple_val, fb_rvalue)
+		  == GS_ERROR)
+		return GS_ERROR;
+
+	    gcall *call = gimple_build_call_internal_vec (ifn, ops);
+	    gimple_seq_add_stmt_without_update (pre_p, call);
+	    *expr_p = create_tmp_var (type);
+	    gimple_call_set_lhs (call, *expr_p);
+	    return GS_ALL_DONE;
+	  }
+	break;
+      }
+
     default:;
     }
 
diff --git a/gcc/common.opt b/gcc/common.opt
index a28ca13385a..3daec85aef9 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1662,9 +1662,8 @@ Name(fp_contract_mode) Type(enum fp_contract_mode) UnknownError(unknown floating
 EnumValue
 Enum(fp_contract_mode) String(off) Value(FP_CONTRACT_OFF)
 
-; Not implemented, fall back to conservative FP_CONTRACT_OFF.
 EnumValue
-Enum(fp_contract_mode) String(on) Value(FP_CONTRACT_OFF)
+Enum(fp_contract_mode) String(on) Value(FP_CONTRACT_ON)
 
 EnumValue
 Enum(fp_contract_mode) String(fast) Value(FP_CONTRACT_FAST)
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 4622dba0121..5cb17954825 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -9269,7 +9269,7 @@
 		 (match_operand:SF 3 "arith_reg_operand" "0")))
    (clobber (reg:SI FPSCR_STAT_REG))
    (use (reg:SI FPSCR_MODES_REG))]
-  "TARGET_SH2E && flag_fp_contract_mode != FP_CONTRACT_OFF"
+  "TARGET_SH2E && flag_fp_contract_mode == FP_CONTRACT_FAST"
   "fmac	%1,%2,%0"
   "&& can_create_pseudo_p ()"
   [(parallel [(set (match_dup 0)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 215ab0dd05c..8c17a81c7d9 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -12077,10 +12077,12 @@ This option is enabled by default at optimization levels @option{-O1},
 such as forming of fused multiply-add operations if the target has
 native support for them.
 @option{-ffp-contract=on} enables floating-point expression contraction
-if allowed by the language standard.  This is currently not implemented
-and treated equal to @option{-ffp-contract=off}.
+if allowed by the language standard.  This is implemented for C and C++,
+where it enables contraction within one expression, but not across
+different statements.
 
-The default is @option{-ffp-contract=fast}.
+The default is @option{-ffp-contract=off} for C in a standards compliant mode
+(@option{-std=c11} or similar), @option{-ffp-contract=fast} otherwise.
 
 @opindex fomit-frame-pointer
 @item -fomit-frame-pointer
diff --git a/gcc/trans-mem.cc b/gcc/trans-mem.cc
index d036e4333db..9c3d1121a03 100644
--- a/gcc/trans-mem.cc
+++ b/gcc/trans-mem.cc
@@ -637,6 +637,9 @@ diagnose_tm_1 (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     {
     case GIMPLE_CALL:
       {
+	if (gimple_call_internal_p (stmt))
+	  break;
+
 	tree fn = gimple_call_fn (stmt);
 
 	if ((d->summary_flags & DIAG_TM_OUTER) == 0

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-06-21 18:31 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-21 18:31 [gcc r14-2023] c-family: implement -ffp-contract=on Alexander Monakov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).