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] PATCH to simplify C++ cleanups


This patch implements gimplification of at least simple C++ testcases
involving cleanups for declared variables and temporaries.  For temps, this
involved introducing the conditional_context stuff from the expanders into
the tree structure.

I'm somewhat uncertain about the implementation strategy for handling
cleanups for temporaries; please see the FIXME comment before
simplify_cleanup_point_expr.  Currently it works by inserting
WITH_CLEANUP_EXPRs into the prequeue as we encounter cleanups, and then
walking through and rewriting them to TRY_FINALLY_EXPRs when we're done
simplifying everything under a CLEANUP_POINT_EXPR.  A simpler approach
would be to always use a flag and insert all the TRY_FINALLY_EXPRs at the
cleaunp point, but that would demand more out of the optimizers.  Thoughts?

2002-11-24  Jason Merrill  <jason@redhat.com>

	Gimplify C++ cleanups.
	* gimplify.c (voidify_wrapper_expr): Split out from...
	(simplify_bind_expr): ...here.
	(simplify_cleanup_point_expr): New fn.
	(simplify_target_expr): New fn.
	(gimple_conditional_context): New fn.
	(gimple_push_condition, gimple_pop_condition): New fns.
	(simplify_expr) [TRY_CATCH_EXPR]: Handle like TRY_FINALLY_EXPR.
	* c-simplify.c (simplify_cleanup): New fn.
	(c_simplify_stmt): Call it and lang_simplify_stmt.
	(simplify_expr_stmt): Wrap the expr in a CLEANUP_POINT_EXPR.
	(simplify_return_stmt, simplify_decl_stmt): Likewise.
	(simplify_stmt_expr): Handle the STMT_EXPR_NO_SCOPE case.
	(is_last_stmt_of_scope): Likewise.
	* c-common.h: Declare c_genericize, c_simplify_stmt and 
	lang_simplify_stmt.
	* c-common.c (lang_simplify_stmt): Define.

	Gimplify EXIT_EXPRs.
	* gimplify.c (gimplify_loop_expr, gimplify_exit_expr): New fns.
	(simplify_expr): Call them.
	* expr.c (expand_expr) [LOOP_EXPR]: Pass 1 again for exit_flag.

	* tree-simple.c (right_assocify_expr): Also set TREE_SIDE_EFFECTS.

	* gimplify.c (simplify_expr): Call STRIP_TYPE_NOPS.
	[REALPART_EXPR]: Don't just return.

	* tree-pretty-print.c (dump_c_node): Handle REFERENCE_TYPE.
	* c-pretty-print.c (dump_c_node): Likewise.  Handle null FOR_INIT_STMT.

cp/:
2002-11-24  Jason Merrill  <jason@redhat.com>

	Gimplify C++ cleanups.
	* decl.c (finish_function): Call c_genericize.
	* cp-simplify.c (cp_simplify_stmt): New fn.
	(genericize_try_block): New fn.
	(cp_simplify_expr): Move INIT_EXPR/TARGET_EXPR code
	to ../gimplify.c.  Handle AGGR_INIT_EXPR.
	(simplify_target_expr): Move to ../gimplify.c.
	(maybe_fixup_loop_cond): Remove.
	(simplify_aggr_init_expr): Split out from...
	* semantics.c (simplify_aggr_init_exprs_r): ...here.
	(expand_body): Don't simplify AGGR_INIT_EXPRs here
	if we're gimplifying.  Handle expanding generic trees.
	* tree.c (init_tree): Set lang_simplify_stmt.
	* cp-tree.h: Declare the new fns.

	* optimize.c (optimize_function): Do pretty dumps.

Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.344.2.16
diff -c -p -r1.344.2.16 c-common.c
*** c-common.c	6 Nov 2002 12:20:56 -0000	1.344.2.16
--- c-common.c	26 Nov 2002 22:36:18 -0000
*************** tree (*make_fname_decl)                P
*** 660,665 ****
--- 660,670 ----
     returns 1 for language-specific statement codes.  */
  int (*lang_statement_code_p)           PARAMS ((enum tree_code));
  
+ /* If non-NULL, the address of a language-specific function that does any
+    language-specific simplification for _STMT nodes and returns 1 iff
+    handled.  */
+ int (*lang_simplify_stmt)           PARAMS ((tree *, tree *));
+ 
  /* If non-NULL, the address of a language-specific function that takes
     any action required right before expand_function_end is called.  */
  void (*lang_expand_function_end)       PARAMS ((void));
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.141.2.13
diff -c -p -r1.141.2.13 c-common.h
*** c-common.h	18 Oct 2002 03:36:38 -0000	1.141.2.13
--- c-common.h	26 Nov 2002 22:36:18 -0000
*************** struct c_language_function GTY(()) {
*** 312,317 ****
--- 312,318 ----
  
  extern int (*lang_statement_code_p)             PARAMS ((enum tree_code));
  extern void (*lang_expand_stmt)                 PARAMS ((tree));
+ extern int (*lang_simplify_stmt)                PARAMS ((tree *, tree *));
  extern void (*lang_expand_decl_stmt)            PARAMS ((tree));
  extern void (*lang_expand_function_end)         PARAMS ((void));
  extern tree gettags				PARAMS ((void));
*************** extern void print_c_node_brief		PARAMS (
*** 1227,1231 ****
--- 1228,1236 ----
  extern void debug_c_tree		PARAMS ((tree));
  extern void debug_c_node		PARAMS ((tree));
  extern void debug_c_node_brief		PARAMS ((tree));
+ 
+ /* In c-simplify.c  */
+ extern void c_genericize		PARAMS ((tree));
+ extern void c_simplify_stmt		PARAMS ((tree *));
  
  #endif /* ! GCC_C_COMMON_H */
Index: c-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-pretty-print.c,v
retrieving revision 1.1.4.16
diff -c -p -r1.1.4.16 c-pretty-print.c
*** c-pretty-print.c	17 Nov 2002 14:39:36 -0000	1.1.4.16
--- c-pretty-print.c	26 Nov 2002 22:36:18 -0000
*************** dump_c_node (buffer, node, spc, brief_du
*** 294,306 ****
  	  }
  	break;
        }
      case POINTER_TYPE:
        if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
          {
  	  tree fnode = TREE_TYPE (node);
  	  dump_c_node (buffer, TREE_TYPE (fnode), spc, brief_dump);
  	  output_add_space (buffer);
! 	  output_add_string (buffer, "(*");
  	  if (TYPE_NAME (node) && DECL_NAME (TYPE_NAME (node)))
  	    output_add_string (buffer, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))));
  	  else
--- 294,311 ----
  	  }
  	break;
        }
+ 
      case POINTER_TYPE:
+     case REFERENCE_TYPE:
+       str = (TREE_CODE (node) == POINTER_TYPE ? "*" : "&");
+ 
        if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
          {
  	  tree fnode = TREE_TYPE (node);
  	  dump_c_node (buffer, TREE_TYPE (fnode), spc, brief_dump);
  	  output_add_space (buffer);
! 	  output_add_character (buffer, '(');
! 	  output_add_string (buffer, str);
  	  if (TYPE_NAME (node) && DECL_NAME (TYPE_NAME (node)))
  	    output_add_string (buffer, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))));
  	  else
*************** dump_c_node (buffer, node, spc, brief_du
*** 331,337 ****
  	  unsigned int quals = TYPE_QUALS (node);
  
            dump_c_node (buffer, TREE_TYPE (node), spc, brief_dump);
! 	  output_add_string (buffer, " *");
  	  
  	  if (quals & TYPE_QUAL_CONST)
  	    output_add_string (buffer, " const");
--- 336,343 ----
  	  unsigned int quals = TYPE_QUALS (node);
  
            dump_c_node (buffer, TREE_TYPE (node), spc, brief_dump);
! 	  output_add_space (buffer);
! 	  output_add_string (buffer, str);
  	  
  	  if (quals & TYPE_QUAL_CONST)
  	    output_add_string (buffer, " const");
*************** dump_c_node (buffer, node, spc, brief_du
*** 348,358 ****
        NIY;
        break;
  
-     case REFERENCE_TYPE:
-       /* FIXME : What is the exact syntax of this node for C? */
-       dump_c_node (buffer, TREE_TYPE (node), spc, brief_dump);
-       break;
- 
      case METHOD_TYPE:
        output_add_string (buffer, IDENTIFIER_POINTER 
  			 (DECL_NAME (TYPE_NAME (TYPE_METHOD_BASETYPE (node)))));
--- 354,359 ----
*************** dump_c_node (buffer, node, spc, brief_du
*** 1212,1218 ****
      case FOR_STMT:
        INDENT (spc);
        output_add_string (buffer, "for (");
!       if (TREE_CODE (FOR_INIT_STMT (node)) == EXPR_STMT)
  	{
  	  dump_c_node (buffer, EXPR_STMT_EXPR (FOR_INIT_STMT (node)), 0,
  		       brief_dump);
--- 1213,1221 ----
      case FOR_STMT:
        INDENT (spc);
        output_add_string (buffer, "for (");
!       if (FOR_INIT_STMT (node) == NULL_TREE)
! 	output_add_character (buffer, ';');
!       else if (TREE_CODE (FOR_INIT_STMT (node)) == EXPR_STMT)
  	{
  	  dump_c_node (buffer, EXPR_STMT_EXPR (FOR_INIT_STMT (node)), 0,
  		       brief_dump);
Index: c-simplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/c-simplify.c,v
retrieving revision 1.1.4.32
diff -c -p -r1.1.4.32 c-simplify.c
*** c-simplify.c	17 Nov 2002 14:39:36 -0000	1.1.4.32
--- c-simplify.c	26 Nov 2002 22:36:18 -0000
*************** static void simplify_compound_literal_ex
*** 80,85 ****
--- 80,86 ----
  static void make_type_writable       PARAMS ((tree));
  static int is_last_stmt_of_scope     PARAMS ((tree));
  static void simplify_block	     PARAMS ((tree *, tree *));
+ static void simplify_cleanup	     PARAMS ((tree *, tree *));
  static tree simplify_c_loop	     PARAMS ((tree, tree, tree, int));
  static void push_context             PARAMS ((void));
  static void pop_context              PARAMS ((void));
*************** c_simplify_stmt (stmt_p)
*** 238,245 ****
  	  break;
  
  	case CLEANUP_STMT:
! 	  abort ();
! 	  goto cont;
  
  	case ASM_STMT:
  	  stmt = build (ASM_EXPR, void_type_node, ASM_STRING (stmt),
--- 239,246 ----
  	  break;
  
  	case CLEANUP_STMT:
! 	  simplify_cleanup (&stmt, &next);
! 	  break;
  
  	case ASM_STMT:
  	  stmt = build (ASM_EXPR, void_type_node, ASM_STRING (stmt),
*************** c_simplify_stmt (stmt_p)
*** 254,259 ****
--- 255,263 ----
  	  goto cont;
  
  	default:
+ 	  if (lang_simplify_stmt && (*lang_simplify_stmt) (&stmt, &next))
+ 	    break;
+ 
  	  fprintf (stderr, "unhandled statement node in c_simplify_stmt ():\n");
  	  debug_tree (stmt);
  	  abort ();
*************** simplify_block (stmt_p, next_p)
*** 378,383 ****
--- 382,407 ----
    *stmt_p = bind;
  }
  
+ /* Genericize a CLEANUP_STMT.  Just wrap everything from here to the end of
+    the block in a TRY_FINALLY_EXPR.  Or a TRY_CATCH_EXPR, if it's an
+    EH-only cleanup.  */
+ 
+ static void
+ simplify_cleanup (stmt_p, next_p)
+      tree *stmt_p;
+      tree *next_p;
+ {
+   tree stmt = *stmt_p;
+   tree body = TREE_CHAIN (stmt);
+   enum tree_code code
+     = (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR);
+ 
+   c_simplify_stmt (&body);
+ 
+   *stmt_p = build (code, void_type_node, body, CLEANUP_EXPR (stmt));
+   *next_p = NULL_TREE;
+ }
+ 
  /*  Simplify an EXPR_STMT node.
  
      STMT is the statement node.
*************** simplify_expr_stmt (stmt_p)
*** 418,423 ****
--- 442,449 ----
  	}
      }
  
+   if (stmts_are_full_exprs_p ())
+     stmt = build1 (CLEANUP_POINT_EXPR, void_type_node, stmt);
    *stmt_p = stmt;
  }
  
*************** simplify_c_loop (cond, body, incr, cond_
*** 514,527 ****
  
    if (cond)
      {
- #if 0
-       exit = build (EXIT_EXPR, void_type_node, cond);
-       EXIT_EXPR_IS_LOOP_COND (exit) = 1;
- #else 
        exit = build_bc_goto (bc_break);
        exit = build (COND_EXPR, void_type_node, cond, empty_stmt_node, exit);
        exit = fold (exit);
- #endif
      }
    else
      exit = NULL_TREE;
--- 540,548 ----
*************** simplify_if_stmt (stmt_p)
*** 604,614 ****
    tree stmt = *stmt_p;
    tree then_ = THEN_CLAUSE (stmt);
    tree else_ = ELSE_CLAUSE (stmt);
  
    c_simplify_stmt (&then_);
    c_simplify_stmt (&else_);
  
!   *stmt_p = build (COND_EXPR, void_type_node, IF_COND (stmt), then_, else_);
  }
  
  /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
--- 625,636 ----
    tree stmt = *stmt_p;
    tree then_ = THEN_CLAUSE (stmt);
    tree else_ = ELSE_CLAUSE (stmt);
+   tree cond = IF_COND (stmt);
  
    c_simplify_stmt (&then_);
    c_simplify_stmt (&else_);
  
!   *stmt_p = build (COND_EXPR, void_type_node, cond, then_, else_);
  }
  
  /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
*************** simplify_switch_stmt (stmt_p)
*** 620,632 ****
    tree stmt = *stmt_p;
    tree body = SWITCH_BODY (stmt);
    tree break_block, switch_;
  
    break_block = begin_bc_block (bc_break);
  
    c_simplify_stmt (&body);
  
!   switch_ = build (SWITCH_EXPR, void_type_node, SWITCH_COND (stmt), body,
! 		   NULL_TREE);
  
    switch_ = finish_bc_block (break_block, switch_);
  
--- 642,654 ----
    tree stmt = *stmt_p;
    tree body = SWITCH_BODY (stmt);
    tree break_block, switch_;
+   tree cond = SWITCH_COND (stmt);
  
    break_block = begin_bc_block (bc_break);
  
    c_simplify_stmt (&body);
  
!   switch_ = build (SWITCH_EXPR, void_type_node, cond, body, NULL_TREE);
  
    switch_ = finish_bc_block (break_block, switch_);
  
*************** static void
*** 639,646 ****
  simplify_return_stmt (stmt_p)
       tree *stmt_p;
  {
!   tree stmt = *stmt_p;
!   *stmt_p = build (RETURN_EXPR, void_type_node, RETURN_STMT_EXPR (stmt));
  }
  
  /*  Simplifies a DECL_STMT node T.
--- 661,671 ----
  simplify_return_stmt (stmt_p)
       tree *stmt_p;
  {
!   tree expr = RETURN_STMT_EXPR (*stmt_p);
!   expr = build1 (RETURN_EXPR, void_type_node, expr);
!   if (stmts_are_full_exprs_p ())
!     expr = build1 (CLEANUP_POINT_EXPR, void_type_node, expr);
!   *stmt_p = expr;
  }
  
  /*  Simplifies a DECL_STMT node T.
*************** simplify_decl_stmt (stmt_p, next_p)
*** 709,715 ****
        if (init && init != error_mark_node && !TREE_STATIC (decl))
  	{
  	  DECL_INITIAL (decl) = NULL_TREE;
! 	  add_tree (build (MODIFY_EXPR, void_type_node, decl, init), &pre);
  	}
      }
  
--- 734,743 ----
        if (init && init != error_mark_node && !TREE_STATIC (decl))
  	{
  	  DECL_INITIAL (decl) = NULL_TREE;
! 	  init = build (MODIFY_EXPR, void_type_node, decl, init);
! 	  if (stmts_are_full_exprs_p ())
! 	    init = build1 (CLEANUP_POINT_EXPR, void_type_node, init);
! 	  add_tree (init, &pre);
  	}
      }
  
*************** simplify_stmt_expr (expr_p)
*** 807,822 ****
        c_simplify_stmt (&body);
  
        /* Now retrofit that last expression into the BIND_EXPR.  */
!       bind = body;
!       STRIP_WFL (bind);
!       substmt = BIND_EXPR_BODY (bind);
        if (substmt == empty_stmt_node)
  	substmt = last_expr;
        else
  	substmt = build (COMPOUND_EXPR, TREE_TYPE (last_expr),
  			 substmt, last_expr);
!       BIND_EXPR_BODY (bind) = substmt;
!       TREE_TYPE (bind) = TREE_TYPE (body) = TREE_TYPE (last_expr);
      }
  
    *expr_p = body;
--- 835,860 ----
        c_simplify_stmt (&body);
  
        /* Now retrofit that last expression into the BIND_EXPR.  */
!       if (!STMT_EXPR_NO_SCOPE (*expr_p))
! 	{
! 	  bind = body;
! 	  STRIP_WFL (bind);
! 	  substmt = BIND_EXPR_BODY (bind);
! 	}
!       else
! 	substmt = body;
! 
        if (substmt == empty_stmt_node)
  	substmt = last_expr;
        else
  	substmt = build (COMPOUND_EXPR, TREE_TYPE (last_expr),
  			 substmt, last_expr);
! 
!       if (!STMT_EXPR_NO_SCOPE (*expr_p))
! 	{
! 	  BIND_EXPR_BODY (bind) = substmt;
! 	  TREE_TYPE (bind) = TREE_TYPE (body) = TREE_TYPE (last_expr);
! 	}
      }
  
    *expr_p = body;
*************** static int
*** 1040,1046 ****
  is_last_stmt_of_scope (stmt)
       tree stmt;
  {
!   return (TREE_CHAIN (stmt)
! 	  && TREE_CODE (TREE_CHAIN (stmt)) == SCOPE_STMT
! 	  && SCOPE_END_P (TREE_CHAIN (stmt)));
  }
--- 1078,1084 ----
  is_last_stmt_of_scope (stmt)
       tree stmt;
  {
!   return (TREE_CHAIN (stmt) == NULL_TREE
! 	  || (TREE_CODE (TREE_CHAIN (stmt)) == SCOPE_STMT
! 	      && SCOPE_END_P (TREE_CHAIN (stmt))));
  }
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.467.2.15
diff -c -p -r1.467.2.15 expr.c
*** expr.c	25 Nov 2002 04:24:57 -0000	1.467.2.15
--- expr.c	26 Nov 2002 22:36:20 -0000
*************** expand_expr (exp, target, tmode, modifie
*** 6892,6898 ****
  
      case LOOP_EXPR:
        push_temp_slots ();
!       expand_start_loop (0);
        expand_expr_stmt_value (TREE_OPERAND (exp, 0), 0, 1);
        expand_end_loop ();
        pop_temp_slots ();
--- 6892,6898 ----
  
      case LOOP_EXPR:
        push_temp_slots ();
!       expand_start_loop (1);
        expand_expr_stmt_value (TREE_OPERAND (exp, 0), 0, 1);
        expand_end_loop ();
        pop_temp_slots ();
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimplify.c,v
retrieving revision 1.1.2.8
diff -c -p -r1.1.2.8 gimplify.c
*** gimplify.c	17 Nov 2002 14:39:37 -0000	1.1.2.8
--- gimplify.c	26 Nov 2002 22:36:20 -0000
*************** static tree build_addr_expr	     PARAMS 
*** 54,73 ****
  static tree add_stmt_to_compound	PARAMS ((tree, tree));
  static void simplify_asm_expr		PARAMS ((tree, tree *));
  static void simplify_bind_expr		PARAMS ((tree *, tree *));
! static inline void remove_suffix     PARAMS ((char *, int));
  static void push_gimplify_context	PARAMS ((void));
  static void pop_gimplify_context	PARAMS ((void));
! static void wrap_with_wfl PARAMS ((tree *));
! static tree copy_if_shared_r         PARAMS ((tree *, int *, void *));
! static tree unmark_visited_r         PARAMS ((tree *, int *, void *));
! static tree mostly_copy_tree_r       PARAMS ((tree *, int *, void *));
  
  static struct gimplify_ctx
  {
    tree current_bind_expr;
    tree temps;
  } *gimplify_ctxp;
-   
  
  static void
  push_gimplify_context ()
--- 54,84 ----
  static tree add_stmt_to_compound	PARAMS ((tree, tree));
  static void simplify_asm_expr		PARAMS ((tree, tree *));
  static void simplify_bind_expr		PARAMS ((tree *, tree *));
! static inline void remove_suffix	PARAMS ((char *, int));
  static void push_gimplify_context	PARAMS ((void));
  static void pop_gimplify_context	PARAMS ((void));
! static void wrap_with_wfl		PARAMS ((tree *));
! static tree copy_if_shared_r		PARAMS ((tree *, int *, void *));
! static tree unmark_visited_r		PARAMS ((tree *, int *, void *));
! static tree mostly_copy_tree_r		PARAMS ((tree *, int *, void *));
! static void simplify_target_expr	PARAMS ((tree *, tree *, tree *));
! static void simplify_cleanup_point_expr PARAMS ((tree *, tree *));
! static bool gimple_conditional_context	PARAMS ((void));
! static void gimple_push_condition	PARAMS ((void));
! static void gimple_pop_condition	PARAMS ((tree *));
! static tree voidify_wrapper_expr	PARAMS ((tree));
! static void gimple_push_cleanup		PARAMS ((tree, tree *));
! static void gimplify_loop_expr		PARAMS ((tree *));
! static void gimplify_exit_expr		PARAMS ((tree *, tree *));
  
  static struct gimplify_ctx
  {
    tree current_bind_expr;
    tree temps;
+   tree conditional_cleanups;
+   int conditions;
+   tree exit_label;
  } *gimplify_ctxp;
  
  static void
  push_gimplify_context ()
*************** gimple_current_bind_expr ()
*** 107,112 ****
--- 118,157 ----
    return gimplify_ctxp->current_bind_expr;
  }
  
+ /* Returns true iff there is a COND_EXPR between us and the innermost
+    CLEANUP_POINT_EXPR.  This info is used by gimple_push_cleanup.  */
+ 
+ static bool
+ gimple_conditional_context ()
+ {
+   return gimplify_ctxp->conditions > 0;
+ }
+ 
+ /* Note that we've entered a COND_EXPR.  */
+ 
+ static void
+ gimple_push_condition ()
+ {
+   ++(gimplify_ctxp->conditions);
+ }
+ 
+ /* Note that we've left a COND_EXPR.  If we're back at unconditional scope
+    now, add any conditional cleanups we've seen to the prequeue.  */
+ 
+ static void
+ gimple_pop_condition (pre_p)
+      tree *pre_p;
+ {
+   int conds = --(gimplify_ctxp->conditions);
+   if (conds == 0)
+     {
+       add_tree (gimplify_ctxp->conditional_cleanups, pre_p);
+       gimplify_ctxp->conditional_cleanups = NULL_TREE;
+     }
+   else if (conds < 0)
+     abort ();
+ }
+ 
  /*  Entry point to the simplification pass.  FNDECL is the FUNCTION_DECL
      node for the function we want to simplify.  */
  
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 218,223 ****
--- 263,271 ----
    if (post_p == NULL)
      post_p = &internal_post;
  
+   /* First strip any uselessness.  */
+   STRIP_TYPE_NOPS (*expr_p);
+ 
    /* Loop over the specific simplifiers until the toplevel node remains the
       same.  */
    do
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 270,277 ****
  
  	case REALPART_EXPR:
  	case IMAGPART_EXPR:
! 	  return simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
! 				simple_test_f, fallback);
  
  	case MODIFY_EXPR:
  	case INIT_EXPR:
--- 318,326 ----
  
  	case REALPART_EXPR:
  	case IMAGPART_EXPR:
! 	  simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
! 			 simple_test_f, fallback);
! 	  break;
  
  	case MODIFY_EXPR:
  	case INIT_EXPR:
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 337,343 ****
  	  break;
  
  	case LOOP_EXPR:
! 	  simplify_stmt (&LOOP_EXPR_BODY (*expr_p));
  	  break;
  
  	case SWITCH_EXPR:
--- 386,392 ----
  	  break;
  
  	case LOOP_EXPR:
! 	  gimplify_loop_expr (expr_p);
  	  break;
  
  	case SWITCH_EXPR:
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 352,359 ****
  	  break;
  
  	case EXIT_EXPR:
! 	  simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, NULL,
! 			 is_simple_condexpr, fb_rvalue);
  	  break;
  
  	case GOTO_EXPR:
--- 401,407 ----
  	  break;
  
  	case EXIT_EXPR:
! 	  gimplify_exit_expr (expr_p, pre_p);
  	  break;
  
  	case GOTO_EXPR:
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 407,416 ****
--- 455,479 ----
  	  break;
  
  	case TRY_FINALLY_EXPR:
+ 	case TRY_CATCH_EXPR:
  	  simplify_stmt (&TREE_OPERAND (*expr_p, 0));
  	  simplify_stmt (&TREE_OPERAND (*expr_p, 1));
  	  break;
  
+ 	case CLEANUP_POINT_EXPR:
+ 	  simplify_cleanup_point_expr (expr_p, pre_p);
+ 	  break;
+ 
+ 	case TARGET_EXPR:
+ 	  simplify_target_expr (expr_p, pre_p, post_p);
+ 	  break;
+ 
+ 	  /* FIXME
+ 	case MIN_EXPR:
+ 	case MAX_EXPR:
+ 	  simplify_minimax_expr (expr_p, pre_p);
+ 	  break; */
+ 
  	  /* If *EXPR_P does not need to be special-cased, handle it
  	     according to its class.  */
  	default:
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 514,533 ****
    return 1;
  }
  
! static void
! simplify_bind_expr (expr_p, pre_p)
!      tree *expr_p;
!      tree *pre_p;
! {
!   tree bind_expr = *expr_p;
  
!   if (!VOID_TYPE_P (TREE_TYPE (bind_expr)))
      {
        tree *p;
        tree temp;
  
!       for (p = &BIND_EXPR_BODY (bind_expr);
! 	   TREE_CODE (*p) == COMPOUND_EXPR;
  	   p = &TREE_OPERAND (*p, 1))
  	{
  	  /* Advance.  Set up the COMPOUND_EXPRs appropriately for what we
--- 577,610 ----
    return 1;
  }
  
! /* WRAPPER is a code such as BIND_EXPR or CLEANUP_POINT_EXPR which can both
!    contain statements and have a value.  Assign its value to a temporary
!    and give it void_type_node.  Returns the temporary, or NULL_TREE if
!    WRAPPER was already void.  */
  
! static tree
! voidify_wrapper_expr (wrapper)
!      tree wrapper;
! {
!   if (!VOID_TYPE_P (TREE_TYPE (wrapper)))
      {
        tree *p;
        tree temp;
  
!       /* Set p to point to the body of the wrapper.  */
!       switch (TREE_CODE (wrapper))
! 	{
! 	case BIND_EXPR:
! 	  /* For a BIND_EXPR, the body is operand 1.  */
! 	  p = &BIND_EXPR_BODY (wrapper);
! 	  break;
! 
! 	default:
! 	  p = &TREE_OPERAND (wrapper, 0);
! 	  break;
! 	}
! 
!       for (; TREE_CODE (*p) == COMPOUND_EXPR;
  	   p = &TREE_OPERAND (*p, 1))
  	{
  	  /* Advance.  Set up the COMPOUND_EXPRs appropriately for what we
*************** simplify_bind_expr (expr_p, pre_p)
*** 543,562 ****
  	}
        else
  	{
! 	  temp = create_tmp_var (TREE_TYPE (bind_expr), "retval");
  	  if (*p != empty_stmt_node)
  	    *p = build (MODIFY_EXPR, TREE_TYPE (temp), temp, *p);
  	}
  
!       *expr_p = temp;
!       TREE_TYPE (bind_expr) = void_type_node;
!       add_tree (bind_expr, pre_p);
      }
  
    gimple_push_bind_expr (bind_expr);
    simplify_stmt (&BIND_EXPR_BODY (bind_expr));
    gimple_pop_bind_expr ();
  
  #if 0
    if (!BIND_EXPR_VARS (bind_expr))
      *expr_p = BIND_EXPR_BODY (bind_expr);
--- 620,657 ----
  	}
        else
  	{
! 	  temp = create_tmp_var (TREE_TYPE (wrapper), "retval");
  	  if (*p != empty_stmt_node)
  	    *p = build (MODIFY_EXPR, TREE_TYPE (temp), temp, *p);
  	}
  
!       TREE_TYPE (wrapper) = void_type_node;
!       return temp;
      }
  
+   return NULL_TREE;
+ }
+ 
+ /* Simplify a BIND_EXPR.  Just voidify and recurse.  */
+ 
+ static void
+ simplify_bind_expr (expr_p, pre_p)
+      tree *expr_p;
+      tree *pre_p;
+ {
+   tree bind_expr = *expr_p;
+   tree temp = voidify_wrapper_expr (bind_expr);
+ 
    gimple_push_bind_expr (bind_expr);
    simplify_stmt (&BIND_EXPR_BODY (bind_expr));
    gimple_pop_bind_expr ();
  
+   if (temp)
+     {
+       *expr_p = temp;
+       add_tree (bind_expr, pre_p);
+     }
+ 
  #if 0
    if (!BIND_EXPR_VARS (bind_expr))
      *expr_p = BIND_EXPR_BODY (bind_expr);
*************** simplify_return_expr (stmt, pre_p)
*** 605,610 ****
--- 700,756 ----
      }
  }
  
+ /* Simplify a LOOP_EXPR.  Normally this just involves simplifying the body,
+    but if the loop contains an EXIT_EXPR, we need to append a label for it
+    to jump to.  */
+ 
+ static void
+ gimplify_loop_expr (expr_p)
+      tree *expr_p;
+ {
+   tree saved_label = gimplify_ctxp->exit_label;
+   gimplify_ctxp->exit_label = NULL_TREE;
+ 
+   simplify_stmt (&LOOP_EXPR_BODY (*expr_p));
+ 
+   if (gimplify_ctxp->exit_label)
+     {
+       tree expr = build1 (LABEL_EXPR, void_type_node,
+ 			  gimplify_ctxp->exit_label);
+       add_tree (expr, expr_p);
+       gimplify_ctxp->exit_label = saved_label;
+     }
+ }
+ 
+ /* Simplify an EXIT_EXPR by converting to a GOTO_EXPR inside a COND_EXPR.
+    This also involves building a label to jump to and communicating it to
+    gimplify_loop_expr through gimplify_ctxp->exit_label.  */
+ 
+ static void
+ gimplify_exit_expr (expr_p, pre_p)
+      tree *expr_p;
+      tree *pre_p;
+ {
+   tree cond = TREE_OPERAND (*expr_p, 0);
+   tree label = gimplify_ctxp->exit_label;
+   tree expr;
+ 
+   if (label == NULL_TREE)
+     {
+       label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+       DECL_ARTIFICIAL (label) = 1;
+       TREE_USED (label) = 1;
+       DECL_CONTEXT (label) = current_function_decl;
+       gimplify_ctxp->exit_label = label;
+     }
+ 
+   simplify_expr (&cond, pre_p, NULL, is_simple_condexpr, fb_rvalue);
+ 
+   expr = build1 (GOTO_EXPR, void_type_node, label);
+   expr = build (COND_EXPR, void_type_node, cond, expr, empty_stmt_node);
+   *expr_p = expr;
+ }
+ 
  /* Simplifies a CONSTRUCTOR node T.
  
     FIXME: Should dynamic initializations from a CONSTRUCTOR be broken
*************** simplify_cond_expr (expr_p, pre_p)
*** 975,983 ****
--- 1121,1134 ----
    /* Now do the normal simplification.  */
    simplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
  		 is_simple_condexpr, fb_rvalue);
+ 
+   gimple_push_condition ();
+   
    simplify_stmt (&TREE_OPERAND (expr, 1));
    simplify_stmt (&TREE_OPERAND (expr, 2));
  
+   gimple_pop_condition (pre_p);
+ 
    /* If we had a value, move the COND_EXPR to the prequeue and use the temp
       in its place.  */
    if (tmp)
*************** simplify_modify_expr (expr_p, pre_p, pos
*** 1004,1015 ****
--- 1155,1178 ----
       tree *pre_p;
       tree *post_p;
  {
+   tree *from;
+   
  #if defined ENABLE_CHECKING
    if (TREE_CODE (*expr_p) != MODIFY_EXPR
        && TREE_CODE (*expr_p) != INIT_EXPR)
      abort ();
  #endif
  
+   /* If we are initializing something from a TARGET_EXPR, strip the
+      TARGET_EXPR and initialize it directly.  */
+   /* What about code that pulls out the temp and uses it elsewhere?  I
+      think that such code never uses the TARGET_EXPR as an initializer.  If
+      I'm wrong, we'll abort because the temp won't have any RTL.  In that
+      case, I guess we'll need to replace references somehow.  */
+   from = &TREE_OPERAND (*expr_p, 1);
+   if (TREE_CODE (*from) == TARGET_EXPR)
+     *from = TARGET_EXPR_INITIAL (*from);
+ 
    /* The distinction between MODIFY_EXPR and INIT_EXPR is no longer
       useful.  */
    if (TREE_CODE (*expr_p) == INIT_EXPR)
*************** mark_not_simple (expr_p)
*** 1696,1699 ****
--- 1859,2012 ----
       tree *expr_p;
  {
    TREE_NOT_GIMPLE (*expr_p) = 1;
+ }
+ 
+ /* Simplify a CLEANUP_POINT_EXPR.  Currently this works by adding
+    WITH_CLEANUP_EXPRs to the prequeue as we encounter cleanups while
+    simplifying the body, and converting them to TRY_FINALLY_EXPRs when we
+    return to this function.
+ 
+    FIXME should we complexify the prequeue handling instead?  Or use flags
+    for all the cleanups and let the optimizer tighten them up?  The current
+    code seems pretty fragile; it will break on a cleanup within any
+    non-conditional nesting.  But any such nesting would be broken, anyway;
+    we can't write a TRY_FINALLY_EXPR that starts inside a nesting construct
+    and continues out of it.  We can do that at the RTL level, though, so
+    having an optimizer to tighten up try/finally regions would be a Good
+    Thing.  */
+ 
+ static void
+ simplify_cleanup_point_expr (expr_p, pre_p)
+      tree *expr_p;
+      tree *pre_p;
+ {
+   gimple_stmt_iterator iter;
+   tree body;
+ 
+   tree temp = voidify_wrapper_expr (*expr_p);
+ 
+   /* We only care about the number of conditions between the innermost
+      CLEANUP_POINT_EXPR and the cleanup.  So save and reset the count.  */
+   int old_conds = gimplify_ctxp->conditions;
+   gimplify_ctxp->conditions = 0;
+ 
+   body = TREE_OPERAND (*expr_p, 0);
+   simplify_stmt (&body);
+ 
+   gimplify_ctxp->conditions = old_conds;  
+   
+   for (iter = gsi_start (&body); !gsi_after_end (iter); )
+     {
+       tree wce = gsi_stmt (iter);
+       if (TREE_CODE (wce) == WITH_CLEANUP_EXPR)
+ 	{
+ 	  tree *container = gsi_container (iter);
+ 	  tree next, tfe;
+ 
+ 	  if (TREE_CODE (*container) == COMPOUND_EXPR)
+ 	    next = TREE_OPERAND (*container, 1);
+ 	  else
+ 	    next = NULL_TREE;
+ 
+ 	  tfe = build (TRY_FINALLY_EXPR, void_type_node,
+ 		       next, TREE_OPERAND (wce, 1));
+ 	  *container = tfe;
+ 	  iter = gsi_start (&TREE_OPERAND (tfe, 0));
+ 	}
+       else
+ 	gsi_step (&iter);
+     }
+   
+   if (temp)
+     {
+       *expr_p = temp;
+       add_tree (body, pre_p);
+     }
+   else
+     *expr_p = body;
+ }
+ 
+ /* Insert a cleanup marker for simplify_cleanup_point_expr.  CLEANUP
+    is the cleanup action required.  */
+ 
+ static void
+ gimple_push_cleanup (cleanup, pre_p)
+      tree cleanup;
+      tree *pre_p;
+ {
+   tree wce;
+ 
+   if (gimple_conditional_context ())
+     {
+       /* If we're in a conditional context, this is more complex.  We only
+ 	 want to run the cleanup if we actually ran the initialization that
+ 	 necessitates it, but we want to run it after the end of the
+ 	 conditional context.  So we wrap the try/finally around the
+ 	 condition and use a flag to determine whether or not to actually
+ 	 run the destructor.  Thus
+ 
+ 	   test ? f(A()) : 0
+ 
+ 	 becomes (approximately)
+ 
+ 	   flag = 0;
+ 	   try {
+ 	     if (test) { A::A(temp); flag = 1; val = f(temp); }
+ 	     else { val = 0; }
+ 	   } finally {
+ 	     if (flag) A::~A(temp);
+ 	   }
+ 	   val
+       */
+ 
+       tree flag = create_tmp_var (integer_type_node, "cleanup");
+       tree ffalse = build (MODIFY_EXPR, void_type_node, flag, integer_zero_node);
+       tree ftrue = build (MODIFY_EXPR, void_type_node, flag, integer_one_node);
+       cleanup = build (COND_EXPR, void_type_node, flag, cleanup, empty_stmt_node);
+       wce = build (WITH_CLEANUP_EXPR, void_type_node, NULL_TREE,
+ 		   cleanup, NULL_TREE);
+       add_tree (ffalse, &gimplify_ctxp->conditional_cleanups);
+       add_tree (wce, &gimplify_ctxp->conditional_cleanups);
+       add_tree (ftrue, pre_p);
+     }
+   else
+     {
+       wce = build (WITH_CLEANUP_EXPR, void_type_node, NULL_TREE,
+ 		   cleanup, NULL_TREE);
+       add_tree (wce, pre_p);
+     }
+ }
+ 
+ /* Simplify a TARGET_EXPR which doesn't appear on the rhs of an INIT_EXPR.  */
+ 
+ static void
+ simplify_target_expr (expr_p, pre_p, post_p)
+      tree *expr_p;
+      tree *pre_p;
+      tree *post_p;
+ {
+   tree targ = *expr_p;
+   tree temp = TARGET_EXPR_SLOT (targ);
+   tree init = TARGET_EXPR_INITIAL (targ);
+ 
+   /* TARGET_EXPR temps aren't part of the enclosing block, so add it to the
+      temps list.  */
+   gimple_add_tmp_var (temp);
+ 
+   /* Add the initialization to pre_p.  In some cases, such as C++
+      constructors, the initialization will happen by side-effect in init;
+      in such cases, init will simplify to temp, so we mustn't build a
+      MODIFY_EXPR.  */
+   simplify_expr (&init, pre_p, post_p, is_simple_rhs, fb_rvalue);
+   if (init != temp)
+     {
+       init = build (MODIFY_EXPR, void_type_node, temp, init);
+       add_tree (init, pre_p);
+     }
+ 
+   /* If needed, push the cleanup for the temp.  */
+   if (TARGET_EXPR_CLEANUP (targ))
+     gimple_push_cleanup (TARGET_EXPR_CLEANUP (targ), pre_p);
+ 
+   *expr_p = temp;
  }
Index: tree-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-pretty-print.c,v
retrieving revision 1.1.2.7
diff -c -p -r1.1.2.7 tree-pretty-print.c
*** tree-pretty-print.c	17 Nov 2002 14:39:37 -0000	1.1.2.7
--- tree-pretty-print.c	26 Nov 2002 22:36:20 -0000
*************** dump_generic_node (buffer, node, spc, fl
*** 205,216 ****
        }
  
      case POINTER_TYPE:
        if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
          {
  	  tree fnode = TREE_TYPE (node);
  	  dump_generic_node (buffer, TREE_TYPE (fnode), spc, flags);
  	  output_add_space (buffer);
! 	  output_add_string (buffer, "(*");
  	  if (TYPE_NAME (node) && DECL_NAME (TYPE_NAME (node)))
  	    output_add_string (buffer, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))));
  	  else
--- 205,220 ----
        }
  
      case POINTER_TYPE:
+     case REFERENCE_TYPE:
+       str = (TREE_CODE (node) == POINTER_TYPE ? "*" : "&");
+ 
        if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
          {
  	  tree fnode = TREE_TYPE (node);
  	  dump_generic_node (buffer, TREE_TYPE (fnode), spc, flags);
  	  output_add_space (buffer);
! 	  output_add_character (buffer, '(');
! 	  output_add_string (buffer, str);
  	  if (TYPE_NAME (node) && DECL_NAME (TYPE_NAME (node)))
  	    output_add_string (buffer, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))));
  	  else
*************** dump_generic_node (buffer, node, spc, fl
*** 241,247 ****
  	  unsigned int quals = TYPE_QUALS (node);
  
            dump_generic_node (buffer, TREE_TYPE (node), spc, flags);
! 	  output_add_string (buffer, " *");
  	  
  	  if (quals & TYPE_QUAL_CONST)
  	    output_add_string (buffer, " const");
--- 245,252 ----
  	  unsigned int quals = TYPE_QUALS (node);
  
            dump_generic_node (buffer, TREE_TYPE (node), spc, flags);
! 	  output_add_space (buffer);
! 	  output_add_string (buffer, str);
  	  
  	  if (quals & TYPE_QUAL_CONST)
  	    output_add_string (buffer, " const");
*************** dump_generic_node (buffer, node, spc, fl
*** 256,266 ****
  
      case OFFSET_TYPE:
        NIY;
-       break;
- 
-     case REFERENCE_TYPE:
-       /* FIXME : What is the exact syntax of this node for C? */
-       dump_generic_node (buffer, TREE_TYPE (node), spc, flags);
        break;
  
      case METHOD_TYPE:
--- 261,266 ----
Index: tree-simple.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-simple.c,v
retrieving revision 1.1.4.18
diff -c -p -r1.1.4.18 tree-simple.c
*** tree-simple.c	17 Nov 2002 14:39:37 -0000	1.1.4.18
--- tree-simple.c	26 Nov 2002 22:36:20 -0000
*************** right_assocify_expr (top)
*** 887,896 ****
  	  /* Replace cur with the lhs; move (a, *) up.  */
  	  *p = lhs;
  
! 	  /* If this is a COMPOUND_EXPR, we need to give (b, c) the type of
! 	     c; previously lhs had the type of b.  For other associative
! 	     tree codes, this should be a NOP.  */
! 	  TREE_TYPE (lhs) = TREE_TYPE (cur);
  
  	  /* Walk through the rhs chain from there until we find something
  	     with a different code.  In this case, c.  */
--- 887,900 ----
  	  /* Replace cur with the lhs; move (a, *) up.  */
  	  *p = lhs;
  
! 	  if (code == COMPOUND_EXPR)
! 	    {
! 	      /* We need to give (b, c) the type of c; previously lhs had
! 		 the type of b.  */
! 	      TREE_TYPE (lhs) = TREE_TYPE (cur);
! 	      if (TREE_SIDE_EFFECTS (cur))
! 		TREE_SIDE_EFFECTS (lhs) = 1;
! 	    }
  
  	  /* Walk through the rhs chain from there until we find something
  	     with a different code.  In this case, c.  */
Index: cp/cp-simplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/Attic/cp-simplify.c,v
retrieving revision 1.1.4.4
diff -c -p -r1.1.4.4 cp-simplify.c
*** cp/cp-simplify.c	1 Oct 2002 14:35:43 -0000	1.1.4.4
--- cp/cp-simplify.c	26 Nov 2002 22:36:24 -0000
*************** Software Foundation, 59 Temple Place - S
*** 28,35 ****
  #include "toplev.h"
  #include "tree-simple.h"
  
! static void simplify_target_expr     PARAMS ((tree *, tree *));
! static void maybe_fixup_loop_cond    PARAMS ((tree *, tree *, tree *));
  
  /* Do C++-specific simplification.  Args are as for simplify_expr.  */
  
--- 28,77 ----
  #include "toplev.h"
  #include "tree-simple.h"
  
! static void genericize_try_block	PARAMS ((tree *));
! 
! /* Genericize a C++ _STMT.  Called from c_simplify_stmt.  */
! 
! int
! cp_simplify_stmt (stmt_p, next_p)
!      tree *stmt_p;
!      tree *next_p ATTRIBUTE_UNUSED;
! {
!   tree stmt = *stmt_p;
!   switch (TREE_CODE (stmt))
!     {
!     case TRY_BLOCK:
!       genericize_try_block (stmt_p);
!       return 1;
! 
!     default:
!       break;
!     }
!   return 0;
! }
! 
! /* Genericize a TRY_BLOCK.  */
! 
! static void
! genericize_try_block (stmt_p)
!      tree *stmt_p;
! {
!   tree stmt = *stmt_p;
! 
!   if (CLEANUP_P (stmt))
!     {
!       /* Just convert to a TRY_CATCH_EXPR.  */
!       tree body = TRY_STMTS (stmt);
!       tree cleanup = TRY_HANDLERS (stmt);
! 
!       c_simplify_stmt (&body);
! 
!       *stmt_p = build (TRY_CATCH_EXPR, void_type_node, body, cleanup);
!     }
!   else
!     /* FIXME a real try block.  */
!     abort ();
! }
  
  /* Do C++-specific simplification.  Args are as for simplify_expr.  */
  
*************** cp_simplify_expr (expr_p, pre_p, post_p)
*** 41,67 ****
  {
    switch (TREE_CODE (*expr_p))
      {
!     case FOR_STMT:
!       maybe_fixup_loop_cond (&FOR_COND (*expr_p), &FOR_BODY (*expr_p),
! 			     pre_p);
!       break;
!     case WHILE_STMT:
!       maybe_fixup_loop_cond (&WHILE_COND (*expr_p), &WHILE_BODY (*expr_p),
! 			     pre_p);
!       break;
!       
!     case INIT_EXPR:
!       {
! 	/* If we are initializing something from a TARGET_EXPR, strip the
! 	   TARGET_EXPR and initialize it directly.  */
! 	tree *from = &TREE_OPERAND (*expr_p, 1);
! 	if (TREE_CODE (*from) == TARGET_EXPR)
! 	  *from = TARGET_EXPR_INITIAL (*from);
! 	/* And then fall through to the default code.  */
! 	break;
!       }
!     case TARGET_EXPR:
!       simplify_target_expr (expr_p, pre_p);
        break;
  
      default:
--- 83,90 ----
  {
    switch (TREE_CODE (*expr_p))
      {
!     case AGGR_INIT_EXPR:
!       simplify_aggr_init_expr (expr_p);
        break;
  
      default:
*************** cp_simplify_expr (expr_p, pre_p, post_p)
*** 71,160 ****
    return c_simplify_expr (expr_p, pre_p, post_p);
  }
  
! /* Simplify a TARGET_EXPR which doesn't appear on the rhs of an INIT_EXPR.  */
  
! static void
! simplify_target_expr (expr_p, pre_p)
!      tree *expr_p;
!      tree *pre_p;
  {
!   tree temp = TARGET_EXPR_SLOT (*expr_p);
!   tree decl = build_stmt (DECL_STMT, temp);
!   tree init = build (INIT_EXPR, TREE_TYPE (temp), temp,
! 		     TARGET_EXPR_INITIAL (*expr_p));
!   add_tree (decl, pre_p);
!   *expr_p = init;
! }
  
! /* Given pointers to the condition and body of a for or while loop,
!    reorganize things so that the condition is just an expression.
  
!    COND_P and BODY_P are pointers to the condition and body of the loop.
!    PRE_P is a list to which we can add effects that need to happen before
!    the loop begins (i.e. as part of the for-init-stmt).  */
  
! static void
! maybe_fixup_loop_cond (cond_p, body_p, pre_p)
!      tree *cond_p;
!      tree *body_p;
!      tree *pre_p;
! {
!   if (TREE_CODE (*cond_p) == TREE_LIST)
      {
!       /* In C++ a condition can be a declaration; to express this,
! 	 the FOR_COND is a TREE_LIST.  The TREE_PURPOSE contains the
! 	 SCOPE_STMT and DECL_STMT, if any, and the TREE_VALUE contains
! 	 the actual value to test.  We want to transform
! 
! 	   for (; T u = init; ) { ... }
! 
! 	 into
! 
! 	   for (tmp = 1; tmp; )
! 	     { T u = init; tmp = u; if (tmp) { ... } }
! 
! 	 The wackiest part of this is handling the SCOPE_STMTs; at first,
! 	 one is in the FOR_COND and the other is after the COMPOUND_STMT in
! 	 the body.  We will use the same SCOPE_STMTs to wrap our new
! 	 block.  */
! 
!       tree scope = TREE_PURPOSE (*cond_p);
!       tree val = TREE_VALUE (*cond_p);
! 
!       if (TREE_CODE (scope) != SCOPE_STMT)
! 	abort ();
!       if (TREE_CHAIN (scope) == NULL_TREE)
! 	{
! 	  /* There isn't actually a decl.  Just move the SCOPE_STMT
! 	     down into the FOR_BODY.  */
! 	  *cond_p = val;
! 	  TREE_CHAIN (scope) = *body_p;
! 	}
!       else
! 	{
! 	  /* There is a decl.  Do the transformation described
! 	     above.  */
! 
! 	  tree if_s, mod, close_scope;
! 	  /* tmp = 1;  */
! 	  *cond_p = get_initialized_tmp_var (boolean_true_node,
! 					     pre_p);
! 	  /* tmp = u; */
! 	  mod = build_modify_expr (*cond_p, NOP_EXPR, val);
! 	  mod = build_stmt (EXPR_STMT, mod);
! 
! 	  /* Separate the actual body block from the SCOPE_STMT.  */
! 	  close_scope = TREE_CHAIN (*body_p);
! 	  TREE_CHAIN (*body_p) = NULL_TREE;
! 
! 	  /* if (tmp) { ... } */
! 	  if_s = build_stmt (IF_STMT, *cond_p, *body_p, NULL_TREE);
! 
! 	  /* Finally, tack it all together.  */
! 	  chainon (scope, mod);
! 	  TREE_CHAIN (mod) = if_s;
! 	  TREE_CHAIN (if_s) = close_scope;
! 	}
!       *body_p = build_stmt (COMPOUND_STMT, scope);
      }
  }
--- 94,160 ----
    return c_simplify_expr (expr_p, pre_p, post_p);
  }
  
! /* Replace the AGGR_INIT_EXPR at *TP with an equivalent CALL_EXPR.  */
  
! void
! simplify_aggr_init_expr (tp)
!      tree *tp;
  {
!   tree aggr_init_expr = *tp;
  
!   /* Form an appropriate CALL_EXPR.  */
!   tree fn = TREE_OPERAND (aggr_init_expr, 0);
!   tree args = TREE_OPERAND (aggr_init_expr, 1);
!   tree slot = TREE_OPERAND (aggr_init_expr, 2);
!   tree type = TREE_TYPE (aggr_init_expr);
  
!   tree call_expr;
!   int copy_from_buffer_p;
  
!   if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr))
      {
!       /* Replace the first argument with the address of the third
! 	 argument to the AGGR_INIT_EXPR.  */
!       cxx_mark_addressable (slot);
!       args = tree_cons (NULL_TREE, 
! 			build1 (ADDR_EXPR, 
! 				build_pointer_type (TREE_TYPE (slot)),
! 				slot),
! 			TREE_CHAIN (args));
!     }
!   call_expr = build (CALL_EXPR, 
! 		     TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
! 		     fn, args, NULL_TREE);
!   TREE_SIDE_EFFECTS (call_expr) = 1;
! 
!   /* If we're using the non-reentrant PCC calling convention, then we
!      need to copy the returned value out of the static buffer into the
!      SLOT.  */
!   copy_from_buffer_p = 0;
! #ifdef PCC_STATIC_STRUCT_RETURN  
!   if (!AGGR_INIT_VIA_CTOR_P (aggr_init_expr) && aggregate_value_p (type))
!     {
!       int old_ac = flag_access_control;
! 
!       flag_access_control = 0;
!       call_expr = build_aggr_init (slot, call_expr,
! 				   DIRECT_BIND | LOOKUP_ONLYCONVERTING);
!       flag_access_control = old_ac;
!       copy_from_buffer_p = 1;
      }
+ #endif
+ 
+   /* If this AGGR_INIT_EXPR indicates the value returned by a
+      function, then we want to use the value of the initialized
+      location as the result.  */
+   if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr) || copy_from_buffer_p)
+     {
+       call_expr = build (COMPOUND_EXPR, type,
+ 			 call_expr, slot);
+       TREE_SIDE_EFFECTS (call_expr) = 1;
+     }
+ 
+   /* Replace the AGGR_INIT_EXPR with the CALL_EXPR.  */
+   TREE_CHAIN (call_expr) = TREE_CHAIN (aggr_init_expr);
+   *tp = call_expr;
  }
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.719.2.17
diff -c -p -r1.719.2.17 cp-tree.h
*** cp/cp-tree.h	25 Nov 2002 04:25:18 -0000	1.719.2.17
--- cp/cp-tree.h	26 Nov 2002 22:36:25 -0000
*************** extern int cp_dump_tree                 
*** 4393,4398 ****
--- 4393,4400 ----
  
  /* in cp-simplify.c */
  extern int cp_simplify_expr		        PARAMS ((tree *, tree *, tree *));
+ extern int cp_simplify_stmt		        PARAMS ((tree *, tree *));
+ extern void simplify_aggr_init_expr		PARAMS ((tree *));
  
  /* -- end of C++ */
  
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.911.2.15
diff -c -p -r1.911.2.15 decl.c
*** cp/decl.c	6 Nov 2002 12:21:26 -0000	1.911.2.15
--- cp/decl.c	26 Nov 2002 22:36:26 -0000
*************** cxx_init_decl_processing ()
*** 6693,6698 ****
--- 6693,6701 ----
       say -fwritable-strings?  */
    if (flag_writable_strings)
      flag_const_strings = 0;
+ 
+   /* Disable for now.  */
+   flag_disable_simple = 1;
  }
  
  /* Generate an initializer for a function naming variable from
*************** finish_function (flags)
*** 14532,14537 ****
--- 14535,14544 ----
        && DECL_INLINE (fndecl))
      warning ("no return statement in function returning non-void");
      
+   /* Genericize before inlining.  */
+   if (!flag_disable_simple)
+     c_genericize (fndecl);
+ 
    /* Clear out memory we no longer need.  */
    free_after_parsing (cfun);
    /* Since we never call rest_of_compilation, we never clear
Index: cp/optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/optimize.c,v
retrieving revision 1.81.10.7
diff -c -p -r1.81.10.7 optimize.c
*** cp/optimize.c	22 Oct 2002 18:28:48 -0000	1.81.10.7
--- cp/optimize.c	26 Nov 2002 22:36:26 -0000
*************** Software Foundation, 59 Temple Place - S
*** 36,41 ****
--- 36,42 ----
  #include "tree-inline.h"
  #include "flags.h"
  #include "langhooks.h"
+ #include "diagnostic.h"
  
  /* Prototypes.  */
  
*************** void
*** 49,55 ****
  optimize_function (fn)
       tree fn;
  {
!   dump_function (TDI_original, fn);
  
    /* While in this function, we may choose to go off and compile
       another function.  For example, we might instantiate a function
--- 50,72 ----
  optimize_function (fn)
       tree fn;
  {
!   FILE *dump_file;
!   int dump_flags;
! 
!   /* Dump the unoptimized tree IR.  */
!   dump_file = dump_begin (TDI_original, &dump_flags);
!   if (dump_file)
!     {
!       fprintf (dump_file, "%s()\n", IDENTIFIER_POINTER (DECL_NAME (fn)));
! 
!       if (dump_flags & TDF_RAW)
! 	dump_node (DECL_SAVED_TREE (fn), TDF_SLIM | dump_flags, dump_file);
!       else
! 	print_c_tree (dump_file, DECL_SAVED_TREE (fn));
!       fprintf (dump_file, "\n");
! 
!       dump_end (TDI_original, dump_file);
!     }
  
    /* While in this function, we may choose to go off and compile
       another function.  For example, we might instantiate a function
*************** optimize_function (fn)
*** 77,93 ****
    /* Undo the call to ggc_push_context above.  */
    --function_depth;
  
- #if 0
    /* Simplify the function.  Don't try to optimize the function if
       simplification failed.  */
    if (!flag_disable_simple
        && simplify_function_tree (fn))
      {
        /* Invoke the SSA tree optimizer.  */
!       if (flag_tree_ssa)
  	optimize_function_tree (fn);
      }
- #endif
  
    dump_function (TDI_optimized, fn);
  }
--- 94,124 ----
    /* Undo the call to ggc_push_context above.  */
    --function_depth;
  
    /* Simplify the function.  Don't try to optimize the function if
       simplification failed.  */
    if (!flag_disable_simple
        && simplify_function_tree (fn))
      {
+       /* Debugging dump after simplification.  */
+       dump_file = dump_begin (TDI_simple, &dump_flags);
+       if (dump_file)
+ 	{
+ 	  fprintf (dump_file, "%s()\n", get_name (fn));
+ 
+ 	  if (dump_flags & TDF_RAW)
+ 	    dump_node (DECL_SAVED_TREE (fn), TDF_SLIM | dump_flags,
+ 		       dump_file);
+ 	  else
+ 	    print_generic_stmt (dump_file, DECL_SAVED_TREE (fn), 0);
+ 	  fprintf (dump_file, "\n");
+ 
+ 	  dump_end (TDI_simple, dump_file);
+ 	}
+ 
        /* Invoke the SSA tree optimizer.  */
!       if (optimize >= 1)
  	optimize_function_tree (fn);
      }
  
    dump_function (TDI_optimized, fn);
  }
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.264.2.15
diff -c -p -r1.264.2.15 semantics.c
*** cp/semantics.c	6 Nov 2002 12:21:28 -0000	1.264.2.15
--- cp/semantics.c	26 Nov 2002 22:36:27 -0000
*************** cp_expand_stmt (t)
*** 2167,2173 ****
  }
  
  /* Called from expand_body via walk_tree.  Replace all AGGR_INIT_EXPRs
!    will equivalent CALL_EXPRs.  */
  
  static tree
  simplify_aggr_init_exprs_r (tp, walk_subtrees, data)
--- 2167,2173 ----
  }
  
  /* Called from expand_body via walk_tree.  Replace all AGGR_INIT_EXPRs
!    with equivalent CALL_EXPRs.  */
  
  static tree
  simplify_aggr_init_exprs_r (tp, walk_subtrees, data)
*************** simplify_aggr_init_exprs_r (tp, walk_sub
*** 2175,2254 ****
       int *walk_subtrees ATTRIBUTE_UNUSED;
       void *data ATTRIBUTE_UNUSED;
  {
-   tree aggr_init_expr;
-   tree call_expr;
-   tree fn;
-   tree args;
-   tree slot;
-   tree type;
-   int copy_from_buffer_p;
- 
-   aggr_init_expr = *tp;
    /* We don't need to walk into types; there's nothing in a type that
       needs simplification.  (And, furthermore, there are places we
       actively don't want to go.  For example, we don't want to wander
       into the default arguments for a FUNCTION_DECL that appears in a
       CALL_EXPR.)  */
!   if (TYPE_P (aggr_init_expr))
      {
        *walk_subtrees = 0;
        return NULL_TREE;
      }
    /* Only AGGR_INIT_EXPRs are interesting.  */
!   else if (TREE_CODE (aggr_init_expr) != AGGR_INIT_EXPR)
      return NULL_TREE;
  
!   /* Form an appropriate CALL_EXPR.  */
!   fn = TREE_OPERAND (aggr_init_expr, 0);
!   args = TREE_OPERAND (aggr_init_expr, 1);
!   slot = TREE_OPERAND (aggr_init_expr, 2);
!   type = TREE_TYPE (aggr_init_expr);
!   if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr))
!     {
!       /* Replace the first argument with the address of the third
! 	 argument to the AGGR_INIT_EXPR.  */
!       cxx_mark_addressable (slot);
!       args = tree_cons (NULL_TREE, 
! 			build1 (ADDR_EXPR, 
! 				build_pointer_type (TREE_TYPE (slot)),
! 				slot),
! 			TREE_CHAIN (args));
!     }
!   call_expr = build (CALL_EXPR, 
! 		     TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
! 		     fn, args, NULL_TREE);
!   TREE_SIDE_EFFECTS (call_expr) = 1;
! 
!   /* If we're using the non-reentrant PCC calling convention, then we
!      need to copy the returned value out of the static buffer into the
!      SLOT.  */
!   copy_from_buffer_p = 0;
! #ifdef PCC_STATIC_STRUCT_RETURN  
!   if (!AGGR_INIT_VIA_CTOR_P (aggr_init_expr) && aggregate_value_p (type))
!     {
!       int old_ac = flag_access_control;
! 
!       flag_access_control = 0;
!       call_expr = build_aggr_init (slot, call_expr,
! 				   DIRECT_BIND | LOOKUP_ONLYCONVERTING);
!       flag_access_control = old_ac;
!       copy_from_buffer_p = 1;
!     }
! #endif
! 
!   /* If this AGGR_INIT_EXPR indicates the value returned by a
!      function, then we want to use the value of the initialized
!      location as the result.  */
!   if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr) || copy_from_buffer_p)
!     {
!       call_expr = build (COMPOUND_EXPR, type,
! 			 call_expr, slot);
!       TREE_SIDE_EFFECTS (call_expr) = 1;
!     }
! 
!   /* Replace the AGGR_INIT_EXPR with the CALL_EXPR.  */
!   TREE_CHAIN (call_expr) = TREE_CHAIN (aggr_init_expr);
!   *tp = call_expr;
  
    /* Keep iterating.  */
    return NULL_TREE;
--- 2175,2195 ----
       int *walk_subtrees ATTRIBUTE_UNUSED;
       void *data ATTRIBUTE_UNUSED;
  {
    /* We don't need to walk into types; there's nothing in a type that
       needs simplification.  (And, furthermore, there are places we
       actively don't want to go.  For example, we don't want to wander
       into the default arguments for a FUNCTION_DECL that appears in a
       CALL_EXPR.)  */
!   if (TYPE_P (*tp))
      {
        *walk_subtrees = 0;
        return NULL_TREE;
      }
    /* Only AGGR_INIT_EXPRs are interesting.  */
!   else if (TREE_CODE (*tp) != AGGR_INIT_EXPR)
      return NULL_TREE;
  
!   simplify_aggr_init_expr (tp);
  
    /* Keep iterating.  */
    return NULL_TREE;
*************** expand_body (fn)
*** 2302,2310 ****
      }
  
    /* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs.  */
!   walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
! 				simplify_aggr_init_exprs_r,
! 				NULL);
  
    /* If this is a constructor or destructor body, we have to clone
       it.  */
--- 2243,2252 ----
      }
  
    /* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs.  */
!   if (flag_disable_simple)
!     walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
! 				  simplify_aggr_init_exprs_r,
! 				  NULL);
  
    /* If this is a constructor or destructor body, we have to clone
       it.  */
*************** expand_body (fn)
*** 2381,2387 ****
    current_function_is_thunk = DECL_THUNK_P (fn);
  
    /* Expand the body.  */
!   expand_stmt (DECL_SAVED_TREE (fn));
  
    /* Statements should always be full-expressions at the outermost set
       of curly braces for a function.  */
--- 2323,2332 ----
    current_function_is_thunk = DECL_THUNK_P (fn);
  
    /* Expand the body.  */
!   if (statement_code_p (TREE_CODE (DECL_SAVED_TREE (fn))))
!     expand_stmt (DECL_SAVED_TREE (fn));
!   else
!     expand_expr_stmt_value (DECL_SAVED_TREE (fn), 0, 0);
  
    /* Statements should always be full-expressions at the outermost set
       of curly braces for a function.  */
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.286.2.15
diff -c -p -r1.286.2.15 tree.c
*** cp/tree.c	1 Nov 2002 18:41:28 -0000	1.286.2.15
--- cp/tree.c	26 Nov 2002 22:36:27 -0000
*************** void
*** 2400,2405 ****
--- 2400,2406 ----
  init_tree ()
  {
    lang_statement_code_p = cp_statement_code_p;
+   lang_simplify_stmt = cp_simplify_stmt;
    list_hash_table = htab_create_ggc (31, list_hash, list_hash_eq, NULL);
  }
  

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