This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tree-ssa] preliminary l-i reorganization patch


This patch, which I'm not checking in, does the bits of reorganization
which can be done without actually changing the target language from C
trees to language-independent trees.  It:

1) Changes the language hook from simplify_function_tree to simplify_expr,
   and splits out c_simplify_expr from simplify_expr.
2) Moves the simplification code for l-i trees to tree-simple.c, and
   is_simple tests for C trees to c-simplify.c.  This is not complete, as
   some of the code for simplifying l-i trees creates C-specific trees.

Thoughts?  Should I check this in now, or keep it in my local tree until
the whole changeover is complete?

*** ./c-common.h.~1~	Wed Aug  7 15:33:09 2002
--- ./c-common.h	Thu Aug  8 23:01:08 2002
*************** extern void dump_time_statistics		PARAMS
*** 1225,1228 ****
--- 1225,1231 ----
  
  extern int c_dump_tree				PARAMS ((void *, tree));
  
+ extern int c_simplify_expr			PARAMS ((tree *, tree *, tree *,
+ 							 int (*) (tree)));
+ 
  #endif /* ! GCC_C_COMMON_H */
*** ./c-simplify.c.~1~	Wed Aug  7 15:33:09 2002
--- ./c-simplify.c	Fri Aug  9 00:31:38 2002
*************** Software Foundation, 59 Temple Place - S
*** 28,34 ****
  #include "system.h"
  #include "tree.h"
  #include "errors.h"
- #include "varray.h"
  #include "c-tree.h"
  #include "c-common.h"
  #include "tree-simple.h"
--- 28,33 ----
*************** Software Foundation, 59 Temple Place - S
*** 61,67 ****
  static void simplify_stmt            PARAMS ((tree *));
  static void simplify_expr_stmt       PARAMS ((tree, tree *, tree *));
  static void simplify_decl_stmt       PARAMS ((tree, tree *, tree *, tree *));
- static void simplify_constructor     PARAMS ((tree, tree *, tree *));
  static void maybe_fixup_loop_cond    PARAMS ((tree *, tree *, tree *));
  static void simplify_for_stmt        PARAMS ((tree, tree *));
  static void simplify_while_stmt      PARAMS ((tree, tree *));
--- 60,65 ----
*************** static void simplify_do_stmt         PAR
*** 69,100 ****
  static void simplify_if_stmt         PARAMS ((tree, tree *));
  static void simplify_switch_stmt     PARAMS ((tree, tree *));
  static void simplify_return_stmt     PARAMS ((tree, tree *));
- typedef enum fallback_t {
-   fb_rvalue=1,
-   fb_lvalue=2,
-   fb_either=1|2
- } fallback_t;
- static void simplify_expr	     PARAMS ((tree *, tree *, tree *,
-                                               int (*) PARAMS ((tree)),
- 					      fallback_t));
- static void simplify_array_ref       PARAMS ((tree *, tree *, tree *));
- static void simplify_compound_lval   PARAMS ((tree *, tree *, tree *));
- static void simplify_self_mod_expr   PARAMS ((tree *, tree *, tree *));
- static void simplify_component_ref   PARAMS ((tree *, tree *, tree *));
- static void simplify_call_expr       PARAMS ((tree *, tree *, tree *));
- static void simplify_tree_list       PARAMS ((tree *, tree *, tree *));
- static void simplify_cond_expr       PARAMS ((tree *, tree *));
- static void simplify_modify_expr     PARAMS ((tree *, tree *, tree *));
- static void simplify_boolean_expr    PARAMS ((tree *, tree *));
- static void simplify_compound_expr   PARAMS ((tree *, tree *, tree *));
- static void simplify_expr_wfl        PARAMS ((tree *, tree *, tree *,
-                                               int (*) PARAMS ((tree))));
- static void simplify_save_expr       PARAMS ((tree *, tree *));
  static void simplify_stmt_expr       PARAMS ((tree *, tree *));
  static void simplify_compound_literal_expr PARAMS ((tree *, tree *, tree *));
- static void simplify_addr_expr       PARAMS ((tree *, tree *, tree *));
  static void make_type_writable       PARAMS ((tree));
- static tree add_tree                 PARAMS ((tree, tree *));
  static tree insert_before_continue   PARAMS ((tree, tree));
  static tree tree_last_decl           PARAMS ((tree));
  static int  stmt_has_effect          PARAMS ((tree));
--- 67,75 ----
*************** static int  expr_has_effect          PAR
*** 102,111 ****
  static tree mostly_copy_tree_r       PARAMS ((tree *, int *, void *));
  static inline void remove_suffix     PARAMS ((char *, int));
  static const char *get_name          PARAMS ((tree));
- static tree build_addr_expr	     PARAMS ((tree));
  static int is_last_stmt_of_scope     PARAMS ((tree));
  static tree tail_expression          PARAMS ((tree *, int));
  
  /* Local variables.  */
  static FILE *dump_file;
  static int dump_flags;
--- 77,93 ----
  static tree mostly_copy_tree_r       PARAMS ((tree *, int *, void *));
  static inline void remove_suffix     PARAMS ((char *, int));
  static const char *get_name          PARAMS ((tree));
  static int is_last_stmt_of_scope     PARAMS ((tree));
  static tree tail_expression          PARAMS ((tree *, int));
  
+ /* Should move to tree-simple.c when the target language loses the C-isms.  */
+ static void simplify_self_mod_expr   PARAMS ((tree *, tree *, tree *));
+ static void simplify_cond_expr       PARAMS ((tree *, tree *));
+ static void simplify_boolean_expr    PARAMS ((tree *, tree *));
+ static void simplify_expr_wfl        PARAMS ((tree *, tree *, tree *,
+                                               int (*) (tree)));
+ 
+ 
  /* Local variables.  */
  static FILE *dump_file;
  static int dump_flags;
*************** static int dump_flags;
*** 116,122 ****
      node for the function we want to simplify.  */
  
  int
