This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
Re: [PATCH][RFC] Add PAREN_EXPR, make flag_associative_math the default for Fortran
- From: Richard Guenther <rguenther at suse dot de>
- To: Tobias Schlüter <tobias dot schlueter at physik dot uni-muenchen dot de>
- Cc: gcc-patches at gcc dot gnu dot org, fortran at gcc dot gnu dot org
- Date: Thu, 3 Jan 2008 15:40:17 +0100 (CET)
- Subject: Re: [PATCH][RFC] Add PAREN_EXPR, make flag_associative_math the default for Fortran
- References: <Pine.LNX.4.64.0801021537230.3891@zhemvz.fhfr.qr> <477BCFA7.2030806@physik.uni-muenchen.de>
On Wed, 2 Jan 2008, Tobias Schlüter wrote:
> Richard Guenther wrote:
> > This adds a middle-end PAREN_EXPR tree code that acts as re-association
> > barrier for floating point expressions. This allows to model the Fortran
> > semantics that allow re-association for expressions that are not
> > explicitly wrapped inside parentheses.
> >
> > This simple patch (not tested yet) for example preserves a + (b - a)
> > if you build with -ffast-math.
> >
> > function testarray (a, b)
> > implicit none
> > real*8 :: a, b, testarray
> >
> > testarray = a + (b - a)
> > end
> >
> > eventually this allows expansion of rounding functions on the tree
> > level (those rely on us preserving stuff like (x + 1e-52) - 1e52 and
> > not constant fold it).
> >
> > The way the patch 'works' is that nothing handles (looks through)
> > PAREN_EXPR at the moment, so it is a conservative implementation. On
> > the RTL level it just relies on the fact that we do not re-associate
> > floating point expressions there (we rely on that fact now anyway).
> >
> > Any thoughts? (Yes, I thought on using a flag on operands or variants
> > of the associative tree operators, but these either don't work do not
> > model the semantics close enough)
>
> This matches the original intent when INTRINSIC_PARENTHESES were introduced in
> the Fortran FE. We also use it to mimic call-by-value semantics (CALL f((X))
> instead of CALL f(X) causes f to receive a pointer to a copy of X, instead of
> X itself), but I don't think this will interfere with your patch.
>
> Thanks for doing this!
And this version of the patch actually survives bootstrap and
regtest on x86_64-unknown-linux-gnu. Two (additional?) failures for
gfortran are
FAIL: gfortran.dg/vect/pr32377.f90 -O scan-tree-dump-times vect
"vectorized 2
loops" 1
FAIL: gfortran.dg/vect/no-vfa-pr32377.f90 scan-tree-dump-times vect
"vectorized
2 loops" 1
at least I see
/space/rguenther/trunk/gcc/testsuite/gfortran.dg/vect/pr32377.f90:9: note:
not vectorized: relevant stmt not supported: D.935_94 = ((D.934_93))
so probably PAREN_EXPR needs to be ignored in some places, in this case
it needs to be handled like a simple copy. Another case where it can
be possibly ignored is operand_equal_p, as ((a + b)) is equal to a + b,
though if we use this equality to substitute either for the other we
need to be careful.
Richard.
2008-01-02 Richard Guenther <rguenther@suse.de>
* tree.def (PAREN_EXPR): New tree code.
* tree-pretty-print.c (dump_generic_node): Handle PAREN_EXPR.
* expr.c (expand_expr_real_1): Likewise.
* tree-inline.c (estimate_num_insns_1): Likewise.
* tree-complex.c (expand_complex_move): Likewise.
* trans-expr.c (gfc_conv_expr_op): Expand INTRINSIC_PARENTHESES
as unary PAREN_EXPR for real and complex typed expressions.
* options.c (gfc_init_options): Enable flag_associative_math if
it isn't disabled automatically.
Index: gcc/tree-pretty-print.c
===================================================================
*** gcc/tree-pretty-print.c (revision 131256)
--- gcc/tree-pretty-print.c (working copy)
*************** dump_generic_node (pretty_printer *buffe
*** 1446,1451 ****
--- 1446,1457 ----
pp_character (buffer, ')');
break;
+ case PAREN_EXPR:
+ pp_string (buffer, "((");
+ dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+ pp_string (buffer, "))");
+ break;
+
case NON_LVALUE_EXPR:
pp_string (buffer, "NON_LVALUE_EXPR <");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
Index: gcc/expr.c
===================================================================
*** gcc/expr.c (revision 131256)
--- gcc/expr.c (working copy)
*************** expand_expr_real_1 (tree exp, rtx target
*** 8043,8048 ****
--- 8043,8049 ----
}
return expand_call (exp, target, ignore);
+ case PAREN_EXPR:
case NON_LVALUE_EXPR:
case NOP_EXPR:
case CONVERT_EXPR:
Index: gcc/tree.def
===================================================================
*** gcc/tree.def (revision 131256)
--- gcc/tree.def (working copy)
*************** DEFTREECODE (LTGT_EXPR, "ltgt_expr", tcc
*** 733,738 ****
--- 733,742 ----
DEFTREECODE (RANGE_EXPR, "range_expr", tcc_binary, 2)
+ /* Represents a re-association barrier for floating point expressions
+ like explicit parenthesis in fortran. */
+ DEFTREECODE (PAREN_EXPR, "paren_expr", tcc_unary, 1)
+
/* Represents a conversion of type of a value.
All conversions, including implicit ones, must be
represented by CONVERT_EXPR or NOP_EXPR nodes. */
Index: gcc/tree-inline.c
===================================================================
*** gcc/tree-inline.c (revision 131256)
--- gcc/tree-inline.c (working copy)
*************** estimate_num_insns_1 (tree *tp, int *wal
*** 2135,2140 ****
--- 2135,2141 ----
case COMPOUND_EXPR:
case BIND_EXPR:
case WITH_CLEANUP_EXPR:
+ case PAREN_EXPR:
case NOP_EXPR:
case CONVERT_EXPR:
case VIEW_CONVERT_EXPR:
Index: gcc/fortran/options.c
===================================================================
*** gcc/fortran/options.c (revision 131256)
--- gcc/fortran/options.c (working copy)
*************** gfc_init_options (unsigned int argc ATTR
*** 121,126 ****
--- 121,131 ----
flag_errno_math = 0;
+ /* Fortran allows re-association. Parenthesis are explicitly preserved
+ and act as re-association barrier. */
+ if (!flag_trapping_math && !flag_signed_zeros)
+ flag_associative_math = 1;
+
set_default_std_flags ();
gfc_option.warn_nonstd_intrinsics = 0;
Index: gcc/tree-complex.c
===================================================================
*** gcc/tree-complex.c (revision 131260)
--- gcc/tree-complex.c (working copy)
*************** expand_complex_move (block_stmt_iterator
*** 763,769 ****
i = build1 (IMAGPART_EXPR, inner_type, lhs);
update_complex_components_on_edge (e, lhs, r, i);
}
! else if (TREE_CODE (rhs) == CALL_EXPR || TREE_SIDE_EFFECTS (rhs))
{
r = build1 (REALPART_EXPR, inner_type, lhs);
i = build1 (IMAGPART_EXPR, inner_type, lhs);
--- 763,770 ----
i = build1 (IMAGPART_EXPR, inner_type, lhs);
update_complex_components_on_edge (e, lhs, r, i);
}
! else if (TREE_CODE (rhs) == CALL_EXPR || TREE_SIDE_EFFECTS (rhs)
! || TREE_CODE (rhs) == PAREN_EXPR)
{
r = build1 (REALPART_EXPR, inner_type, lhs);
i = build1 (IMAGPART_EXPR, inner_type, lhs);
Index: gcc/fortran/trans-expr.c
===================================================================
*** gcc/fortran/trans-expr.c (revision 131260)
--- gcc/fortran/trans-expr.c (working copy)
*************** gfc_conv_expr_op (gfc_se * se, gfc_expr
*** 1065,1072 ****
lop = 0;
switch (expr->value.op.operator)
{
- case INTRINSIC_UPLUS:
case INTRINSIC_PARENTHESES:
gfc_conv_expr (se, expr->value.op.op1);
return;
--- 1065,1081 ----
lop = 0;
switch (expr->value.op.operator)
{
case INTRINSIC_PARENTHESES:
+ if (expr->ts.type == BT_REAL
+ || expr->ts.type == BT_COMPLEX)
+ {
+ gfc_conv_unary_op (PAREN_EXPR, se, expr);
+ gcc_assert (FLOAT_TYPE_P (TREE_TYPE (se->expr)));
+ return;
+ }
+
+ /* Fallthrough. */
+ case INTRINSIC_UPLUS:
gfc_conv_expr (se, expr->value.op.op1);
return;