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.