! c_simplify_function_tree (fndecl)
       tree fndecl;
  {
    tree fnbody;
--- 98,104 ----
      node for the function we want to simplify.  */
  
  int
! simplify_function_tree (fndecl)
       tree fndecl;
  {
    tree fnbody;
*************** c_simplify_function_tree (fndecl)
*** 149,155 ****
    pushlevel (0);
  
    /* Simplify the function's body.  */
!   simplify_stmt (&fnbody);
  
    /* Declare the new temporary variables.  */
    declare_tmp_vars (getdecls(), fnbody);
--- 131,137 ----
    pushlevel (0);
  
    /* Simplify the function's body.  */
!   simplify_expr (&fnbody, NULL, NULL, NULL, fb_rvalue);
  
    /* Declare the new temporary variables.  */
    declare_tmp_vars (getdecls(), fnbody);
*************** simplify_decl_stmt (t, pre_p, mid_p, pos
*** 972,998 ****
    add_tree (post, post_p);
  }
  
- /* Simplifies a CONSTRUCTOR node T.
- 
-    FIXME: Should dynamic initializations from a CONSTRUCTOR be broken
-    up into multiple assignments?  */
- 
- static void
- simplify_constructor (t, pre_p, post_p)
-      tree t;
-      tree *pre_p;
-      tree *post_p;
- {
-   tree elt_list;
- 
-   if (is_simple_constructor (t))
-     return;
- 
-   for (elt_list = CONSTRUCTOR_ELTS (t); elt_list;
-        elt_list = TREE_CHAIN (elt_list))
-     simplify_expr (&TREE_VALUE (elt_list), pre_p, post_p,
- 		   is_simple_constructor_elt, fb_rvalue);
- }
  
  /* Simplify a C99 compound literal expression.  This just means adding the
     DECL_STMT before the current EXPR_STMT and using its anonymous decl
--- 954,959 ----
*************** simplify_compound_literal_expr (expr_p, 
*** 1041,1047 ****
          bit is set, an rvalue is OK.  If the 2 bit is set, an lvalue is OK.
          If both are set, either is OK, but an lvalue is preferable.  */
  
! static void
  simplify_expr (expr_p, pre_p, post_p, simple_test_f, fallback)
       tree *expr_p;
       tree *pre_p;
--- 1002,1008 ----
          bit is set, an rvalue is OK.  If the 2 bit is set, an lvalue is OK.
          If both are set, either is OK, but an lvalue is preferable.  */
  
! void
  simplify_expr (expr_p, pre_p, post_p, simple_test_f, fallback)
       tree *expr_p;
       tree *pre_p;
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 1051,1056 ****
--- 1012,1027 ----
  {
    tree tmp;
    tree internal_post = NULL_TREE;
+   int done;
+ 
+   if (pre_p == NULL)
+     {
+       /* Temporary kludge: If pre_p is null, this is a statement.  Hand of
+ 	 to the C-specific code.  Soon we will have a l-i notion of
+ 	 statements.  */
+       (*lang_hooks.simplify_expr) (expr_p, pre_p, post_p, simple_test_f);
+       return;
+     }
  
    if (simple_test_f == NULL)
      abort ();
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 1062,1070 ****
    if (post_p == NULL)
      post_p = &internal_post;
  
!   /* First deal with the special cases.  */
!   switch (TREE_CODE (*expr_p))
      {
      case POSTINCREMENT_EXPR:
      case POSTDECREMENT_EXPR:
      case PREINCREMENT_EXPR:
--- 1033,1047 ----
    if (post_p == NULL)
      post_p = &internal_post;
  
!   /* First do any language-specific simplification.  */
!   done = (*lang_hooks.simplify_expr) (expr_p, pre_p, post_p, simple_test_f);
! 
!   if (done)
!     /* The frontend completely simplified this node.  */;
!   else switch (TREE_CODE (*expr_p))
      {
+       /* First deal with the special cases.  */
+ 
      case POSTINCREMENT_EXPR:
      case POSTDECREMENT_EXPR:
      case PREINCREMENT_EXPR:
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 1122,1129 ****
        simplify_addr_expr (expr_p, pre_p, post_p);
        break;
  
!     /* va_arg expressions should also be left alone to avoid confusing the
!        vararg code.  FIXME: Is this really necessary?  */
      case VA_ARG_EXPR:
        break;
  
--- 1099,1106 ----
        simplify_addr_expr (expr_p, pre_p, post_p);
        break;
  
!       /* va_arg expressions should also be left alone to avoid confusing the
! 	 vararg code.  FIXME: Is this really necessary?  */
      case VA_ARG_EXPR:
        break;
  
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 1134,1175 ****
      case FIX_FLOOR_EXPR:
      case FIX_ROUND_EXPR:
        simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
! 	             is_simple_varname, fb_rvalue);
        break;
  
      case INDIRECT_REF:
        simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_simple_id,
! 	             fb_rvalue);
        break;
  
      case NEGATE_EXPR:
        simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_simple_val,
! 	             fb_rvalue);
        break;
  
!     /* Constants need not be simplified.  */
      case INTEGER_CST:
      case REAL_CST:
      case STRING_CST:
      case COMPLEX_CST:
        break;
  
-     case COMPOUND_LITERAL_EXPR:
-       simplify_compound_literal_expr (expr_p, pre_p, post_p);
-       break;
- 
      case CONSTRUCTOR:
        simplify_constructor (*expr_p, pre_p, post_p);
        break;
  
!     /* The following are special cases that are not handled by the original
!        SIMPLE grammar.  */
!     case STMT_EXPR:
!       simplify_stmt_expr (expr_p, pre_p);
!       break;
! 
!     /* SAVE_EXPR nodes are converted into a SIMPLE identifier and
!        eliminated.  */
      case SAVE_EXPR:
        simplify_save_expr (expr_p, pre_p);
        break;
--- 1111,1142 ----
      case FIX_FLOOR_EXPR:
      case FIX_ROUND_EXPR:
        simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
! 		     is_simple_varname, fb_rvalue);
        break;
  
      case INDIRECT_REF:
        simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_simple_id,
! 		     fb_rvalue);
        break;
  
      case NEGATE_EXPR:
        simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_simple_val,
! 		     fb_rvalue);
        break;
  
!       /* Constants need not be simplified.  */
      case INTEGER_CST:
      case REAL_CST:
      case STRING_CST:
      case COMPLEX_CST:
        break;
  
      case CONSTRUCTOR:
        simplify_constructor (*expr_p, pre_p, post_p);
        break;
  
!       /* SAVE_EXPR nodes are converted into a SIMPLE identifier and
! 	 eliminated.  */
      case SAVE_EXPR:
        simplify_save_expr (expr_p, pre_p);
        break;
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 1178,1186 ****
        simplify_expr_wfl (expr_p, pre_p, post_p, simple_test_f);
        break;
  
!     /* FIXME: This breaks stage2.  I still haven't figured out why.  When
! 	      fixing remember to undo a similar change in
! 	      is_simple_unary_expr.  */
      case BIT_FIELD_REF:
  #if 0
        simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_simple_id);
--- 1145,1153 ----
        simplify_expr_wfl (expr_p, pre_p, post_p, simple_test_f);
        break;
  
!       /* FIXME: This breaks stage2.  I still haven't figured out why.  When
! 	 fixing remember to undo a similar change in
! 	 is_simple_unary_expr.  */
      case BIT_FIELD_REF:
  #if 0
        simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_simple_id);
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 1191,1210 ****
  
      case NON_LVALUE_EXPR:
        simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, simple_test_f,
! 	             fb_rvalue);
        break;
  
!     /* If *EXPR_P does not need to be special-cased, handle it according to
!        its class.  */
      default:
        {
  	if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '1')
  	  {
  	    simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
! 	                   is_simple_val, fb_rvalue);
  	  }
  	else if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '2'
! 	         || TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '<'
  		 || TREE_CODE (*expr_p) == TRUTH_AND_EXPR
  		 || TREE_CODE (*expr_p) == TRUTH_OR_EXPR
  		 || TREE_CODE (*expr_p) == TRUTH_XOR_EXPR)
--- 1158,1177 ----
  
      case NON_LVALUE_EXPR:
        simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, simple_test_f,
! 		     fb_rvalue);
        break;
  
!       /* If *EXPR_P does not need to be special-cased, handle it according to
! 	 its class.  */
      default:
        {
  	if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '1')
  	  {
  	    simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
! 			   is_simple_val, fb_rvalue);
  	  }
  	else if (TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '2'
! 		 || TREE_CODE_CLASS (TREE_CODE (*expr_p)) == '<'
  		 || TREE_CODE (*expr_p) == TRUTH_AND_EXPR
  		 || TREE_CODE (*expr_p) == TRUTH_OR_EXPR
  		 || TREE_CODE (*expr_p) == TRUTH_XOR_EXPR)
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 1271,1399 ****
      add_tree (internal_post, pre_p);
  }
  
! /*  Build an expression for the address of T.  Folds away INDIRECT_REF to
!     avoid confusing the simplify process.  */
  
! static tree
! build_addr_expr (t)
!      tree t;
! {
!   tree ptrtype = build_pointer_type (TREE_TYPE (t));
!   if (TREE_CODE (t) == INDIRECT_REF)
!     {
!       t = TREE_OPERAND (t, 0);
!       if (TREE_TYPE (t) != ptrtype)
! 	t = build1 (NOP_EXPR, ptrtype, t);
!     }
!   else
!     t = build1 (ADDR_EXPR, ptrtype, t);
! 
!   return t;
! }
! 
!   
! /*  Re-write the ARRAY_REF node pointed by EXPR_P.
! 
!     PRE_P points to the list where side effects that must happen before
! 	*EXPR_P should be stored.
! 
!     POST_P points to the list where side effects that must happen after
! 	*EXPR_P should be stored.
! 
!     FIXME: ARRAY_REF currently doesn't accept a pointer as the array
!     argument, so this simplification uses an INDIRECT_REF of ARRAY_TYPE.
!     ARRAY_REF should be extended.  */
! 
! static void
! simplify_array_ref (expr_p, pre_p, post_p)
       tree *expr_p;
       tree *pre_p;
       tree *post_p;
  {
! #if 1
!   /* Handle array and member refs together for now.  When alias analysis
!      improves, we may want to go back to handling them separately.  */
!   simplify_compound_lval (expr_p, pre_p, post_p);
! #else
!   tree *p;
!   varray_type dim_stack;
! 
!   if (TREE_CODE (*expr_p) != ARRAY_REF)
!     abort ();
! 
!   VARRAY_GENERIC_PTR_INIT (dim_stack, 10, "dim_stack");
! 
!   /* Create a stack with all the dimensions of the array so that they can
!      be simplified from left to right.  */
!   for (p = expr_p; TREE_CODE (*p) == ARRAY_REF; p = &TREE_OPERAND (*p, 0))
!     VARRAY_PUSH_GENERIC_PTR (dim_stack, (PTR) &TREE_OPERAND (*p, 1));
! 
!   /* After the loop above, 'p' points to the first non-ARRAY_REF,
!      and 'dim_stack' is a stack of pointers to all the dimensions in left
!      to right order (the leftmost dimension is at the top of the stack).
! 
!      Simplify the base, and then each of the dimensions from left to
!      right.  */
! 
!   simplify_expr (p, pre_p, post_p, is_simple_min_lval, fb_lvalue);
! 
!   for (; VARRAY_ACTIVE_SIZE (dim_stack) > 0; VARRAY_POP (dim_stack))
      {
!       tree *dim_p = (tree *)VARRAY_TOP_GENERIC_PTR (dim_stack);
!       simplify_expr (dim_p, pre_p, post_p, is_simple_val, fb_rvalue);
      }
- #endif
- }
- 
- /* Simplify the COMPONENT_REF or ARRAY_REF node pointed by EXPR_P.
- 
-    PRE_P points to the list where side effects that must happen before
-      *EXPR_P should be stored.
- 
-    POST_P points to the list where side effects that must happen after
-      *EXPR_P should be stored.  */
- 
- static void
- simplify_compound_lval (expr_p, pre_p, post_p)
-      tree *expr_p;
-      tree *pre_p;
-      tree *post_p;
- {
-   tree *p;
-   enum tree_code code;
-   varray_type dim_stack;
  
!   if (TREE_CODE (*expr_p) != ARRAY_REF && TREE_CODE (*expr_p) != COMPONENT_REF)
!     abort ();
! 
!   /* Create a stack with all the array dimensions so that they can be
!      simplified from left to right (to match user expectations).  */
!   VARRAY_GENERIC_PTR_INIT (dim_stack, 10, "dim_stack");
! 
!   for (p = expr_p;
!        TREE_CODE (*p) == ARRAY_REF || TREE_CODE (*p) == COMPONENT_REF;
!        p = &TREE_OPERAND (*p, 0))
      {
!       code = TREE_CODE (*p);
!       if (code == ARRAY_REF)
! 	VARRAY_PUSH_GENERIC_PTR (dim_stack, (PTR) &TREE_OPERAND (*p, 1));
!     }
! 
!   /* Now 'p' points to the first bit that isn't an ARRAY_REF or
!      COMPONENT_REF, 'code' is the TREE_CODE of the last bit that was, and
!      'dim_stack' is a stack of pointers to all the dimensions in left to
!      right order (the leftmost dimension is at the top of the stack).
! 
!      Simplify the base, and then each of the dimensions from left to
!      right.  */
!   simplify_expr (p, pre_p, post_p, is_simple_min_lval,
! 		 code == COMPONENT_REF ? fb_either : fb_lvalue);
  
!   for (; VARRAY_ACTIVE_SIZE (dim_stack) > 0; VARRAY_POP (dim_stack))
!     {
!       tree *dim_p = (tree *)VARRAY_TOP_GENERIC_PTR (dim_stack);
!       simplify_expr (dim_p, pre_p, post_p, is_simple_val, fb_rvalue);
      }
  }
  
  /*  Simplify the self modifying expression pointed by EXPR_P (++, --, +=, -=).
--- 1238,1272 ----
      add_tree (internal_post, pre_p);
  }
  
! /* Do C-specific simplification.  Args are as for simplify_expr.  */
  
! int
! c_simplify_expr (expr_p, pre_p, post_p, simple_test_f)
       tree *expr_p;
       tree *pre_p;
       tree *post_p;
+      int (*simple_test_f) PARAMS ((tree)) ATTRIBUTE_UNUSED;
  {
!   if (pre_p == NULL)
      {
!       simplify_stmt (expr_p);
!       return 1;
      }
  
!   switch (TREE_CODE (*expr_p))
      {
!     case COMPOUND_LITERAL_EXPR:
!       simplify_compound_literal_expr (expr_p, pre_p, post_p);
!       return 1;
!       break;
  
!     case STMT_EXPR:
!       simplify_stmt_expr (expr_p, pre_p);
!       return 1;
!       break;
      }
+ 
+   return 0;
  }
  
  /*  Simplify the self modifying expression pointed by EXPR_P (++, --, +=, -=).
*************** simplify_self_mod_expr (expr_p, pre_p, p
*** 1453,1547 ****
    *expr_p = lvalue;
  }
  
- 
- /*  Simplify the COMPONENT_REF node pointed by EXPR_P.
- 
-     PRE_P points to the list where side effects that must happen before
- 	*EXPR_P should be stored.
- 
-     POST_P points to the list where side effects that must happen after
-         *EXPR_P should be stored.  */
- 
- static void
- simplify_component_ref (expr_p, pre_p, post_p)
-      tree *expr_p;
-      tree *pre_p;
-      tree *post_p;
- {
- #if 1
-   /* Handle array and member refs together for now.  When alias analysis
-      improves, we may want to go back to handling them separately.  */
-   simplify_compound_lval (expr_p, pre_p, post_p);
- #else
-   tree *p;
- 
-   if (TREE_CODE (*expr_p) != COMPONENT_REF)
-     abort ();
- 
-   for (p = expr_p; TREE_CODE (*p) == COMPONENT_REF; p = &TREE_OPERAND (*p, 0))
-     if (! is_simple_id (TREE_OPERAND (*p, 1)))
-       /* The RHS of a COMPONENT_REF should always be a FIELD_DECL.  */
-       abort ();
- 
-   /* Now we're down to the first bit that isn't a COMPONENT_REF.  */
-   simplify_expr (p, pre_p, post_p, is_simple_min_lval, fb_either);
- #endif
- }
- 
- 
- /*  Simplify the CALL_EXPR node pointed by EXPR_P.
- 
-     PRE_P points to the list where side effects that must happen before
- 	*EXPR_P should be stored.
- 
-     POST_P points to the list where side effects that must happen after
-     	*EXPR_P should be stored.  */
- 
- static void
- simplify_call_expr (expr_p, pre_p, post_p)
-      tree *expr_p;
-      tree *pre_p;
-      tree *post_p;
- {
-   if (TREE_CODE (*expr_p) != CALL_EXPR)
-     abort ();
- 
-   /* Some builtins cannot be simplified because they require specific
-      arguments (e.g., __builtin_stdarg_start).  */
-   if (!is_simplifiable_builtin (*expr_p))
-     return;
- 
-   simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_simple_id,
-                  fb_rvalue);
-   simplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p, is_simple_arglist,
-                  fb_rvalue);
- }
- 
- /*  Simplify the TREE_LIST node pointed by EXPR_P.
- 
-     PRE_P points to the list where side effects that must happen before
- 	*EXPR_P should be stored.
- 
-     POST_P points to the list where side effects that must happen after
-         *EXPR_P should be stored.  */
- 
- static void
- simplify_tree_list (expr_p, pre_p, post_p)
-      tree *expr_p;
-      tree *pre_p;
-      tree *post_p;
- {
-   tree op;
- 
-   if (TREE_CODE (*expr_p) != TREE_LIST)
-     abort ();
- 
-   for (op = *expr_p; op; op = TREE_CHAIN (op))
-     simplify_expr (&TREE_VALUE (op), pre_p, post_p, is_simple_val,
- 		   fb_rvalue);
- }
- 
- 
  /*  Convert the conditional expression pointed by EXPR_P '(p) ? a : b;'
      into
  
--- 1326,1331 ----
*************** simplify_cond_expr (expr_p, pre_p)
*** 1603,1637 ****
    *expr_p = tmp;
  }
  
- 
- /*  Simplify the MODIFY_EXPR node pointed by EXPR_P.
- 
-     PRE_P points to the list where side effects that must happen before
- 	*EXPR_P should be stored.
- 
-     POST_P points to the list where side effects that must happen after
-         *EXPR_P should be stored.  */
- 
- static void
- simplify_modify_expr (expr_p, pre_p, post_p)
-      tree *expr_p;
-      tree *pre_p;
-      tree *post_p;
- {
-   if (TREE_CODE (*expr_p) != MODIFY_EXPR
-       && TREE_CODE (*expr_p) != INIT_EXPR)
-     abort ();
- 
-   simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
- 		 is_simple_modify_expr_lhs, fb_lvalue);
-   simplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p, is_simple_rhs,
-                  fb_rvalue);
- 
-   add_tree (*expr_p, pre_p);
-   *expr_p = TREE_OPERAND (*expr_p, 0);
- }
- 
- 
  /*  Simplify TRUTH_ANDIF_EXPR and TRUTH_ORIF_EXPR expressions.  EXPR_P
      points to the expression to simplify.
  
--- 1387,1392 ----
*************** simplify_boolean_expr (expr_p, pre_p)
*** 1711,1805 ****
    *expr_p = t;
  }
  
- 
- /*  Simplifies an expression sequence.  This function simplifies each
-     expression and re-writes the original expression with the last
-     expression of the sequence in SIMPLE form.
- 
-     PRE_P points to the list where the side effects for all the expressions
- 	in the sequence will be emitted.
- 
-     POST_P points to the list where the post side effects for the last
-         expression in the sequence are emitted.  */
- 
- static void
- simplify_compound_expr (expr_p, pre_p, post_p)
-      tree *expr_p;
-      tree *pre_p;
-      tree *post_p;
- {
-   tree *expr_s, *pre_expr_s, *post_expr_s;
-   tree t, ret;
-   int i, num;
- 
-   if (TREE_CODE (*expr_p) != COMPOUND_EXPR)
-     abort ();
- 
-   /* Count all the expressions in the sequence.  */
-   num = 2;
-   t = *expr_p;
-   while (TREE_OPERAND (t, 1)
-          && TREE_CODE (TREE_OPERAND (t, 1)) == COMPOUND_EXPR)
-     {
-       num++;
-       t = TREE_OPERAND (t, 1);
-     }
- 
-   /* Collect all the expressions in the sequence into the EXPR_S array.  */
-   expr_s = (tree *) xmalloc (num * sizeof (tree));
-   memset (expr_s, 0, num * sizeof (tree));
- 
-   pre_expr_s = (tree *) xmalloc (num * sizeof (tree));
-   memset (pre_expr_s, 0, num * sizeof (tree));
- 
-   post_expr_s = (tree *) xmalloc (num * sizeof (tree));
-   memset (post_expr_s, 0, num * sizeof (tree));
- 
-   t = *expr_p;
-   for (i = 0; i < num; i++)
-     {
-       if (i < num - 1)
- 	{
- 	  expr_s[i] = TREE_OPERAND (t, 0);
- 	  t = TREE_OPERAND (t, 1);
- 	}
-       else
- 	expr_s[i] = t;
-     }
- 
- 
-   /* Simplify each expression in the array.  Add all the side effects and
-      the simplified expressions to PRE_P.  POST_P will contain the post
-      side-effects of the last expression in the sequence.  After
-      simplification, we return the last expression of the sequence.  */
-   for (i = 0; i < num; i++)
-     {
-       simplify_expr (&expr_s[i], &pre_expr_s[i], &post_expr_s[i],
- 	             is_simple_expr, fb_rvalue);
- 
-       /* Add the side-effects and the simplified expression to PRE_P.  
- 	 This is necessary because the comma operator represents a sequence
- 	 point.  */
-       add_tree (pre_expr_s[i], pre_p);
- 
-       if (i < num - 1)
- 	{
- 	  add_tree (expr_s[i], pre_p);
- 	  add_tree (post_expr_s[i], pre_p);
- 	}
-     }
- 
-   ret = expr_s[num - 1];
-   add_tree (post_expr_s[num - 1], post_p);
- 
-   free (expr_s);
-   free (pre_expr_s);
-   free (post_expr_s);
- 
-   *expr_p = ret;
- }
- 
- 
  /*  Simplify an EXPR_WITH_FILE_LOCATION.  EXPR_P points to the expression
      to simplify.
  
--- 1466,1471 ----
*************** simplify_expr_wfl (expr_p, pre_p, post_p
*** 1883,1915 ****
    add_tree (post, post_p);
  }
  
- /*  Simplify a SAVE_EXPR node.  EXPR_P points to the expression to
-     simplify.  After simplification, EXPR_P will point to a new temporary
-     that holds the original value of the SAVE_EXPR node.
- 
-     PRE_P points to the list where side effects that must happen before
-         *EXPR_P should be stored.  */
- 
- static void
- simplify_save_expr (expr_p, pre_p)
-      tree *expr_p;
-      tree *pre_p;
- {
-   if (TREE_CODE (*expr_p) != SAVE_EXPR)
-     abort ();
- 
-   /* If the operand is already a SIMPLE temporary, just re-write the
-      SAVE_EXPR node.  */
-   if (is_simple_tmp_var (TREE_OPERAND (*expr_p, 0)))
-     *expr_p = TREE_OPERAND (*expr_p, 0);
-   else
-     {
-       TREE_OPERAND (*expr_p, 0) =
- 	get_initialized_tmp_var (TREE_OPERAND (*expr_p, 0), pre_p);
-       *expr_p = TREE_OPERAND (*expr_p, 0);
-     }
- }
- 
  /* Simplify a STMT_EXPR.  EXPR_P points to the expression to simplify.
      After simplification, if the STMT_EXPR returns a value, EXPR_P will
      point to a new temporary that holds that value; otherwise it will be
--- 1549,1554 ----
*************** simplify_stmt_expr (expr_p, pre_p)
*** 1967,2004 ****
    add_tree (body, pre_p);
  }
  
- /*  Re-write the ADDR_EXPR node pointed by EXPR_P
- 
-     PRE_P points to the list where side effects that must happen before
- 	*EXPR_P should be stored.
- 
-     POST_P points to the list where side effects that must happen after
- 	*EXPR_P should be stored.  */
- 
- static void
- simplify_addr_expr (expr_p, pre_p, post_p)
-      tree *expr_p;
-      tree *pre_p;
-      tree *post_p;
- {
-   /* Check if we are dealing with an expression of the form '&*ptr'.
-      While the front end folds away '&*ptr' into 'ptr', these
-      expressions may be generated internally by the compiler (e.g.,
-      builtins like __builtin_va_end).  */
-   if (TREE_CODE (TREE_OPERAND (*expr_p, 0)) != INDIRECT_REF)
-     simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, 
- 		   is_simple_addr_expr_arg, fb_lvalue);
-   else
-     {
-       /* Fold &*EXPR into EXPR and simplify EXPR into a legal argument for
- 	 ADDR_EXPR.  Notice that we need to request an rvalue because EXPR is
- 	 already the lvalue that we were looking for originally.  */
-       *expr_p = TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0);
-       simplify_expr (expr_p, pre_p, post_p, is_simple_addr_expr_arg, fb_rvalue);
-     }
- }
- 
- 
  /* Code generation.  */
  
  /*  Replaces T; by a COMPOUND_STMT containing {T;}.  */
--- 1606,1611 ----
*************** tree_build_scope (t)
*** 2053,2059 ****
      Return the newly added list node or NULL_TREE if T was not added to
      LIST_P.  */
  
! static tree
  add_tree (t, list_p)
      tree t;
      tree *list_p;
--- 1660,1666 ----
      Return the newly added list node or NULL_TREE if T was not added to
      LIST_P.  */
  
! tree
  add_tree (t, list_p)
      tree t;
      tree *list_p;
*************** tail_expression (chain, decl_is_bad)
*** 2683,2685 ****
--- 2290,2318 ----
      }
    return NULL_TREE;
  }
+ 
+ /* Returns nonzero if STMT is a SIMPLE declaration, i.e. one with no
+    initializer.
+ 
+    This is not appropriate for static decls, so we leave them alone.  */
+ 
+ int
+ is_simple_decl_stmt (stmt)
+      tree stmt;
+ {
+   tree decl = DECL_STMT_DECL (stmt);
+   tree init = DECL_INITIAL (decl);
+ 
+   if (!is_simple_val (DECL_SIZE_UNIT (decl)))
+     return 0;
+ 
+   /* Plain decls are simple.  */
+   if (init == NULL_TREE || init == error_mark_node)
+     return 1;
+ 
+   /* Don't mess with a compile-time initializer.  */
+   if (TREE_STATIC (decl))
+     return 1;
+ 
+   return 0;
+ }
*** ./c-tree.h.~1~	Wed Aug  7 15:33:09 2002
--- ./c-tree.h	Thu Aug  8 23:34:10 2002
*************** extern void c_finish_incomplete_decl PAR
*** 327,343 ****
  extern GTY(()) tree static_ctors;
  extern GTY(()) tree static_dtors;
  
- /* In c-simplify.c  */
- extern int c_simplify_function_tree PARAMS ((tree));
- 
- /* In c-pretty-print.c  */
- extern void print_c_tree  PARAMS ((FILE*, tree));
- extern void print_c_node  PARAMS ((FILE*, tree));
- extern void debug_c_tree  PARAMS ((tree));
- extern void debug_c_node  PARAMS ((tree));
- 
- /* In c-call-graph.c  */
- extern void print_call_graph PARAMS ((FILE*, tree));
- extern void debug_call_graph PARAMS ((tree));
- 
  #endif /* ! GCC_C_TREE_H */
--- 327,330 ----
*** ./langhooks-def.h.~1~	Wed Aug  7 15:33:09 2002
--- ./langhooks-def.h	Thu Aug  8 23:12:10 2002
*************** void lhd_tree_inlining_end_inlining		PAR
*** 82,88 ****
  tree lhd_tree_inlining_convert_parm_for_inlining PARAMS ((tree, tree, tree));
  
  /* Declarations for tree simplification hooks.  */
! int lhd_simplify_function_tree			PARAMS ((tree));
  
  #define LANG_HOOKS_NAME			"GNU unknown"
  #define LANG_HOOKS_IDENTIFIER_SIZE	sizeof (struct lang_identifier)
--- 82,89 ----
  tree lhd_tree_inlining_convert_parm_for_inlining PARAMS ((tree, tree, tree));
  
  /* Declarations for tree simplification hooks.  */
! int lhd_simplify_expr			     PARAMS ((tree *, tree *, tree *,
! 						      int (*)(tree)));
  
  #define LANG_HOOKS_NAME			"GNU unknown"
  #define LANG_HOOKS_IDENTIFIER_SIZE	sizeof (struct lang_identifier)
*************** int lhd_simplify_function_tree			PARAMS 
*** 170,177 ****
  }
  
  /* Hooks for tree simplification.  */
! #define LANG_HOOKS_SIMPLIFY_FUNCTION_TREE \
!   lhd_simplify_function_tree
  
  /* Tree dump hooks.  */
  int lhd_tree_dump_dump_tree 			PARAMS ((void *, tree));
--- 171,177 ----
  }
  
  /* Hooks for tree simplification.  */
! #define LANG_HOOKS_SIMPLIFY_EXPR lhd_simplify_expr
  
  /* Tree dump hooks.  */
  int lhd_tree_dump_dump_tree 			PARAMS ((void *, tree));
*************** int lhd_tree_dump_type_quals			PARAMS ((
*** 265,271 ****
    LANG_HOOKS_TREE_DUMP_INITIALIZER, \
    LANG_HOOKS_DECLS, \
    LANG_HOOKS_FOR_TYPES_INITIALIZER, \
!   LANG_HOOKS_SIMPLIFY_FUNCTION_TREE \
  }
  
  #endif /* GCC_LANG_HOOKS_DEF_H */
--- 265,271 ----
    LANG_HOOKS_TREE_DUMP_INITIALIZER, \
    LANG_HOOKS_DECLS, \
    LANG_HOOKS_FOR_TYPES_INITIALIZER, \
!   LANG_HOOKS_SIMPLIFY_EXPR \
  }
  
  #endif /* GCC_LANG_HOOKS_DEF_H */
*** ./langhooks.c.~1~	Wed Aug  7 15:33:09 2002
--- ./langhooks.c	Thu Aug  8 22:48:37 2002
*************** lhd_expr_size (exp)
*** 436,447 ****
      return size_in_bytes (TREE_TYPE (exp));
  }
  
! /* lang_hooks.simplify_function_tree re-writes the body of function FNDECL
!    into SIMPLE form.  */
  
  int
! lhd_simplify_function_tree (fndecl)
!      tree fndecl ATTRIBUTE_UNUSED;
  {
    return 0;
  }
--- 436,449 ----
      return size_in_bytes (TREE_TYPE (exp));
  }
  
! /* lang_hooks.simplify_expr re-writes *EXPR_P into SIMPLE form.  */
  
  int
! lhd_simplify_expr (expr_p, pre_p, post_p, simple_test_f)
!      tree *expr_p ATTRIBUTE_UNUSED;
!      tree *pre_p ATTRIBUTE_UNUSED;
!      tree *post_p ATTRIBUTE_UNUSED;
!      int (*simple_test_f) PARAMS ((tree)) ATTRIBUTE_UNUSED;
  {
    return 0;
  }
*** ./langhooks.h.~1~	Wed Aug  7 15:33:09 2002
--- ./langhooks.h	Thu Aug  8 23:12:16 2002
*************** struct lang_hooks
*** 354,363 ****
  
    struct lang_hooks_for_types types;
  
!   /* Given FUNCTION_DECL tree node, this function converts the body of the
!      function into SIMPLE form.  The SIMPLE grammar is defined and
!      documented in tree-simple.c  */
!   int (*simplify_function_tree) PARAMS ((tree));
  
    /* Whenever you add entries here, make sure you adjust langhooks-def.h
       and langhooks.c accordingly.  */
--- 354,363 ----
  
    struct lang_hooks_for_types types;
  
!   /* Perform language-specific simplification on the argument.  Returns
!      1 if simplification is complete, or 0 to use default simplification
!      semantics.  */
!   int (*simplify_expr) PARAMS ((tree *, tree *, tree *, int (*)(tree)));
  
    /* Whenever you add entries here, make sure you adjust langhooks-def.h
       and langhooks.c accordingly.  */
*** ./tree-simple.c.~1~	Wed Aug  7 15:33:09 2002
--- ./tree-simple.c	Thu Aug  8 23:31:45 2002
*************** Boston, MA 02111-1307, USA.  */
*** 22,34 ****
  #include "config.h"
  #include "system.h"
  #include "tree.h"
- /* ??? SIMPLE trees use many tree nodes defined in the C front end.  These
-        should be moved to tree.def.  */ 
- #include "c-tree.h"
  #include "tree-simple.h"
  #include "output.h"
  #include "rtl.h"
  #include "expr.h"
  
  /*  SIMPLE C Grammar
    
--- 22,33 ----
  #include "config.h"
  #include "system.h"
  #include "tree.h"
  #include "tree-simple.h"
  #include "output.h"
  #include "rtl.h"
  #include "expr.h"
+ #include "diagnostic.h"
+ #include "varray.h"
  
  /*  SIMPLE C Grammar
    
*************** Boston, MA 02111-1307, USA.  */
*** 234,346 ****
  	      | RETURN val ';'
  	      | RETURN '(' val ')' ';'  */
  
- int
- is_simple_stmt (t)
-      tree t;
- {
-   if (t == NULL_TREE)
-     return 1;
- 
-   switch (TREE_CODE (t))
-     {
-     case COMPOUND_STMT:
-       return is_simple_compstmt (COMPOUND_BODY (t));
- 
-     case SCOPE_STMT:
-       return is_simple_compstmt (t);
- 
-     case EXPR_STMT:
-       return is_simple_expr (EXPR_STMT_EXPR (t));
- 
-     case IF_STMT:
-       return (is_simple_condexpr (IF_COND (t))
- 	      && is_simple_stmt (THEN_CLAUSE (t))
- 	      && is_simple_stmt (ELSE_CLAUSE (t)));
- 
-     case WHILE_STMT:
-       return (is_simple_condexpr (WHILE_COND (t))
- 	      && is_simple_stmt (WHILE_BODY (t)));
- 
-     case DO_STMT:
-       return (is_simple_condexpr (DO_COND (t))
- 	      && is_simple_stmt (DO_BODY (t)));
- 
-     case FOR_STMT:
-       {
- 	int s1, s2, s3, s4;
- 
- 	if (TREE_CODE (FOR_INIT_STMT (t)) == DECL_STMT)
- 	  s1 = 0;
- 	else
- 	  s1 = is_simple_exprseq (EXPR_STMT_EXPR (FOR_INIT_STMT (t)));
- 
- 	s2 = is_simple_condexpr (FOR_COND (t));
- 	s3 = is_simple_exprseq (FOR_EXPR (t));
- 	s4 = is_simple_stmt (FOR_BODY (t));
- 
- 	return (s1 && s2 && s3 && s4);
-       }
- 
-     /* Note that we can assume that we don't need to special case the body
-        of the switch() statement.  If we got to this stage, we can assume
-        that the switch() is properly formed (i.e., it will be a compound
-        statement containing all the case labels).  */
-     case SWITCH_STMT:
-       return (is_simple_val (SWITCH_COND (t))
- 	      && is_simple_stmt (SWITCH_BODY (t)));
- 
-     case FILE_STMT:
-     case LABEL_STMT:
-     case GOTO_STMT:
-     case ASM_STMT:
-     case CASE_LABEL:
-     case CONTINUE_STMT:
-     case BREAK_STMT:
-       return 1;
- 
-     case RETURN_STMT:
-       {
- 	tree type = TREE_TYPE (TREE_TYPE (current_function_decl));
- 	if (TREE_CODE (type) != VOID_TYPE
- 	    && RETURN_EXPR (t))
- 	  return is_simple_rhs (TREE_OPERAND (RETURN_EXPR (t), 1));
- 	else
- 	  return 1;
-       }
- 
-     case DECL_STMT:
-       return is_simple_decl_stmt (t);
- 
-     default:
-       return 0;
-     }
- }
- 
- /* Returns nonzero if STMT is a SIMPLE declaration, i.e. one with no
-    initializer.
- 
-    This is not appropriate for static decls, so we leave them alone.  */
- 
- int
- is_simple_decl_stmt (stmt)
-      tree stmt;
- {
-   tree decl = DECL_STMT_DECL (stmt);
-   tree init = DECL_INITIAL (decl);
- 
-   if (!is_simple_val (DECL_SIZE_UNIT (decl)))
-     return 0;
- 
-   /* Plain decls are simple.  */
-   if (init == NULL_TREE || init == error_mark_node)
-     return 1;
- 
-   /* Don't mess with a compile-time initializer.  */
-   if (TREE_STATIC (decl))
-     return 1;
- 
-   return 0;
- }
  
  /* Returns nonzero if T is a simple CONSTRUCTOR:
  
--- 233,238 ----
*************** is_simple_initializer (t)
*** 401,433 ****
  	      | '{' decls all_stmts '}'
  	      | '{' decls '}'  */
  
