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.