[PATCH][RFC] Add PAREN_EXPR, make flag_associative_math the default for Fortran

Richard Guenther rguenther@suse.de
Wed Jan 2 14:51:00 GMT 2008


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)

Thanks,
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.

	* trans-expr.c (gfc_conv_expr_op): Expand INTRINSIC_PARENTHESES
	as unary PAREN_EXPR.
	* 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/trans-expr.c
===================================================================
*** gcc/fortran/trans-expr.c	(revision 131256)
--- gcc/fortran/trans-expr.c	(working copy)
*************** gfc_conv_expr_op (gfc_se * se, gfc_expr 
*** 1066,1075 ****
    switch (expr->value.op.operator)
      {
      case INTRINSIC_UPLUS:
-     case INTRINSIC_PARENTHESES:
        gfc_conv_expr (se, expr->value.op.op1);
        return;
  
      case INTRINSIC_UMINUS:
        gfc_conv_unary_op (NEGATE_EXPR, se, expr);
        return;
--- 1066,1078 ----
    switch (expr->value.op.operator)
      {
      case INTRINSIC_UPLUS:
        gfc_conv_expr (se, expr->value.op.op1);
        return;
  
+     case INTRINSIC_PARENTHESES:
+       gfc_conv_unary_op (PAREN_EXPR, se, expr);
+       return;
+ 
      case INTRINSIC_UMINUS:
        gfc_conv_unary_op (NEGATE_EXPR, se, expr);
        return;
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;



More information about the Fortran mailing list