- int
- is_simple_compstmt (t)
-      tree t;
- {
-   if (t == NULL_TREE)
-     return 1;
- 
-   /* Look for '{'.  */
-   if (TREE_CODE (t) != SCOPE_STMT
-       || !SCOPE_BEGIN_P (t))
-     return 0;
- 
-   /* Test all the statements in the body.  */
-   for (t = TREE_CHAIN (t);
-        t && !(TREE_CODE (t) == SCOPE_STMT && SCOPE_END_P (t));
-        t = TREE_CHAIN (t))
-     if (!is_simple_stmt (t))
-       return 0;
- 
-   /* Look for '}'.  */
-   if (t
-       && (TREE_CODE (t) != SCOPE_STMT
- 	  || !SCOPE_END_P (t)))
-     return 0;
- 
-   return 1;
- }
  
  
  
--- 293,298 ----
*************** is_simplifiable_builtin (expr)
*** 1071,1073 ****
--- 936,1379 ----
        return 1;
      }
  }
+ 
+ /* Given a COMPOUND_EXPR TOP, reorganize all of the nested COMPOUND_EXPRs
+    so that they only appear as the second operand.  */
+ 
+ tree
+ rationalize_compound_expr (top)
+      tree top;
+ {
+   tree cur = top;
+   while (TREE_CODE (cur) == COMPOUND_EXPR)
+     {
+       tree lhs = TREE_OPERAND (cur, 0);
+       tree rhs = TREE_OPERAND (cur, 1);
+       if (TREE_CODE (lhs) == COMPOUND_EXPR)
+ 	{
+ 	  /* We have ((a, b), c).  Rearrange to (a, (b, c)).  */
+ 	  tree lhs1 = TREE_OPERAND (lhs, 0);
+ 	  tree rhs1 = TREE_OPERAND (lhs, 1);
+ 
+ 	  /* Change lhs from (a, b) to (b, c).  */
+ 	  TREE_OPERAND (lhs, 0) = rhs1;
+ 	  TREE_OPERAND (lhs, 1) = rhs;
+ 
+ 	  /* Change cur from (lhs, c) to (a, lhs), i.e. (a, (b, c)).  */
+ 	  TREE_OPERAND (cur, 0) = lhs1;
+ 	  TREE_OPERAND (cur, 1) = lhs;
+ 	}
+       else
+ 	cur = rhs;
+     }
+   return top;
+ }
+ 
+ /* Simplifies a CONSTRUCTOR node T.
+ 
+    FIXME: Should dynamic initializations from a CONSTRUCTOR be broken
+    up into multiple assignments?  */
+ 
+ void
+ simplify_constructor (t, pre_p, post_p)
+      tree t;
+      tree *pre_p;
+      tree *post_p;
+ {
+   tree elt_list;
+ 
+   if (is_simple_constructor (t))
+     return;
+ 
+   for (elt_list = CONSTRUCTOR_ELTS (t); elt_list;
+        elt_list = TREE_CHAIN (elt_list))
+     simplify_expr (&TREE_VALUE (elt_list), pre_p, post_p,
+ 		   is_simple_constructor_elt, fb_rvalue);
+ }
+ 
+ /*  Build an expression for the address of T.  Folds away INDIRECT_REF to
+     avoid confusing the simplify process.  */
+ 
+ tree
+ build_addr_expr (t)
+      tree t;
+ {
+   tree ptrtype = build_pointer_type (TREE_TYPE (t));
+   if (TREE_CODE (t) == INDIRECT_REF)
+     {
+       t = TREE_OPERAND (t, 0);
+       if (TREE_TYPE (t) != ptrtype)
+ 	t = build1 (NOP_EXPR, ptrtype, t);
+     }
+   else
+     t = build1 (ADDR_EXPR, ptrtype, t);
+ 
+   return t;
+ }
+ 
+   
+ /*  Re-write the ARRAY_REF node pointed by EXPR_P.
+ 
+     PRE_P points to the list where side effects that must happen before
+ 	*EXPR_P should be stored.
+ 
+     POST_P points to the list where side effects that must happen after
+ 	*EXPR_P should be stored.
+ 
+     FIXME: ARRAY_REF currently doesn't accept a pointer as the array
+     argument, so this simplification uses an INDIRECT_REF of ARRAY_TYPE.
+     ARRAY_REF should be extended.  */
+ 
+ void
+ simplify_array_ref (expr_p, pre_p, post_p)
+      tree *expr_p;
+      tree *pre_p;
+      tree *post_p;
+ {
+ #if 1
+   /* Handle array and member refs together for now.  When alias analysis
+      improves, we may want to go back to handling them separately.  */
+   simplify_compound_lval (expr_p, pre_p, post_p);
+ #else
+   tree *p;
+   varray_type dim_stack;
+ 
+   if (TREE_CODE (*expr_p) != ARRAY_REF)
+     abort ();
+ 
+   VARRAY_GENERIC_PTR_INIT (dim_stack, 10, "dim_stack");
+ 
+   /* Create a stack with all the dimensions of the array so that they can
+      be simplified from left to right.  */
+   for (p = expr_p; TREE_CODE (*p) == ARRAY_REF; p = &TREE_OPERAND (*p, 0))
+     VARRAY_PUSH_GENERIC_PTR (dim_stack, (PTR) &TREE_OPERAND (*p, 1));
+ 
+   /* After the loop above, 'p' points to the first non-ARRAY_REF,
+      and 'dim_stack' is a stack of pointers to all the dimensions in left
+      to right order (the leftmost dimension is at the top of the stack).
+ 
+      Simplify the base, and then each of the dimensions from left to
+      right.  */
+ 
+   simplify_expr (p, pre_p, post_p, is_simple_min_lval, fb_lvalue);
+ 
+   for (; VARRAY_ACTIVE_SIZE (dim_stack) > 0; VARRAY_POP (dim_stack))
+     {
+       tree *dim_p = (tree *)VARRAY_TOP_GENERIC_PTR (dim_stack);
+       simplify_expr (dim_p, pre_p, post_p, is_simple_val, fb_rvalue);
+     }
+ #endif
+ }
+ 
+ /* Simplify the COMPONENT_REF or ARRAY_REF node pointed by EXPR_P.
+ 
+    PRE_P points to the list where side effects that must happen before
+      *EXPR_P should be stored.
+ 
+    POST_P points to the list where side effects that must happen after
+      *EXPR_P should be stored.  */
+ 
+ void
+ simplify_compound_lval (expr_p, pre_p, post_p)
+      tree *expr_p;
+      tree *pre_p;
+      tree *post_p;
+ {
+   tree *p;
+   enum tree_code code;
+   varray_type dim_stack;
+ 
+   if (TREE_CODE (*expr_p) != ARRAY_REF && TREE_CODE (*expr_p) != COMPONENT_REF)
+     abort ();
+ 
+   /* Create a stack with all the array dimensions so that they can be
+      simplified from left to right (to match user expectations).  */
+   VARRAY_GENERIC_PTR_INIT (dim_stack, 10, "dim_stack");
+ 
+   for (p = expr_p;
+        TREE_CODE (*p) == ARRAY_REF || TREE_CODE (*p) == COMPONENT_REF;
+        p = &TREE_OPERAND (*p, 0))
+     {
+       code = TREE_CODE (*p);
+       if (code == ARRAY_REF)
+ 	VARRAY_PUSH_GENERIC_PTR (dim_stack, (PTR) &TREE_OPERAND (*p, 1));
+     }
+ 
+   /* Now 'p' points to the first bit that isn't an ARRAY_REF or
+      COMPONENT_REF, 'code' is the TREE_CODE of the last bit that was, and
+      'dim_stack' is a stack of pointers to all the dimensions in left to
+      right order (the leftmost dimension is at the top of the stack).
+ 
+      Simplify the base, and then each of the dimensions from left to
+      right.  */
+   simplify_expr (p, pre_p, post_p, is_simple_min_lval,
+ 		 code == COMPONENT_REF ? fb_either : fb_lvalue);
+ 
+   for (; VARRAY_ACTIVE_SIZE (dim_stack) > 0; VARRAY_POP (dim_stack))
+     {
+       tree *dim_p = (tree *)VARRAY_TOP_GENERIC_PTR (dim_stack);
+       simplify_expr (dim_p, pre_p, post_p, is_simple_val, fb_rvalue);
+     }
+ }
+ 
+ /*  Simplify the COMPONENT_REF node pointed by EXPR_P.
+ 
+     PRE_P points to the list where side effects that must happen before
+ 	*EXPR_P should be stored.
+ 
+     POST_P points to the list where side effects that must happen after
+         *EXPR_P should be stored.  */
+ 
+ void
+ simplify_component_ref (expr_p, pre_p, post_p)
+      tree *expr_p;
+      tree *pre_p;
+      tree *post_p;
+ {
+ #if 1
+   /* Handle array and member refs together for now.  When alias analysis
+      improves, we may want to go back to handling them separately.  */
+   simplify_compound_lval (expr_p, pre_p, post_p);
+ #else
+   tree *p;
+ 
+   if (TREE_CODE (*expr_p) != COMPONENT_REF)
+     abort ();
+ 
+   for (p = expr_p; TREE_CODE (*p) == COMPONENT_REF; p = &TREE_OPERAND (*p, 0))
+     if (! is_simple_id (TREE_OPERAND (*p, 1)))
+       /* The RHS of a COMPONENT_REF should always be a FIELD_DECL.  */
+       abort ();
+ 
+   /* Now we're down to the first bit that isn't a COMPONENT_REF.  */
+   simplify_expr (p, pre_p, post_p, is_simple_min_lval, fb_either);
+ #endif
+ }
+ 
+ 
+ /*  Simplify the CALL_EXPR node pointed by EXPR_P.
+ 
+     PRE_P points to the list where side effects that must happen before
+ 	*EXPR_P should be stored.
+ 
+     POST_P points to the list where side effects that must happen after
+     	*EXPR_P should be stored.  */
+ 
+ void
+ simplify_call_expr (expr_p, pre_p, post_p)
+      tree *expr_p;
+      tree *pre_p;
+      tree *post_p;
+ {
+   if (TREE_CODE (*expr_p) != CALL_EXPR)
+     abort ();
+ 
+   /* Some builtins cannot be simplified because they require specific
+      arguments (e.g., __builtin_stdarg_start).  */
+   if (!is_simplifiable_builtin (*expr_p))
+     return;
+ 
+   simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_simple_id,
+                  fb_rvalue);
+   simplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p, is_simple_arglist,
+                  fb_rvalue);
+ }
+ 
+ /*  Simplify the TREE_LIST node pointed by EXPR_P.
+ 
+     PRE_P points to the list where side effects that must happen before
+ 	*EXPR_P should be stored.
+ 
+     POST_P points to the list where side effects that must happen after
+         *EXPR_P should be stored.  */
+ 
+ void
+ simplify_tree_list (expr_p, pre_p, post_p)
+      tree *expr_p;
+      tree *pre_p;
+      tree *post_p;
+ {
+   tree op;
+ 
+   if (TREE_CODE (*expr_p) != TREE_LIST)
+     abort ();
+ 
+   for (op = *expr_p; op; op = TREE_CHAIN (op))
+     simplify_expr (&TREE_VALUE (op), pre_p, post_p, is_simple_val,
+ 		   fb_rvalue);
+ }
+ 
+ /*  Simplify the MODIFY_EXPR node pointed by EXPR_P.
+ 
+     PRE_P points to the list where side effects that must happen before
+ 	*EXPR_P should be stored.
+ 
+     POST_P points to the list where side effects that must happen after
+         *EXPR_P should be stored.  */
+ 
+ void
+ simplify_modify_expr (expr_p, pre_p, post_p)
+      tree *expr_p;
+      tree *pre_p;
+      tree *post_p;
+ {
+   if (TREE_CODE (*expr_p) != MODIFY_EXPR
+       && TREE_CODE (*expr_p) != INIT_EXPR)
+     abort ();
+ 
+   simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+ 		 is_simple_modify_expr_lhs, fb_lvalue);
+   simplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p, is_simple_rhs,
+                  fb_rvalue);
+ 
+   add_tree (*expr_p, pre_p);
+   *expr_p = TREE_OPERAND (*expr_p, 0);
+ }
+ 
+ 
+ /*  Simplifies an expression sequence.  This function simplifies each
+     expression and re-writes the original expression with the last
+     expression of the sequence in SIMPLE form.
+ 
+     PRE_P points to the list where the side effects for all the expressions
+ 	in the sequence will be emitted.
+ 
+     POST_P points to the list where the post side effects for the last
+         expression in the sequence are emitted.  */
+ 
+ void
+ simplify_compound_expr (expr_p, pre_p, post_p)
+      tree *expr_p;
+      tree *pre_p;
+      tree *post_p;
+ {
+   tree *expr_s, *pre_expr_s, *post_expr_s;
+   tree t, ret;
+   int i, num;
+ 
+   if (TREE_CODE (*expr_p) != COMPOUND_EXPR)
+     abort ();
+ 
+   /* Count all the expressions in the sequence.  */
+   num = 2;
+   t = *expr_p;
+   while (TREE_OPERAND (t, 1)
+          && TREE_CODE (TREE_OPERAND (t, 1)) == COMPOUND_EXPR)
+     {
+       num++;
+       t = TREE_OPERAND (t, 1);
+     }
+ 
+   /* Collect all the expressions in the sequence into the EXPR_S array.  */
+   expr_s = (tree *) xmalloc (num * sizeof (tree));
+   memset (expr_s, 0, num * sizeof (tree));
+ 
+   pre_expr_s = (tree *) xmalloc (num * sizeof (tree));
+   memset (pre_expr_s, 0, num * sizeof (tree));
+ 
+   post_expr_s = (tree *) xmalloc (num * sizeof (tree));
+   memset (post_expr_s, 0, num * sizeof (tree));
+ 
+   t = *expr_p;
+   for (i = 0; i < num; i++)
+     {
+       if (i < num - 1)
+ 	{
+ 	  expr_s[i] = TREE_OPERAND (t, 0);
+ 	  t = TREE_OPERAND (t, 1);
+ 	}
+       else
+ 	expr_s[i] = t;
+     }
+ 
+ 
+   /* Simplify each expression in the array.  Add all the side effects and
+      the simplified expressions to PRE_P.  POST_P will contain the post
+      side-effects of the last expression in the sequence.  After
+      simplification, we return the last expression of the sequence.  */
+   for (i = 0; i < num; i++)
+     {
+       simplify_expr (&expr_s[i], &pre_expr_s[i], &post_expr_s[i],
+ 	             is_simple_expr, fb_rvalue);
+ 
+       /* Add the side-effects and the simplified expression to PRE_P.  
+ 	 This is necessary because the comma operator represents a sequence
+ 	 point.  */
+       add_tree (pre_expr_s[i], pre_p);
+ 
+       if (i < num - 1)
+ 	{
+ 	  add_tree (expr_s[i], pre_p);
+ 	  add_tree (post_expr_s[i], pre_p);
+ 	}
+     }
+ 
+   ret = expr_s[num - 1];
+   add_tree (post_expr_s[num - 1], post_p);
+ 
+   free (expr_s);
+   free (pre_expr_s);
+   free (post_expr_s);
+ 
+   *expr_p = ret;
+ }
+ 
+ 
+ /*  Simplify a SAVE_EXPR node.  EXPR_P points to the expression to
+     simplify.  After simplification, EXPR_P will point to a new temporary
+     that holds the original value of the SAVE_EXPR node.
+ 
+     PRE_P points to the list where side effects that must happen before
+         *EXPR_P should be stored.  */
+ 
+ void
+ simplify_save_expr (expr_p, pre_p)
+      tree *expr_p;
+      tree *pre_p;
+ {
+   if (TREE_CODE (*expr_p) != SAVE_EXPR)
+     abort ();
+ 
+   /* If the operand is already a SIMPLE temporary, just re-write the
+      SAVE_EXPR node.  */
+   if (is_simple_tmp_var (TREE_OPERAND (*expr_p, 0)))
+     *expr_p = TREE_OPERAND (*expr_p, 0);
+   else
+     {
+       TREE_OPERAND (*expr_p, 0) =
+ 	get_initialized_tmp_var (TREE_OPERAND (*expr_p, 0), pre_p);
+       *expr_p = TREE_OPERAND (*expr_p, 0);
+     }
+ }
+ 
+ /*  Re-write the ADDR_EXPR node pointed by EXPR_P
+ 
+     PRE_P points to the list where side effects that must happen before
+ 	*EXPR_P should be stored.
+ 
+     POST_P points to the list where side effects that must happen after
+ 	*EXPR_P should be stored.  */
+ 
+ void
+ simplify_addr_expr (expr_p, pre_p, post_p)
+      tree *expr_p;
+      tree *pre_p;
+      tree *post_p;
+ {
+   /* Check if we are dealing with an expression of the form '&*ptr'.
+      While the front end folds away '&*ptr' into 'ptr', these
+      expressions may be generated internally by the compiler (e.g.,
+      builtins like __builtin_va_end).  */
+   if (TREE_CODE (TREE_OPERAND (*expr_p, 0)) != INDIRECT_REF)
+     simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, 
+ 		   is_simple_addr_expr_arg, fb_lvalue);
+   else
+     {
+       /* Fold &*EXPR into EXPR and simplify EXPR into a legal argument for
+ 	 ADDR_EXPR.  Notice that we need to request an rvalue because EXPR is
+ 	 already the lvalue that we were looking for originally.
+          ??? is_simple_addr_expr_arg is wrong here.  */
+       *expr_p = TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0);
+       simplify_expr (expr_p, pre_p, post_p, is_simple_addr_expr_arg, fb_rvalue);
+     }
+ }
*** ./tree-simple.h.~1~	Wed Aug  7 15:33:09 2002
--- ./tree-simple.h	Fri Aug  9 00:36:19 2002
*************** int is_simple_constructor_elt          P
*** 67,70 ****
--- 67,98 ----
  int is_simple_initializer              PARAMS ((tree));
  int is_simplifiable_builtin            PARAMS ((tree));
  
+ /* FIXME this needs a better name.  */
+ tree add_tree			       PARAMS ((tree, tree *));
+ /* FIXME we should deduce this from the predicate.  */
+ typedef enum fallback_t {
+   fb_rvalue=1,
+   fb_lvalue=2,
+   fb_either=1|2
+ } fallback_t;
+ void simplify_expr		       PARAMS ((tree *, tree *, tree *,
+ 						int (*) PARAMS ((tree)),
+ 						fallback_t));
+ 
+ 
+ /* FIXME These should become static decls in tree-simple.c once
+    simplify_expr moves there.  */
+ void simplify_constructor     PARAMS ((tree, tree *, tree *));
+ void simplify_array_ref       PARAMS ((tree *, tree *, tree *));
+ void simplify_compound_lval   PARAMS ((tree *, tree *, tree *));
+ void simplify_component_ref   PARAMS ((tree *, tree *, tree *));
+ void simplify_call_expr       PARAMS ((tree *, tree *, tree *));
+ void simplify_tree_list       PARAMS ((tree *, tree *, tree *));
+ void simplify_modify_expr     PARAMS ((tree *, tree *, tree *));
+ void simplify_compound_expr   PARAMS ((tree *, tree *, tree *));
+ void simplify_save_expr       PARAMS ((tree *, tree *));
+ void simplify_addr_expr       PARAMS ((tree *, tree *, tree *));
+ tree build_addr_expr	      PARAMS ((tree));
+ 
+ 
  #endif /* _TREE_SIMPLE_H */
