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.
This commit is contained in:
parent
577223aebc
commit
1c1dd39625
5 changed files with 89 additions and 6 deletions
|
@ -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:;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue