Hello,

during expansion of expressions, gimplification creates a lot of temporary
variables.  VAR_DECLs are fairly large (88 bytes on i686), and
additionally an annotation (44 bytes on i686) are allocated for each of
them (some of them even get names, for additional ~50 bytes of memory
each).  This is quite wasteful.

Basic observation is that these temporaries have exactly one definition.
It is therefore possible to generate directly SSA_NAMEs for them,
setting SSA_NAME_VAR to NULL (and be careful to never rewrite them out
of ssa).  Theoretically, it should need only a few changes to gimplification,
into- and out-of-ssa, and expand, and everything should work.  Unfortunately,
lot of SSA passes looks on SSA_NAME_VAR.  This seems wrong to me, but
changing all the places would be very hard.

However, if we instead put a really minimal DECL node (we allocate only
one per type, and consisting just of struct tree_common -- 16 bytes) as
a SSA_NAME_VAR, things are much easier to get working.

The patch below is the first attempt for the idea (completely untested,
I just made it to work somehow so that I may measure its usefullness).
We get the following results (for combine.i):

-O0:
 TOTAL                 :   3.91            22668 kB
 TOTAL                 :   3.87            22096 kB (-2.5%)

-O1:
 TOTAL                 :  20.77            34640 kB
 TOTAL                 :  20.26            33688 kB (-2.7%)

-O2:
 TOTAL                 :  25.93            41116 kB
 TOTAL                 :  25.80            40582 kB (-1.2%)

That is, we need about 2% less memory, and also the compilation seems to
be a bit faster (maybe because of the memory savings, or possibly
because less work needs to be done in into- and outof- ssa passes).

However, this idea is a bit hackish, so I would like to hear an opinion
about it before I spend more time on testing it.

Zdenek

Index: tree-into-ssa.c
===================================================================
*** tree-into-ssa.c     (revision 108807)
--- tree-into-ssa.c     (working copy)
*************** mark_def_sites (struct dom_walk_data *wa
*** 650,655 ****
--- 650,668 ----
                            SSA_OP_USE | SSA_OP_VUSE | SSA_OP_VMUSTKILL)
      {
        tree sym = USE_FROM_PTR (use_p);
+ 
+       if (TREE_CODE (sym) == SSA_NAME)
+       {
+         /* Only gimplifier temporaries are now in ssa form.  We had already
+            seen the definition, so we have assigned a version to the ssa
+            name, and the definition must dominate it.  */
+         gcc_assert (TMP_NAME_P (sym));
+         gcc_assert (SSA_NAME_VERSION (sym) != 0);
+         gcc_assert (dominated_by_p (CDI_DOMINATORS, bb,
+                                     bb_for_stmt (SSA_NAME_DEF_STMT (sym))));
+         continue;
+       }
+ 
        gcc_assert (DECL_P (sym));
        if (!bitmap_bit_p (kills, DECL_UID (sym)))
        set_livein_block (sym, bb);
*************** mark_def_sites (struct dom_walk_data *wa
*** 674,679 ****
--- 687,700 ----
    /* Now process the defs and must-defs made by this statement.  */
    FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF | SSA_OP_VMUSTDEF)
      {
+       if (TREE_CODE (def) == SSA_NAME)
+       {
+         gcc_assert (TMP_NAME_P (def));
+         gcc_assert (SSA_NAME_VERSION (def) == 0);
+         gcc_assert (SSA_NAME_DEF_STMT (def) == stmt);
+         register_tmp_ssa_name (def);
+         continue;
+       }
        gcc_assert (DECL_P (def));
        set_def_block (def, bb, false);
        bitmap_set_bit (kills, DECL_UID (def));
*************** rewrite_stmt (struct dom_walk_data *walk
*** 1039,1044 ****
--- 1060,1067 ----
                              SSA_OP_ALL_USES|SSA_OP_ALL_KILLS)
        {
        tree var = USE_FROM_PTR (use_p);
+       if (TMP_NAME_P (var))
+         continue;
        gcc_assert (DECL_P (var));
        SET_USE (use_p, get_reaching_def (var));
        }
*************** rewrite_stmt (struct dom_walk_data *walk
*** 1048,1053 ****
--- 1071,1078 ----
      FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_ALL_DEFS)
        {
        tree var = DEF_FROM_PTR (def_p);
+       if (TMP_NAME_P (var))
+         continue;
        gcc_assert (DECL_P (var));
        SET_DEF (def_p, make_ssa_name (var, stmt));
        register_new_def (DEF_FROM_PTR (def_p), &block_defs_stack);
Index: tree-pretty-print.c
===================================================================
*** tree-pretty-print.c (revision 108807)
--- tree-pretty-print.c (working copy)
*************** dump_generic_node (pretty_printer *buffe
*** 708,713 ****
--- 708,717 ----
        dump_decl_name (buffer, node, flags);
        break;
  
+     case GVAR_DECL:
+       pp_printf (buffer, "<tmp%u>", DECL_UID (node));
+       break;
+ 
      case RESULT_DECL:
        pp_string (buffer, "<retval>");
        break;
Index: tree.c
===================================================================
*** tree.c      (revision 108807)
--- tree.c      (working copy)
*************** static const char * const tree_node_kind
*** 100,106 ****
  };
  #endif /* GATHER_STATISTICS */
  
! /* Unique id for next decl created.  */
  static GTY(()) int next_decl_uid;
  /* Unique id for next type created.  */
  static GTY(()) int next_type_uid = 1;
--- 100,108 ----
  };
  #endif /* GATHER_STATISTICS */
  
! /* Unique id for next decl created.  Even uids are used for decls, odd
!    ones are reserved for uids of gimplifier temporaries (for those,
!    the uid is derived from uid of their type).  */
  static GTY(()) int next_decl_uid;
  /* Unique id for next type created.  */
  static GTY(()) int next_type_uid = 1;
*************** tree_code_size (enum tree_code code)
*** 283,288 ****
--- 285,292 ----
            return sizeof (struct tree_field_decl);
          case PARM_DECL:
            return sizeof (struct tree_parm_decl);
+         case GVAR_DECL:
+           return sizeof (struct tree_common);
          case VAR_DECL:
            return sizeof (struct tree_var_decl);
          case LABEL_DECL:
*************** make_node_stat (enum tree_code code MEM_
*** 490,495 ****
--- 494,501 ----
        break;
  
      case tcc_declaration:
+       if (code == GVAR_DECL)
+       break;
        if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
        DECL_IN_SYSTEM_HEADER (t) = in_system_header;
        if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
*************** make_node_stat (enum tree_code code MEM_
*** 501,507 ****
          DECL_POINTER_ALIAS_SET (t) = -1;
        }
        DECL_SOURCE_LOCATION (t) = input_location;
!       DECL_UID (t) = next_decl_uid++;
  
        break;
  
--- 507,514 ----
          DECL_POINTER_ALIAS_SET (t) = -1;
        }
        DECL_SOURCE_LOCATION (t) = input_location;
!       SET_DECL_UID (t, next_decl_uid);
!       next_decl_uid += 2;
  
        break;
  
*************** copy_node_stat (tree node MEM_STAT_DECL)
*** 575,581 ****
  
    if (TREE_CODE_CLASS (code) == tcc_declaration)
      {
!       DECL_UID (t) = next_decl_uid++;
        if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
          && DECL_HAS_VALUE_EXPR_P (node))
        {
--- 582,589 ----
  
    if (TREE_CODE_CLASS (code) == tcc_declaration)
      {
!       SET_DECL_UID (t, next_decl_uid);
!       next_decl_uid += 2;
        if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
          && DECL_HAS_VALUE_EXPR_P (node))
        {
*************** tree_node_structure (tree t)
*** 1979,1984 ****
--- 1987,1994 ----
        {
        switch (code)
          {
+         case GVAR_DECL:
+           return TS_COMMON;
          case FIELD_DECL:
            return TS_FIELD_DECL;
          case PARM_DECL:
*************** in_array_bounds_p (tree ref)
*** 6669,6674 ****
--- 6679,6687 ----
  bool
  is_global_var (tree t)
  {
+   if (TREE_CODE (t) == GVAR_DECL)
+     return false;
+ 
    if (MTAG_P (t))
      return (TREE_STATIC (t) || MTAG_GLOBAL (t));
    else
Index: tree.h
===================================================================
*** tree.h      (revision 108807)
--- tree.h      (working copy)
*************** extern const enum tree_code_class tree_c
*** 100,105 ****
--- 100,111 ----
  #define DECL_P(CODE)\
          (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_declaration)
  
+ /* True if this is a ssa name for gimple temporary.  */
+ 
+ #define TMP_NAME_P(NODE) \
+       (TREE_CODE (NODE) == SSA_NAME \
+        && TREE_CODE (SSA_NAME_VAR (NODE)) == GVAR_DECL)
+ 
  /* Nonzero if CODE represents a memory tag.  */
  
  #define MTAG_P(CODE) \
*************** struct tree_binfo GTY (())
*** 1986,1999 ****
         || TREE_CODE (DECL) == PARM_DECL                               \
         || TREE_CODE (DECL) == RESULT_DECL                             \
         || MTAG_P (DECL)                                               \
!        || (TREE_CODE (DECL) == SSA_NAME                               \
!            && (TREE_CODE (SSA_NAME_VAR (DECL)) == VAR_DECL            \
!                || TREE_CODE (SSA_NAME_VAR (DECL)) == PARM_DECL        \
!                || TREE_CODE (SSA_NAME_VAR (DECL)) == RESULT_DECL      \
!                || MTAG_P (SSA_NAME_VAR (DECL)))))
! 
! 
! 
  
  /* Enumerate visibility settings.  */
  #ifndef SYMBOL_VISIBILITY_DEFINED
--- 1992,1998 ----
         || TREE_CODE (DECL) == PARM_DECL                               \
         || TREE_CODE (DECL) == RESULT_DECL                             \
         || MTAG_P (DECL)                                               \
!        || TREE_CODE (DECL) == SSA_NAME)
  
  /* Enumerate visibility settings.  */
  #ifndef SYMBOL_VISIBILITY_DEFINED
*************** struct function;
*** 2015,2021 ****
  #define DECL_NAME(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.name)
  
  /* Every ..._DECL node gets a unique number.  */
! #define DECL_UID(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.uid)
  
  /* These two fields describe where in the source code the declaration
     was.  If the declaration appears in several places (as for a C
--- 2014,2025 ----
  #define DECL_NAME(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.name)
  
  /* Every ..._DECL node gets a unique number.  */
! #define SET_DECL_UID(NODE, UID) \
!   (DECL_MINIMAL_CHECK (NODE)->decl_minimal.uid = (UID))
! #define DECL_UID(NODE) \
!   (TREE_CODE (NODE) == GVAR_DECL \
!    ? (2 * TYPE_UID (TREE_TYPE (NODE)) + 1) \
!    : DECL_MINIMAL_CHECK (NODE)->decl_minimal.uid)
  
  /* These two fields describe where in the source code the declaration
     was.  If the declaration appears in several places (as for a C
*************** extern void phinodes_print_statistics (v
*** 3151,3156 ****
--- 3155,3161 ----
  extern void init_ssanames (void);
  extern void fini_ssanames (void);
  extern tree make_ssa_name (tree, tree);
+ extern void register_tmp_ssa_name (tree);
  extern tree duplicate_ssa_name (tree, tree);
  extern void duplicate_ssa_name_ptr_info (tree, struct ptr_info_def *);
  extern void release_ssa_name (tree);
*************** extern void gimplify_function_tree (tree
*** 4129,4134 ****
--- 4134,4140 ----
  extern const char *get_name (tree);
  extern tree unshare_expr (tree);
  extern void sort_case_labels (tree);
+ tree gvar_for_type (tree);
  
  /* If KIND=='I', return a suitable global initializer (constructor) name.
     If KIND=='D', return a suitable global clean-up (destructor) name.  */
Index: tree-gimple.c
===================================================================
*** tree-gimple.c       (revision 108807)
--- tree-gimple.c       (working copy)
*************** is_gimple_reg (tree t)
*** 268,273 ****
--- 268,275 ----
  {
    if (TREE_CODE (t) == SSA_NAME)
      t = SSA_NAME_VAR (t);
+   if (TREE_CODE (t) == GVAR_DECL)
+     return true;
  
    if (MTAG_P (t))
      return false;
Index: tree-ssa-copyrename.c
===================================================================
*** tree-ssa-copyrename.c       (revision 108807)
--- tree-ssa-copyrename.c       (working copy)
*************** copy_rename_partition_coalesce (var_map 
*** 188,195 ****
        return;
      }
  
!   ign1 = TREE_CODE (root1) == VAR_DECL && DECL_IGNORED_P (root1);
!   ign2 = TREE_CODE (root2) == VAR_DECL && DECL_IGNORED_P (root2);
  
    /* Never attempt to coalesce 2 user variables unless one is an inline 
       variable.  */
--- 188,197 ----
        return;
      }
  
!   ign1 = (TREE_CODE (root1) == GVAR_DECL
!         || (TREE_CODE (root1) == VAR_DECL && DECL_IGNORED_P (root1)));
!   ign2 = (TREE_CODE (root2) == GVAR_DECL
!         || (TREE_CODE (root2) == VAR_DECL && DECL_IGNORED_P (root2)));
  
    /* Never attempt to coalesce 2 user variables unless one is an inline 
       variable.  */
Index: tree-ssa-alias.c
===================================================================
*** tree-ssa-alias.c    (revision 108807)
--- tree-ssa-alias.c    (working copy)
*************** debug_may_aliases_for (tree var)
*** 2187,2192 ****
--- 2187,2195 ----
  bool
  may_be_aliased (tree var)
  {
+   if (TREE_CODE (var) == GVAR_DECL)
+     return false;
+ 
    /* Obviously.  */
    if (TREE_ADDRESSABLE (var))
      return true;
*************** create_structure_vars (void)
*** 2814,2820 ****
    FOR_EACH_REFERENCED_VAR_SAFE (var, varvec, rvi)
      {
        /* The C++ FE creates vars without DECL_SIZE set, for some reason.  */
!       if (var           
          && DECL_SIZE (var)
          && var_can_have_subvars (var)
          && !MTAG_P (var)
--- 2817,2824 ----
    FOR_EACH_REFERENCED_VAR_SAFE (var, varvec, rvi)
      {
        /* The C++ FE creates vars without DECL_SIZE set, for some reason.  */
!       if (var
!         && TREE_CODE (var) != GVAR_DECL
          && DECL_SIZE (var)
          && var_can_have_subvars (var)
          && !MTAG_P (var)
Index: expr.c
===================================================================
*** expr.c      (revision 108807)
--- expr.c      (working copy)
*************** expand_expr_real (tree exp, rtx target, 
*** 6561,6566 ****
--- 6561,6593 ----
    return ret;
  }
  
+ /* Returns pseudoregister used for ssa name NAME.  */
+ 
+ static rtx
+ reg_for_ssa_name (tree name)
+ {
+   rtx x = SSA_NAME_AUX (name);
+   tree type = TREE_TYPE (name);
+   int unsignedp = TYPE_UNSIGNED (type);
+   enum machine_mode x_mode = TYPE_MODE (type);
+   enum machine_mode reg_mode = promote_mode (type, x_mode, &unsignedp, 0);
+   
+   if (!x)
+     {
+       x = gen_reg_rtx (reg_mode);
+       SSA_NAME_AUX (name) = x;
+     }
+ 
+   if (x_mode != reg_mode)
+     {
+       x = gen_lowpart_SUBREG (x_mode, x);
+       SUBREG_PROMOTED_VAR_P (x) = 1;
+       SUBREG_PROMOTED_UNSIGNED_SET (x, unsignedp);
+     }
+ 
+   return x;
+ }
+ 
  static rtx
  expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                    enum expand_modifier modifier, rtx *alt_rtl)
*************** expand_expr_real_1 (tree exp, rtx target
*** 6671,6678 ****
        }
  
      case SSA_NAME:
!       return expand_expr_real_1 (SSA_NAME_VAR (exp), target, tmode, modifier,
!                                NULL);
  
      case PARM_DECL:
      case VAR_DECL:
--- 6698,6705 ----
        }
  
      case SSA_NAME:
!       gcc_assert (TMP_NAME_P (exp));
!       return reg_for_ssa_name (exp);
  
      case PARM_DECL:
      case VAR_DECL:
Index: c-decl.c
===================================================================
*** c-decl.c    (revision 108807)
--- c-decl.c    (working copy)
*************** merge_decls (tree newdecl, tree olddecl,
*** 1850,1856 ****
                (char *) newdecl + sizeof (struct tree_decl_common),
                sizeof (struct tree_decl_non_common) - sizeof (struct 
tree_decl_common));
        }
!     DECL_UID (olddecl) = olddecl_uid;
      DECL_CONTEXT (olddecl) = olddecl_context;
    }
  
--- 1850,1856 ----
                (char *) newdecl + sizeof (struct tree_decl_common),
                sizeof (struct tree_decl_non_common) - sizeof (struct 
tree_decl_common));
        }
!     SET_DECL_UID (olddecl, olddecl_uid);
      DECL_CONTEXT (olddecl) = olddecl_context;
    }
  
Index: ipa-type-escape.c
===================================================================
*** ipa-type-escape.c   (revision 108807)
--- ipa-type-escape.c   (working copy)
*************** Software Foundation, 51 Franklin Street,
*** 60,72 ****
     this phase has been run.  */
  static bool initialized = false;
  
- /* This bitmap contains the set of local vars that are the lhs of
-    calls to mallocs.  These variables, when seen on the rhs as part of
-    a cast, the cast are not marked as doing bad things to the type
-    even though they are generally of the form 
-    "foo = (type_of_foo)void_temp". */
- static bitmap results_of_malloc;
- 
  /* Scratch bitmap for avoiding work. */
  static bitmap been_there_done_that;
  static bitmap bitmap_tmp;
--- 60,65 ----
*************** check_cast_type (tree to_type, tree from
*** 649,654 ****
--- 642,664 ----
    return CT_SIDEWAYS;
  }     
  
+ /* Returns true if STMT is a call to malloc.  */
+ 
+ static bool
+ malloc_stmt_p (tree stmt)
+ {
+   tree call;
+ 
+   if (TREE_CODE (stmt) != MODIFY_EXPR)
+     return false;
+ 
+   call = TREE_OPERAND (stmt, 1);
+   if (TREE_CODE (call) != CALL_EXPR)
+     return false;
+ 
+   return (call_expr_flags (call) & ECF_MALLOC) != 0;
+ }
+ 
  /* Check a cast FROM this variable, TO_TYPE.  Mark the escaping types
     if appropriate.  */ 
  static void
*************** check_cast (tree to_type, tree from) 
*** 692,698 ****
        {
        /* If this is a cast from the local that is a result from a
           call to malloc, do not mark the cast as bad.  */
!       if (DECL_P (from) && !bitmap_bit_p (results_of_malloc, DECL_UID (from)))
          mark_type (to_type, FULL_ESCAPE);
        }
    else if (from_interesting_type)
--- 702,709 ----
        {
        /* If this is a cast from the local that is a result from a
           call to malloc, do not mark the cast as bad.  */
!       if (TREE_CODE (from) != SSA_NAME
!           || !malloc_stmt_p (SSA_NAME_DEF_STMT (from)))
          mark_type (to_type, FULL_ESCAPE);
        }
    else if (from_interesting_type)
*************** get_asm_expr_operands (tree stmt)
*** 1013,1022 ****
     this is either an indirect call, a call outside the compilation
     unit.  */
  
! static bool
  check_call (tree call_expr) 
  {
-   int flags = call_expr_flags(call_expr);
    tree operand_list = TREE_OPERAND (call_expr, 1);
    tree operand;
    tree callee_t = get_callee_fndecl (call_expr);
--- 1024,1032 ----
     this is either an indirect call, a call outside the compilation
     unit.  */
  
! static void
  check_call (tree call_expr) 
  {
    tree operand_list = TREE_OPERAND (call_expr, 1);
    tree operand;
    tree callee_t = get_callee_fndecl (call_expr);
*************** check_call (tree call_expr) 
*** 1136,1142 ****
          mark_interesting_type (type, EXPOSED_PARAMETER);
        }
      }
-   return (flags & ECF_MALLOC);
  }
  
  /* CODE is the operation on OP0 and OP1.  OP0 is the operand that we
--- 1146,1151 ----
*************** scan_for_refs (tree *tp, int *walk_subtr
*** 1264,1274 ****
                check_rhs_var (rhs);
                break;
              case CALL_EXPR: 
!               /* If this is a call to malloc, squirrel away the
!                  result so we do mark the resulting cast as being
!                  bad.  */
!               if (check_call (rhs))
!                 bitmap_set_bit (results_of_malloc, DECL_UID (lhs));
                break;
              default:
                break;
--- 1273,1279 ----
                check_rhs_var (rhs);
                break;
              case CALL_EXPR: 
!               check_call (rhs);
                break;
              default:
                break;
*************** ipa_init (void) 
*** 1314,1320 ****
    global_types_exposed_parameter = BITMAP_ALLOC (&ipa_obstack);
    global_types_full_escape = BITMAP_ALLOC (&ipa_obstack);
    global_types_seen = BITMAP_ALLOC (&ipa_obstack);
-   results_of_malloc = BITMAP_ALLOC (&ipa_obstack);
  
    uid_to_canon_type = splay_tree_new (splay_tree_compare_ints, 0, 0);
    all_canon_types = splay_tree_new (compare_type_brand, 0, 0);
--- 1319,1324 ----
*************** type_escape_execute (void)
*** 1822,1828 ****
    BITMAP_FREE (global_types_exposed_parameter);
    BITMAP_FREE (been_there_done_that);
    BITMAP_FREE (bitmap_tmp);
-   BITMAP_FREE (results_of_malloc);
  }
  
  static bool
--- 1826,1831 ----
Index: alias.c
===================================================================
*** alias.c     (revision 108807)
--- alias.c     (working copy)
*************** get_alias_set (tree t)
*** 522,528 ****
        {
          tree decl = find_base_decl (TREE_OPERAND (inner, 0));
  
!         if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
            {
              /* If we haven't computed the actual alias set, do it now.  */
              if (DECL_POINTER_ALIAS_SET (decl) == -2)
--- 522,530 ----
        {
          tree decl = find_base_decl (TREE_OPERAND (inner, 0));
  
!         if (decl
!             && TREE_CODE (decl) != GVAR_DECL
!             && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
            {
              /* If we haven't computed the actual alias set, do it now.  */
              if (DECL_POINTER_ALIAS_SET (decl) == -2)
Index: gimplify.c
===================================================================
*** gimplify.c  (revision 108807)
--- gimplify.c  (working copy)
*************** static struct gimplify_ctx
*** 55,116 ****
    tree exit_label;
    tree return_temp;
    VEC(tree,heap) *case_labels;
-   /* The formal temporary table.  Should this be persistent?  */
-   htab_t temp_htab;
    int conditions;
    bool save_stack;
    bool into_ssa;
  } *gimplify_ctxp;
  
  
- /* Formal (expression) temporary table handling: Multiple occurrences of
-    the same scalar expression are evaluated into the same temporary.  */
- 
- typedef struct gimple_temp_hash_elt
- {
-   tree val;   /* Key */
-   tree temp;  /* Value */
- } elt_t;
- 
  /* Forward declarations.  */
  static enum gimplify_status gimplify_compound_expr (tree *, tree *, bool);
  #ifdef ENABLE_CHECKING
  static bool cpt_same_type (tree a, tree b);
  #endif
  
- 
- /* Return a hash value for a formal temporary table entry.  */
- 
- static hashval_t
- gimple_tree_hash (const void *p)
- {
-   tree t = ((const elt_t *) p)->val;
-   return iterative_hash_expr (t, 0);
- }
- 
- /* Compare two formal temporary table entries.  */
- 
- static int
- gimple_tree_eq (const void *p1, const void *p2)
- {
-   tree t1 = ((const elt_t *) p1)->val;
-   tree t2 = ((const elt_t *) p2)->val;
-   enum tree_code code = TREE_CODE (t1);
- 
-   if (TREE_CODE (t2) != code
-       || TREE_TYPE (t1) != TREE_TYPE (t2))
-     return 0;
- 
-   if (!operand_equal_p (t1, t2, 0))
-     return 0;
- 
-   /* Only allow them to compare equal if they also hash equal; otherwise
-      results are nondeterminate, and we fail bootstrap comparison.  */
-   gcc_assert (gimple_tree_hash (p1) == gimple_tree_hash (p2));
- 
-   return 1;
- }
- 
  /* Set up a context for the gimplifier.  */
  
  void
--- 55,72 ----
*************** push_gimplify_context (void)
*** 119,129 ****
    gcc_assert (!gimplify_ctxp);
    gimplify_ctxp
      = (struct gimplify_ctx *) xcalloc (1, sizeof (struct gimplify_ctx));
-   if (optimize)
-     gimplify_ctxp->temp_htab
-       = htab_create (1000, gimple_tree_hash, gimple_tree_eq, free);
-   else
-     gimplify_ctxp->temp_htab = NULL;
  }
  
  /* Tear down a context for the gimplifier.  If BODY is non-null, then
--- 75,80 ----
*************** pop_gimplify_context (tree body)
*** 151,158 ****
             htab_collisions (gimplify_ctxp->temp_htab));
  #endif
  
-   if (optimize)
-     htab_delete (gimplify_ctxp->temp_htab);
    free (gimplify_ctxp);
    gimplify_ctxp = NULL;
  }
--- 102,107 ----
*************** get_name (tree t)
*** 425,431 ****
  
    stripped_decl = t;
    STRIP_NOPS (stripped_decl);
!   if (DECL_P (stripped_decl) && DECL_NAME (stripped_decl))
      return IDENTIFIER_POINTER (DECL_NAME (stripped_decl));
    else
      {
--- 374,382 ----
  
    stripped_decl = t;
    STRIP_NOPS (stripped_decl);
!   if (DECL_P (stripped_decl)
!       && TREE_CODE (stripped_decl) != GVAR_DECL
!       && DECL_NAME (stripped_decl))
      return IDENTIFIER_POINTER (DECL_NAME (stripped_decl));
    else
      {
*************** get_name (tree t)
*** 440,494 ****
      }
  }
  
! /* Create a temporary with a name derived from VAL.  Subroutine of
!    lookup_tmp_var; nobody else should call this function.  */
  
! static inline tree
! create_tmp_from_val (tree val)
  {
!   return create_tmp_var (TYPE_MAIN_VARIANT (TREE_TYPE (val)), get_name (val));
  }
  
! /* Create a temporary to hold the value of VAL.  If IS_FORMAL, try to reuse
!    an existing expression temporary.  */
  
  static tree
  lookup_tmp_var (tree val, bool is_formal)
  {
!   tree ret;
  
!   /* If not optimizing, never really reuse a temporary.  local-alloc
!      won't allocate any variable that is used in more than one basic
!      block, which means it will go into memory, causing much extra
!      work in reload and final and poorer code generation, outweighing
!      the extra memory allocation here.  */
!   if (!optimize || !is_formal || TREE_SIDE_EFFECTS (val))
!     ret = create_tmp_from_val (val);
!   else
      {
!       elt_t elt, *elt_p;
!       void **slot;
  
!       elt.val = val;
!       slot = htab_find_slot (gimplify_ctxp->temp_htab, (void *)&elt, INSERT);
!       if (*slot == NULL)
!       {
!         elt_p = XNEW (elt_t);
!         elt_p->val = val;
!         elt_p->temp = ret = create_tmp_from_val (val);
!         *slot = (void *) elt_p;
!       }
!       else
!       {
!         elt_p = (elt_t *) *slot;
!           ret = elt_p->temp;
!       }
      }
! 
!   if (is_formal)
!     DECL_GIMPLE_FORMAL_TEMP_P (ret) = 1;
! 
!   return ret;
  }
  
  /* Returns a formal temporary variable initialized with VAL.  PRE_P is as
--- 391,447 ----
      }
  }
  
! /* Table of gimple var for type.  */
  
! static GTY((param_is (struct int_tree_map))) htab_t gvar_for_types;
! 
! /* Returns the unique GVAR_DECL for temporary variables of TYPE.  */
! 
! tree
! gvar_for_type (tree type)
  {
!   struct int_tree_map *h, in;
!   void **slot;
!   unsigned uid = TYPE_UID (type);
! 
!   if (!gvar_for_types)
!     gvar_for_types = htab_create_ggc (20, int_tree_map_hash, 
!                                     int_tree_map_eq, NULL);
! 
!   in.uid = uid;
!   slot = htab_find_slot_with_hash (gvar_for_types, &in, uid, INSERT);
!   if (*slot)
!     h = *slot;
!   else
!     {
!       h = GGC_NEW (struct int_tree_map);
!       h->uid = uid;
!       h->to = make_node (GVAR_DECL);
!       TREE_TYPE (h->to) = type;
!       *slot = h;
!     }
! 
!   return h->to;
  }
  
! /* Create a temporary to hold the value of VAL.  If IS_FORMAL, create a ssa
!    name for it as well.  */
  
  static tree
  lookup_tmp_var (tree val, bool is_formal)
  {
!   tree type = TYPE_MAIN_VARIANT (TREE_TYPE (val));
  
!   if (is_formal)
      {
!       tree var = make_ssa_name (gvar_for_type (type), NULL_TREE);
  
!       if (SSA_NAME_VERSION (var) != 0)
!       add_referenced_tmp_var (SSA_NAME_VAR (var));
!       return var;
      }
!   else
!     return create_tmp_var (type, get_name (val));
  }
  
  /* Returns a formal temporary variable initialized with VAL.  PRE_P is as
*************** lookup_tmp_var (tree val, bool is_formal
*** 506,537 ****
  static tree
  internal_get_tmp_var (tree val, tree *pre_p, tree *post_p, bool is_formal)
  {
!   tree t, mod;
  
    gimplify_expr (&val, pre_p, post_p, is_gimple_formal_tmp_rhs, fb_rvalue);
  
-   t = lookup_tmp_var (val, is_formal);
- 
    if (is_formal)
      {
!       tree u = find_single_pointer_decl (val);
  
!       if (u && TREE_CODE (u) == VAR_DECL && DECL_BASED_ON_RESTRICT_P (u))
!       u = DECL_GET_RESTRICT_BASE (u);
!       if (u && TYPE_RESTRICT (TREE_TYPE (u)))
        {
!         if (DECL_BASED_ON_RESTRICT_P (t))
!           gcc_assert (u == DECL_GET_RESTRICT_BASE (t));
!         else
!           {
!             DECL_BASED_ON_RESTRICT_P (t) = 1;
!             SET_DECL_RESTRICT_BASE (t, u);
!           }
        }
      }
  
!   if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
!     DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
  
    mod = build2 (MODIFY_EXPR, TREE_TYPE (t), t, val);
  
--- 459,500 ----
  static tree
  internal_get_tmp_var (tree val, tree *pre_p, tree *post_p, bool is_formal)
  {
!   tree t, mod, restr_base = NULL_TREE;
  
    gimplify_expr (&val, pre_p, post_p, is_gimple_formal_tmp_rhs, fb_rvalue);
  
    if (is_formal)
      {
!       restr_base = find_single_pointer_decl (val);
  
!       if (restr_base)
        {
!         if (TREE_CODE (restr_base) == VAR_DECL
!             && DECL_BASED_ON_RESTRICT_P (restr_base))
!           restr_base = DECL_GET_RESTRICT_BASE (restr_base);
!         else if (!TYPE_RESTRICT (TREE_TYPE (restr_base)))
!           restr_base = NULL_TREE;
        }
      }
  
!   t = lookup_tmp_var (val,
!                     is_formal
!                     && (restr_base == NULL_TREE)
!                     && is_gimple_reg_type (TREE_TYPE (val)));
! 
!   if (restr_base != NULL_TREE)
!     {
!       DECL_BASED_ON_RESTRICT_P (t) = 1;
!       SET_DECL_RESTRICT_BASE (t, restr_base);
!     }
! 
!   if (TREE_CODE (t) != SSA_NAME)
!     {
!       if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
!       DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
!       if (is_formal)
!       DECL_GIMPLE_FORMAL_TEMP_P (t) = 1;
!     }
  
    mod = build2 (MODIFY_EXPR, TREE_TYPE (t), t, val);
  
*************** gimplify_modify_expr (tree *expr_p, tree
*** 3338,3350 ****
        && is_gimple_reg (TREE_OPERAND (*to_p, 0)))
      return gimplify_modify_expr_complex_part (expr_p, pre_p, want_value);
  
!   if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
      {
!       /* If we've somehow already got an SSA_NAME on the LHS, then
!        we're probably modified it twice.  Not good.  */
!       gcc_assert (TREE_CODE (*to_p) != SSA_NAME);
!       *to_p = make_ssa_name (*to_p, *expr_p);
      }
  
    if (want_value)
      {
--- 3301,3314 ----
        && is_gimple_reg (TREE_OPERAND (*to_p, 0)))
      return gimplify_modify_expr_complex_part (expr_p, pre_p, want_value);
  
!   if (TREE_CODE (*to_p) == SSA_NAME)
      {
!       /* This must be the single definition of the ssa name.  */
!       gcc_assert (SSA_NAME_DEF_STMT (*to_p) == NULL_TREE);
!       SSA_NAME_DEF_STMT (*to_p) = *expr_p;
      }
+   else if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
+     *to_p = make_ssa_name (*to_p, *expr_p);
  
    if (want_value)
      {
*************** force_gimple_operand (tree expr, tree *s
*** 5028,5034 ****
    push_gimplify_context ();
    gimplify_ctxp->into_ssa = in_ssa_p;
  
!   if (var)
      expr = build2 (MODIFY_EXPR, TREE_TYPE (var), var, expr);
  
    ret = gimplify_expr (&expr, stmts, NULL,
--- 4992,4998 ----
    push_gimplify_context ();
    gimplify_ctxp->into_ssa = in_ssa_p;
  
!   if (var && TREE_CODE (var) != GVAR_DECL)
      expr = build2 (MODIFY_EXPR, TREE_TYPE (var), var, expr);
  
    ret = gimplify_expr (&expr, stmts, NULL,
Index: tree.def
===================================================================
*** tree.def    (revision 108807)
--- tree.def    (working copy)
*************** DEFTREECODE (CONST_DECL, "const_decl", t
*** 357,362 ****
--- 357,363 ----
  DEFTREECODE (PARM_DECL, "parm_decl", tcc_declaration, 0)
  DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
  DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
+ DEFTREECODE (GVAR_DECL, "gimple_var_decl", tcc_declaration, 0)
  
  /* Memory tags used in tree-ssa to represent memory locations in
     virtual SSA.  */
Index: tree-dfa.c
===================================================================
*** tree-dfa.c  (revision 108807)
--- tree-dfa.c  (working copy)
*************** find_vars_r (tree *tp, int *walk_subtree
*** 560,572 ****
  
    /* If T is a regular variable that the optimizers are interested
       in, add it to the list of variables.  */
!   if (SSA_VAR_P (*tp))
      add_referenced_var (*tp, walk_state);
  
    /* Type, _DECL and constant nodes have no interesting children.
       Ignore them.  */
    else if (IS_TYPE_OR_DECL_P (*tp) || CONSTANT_CLASS_P (*tp))
!     *walk_subtrees = 0;
  
    return NULL_TREE;
  }
--- 560,577 ----
  
    /* If T is a regular variable that the optimizers are interested
       in, add it to the list of variables.  */
!   *walk_subtrees = 0;
!   if (TREE_CODE (*tp) == SSA_NAME)
!     add_referenced_var (SSA_NAME_VAR (*tp), walk_state);
!   else if (SSA_VAR_P (*tp))
      add_referenced_var (*tp, walk_state);
  
    /* Type, _DECL and constant nodes have no interesting children.
       Ignore them.  */
    else if (IS_TYPE_OR_DECL_P (*tp) || CONSTANT_CLASS_P (*tp))
!     ;
!   else
!     *walk_subtrees = 1;
  
    return NULL_TREE;
  }
*************** tree 
*** 623,628 ****
--- 628,637 ----
  default_def (tree var)
  {
    struct int_tree_map *h, in;
+ 
+   if (TREE_CODE (var) == GVAR_DECL)
+     return NULL_TREE;
+ 
    gcc_assert (SSA_VAR_P (var));
    in.uid = DECL_UID (var);
    h = (struct int_tree_map *) htab_find_with_hash (default_defs, &in,
*************** add_referenced_var (tree var, struct wal
*** 701,707 ****
        mark_call_clobbered (var);
  
        /* Tag's don't have DECL_INITIAL.  */
!       if (MTAG_P (var))
        return;
        
        /* Scan DECL_INITIAL for pointer variables as they may contain
--- 710,716 ----
        mark_call_clobbered (var);
  
        /* Tag's don't have DECL_INITIAL.  */
!       if (MTAG_P (var) || TREE_CODE (var) == GVAR_DECL)
        return;
        
        /* Scan DECL_INITIAL for pointer variables as they may contain
Index: tree-ssa-live.c
===================================================================
*** tree-ssa-live.c     (revision 108807)
--- tree-ssa-live.c     (working copy)
*************** create_ssa_var_map (int flags)
*** 381,388 ****
          stmt = bsi_stmt (bsi);
  
          /* Register USE and DEF operands in each statement.  */
!         FOR_EACH_SSA_TREE_OPERAND (use , stmt, iter, SSA_OP_USE)
            {
              register_ssa_partition (map, use, true);
  
  #ifdef ENABLE_CHECKING
--- 381,391 ----
          stmt = bsi_stmt (bsi);
  
          /* Register USE and DEF operands in each statement.  */
!         FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
            {
+             if (TMP_NAME_P (use))
+               continue;
+ 
              register_ssa_partition (map, use, true);
  
  #ifdef ENABLE_CHECKING
*************** create_ssa_var_map (int flags)
*** 392,397 ****
--- 395,403 ----
  
          FOR_EACH_SSA_TREE_OPERAND (dest, stmt, iter, SSA_OP_DEF)
            {
+             if (TMP_NAME_P (dest))
+               continue;
+ 
              register_ssa_partition (map, dest, false);
  
  #ifdef ENABLE_CHECKING
Index: print-tree.c
===================================================================
*** print-tree.c        (revision 108807)
--- print-tree.c        (working copy)
*************** print_node (FILE *file, const char *pref
*** 224,230 ****
    /* Print the name, if any.  */
    if (class == tcc_declaration)
      {
!       if (DECL_NAME (node))
        fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
        else if (TREE_CODE (node) == LABEL_DECL
               && LABEL_DECL_UID (node) != -1)
--- 224,232 ----
    /* Print the name, if any.  */
    if (class == tcc_declaration)
      {
!       if (TREE_CODE (node) == GVAR_DECL)
!       fprintf (file, "%c.%u", 'T', DECL_UID (node));
!       else if (DECL_NAME (node))
        fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
        else if (TREE_CODE (node) == LABEL_DECL
               && LABEL_DECL_UID (node) != -1)
Index: tree-ssa.c
===================================================================
*** tree-ssa.c  (revision 108807)
--- tree-ssa.c  (working copy)
*************** delete_tree_ssa (void)
*** 817,828 ****
    for (i = 0; i < num_ssa_names; i++)
      {
        tree var = ssa_name (i);
!       if (var && TREE_CODE (var) == SSA_NAME)
          {
          SSA_NAME_IMM_USE_NODE (var).prev = &(SSA_NAME_IMM_USE_NODE (var));
          SSA_NAME_IMM_USE_NODE (var).next = &(SSA_NAME_IMM_USE_NODE (var));
        }
-       release_ssa_name (var);
      }
  
    /* Remove annotations from every tree in the function.  */
--- 817,830 ----
    for (i = 0; i < num_ssa_names; i++)
      {
        tree var = ssa_name (i);
!       if (var 
!         && TREE_CODE (var) == SSA_NAME
!         && !TMP_NAME_P (var))
          {
          SSA_NAME_IMM_USE_NODE (var).prev = &(SSA_NAME_IMM_USE_NODE (var));
          SSA_NAME_IMM_USE_NODE (var).next = &(SSA_NAME_IMM_USE_NODE (var));
+         release_ssa_name (var);
        }
      }
  
    /* Remove annotations from every tree in the function.  */
Index: tree-inline.c
===================================================================
*** tree-inline.c       (revision 108807)
--- tree-inline.c       (working copy)
*************** remap_decl (tree decl, inline_data *id)
*** 200,251 ****
    if (!n)
      {
        /* Make a copy of the variable or label.  */
!       tree t;
!       t = copy_decl_for_dup (decl, fn, id->caller, id->versioning_p);
!      
!       /* Remember it, so that if we encounter this local entity again
!        we can reuse this copy.  Do this early because remap_type may
!        need this decl for TYPE_STUB_DECL.  */
!       insert_decl_map (id, decl, t);
  
!       /* Remap types, if necessary.  */
!       TREE_TYPE (t) = remap_type (TREE_TYPE (t), id);
!       if (TREE_CODE (t) == TYPE_DECL)
!         DECL_ORIGINAL_TYPE (t) = remap_type (DECL_ORIGINAL_TYPE (t), id);
! 
!       /* Remap sizes as necessary.  */
!       walk_tree (&DECL_SIZE (t), copy_body_r, id, NULL);
!       walk_tree (&DECL_SIZE_UNIT (t), copy_body_r, id, NULL);
! 
!       /* If fields, do likewise for offset and qualifier.  */
!       if (TREE_CODE (t) == FIELD_DECL)
!       {
!         walk_tree (&DECL_FIELD_OFFSET (t), copy_body_r, id, NULL);
!         if (TREE_CODE (DECL_CONTEXT (t)) == QUAL_UNION_TYPE)
!           walk_tree (&DECL_QUALIFIER (t), copy_body_r, id, NULL);
!       }
! 
! #if 0
!       /* FIXME handle anon aggrs.  */
!       if (! DECL_NAME (t) && TREE_TYPE (t)
!         && lang_hooks.tree_inlining.anon_aggr_type_p (TREE_TYPE (t)))
!       {
!         /* For a VAR_DECL of anonymous type, we must also copy the
!            member VAR_DECLS here and rechain the DECL_ANON_UNION_ELEMS.  */
!         tree members = NULL;
!         tree src;
  
!         for (src = DECL_ANON_UNION_ELEMS (t); src;
!              src = TREE_CHAIN (src))
            {
!             tree member = remap_decl (TREE_VALUE (src), id);
! 
!             gcc_assert (!TREE_PURPOSE (src));
!             members = tree_cons (NULL, member, members);
            }
!         DECL_ANON_UNION_ELEMS (t) = nreverse (members);
        }
- #endif
  
        /* Remember it, so that if we encounter this local entity
         again we can reuse this copy.  */
--- 200,240 ----
    if (!n)
      {
        /* Make a copy of the variable or label.  */
!       tree t, type;
  
!       if (TREE_CODE (decl) == SSA_NAME)
!       {
!         gcc_assert (TMP_NAME_P (decl));
!         type = remap_type (TREE_TYPE (decl), id);
!         t = make_ssa_name (gvar_for_type (type), NULL_TREE);
!       }
!       else
!       {
!         t = copy_decl_for_dup (decl, fn, id->caller, id->versioning_p);
!      
!         /* Remember it, so that if we encounter this local entity again
!            we can reuse this copy.  Do this early because remap_type may
!            need this decl for TYPE_STUB_DECL.  */
!         insert_decl_map (id, decl, t);
! 
!         /* Remap types, if necessary.  */
!         TREE_TYPE (t) = remap_type (TREE_TYPE (t), id);
!         if (TREE_CODE (t) == TYPE_DECL)
!           DECL_ORIGINAL_TYPE (t) = remap_type (DECL_ORIGINAL_TYPE (t), id);
! 
!         /* Remap sizes as necessary.  */
!         walk_tree (&DECL_SIZE (t), copy_body_r, id, NULL);
!         walk_tree (&DECL_SIZE_UNIT (t), copy_body_r, id, NULL);
  
!         /* If fields, do likewise for offset and qualifier.  */
!         if (TREE_CODE (t) == FIELD_DECL)
            {
!             walk_tree (&DECL_FIELD_OFFSET (t), copy_body_r, id, NULL);
!             if (TREE_CODE (DECL_CONTEXT (t)) == QUAL_UNION_TYPE)
!               walk_tree (&DECL_QUALIFIER (t), copy_body_r, id, NULL);
            }
! 
        }
  
        /* Remember it, so that if we encounter this local entity
         again we can reuse this copy.  */
*************** copy_body_r (tree *tp, int *walk_subtree
*** 547,552 ****
--- 536,546 ----
          return (tree) (void *)1;
        }
      }
+   else if (TREE_CODE (*tp) == SSA_NAME)
+     {
+       *tp = remap_decl (*tp, id);
+       *walk_subtrees = 0;
+     }
  
    /* Local variables and labels need to be replaced by equivalent
       variables.  We don't want to copy static variables; there's only
*************** copy_body_r (tree *tp, int *walk_subtree
*** 707,712 ****
--- 701,722 ----
          recompute_tree_invariant_for_addr_expr (*tp);
          *walk_subtrees = 0;
        }
+ 
+       if (TREE_CODE (*tp) == MODIFY_EXPR)
+       {
+         tree op;
+ 
+         walk_tree (&TREE_OPERAND (*tp, 0), copy_body_r, id, NULL);
+         walk_tree (&TREE_OPERAND (*tp, 1), copy_body_r, id, NULL);
+         op = TREE_OPERAND (*tp, 0);
+         if (TREE_CODE (op) == SSA_NAME)
+           {
+             gcc_assert (SSA_NAME_DEF_STMT (op) == NULL_TREE);
+             SSA_NAME_DEF_STMT (op) = *tp;
+           }
+         *walk_subtrees = 0;
+         return NULL_TREE;
+       }
      }
  
    /* Keep iterating.  */
Index: tree-outof-ssa.c
===================================================================
*** tree-outof-ssa.c    (revision 108807)
--- tree-outof-ssa.c    (working copy)
*************** check_replaceable (temp_expr_table_p tab
*** 1584,1590 ****
    /* Add this expression to the dependency list for each use partition.  */
    FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
      {
!       add_dependance (tab, version, var);
      }
  
    /* If there are VUSES, add a dependence on virtual defs.  */
--- 1584,1591 ----
    /* Add this expression to the dependency list for each use partition.  */
    FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
      {
!       if (!TMP_NAME_P (var))
!       add_dependance (tab, version, var);
      }
  
    /* If there are VUSES, add a dependence on virtual defs.  */
*************** rewrite_trees (var_map map, tree *values
*** 1902,1907 ****
--- 1903,1910 ----
          copy_use_p = NULL_USE_OPERAND_P;
          FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
            {
+             if (TMP_NAME_P (USE_FROM_PTR (use_p)))
+               continue;
              if (replace_use_variable (map, use_p, values))
                changed = true;
              copy_use_p = use_p;
*************** rewrite_trees (var_map map, tree *values
*** 1917,1923 ****
            {
              /* Mark this stmt for removal if it is the list of replaceable 
                 expressions.  */
!             if (values && values[SSA_NAME_VERSION (DEF_FROM_PTR (def_p))])
                remove = true;
              else
                {
--- 1920,1928 ----
            {
              /* Mark this stmt for removal if it is the list of replaceable 
                 expressions.  */
!             if (TMP_NAME_P (DEF_FROM_PTR (def_p)))
!               ;
!             else if (values && values[SSA_NAME_VERSION (DEF_FROM_PTR 
(def_p))])
                remove = true;
              else
                {
*************** rewrite_trees (var_map map, tree *values
*** 1935,1941 ****
            }
          else
            FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_DEF)
!             if (replace_def_variable (map, def_p, NULL))
                changed = true;
  
          /* Remove any stmts marked for removal.  */
--- 1940,1947 ----
            }
          else
            FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_DEF)
!             if (!TMP_NAME_P (DEF_FROM_PTR (def_p))
!                 && replace_def_variable (map, def_p, NULL))
                changed = true;
  
          /* Remove any stmts marked for removal.  */
*************** insert_backedge_copies (void)
*** 2489,2494 ****
--- 2495,2582 ----
      }
  }
  
+ /* Copy information from FROM_ANN to TO_ANN.  */
+ 
+ static void
+ copy_var_ann (var_ann_t to_ann, var_ann_t from_ann)
+ {
+   to_ann->type_mem_tag = from_ann->type_mem_tag;
+ 
+   if (from_ann->may_aliases)
+     {
+       unsigned i;
+       tree al;
+ 
+       to_ann->may_aliases = VEC_alloc (tree, gc,
+                                      VEC_length (tree,
+                                                  from_ann->may_aliases));
+ 
+       for (i = 0; VEC_iterate (tree, from_ann->may_aliases, i, al); i++)
+       VEC_quick_push (tree, to_ann->may_aliases, al);
+     }
+ }
+ 
+ /* We would like to keep the ssa names for gimplifier temporaries.  Phi
+    nodes for gimplifier temporary ssa names are fairly rare, but they
+    may appear due to code duplication.  Persuading rest of out-of-ssa not
+    to create temporary variables for these ssa names is somewhat nontrivial,
+    so we avoid it -- we just create the new temporary variables for those
+    tmp ssa names that appear in phi nodes, and don't tell out-of-ssa about the
+    rest.  */
+ 
+ static void
+ eliminate_tmp_name_phis (void)
+ {
+   basic_block bb;
+   tree phi, name, var, old_var;
+   ssa_op_iter oi;
+   use_operand_p use;
+ 
+   FOR_EACH_BB (bb)
+     {
+       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+       {
+         if (!is_gimple_reg (PHI_RESULT (phi)))
+           continue;
+ 
+         var = NULL_TREE;
+         old_var = NULL_TREE;
+         name = PHI_RESULT (phi);
+ 
+         if (TMP_NAME_P (name))
+           {
+             var = create_tmp_var (TREE_TYPE (name), NULL);
+             old_var = SSA_NAME_VAR (name);
+ 
+             SSA_NAME_VAR (name) = var;
+           }
+         FOR_EACH_PHI_ARG (use, phi, oi, SSA_OP_USE)
+           {
+             name = USE_FROM_PTR (use);
+ 
+             if (!TMP_NAME_P (name))
+               continue;
+ 
+             if (!var)
+               {
+                 var = create_tmp_var (TREE_TYPE (name), NULL);
+                 old_var = SSA_NAME_VAR (name);
+               }
+             else
+               gcc_assert (SSA_NAME_VAR (name) == old_var);
+ 
+             SSA_NAME_VAR (name) = var;
+           }
+ 
+         if (var)
+           {
+             add_referenced_tmp_var (var);
+             copy_var_ann (var_ann (var), var_ann (old_var));
+           }
+       }
+     }
+ }
+ 
  /* Take the current function out of SSA form, as described in
     R. Morgan, ``Building an Optimizing Compiler'',
     Butterworth-Heinemann, Boston, MA, 1998. pp 176-186.  */
*************** rewrite_out_of_ssa (void)
*** 2500,2505 ****
--- 2588,2595 ----
    int var_flags = 0;
    int ssa_flags = 0;
  
+   eliminate_tmp_name_phis ();
+ 
    /* If elimination of a PHI requires inserting a copy on a backedge,
       then we will have to split the backedge which has numerous
       undesirable performance effects.
Index: tree-cfg.c
===================================================================
*** tree-cfg.c  (revision 108807)
--- tree-cfg.c  (working copy)
*************** verify_expr (tree *tp, int *walk_subtree
*** 3250,3255 ****
--- 3250,3287 ----
        }
        break;
  
+     case TARGET_MEM_REF:
+       /* Ignore TMR_ORIGINAL and TMR_TAG.  */
+       if (TMR_SYMBOL (t) && !DECL_P (TMR_SYMBOL (t)))
+       {
+         error ("tmr symbol is not a decl");
+         return t;
+       }
+ 
+       if (TMR_BASE (t) && !is_gimple_val (TMR_BASE (t)))
+       {
+         error ("invalid tmr base");
+         return t;
+       }
+       if (TMR_INDEX (t) && !is_gimple_val (TMR_INDEX (t)))
+       {
+         error ("invalid tmr index");
+         return t;
+       }
+       if (TMR_STEP (t) && TREE_CODE (TMR_STEP (t)) != INTEGER_CST)
+       {
+         error ("invalid tmr step");
+         return t;
+       }
+       if (TMR_OFFSET (t) && TREE_CODE (TMR_OFFSET (t)) != INTEGER_CST)
+       {
+         error ("invalid tmr offset");
+         return t;
+       }
+ 
+       *walk_subtrees = 0;
+       break;
+ 
      case NOP_EXPR:
      case CONVERT_EXPR:
      case FIX_TRUNC_EXPR:
Index: tree-ssanames.c
===================================================================
*** tree-ssanames.c     (revision 108807)
--- tree-ssanames.c     (working copy)
*************** make_ssa_name (tree var, tree stmt)
*** 123,130 ****
    tree t;
    use_operand_p imm;
  
!   gcc_assert (DECL_P (var)
!             || TREE_CODE (var) == INDIRECT_REF);
  
    gcc_assert (!stmt || EXPR_P (stmt) || TREE_CODE (stmt) == PHI_NODE);
  
--- 123,129 ----
    tree t;
    use_operand_p imm;
  
!   gcc_assert (DECL_P (var));
  
    gcc_assert (!stmt || EXPR_P (stmt) || TREE_CODE (stmt) == PHI_NODE);
  
*************** make_ssa_name (tree var, tree stmt)
*** 145,152 ****
    else
      {
        t = make_node (SSA_NAME);
!       SSA_NAME_VERSION (t) = num_ssa_names;
!       VEC_safe_push (tree, gc, ssa_names, t);
  #ifdef GATHER_STATISTICS
        ssa_name_nodes_created++;
  #endif
--- 144,162 ----
    else
      {
        t = make_node (SSA_NAME);
!       if (ssa_names)
!       {
!         SSA_NAME_VERSION (t) = num_ssa_names;
!         VEC_safe_push (tree, gc, ssa_names, t);
!       }
!       else
!       {
!         /* The ssa name allocated from gimplification.  We won't assign it
!            a real version till the first time ssa form is built for the
!            function.  */
!         gcc_assert (TREE_CODE (var) == GVAR_DECL);
!         SSA_NAME_VERSION (t) = 0;
!       }
  #ifdef GATHER_STATISTICS
        ssa_name_nodes_created++;
  #endif
*************** make_ssa_name (tree var, tree stmt)
*** 166,171 ****
--- 176,189 ----
    return t;
  }
  
+ /* Assign version and position in the list of ssa names to NAME.  */
+ 
+ void
+ register_tmp_ssa_name (tree name)
+ {
+   SSA_NAME_VERSION (name) = num_ssa_names;
+   VEC_safe_push (tree, gc, ssa_names, name);
+ }
  
  /* We no longer need the SSA_NAME expression VAR, release it so that
     it may be reused. 

Reply via email to