*** ./tree.def.~1~	Wed Aug  7 15:33:09 2002
--- ./tree.def	Tue Aug  6 10:58:55 2002
*************** DEFTREECODE (TARGET_EXPR, "target_expr",
*** 443,452 ****
  DEFTREECODE (COND_EXPR, "cond_expr", 'e', 3)
  
  /* Declare local variables, including making RTL and allocating space.
!    Operand 0 is a chain of VAR_DECL nodes for the variables.
!    Operand 1 is the body, the expression to be computed using 
     the variables.  The value of operand 1 becomes that of the BIND_EXPR.
!    Operand 2 is the BLOCK that corresponds to these bindings
     for debugging purposes.  If this BIND_EXPR is actually expanded,
     that sets the TREE_USED flag in the BLOCK.
  
--- 443,452 ----
  DEFTREECODE (COND_EXPR, "cond_expr", 'e', 3)
  
  /* Declare local variables, including making RTL and allocating space.
!    BIND_EXPR_VARS is a chain of VAR_DECL nodes for the variables.
!    BIND_EXPR_BODY is the body, the expression to be computed using 
     the variables.  The value of operand 1 becomes that of the BIND_EXPR.
!    BIND_EXPR_BLOCK is the BLOCK that corresponds to these bindings
     for debugging purposes.  If this BIND_EXPR is actually expanded,
     that sets the TREE_USED flag in the BLOCK.
  
*************** DEFTREECODE (VA_ARG_EXPR, "va_arg_expr",
*** 771,778 ****
  /* Evaluate operand 1.  If and only if an exception is thrown during
     the evaluation of operand 1, evaluate operand 2.
  
!    This differs from WITH_CLEANUP_EXPR, in that operand 2 is never
!    evaluated unless an exception is throw.  */
  DEFTREECODE (TRY_CATCH_EXPR, "try_catch_expr", 'e', 2)
  
  /* Evaluate the first operand.
--- 771,778 ----
  /* Evaluate operand 1.  If and only if an exception is thrown during
     the evaluation of operand 1, evaluate operand 2.
  
!    This differs from TRY_FINALLY_EXPR in that operand 2 is not evaluated
!    on a normal or jump exit, only on an exception.  */
  DEFTREECODE (TRY_CATCH_EXPR, "try_catch_expr", 'e', 2)
  
  /* Evaluate the first operand.
*** ./tree.h.~1~	Wed Aug  7 15:33:09 2002
--- ./tree.h	Thu Aug  8 23:11:39 2002
*************** struct tree_exp GTY(())
*** 891,896 ****
--- 891,901 ----
      operands[1];
  };
  
+ /* The operands of a BIND_EXPR.  */
+ #define BIND_EXPR_VARS(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 0))
+ #define BIND_EXPR_BODY(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 1))
+ #define BIND_EXPR_BLOCK(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 2))
+ 
  /* In a BLOCK node.  */
  #define BLOCK_VARS(NODE) (BLOCK_CHECK (NODE)->block.vars)
  #define BLOCK_SUBBLOCKS(NODE) (BLOCK_CHECK (NODE)->block.subblocks)
*************** extern int dump_switch_p                
*** 3110,3115 ****
--- 3115,3121 ----
  extern void dump_enable_all_ssa         PARAMS ((void));
  const char *dump_flag_name	PARAMS ((enum tree_dump_index));
  
+ extern int simplify_function_tree      PARAMS ((tree));
  
  /* Redefine abort to report an internal error w/o coredump, and
     reporting the location of the error in the source file.  This logic
*** ./c-lang.c.~1~	Fri Aug  2 11:41:28 2002
--- ./c-lang.c	Thu Aug  8 22:49:32 2002
*************** static void c_init_options PARAMS ((void
*** 114,122 ****
  #define LANG_HOOKS_TYPE_PROMOTES_TO c_type_promotes_to
  
  /* Hooks for tree simplification.  */
! #undef LANG_HOOKS_SIMPLIFY_FUNCTION_TREE
! #define LANG_HOOKS_SIMPLIFY_FUNCTION_TREE \
!   c_simplify_function_tree
  
  /* ### When changing hooks, consider if ObjC needs changing too!! ### */
  
--- 114,121 ----
  #define LANG_HOOKS_TYPE_PROMOTES_TO c_type_promotes_to
  
  /* Hooks for tree simplification.  */
! #undef LANG_HOOKS_SIMPLIFY_EXPR
! #define LANG_HOOKS_SIMPLIFY_EXPR c_simplify_expr
  
  /* ### When changing hooks, consider if ObjC needs changing too!! ### */
  
*** ./c-decl.c.~1~	Wed Aug  7 15:27:11 2002
--- ./c-decl.c	Thu Aug  8 22:59:45 2002
*************** c_expand_body (fndecl, nested_p, can_def
*** 6713,6719 ****
    /* Simplify the function.  Don't try to optimize the function if
       simplification failed.  */
    if (!flag_disable_simple
!       && (*lang_hooks.simplify_function_tree) (fndecl))
      {
        /* Invoke the SSA tree optimizer.  */
        if (flag_tree_ssa)
--- 6713,6719 ----
    /* Simplify the function.  Don't try to optimize the function if
       simplification failed.  */
    if (!flag_disable_simple
!       && simplify_function_tree (fndecl))
      {
        /* Invoke the SSA tree optimizer.  */
        if (flag_tree_ssa)
*** ./diagnostic.h.~1~	Wed Aug  7 15:27:14 2002
--- ./diagnostic.h	Thu Aug  8 23:34:12 2002
*************** extern char *file_name_as_prefix	PARAMS 
*** 328,331 ****
--- 328,341 ----
  
  extern void debug_output_buffer		PARAMS ((output_buffer *));
  
+ /* In c-pretty-print.c  */
+ extern void print_c_tree  PARAMS ((FILE*, tree));
+ extern void print_c_node  PARAMS ((FILE*, tree));
+ extern void debug_c_tree  PARAMS ((tree));
+ extern void debug_c_node  PARAMS ((tree));
+ 
+ /* In c-call-graph.c  */
+ extern void print_call_graph PARAMS ((FILE*, tree));
+ extern void debug_call_graph PARAMS ((tree));
+ 
  #endif /* ! GCC_DIAGNOSTIC_H */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]