+2012-08-10 Richard Guenther <rguenther@suse.de>
+
+ * tree.h (SSA_NAME_VAR): Return NULL_TREE if an IDENTIFIER_NODE
+ is recorded as var.
+ (SSA_NAME_IDENTIFIER): Return the IDENTIFIER_NODE of the SSA_NAME
+ or its SSA_NAME_VAR.
+ (SET_SSA_NAME_VAR_OR_IDENTIFIER): New setter.
+ * tree-ssanames.c (make_ssa_name_fn): Handle creating anonymous
+ SSA names by passing a type instead of a variable decl.
+ (release_ssa_name): Use SET_SSA_NAME_VAR_OR_IDENTIFIER.
+ (copy_ssa_name_fn): Handle anonymous SSA names.
+ (replace_ssa_name_symbol): Use SET_SSA_NAME_VAR_OR_IDENTIFIER.
+ * tree-flow-inline.h (make_temp_ssa_name): New inline function.
+ * tree-pretty-print.c (dump_generic_node): Use SSA_NAME_IDENTIFIER,
+ dump SSA names without a name as <anon>.
+ * cfgexpand.c (expand_used_vars): Assing anonymous SSA names we are
+ going to expand a decl.
+ (gimple_expand_cfg): Assign all SSA names of a partition the
+ decl we created for its leader.
+ * tree-ssa.c (target_for_debug_bind): Handle SSA_NAMEs.
+ (verify_ssa_name): Handle anonymous SSA names.
+ (verify_def): Likewise.
+ * tree-predcom.c (eliminate_temp_copies): Likewise.
+ * tree-ssa-copyrename.c (copy_rename_partition_coalesce): Likewise.
+ * tree-ssa-live.c (var_map_base_init): Compute conflicts for
+ anonymous SSA names with the same type.
+ (mark_all_vars_used_1): Handle anonymous SSA names.
+ (verify_live_on_entry): Likewise.
+ * tree-ssa-coalesce.c (abnormal_corrupt): Remove.
+ (create_outofssa_var_map): Adjust with respect to conflicts we
+ compute for anonymous SSA names. Do not restrict abnormal
+ coalescing.
+ (coalesce_partitions): Do not restrict abnormal coalescing.
+ Assert we only ever coalesce variables we computed conflicts for.
+ * tree-ssa-ter.c (process_replaceable): Do not restrict TER
+ of anonymous names.
+ * expr.c (expand_expr_real_1): Handle anonymous SSA names
+ expanded from IVOPTs by creating a raw REG here.
+ * tree-cfg.c (replace_ssa_name): Handle anonymous SSA names.
+ (dump_function_to_file): Dump anonymous SSA names alongside
+ with their types in the variable list.
+ (verify_gimple_return): Guard use of SSA_NAME_VAR.
+ * tree-into-ssa.c (mark_for_renaming): Handle a NULL symbol.
+ (rewrite_into_ssa): Make SSA names anonymous.
+ * tree-ssa-structalias.c (alias_get_name): Rewrite.
+ * tree-ssa-uninit.c (ssa_undefined_value_p): Handle anonymous
+ SSA names.
+ (warn_uninitialized_phi): Likewise.
+ * tree-ssa-loop-ivopts.c (prepare_decl_rtl): Defer expanding
+ anonymous SSA names to the expander.
+ (determine_iv_cost): Anonymous SSA names are artificial.
+ * tree-ssa-loop-manip.c (tree_transform_and_unroll_loop):
+ Handle anonymous SSA names.
+ * lto-streamer-out.c (output_ssa_names): Stream SSA_NAME_VAR
+ or if NULL, the type of the SSA name.
+ * tree-inline.c (remap_ssa_name): Handle anonymous SSA names,
+ remap names as anonymous where appropriate.
+ (insert_init_stmt): Pass SSA names down to insert_init_debug_bind.
+ * tree-ssa-uncprop.c (uncprop_into_successor_phis): Adjust
+ according to what we create conflicts for in out-of-SSA
+ coalescing.
+ * tree-parloops.c (separate_decls_in_region_name): Handle
+ anonymous SSA names.
+ (add_field_for_name): Likewise.
+ * tree.c (get_name): Handle SSA names.
+ * tree-ssa-loop-im.c (gen_lsm_tmp_name): Defer to get_name for
+ SSA_NAMEs.
+ * tree-vect-loop-manip.c (adjust_debug_stmts): Use
+ virtual_operand_p.
+ * tree-sra.c (create_access_replacement): Give up generating
+ a DECL_DEBUG_EXPR for SSA names in the memory reference.
+ (replace_removed_params_ssa_names): Guard use of SSA_NAME_VAR.
+ * tree-complex.c (get_component_ssa_name): Handle anonymous
+ SSA names.
+ (set_component_ssa_name): Likewise.
+ * tree-ssa-sccvn.c (visit_reference_op_load): Likewise.
+ * tree-object-size.c (collect_object_sizes_for): Handle
+ uninitialized SSA names properly.
+ * ipa-inline-analysis.c (eliminated_by_inlining_prob): Guard use of
+ SSA_NAME_VAR.
+ * ipa-split.c (test_nonssa_use): Likewise.
+ (consider_split): Likewise.
+ (mark_nonssa_use): Likewise.
+
2012-08-09 Jan Hubicka <jh@suse.cz>
PR middle-end/54146
+2012-08-10 Richard Guenther <rguenther@suse.de>
+
+ * c-pretty-print.c (pp_c_expression): Handle anonymous SSA names.
+
2012-08-07 Steven Bosscher <steven@gcc.gnu.org>
* c-pretty-print.c (pp_c_function_definition): Use pp_newline_and_flush
break;
case SSA_NAME:
- if (!DECL_ARTIFICIAL (SSA_NAME_VAR (e)))
+ if (SSA_NAME_VAR (e)
+ && !DECL_ARTIFICIAL (SSA_NAME_VAR (e)))
pp_c_expression (pp, SSA_NAME_VAR (e));
else
pp_c_ws_string (pp, M_("<unknown>"));
{
tree var, outer_block = DECL_INITIAL (current_function_decl);
VEC(tree,heap) *maybe_local_decls = NULL;
+ struct pointer_map_t *ssa_name_decls;
unsigned i;
unsigned len;
init_vars_expansion ();
+ ssa_name_decls = pointer_map_create ();
for (i = 0; i < SA.map->num_partitions; i++)
{
tree var = partition_to_var (SA.map, i);
gcc_assert (is_gimple_reg (var));
+
+ /* Assign decls to each SSA name partition, share decls for partitions
+ we could have coalesced (those with the same type). */
+ if (SSA_NAME_VAR (var) == NULL_TREE)
+ {
+ void **slot = pointer_map_insert (ssa_name_decls, TREE_TYPE (var));
+ if (!*slot)
+ *slot = (void *) create_tmp_reg (TREE_TYPE (var), NULL);
+ replace_ssa_name_symbol (var, (tree) *slot);
+ }
+
if (TREE_CODE (SSA_NAME_VAR (var)) == VAR_DECL)
expand_one_var (var, true, true);
else
}
}
}
+ pointer_map_destroy (ssa_name_decls);
/* At this point all variables on the local_decls with TREE_USED
set are not associated with any block scope. Lay them out. */
rtx r;
if (!name
- || !POINTER_TYPE_P (TREE_TYPE (name))
/* We might have generated new SSA names in
update_alias_info_with_stack_vars. They will have a NULL
defining statements, and won't be part of the partitioning,
part = var_to_partition (SA.map, name);
if (part == NO_PARTITION)
continue;
+
+ /* Adjust all partition members to get the underlying decl of
+ the representative which we might have created in expand_one_var. */
+ if (SSA_NAME_VAR (name) == NULL_TREE)
+ {
+ tree leader = partition_to_var (SA.map, part);
+ gcc_assert (SSA_NAME_VAR (leader) != NULL_TREE);
+ replace_ssa_name_symbol (name, SSA_NAME_VAR (leader));
+ }
+ if (!POINTER_TYPE_P (TREE_TYPE (name)))
+ continue;
+
r = SA.partition_to_pseudo[part];
if (REG_P (r))
mark_reg_pointer (r, get_pointer_alignment (name));
+2012-08-10 Richard Guenther <rguenther@suse.de>
+
+ * error.c (dump_expr): Handle anonymous SSA names.
+
2012-08-07 Steven Bosscher <steven@gcc.gnu.org>
* error.c (print_instantiation_context): Pretty-print a newline before
break;
case SSA_NAME:
- if (!DECL_ARTIFICIAL (SSA_NAME_VAR (t)))
+ if (SSA_NAME_VAR (t)
+ && !DECL_ARTIFICIAL (SSA_NAME_VAR (t)))
dump_expr (SSA_NAME_VAR (t), flags);
else
pp_cxx_ws_string (cxx_pp, M_("<unknown>"));
base variable. This unnecessarily allocates a pseudo, see how we can
reuse it, if partition base vars have it set already. */
if (!currently_expanding_to_rtl)
- return expand_expr_real_1 (SSA_NAME_VAR (exp), target, tmode, modifier,
- NULL);
+ {
+ tree var = SSA_NAME_VAR (exp);
+ if (var && DECL_RTL_SET_P (var))
+ return DECL_RTL (var);
+ return gen_raw_REG (TYPE_MODE (TREE_TYPE (exp)),
+ LAST_VIRTUAL_REGISTER + 1);
+ }
g = get_gimple_for_ssa_name (exp);
/* For EXPAND_INITIALIZER try harder to get something simpler. */
|| (TREE_CODE(inner_lhs) == MEM_REF
&& (unmodified_parm (stmt, TREE_OPERAND (inner_lhs, 0))
|| (TREE_CODE (TREE_OPERAND (inner_lhs, 0)) == SSA_NAME
- && TREE_CODE (SSA_NAME_VAR
- (TREE_OPERAND (inner_lhs, 0)))
- == RESULT_DECL))))
+ && SSA_NAME_VAR (TREE_OPERAND (inner_lhs, 0))
+ && TREE_CODE (SSA_NAME_VAR (TREE_OPERAND
+ (inner_lhs, 0))) == RESULT_DECL))))
lhs_free = true;
if (lhs_free
&& (is_gimple_reg (rhs) || is_gimple_min_invariant (rhs)))
to pretend that the value pointed to is actual result decl. */
if ((TREE_CODE (t) == MEM_REF || INDIRECT_REF_P (t))
&& TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME
+ && SSA_NAME_VAR (TREE_OPERAND (t, 0))
&& TREE_CODE (SSA_NAME_VAR (TREE_OPERAND (t, 0))) == RESULT_DECL
&& DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
return
/* Special case is value returned by reference we record as if it was non-ssa
set to result_decl. */
else if (TREE_CODE (retval) == SSA_NAME
+ && SSA_NAME_VAR (retval)
&& TREE_CODE (SSA_NAME_VAR (retval)) == RESULT_DECL
&& DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
current->split_part_set_retval
to pretend that the value pointed to is actual result decl. */
if ((TREE_CODE (t) == MEM_REF || INDIRECT_REF_P (t))
&& TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME
+ && SSA_NAME_VAR (TREE_OPERAND (t, 0))
&& TREE_CODE (SSA_NAME_VAR (TREE_OPERAND (t, 0))) == RESULT_DECL
&& DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
return
streamer_write_uhwi (ob, i);
streamer_write_char_stream (ob->main_stream,
SSA_NAME_IS_DEFAULT_DEF (ptr));
- stream_write_tree (ob, SSA_NAME_VAR (ptr), true);
+ if (SSA_NAME_VAR (ptr))
+ stream_write_tree (ob, SSA_NAME_VAR (ptr), true);
+ else
+ /* ??? This drops SSA_NAME_IDENTIFIER on the floor. */
+ stream_write_tree (ob, TREE_TYPE (ptr), true);
}
streamer_write_zero (ob);
+2012-08-10 Richard Guenther <rguenther@suse.de>
+
+ * g++.dg/plugin/selfassign.c: Adjust.
+ * gcc.dg/plugin/selfassign.c: Likewise.
+ * gcc.dg/strlenopt-11.c: Likewise.
+ * gcc.dg/strlenopt-13.c: Likewise.
+ * gcc.dg/no-strict-overflow-4.c: Likewise.
+ * gcc.dg/strict-overflow-4.c: Likewise.
+ * gcc.dg/tree-ssa/alias-11.c: Likewise.
+ * gcc.dg/tree-ssa/alias-6.c: Likewise.
+ * gcc.dg/tree-ssa/asm-3.c: Likewise.
+ * gcc.dg/tree-ssa/pr18908.c: Likewise.
+ * gcc.dg/tree-ssa/pr19431.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-pre-21.c: Likewise.
+ * gcc.dg/tree-ssa/phi-opt-10.c: Likewise.
+ * gcc.dg/tree-ssa/phi-opt-7.c: Likewise.
+ * gcc.dg/tree-ssa/slsr-27.c: Likewise.
+ * gcc.dg/tree-ssa/slsr-28.c: Likewise.
+ * gcc.dg/tree-ssa/slsr-29.c: Likewise.
+ * gcc.dg/pr46309.c: Likewise.
+ * gcc.dg/tree-ssa/loop-5.c: Likewise.
+
2012-08-09 Uros Bizjak <ubizjak@gmail.com>
* gcc.c-torture/compile/20120727-1.c (dg-options): Add -mfpmath=387
e.g. D.1797_14, we need to grab the rhs of its SSA def
statement (i.e. foo.x). */
tree vdecl = SSA_NAME_VAR (expr);
- if (DECL_ARTIFICIAL (vdecl)
+ if ((!vdecl || DECL_ARTIFICIAL (vdecl))
&& !gimple_nop_p (SSA_NAME_DEF_STMT (expr)))
{
gimple def_stmt = SSA_NAME_DEF_STMT (expr);
static tree
get_non_ssa_expr (tree expr)
{
+ if (!expr)
+ return NULL_TREE;
switch (TREE_CODE (expr))
{
case VAR_DECL:
case SSA_NAME:
{
tree vdecl = SSA_NAME_VAR (expr);
- if (DECL_ARTIFICIAL (vdecl)
+ if ((!vdecl || DECL_ARTIFICIAL (vdecl))
&& !gimple_nop_p (SSA_NAME_DEF_STMT (expr)))
{
gimple def_stmt = SSA_NAME_DEF_STMT (expr);
if (TREE_CODE (lhs) == SSA_NAME)
{
lhs = SSA_NAME_VAR (lhs);
- if (DECL_ARTIFICIAL (lhs))
+ if (!lhs || DECL_ARTIFICIAL (lhs))
return;
}
return i + 1 > i;
}
-/* We expect to see "<bb N>"; confirm that, so that we know to count
- it in the real test. */
-/* { dg-final { scan-tree-dump-times "<bb\[^>\]*>" 1 "optimized" } } */
-/* { dg-final { scan-tree-dump-times ">|<" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump "\[^ \]*_.(\\\(D\\\))? (>|<) \[^ \]*_." "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
e.g. D.1797_14, we need to grab the rhs of its SSA def
statement (i.e. foo.x). */
tree vdecl = SSA_NAME_VAR (expr);
- if (DECL_ARTIFICIAL (vdecl)
+ if ((!vdecl || DECL_ARTIFICIAL (vdecl))
&& !gimple_nop_p (SSA_NAME_DEF_STMT (expr)))
{
gimple def_stmt = SSA_NAME_DEF_STMT (expr);
static tree
get_non_ssa_expr (tree expr)
{
+ if (!expr)
+ return NULL_TREE;
switch (TREE_CODE (expr))
{
case VAR_DECL:
case SSA_NAME:
{
tree vdecl = SSA_NAME_VAR (expr);
- if (DECL_ARTIFICIAL (vdecl)
+ if ((!vdecl || DECL_ARTIFICIAL (vdecl))
&& !gimple_nop_p (SSA_NAME_DEF_STMT (expr)))
{
gimple def_stmt = SSA_NAME_DEF_STMT (expr);
if (TREE_CODE (lhs) == SSA_NAME)
{
lhs = SSA_NAME_VAR (lhs);
- if (DECL_ARTIFICIAL (lhs))
+ if (!lhs || DECL_ARTIFICIAL (lhs))
return;
}
/* { dg-final { scan-tree-dump-times "Optimizing range tests a_\[0-9\]*.D. -.1, 1. and -.2, 2.\[\n\r\]* into" 1 "reassoc1" } } */
/* { dg-final { scan-tree-dump-times "Optimizing range tests a_\[0-9\]*.D. -.0, 31. and -.64, 95.\[\n\r\]* into" 2 "reassoc1" } } */
/* { dg-final { scan-tree-dump-times "Optimizing range tests a_\[0-9\]*.D. -.128, 159. and -.192, 223.\[\n\r\]* into" 1 "reassoc1" } } */
-/* { dg-final { scan-tree-dump-times "Optimizing range tests D.\[0-9\]*_\[0-9\]* -.0, 31. and -.128, 159.\[\n\r\]* into" 1 "reassoc2" } } */
+/* { dg-final { scan-tree-dump-times "Optimizing range tests \[^\r\n\]*_\[0-9\]* -.0, 31. and -.128, 159.\[\n\r\]* into" 1 "reassoc2" } } */
/* { dg-final { cleanup-tree-dump "reassoc1" } } */
/* { dg-final { cleanup-tree-dump "reassoc2" } } */
return i + 1 > i;
}
-/* We expect to see "<bb N>"; confirm that, so that we know to count
- it in the real test. */
-/* { dg-final { scan-tree-dump-times "<bb\[^>\]*>" 1 "optimized" } } */
-/* { dg-final { scan-tree-dump-times ">|<" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump "return 1;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
-/* { dg-final { scan-tree-dump-times " D\.\[0-9_\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.0. = " 1 "strlen" } } */
-/* { dg-final { scan-tree-dump-times " D\.\[0-9_\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.6. = " 1 "strlen" } } */
-/* { dg-final { scan-tree-dump-times " D\.\[0-9_\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.9. = " 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.0. = " 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.6. = " 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.9. = " 1 "strlen" } } */
/* { dg-final { cleanup-tree-dump "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
-/* { dg-final { scan-tree-dump-times " D\.\[0-9_\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.0. = " 1 "strlen" } } */
-/* { dg-final { scan-tree-dump-times " D\.\[0-9_\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.1. = " 1 "strlen" } } */
-/* { dg-final { scan-tree-dump-times " D\.\[0-9_\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.5. = " 1 "strlen" } } */
-/* { dg-final { scan-tree-dump-times " D\.\[0-9_\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.6. = " 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.0. = " 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.1. = " 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.5. = " 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times " _\[0-9\]* = strlen \\(\[^\n\r\]*;\[\n\r\]* l.6. = " 1 "strlen" } } */
/* { dg-final { cleanup-tree-dump "strlen" } } */
}
/* We need to have both: a load from "a[0]" and a load from "*p.a",
- the latter can be an ssa temporary. */
+ the latter is an ssa temporary. */
/* { dg-final { scan-tree-dump "= a.0.;" "optimized" } } */
-/* { dg-final { scan-tree-dump "= \\*\[pD\]" "optimized" } } */
+/* { dg-final { scan-tree-dump "= \\*\[^\r\n\]*_.;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
}
/* We need to have both: a load from "a[0]" and a load from "*p.a",
- the latter can be an ssa temporary. */
+ the latter is an ssa temporary. */
/* { dg-final { scan-tree-dump "= a.0.;" "optimized" } } */
-/* { dg-final { scan-tree-dump "= \\*\[pD\]" "optimized" } } */
+/* { dg-final { scan-tree-dump "= \\*\[^\r\n\]*_.;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* { dg-final { scan-tree-dump-times "hardreg" 3 "optimized" } } */
/* In particular, hardreg should *not* appear in the call to bar. */
-/* { dg-final { scan-tree-dump-times "bar \[(\]t_.\[)\]" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "bar \[(\]\[^\n\r\]*_.\[)\]" 1 "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* Only iter variable should remain. */
-/* { dg-final { scan-tree-dump-times "int iter" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "int jiter" 0 "optimized" } } */
/* And jter shouldn't be an induction variable anymore (no PHI node). */
/* { dg-final { scan-tree-dump-times "jter_\[0-9\]* = PHI" 0 "optimized" } } */
int spaceship1 (long a) { return a > 0 ? 1 : a < 0 ? -1 : 0; }
int spaceship2 (long a) { return a > 0 ? 1 : a == 0 ? 0 : -1; }
-/* { dg-final { scan-tree-dump-times " = -D" 4 "optimized"} } */
+/* { dg-final { scan-tree-dump-times " = -\[^\r\n\]*_.;" 4 "optimized"} } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* There should be one ifs as one of them should be changed into
a conditional and the other should be there still. */
/* { dg-final { scan-tree-dump-times "if" 1 "optimized" } }*/
-/* { dg-final { scan-tree-dump-times "D.\[0-9\]*_\[0-9\]* = c_\[0-9\]*.D. != 0" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\[^\r\n\]*_. = c_\[0-9\]*.D. != 0" 1 "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
_Bool f3(_Bool *p) { *p ^= 1; }
/* We should be able to canonicalize the above to use bitwise not. */
-/* { dg-final { scan-tree-dump "~D" "forwprop1" } } */
+/* { dg-final { scan-tree-dump "~\[^\n\r\]*_.;" "forwprop1" } } */
/* { dg-final { scan-tree-dump-not "\\\^ 1" "forwprop1" } } */
/* { dg-final { cleanup-tree-dump "forwprop1" } } */
return *f1;
}
-/* { dg-final { scan-tree-dump "i1_. = PHI <i1_\[^,\]*, j1_\[^>\]*>" "optimized" } } */
-/* { dg-final { scan-tree-dump "return i1_.;" "optimized" } } */
+/* { dg-final { scan-tree-dump "\[^\r\n\]*_. = PHI <i1_\[^,\]*, j1_\[^>\]*>" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
}
/* { dg-final { scan-tree-dump-times "\\* 4;" 1 "dom2" } } */
-/* { dg-final { scan-tree-dump-times "p_\\d\+\\(D\\) \\+ D" 1 "dom2" } } */
-/* { dg-final { scan-tree-dump-times "MEM\\\[\\(struct x \\*\\)D" 3 "dom2" } } */
+/* { dg-final { scan-tree-dump-times "p_\\d\+\\(D\\) \\+ \[^\r\n\]*_\\d\+;" 1 "dom2" } } */
+/* { dg-final { scan-tree-dump-times "MEM\\\[\\(struct x \\*\\)\[^\r\n\]*_\\d\+" 3 "dom2" } } */
/* { dg-final { cleanup-tree-dump "dom2" } } */
}
/* { dg-final { scan-tree-dump-times "\\* 4;" 1 "dom2" } } */
-/* { dg-final { scan-tree-dump-times "p_\\d\+\\(D\\) \\+ D" 1 "dom2" } } */
-/* { dg-final { scan-tree-dump-times "MEM\\\[\\(struct x \\*\\)D" 9 "dom2" } } */
+/* { dg-final { scan-tree-dump-times "p_\\d\+\\(D\\) \\+ \[^\r\n\]*_\\d\+" 1 "dom2" } } */
+/* { dg-final { scan-tree-dump-times "MEM\\\[\\(struct x \\*\\)\[^\r\n\]*_\\d\+" 9 "dom2" } } */
/* { dg-final { cleanup-tree-dump "dom2" } } */
}
/* { dg-final { scan-tree-dump-times "\\* 4;" 1 "dom2" } } */
-/* { dg-final { scan-tree-dump-times "p_\\d\+\\(D\\) \\+ D" 1 "dom2" } } */
-/* { dg-final { scan-tree-dump-times "MEM\\\[\\(struct x \\*\\)D" 9 "dom2" } } */
+/* { dg-final { scan-tree-dump-times "p_\\d\+\\(D\\) \\+ \[^\r\n\]*_\\d\+" 1 "dom2" } } */
+/* { dg-final { scan-tree-dump-times "MEM\\\[\\(struct x \\*\\)\[^\r\n\]*_\\d\+" 9 "dom2" } } */
/* { dg-final { cleanup-tree-dump "dom2" } } */
/* There should be only two loads left. */
-/* { dg-final { scan-tree-dump-times "= \\\*D\[^\n;\]*;" 2 "pre" } } */
+/* { dg-final { scan-tree-dump-times "= \\\*\[^\n;\]*;" 2 "pre" } } */
/* { dg-final { cleanup-tree-dump "pre" } } */
if ((TREE_CODE (op) == RESULT_DECL
&& DECL_BY_REFERENCE (op))
|| (TREE_CODE (op) == SSA_NAME
+ && SSA_NAME_VAR (op)
&& TREE_CODE (SSA_NAME_VAR (op)) == RESULT_DECL
&& DECL_BY_REFERENCE (SSA_NAME_VAR (op))))
op = TREE_TYPE (op);
tree to_context)
{
void **loc;
- tree new_name, decl = SSA_NAME_VAR (name);
+ tree new_name;
gcc_assert (is_gimple_reg (name));
if (!loc)
{
- replace_by_duplicate_decl (&decl, vars_map, to_context);
-
- new_name = make_ssa_name_fn (DECL_STRUCT_FUNCTION (to_context),
- decl, SSA_NAME_DEF_STMT (name));
- if (SSA_NAME_IS_DEFAULT_DEF (name))
- set_ssa_default_def (DECL_STRUCT_FUNCTION (to_context), decl, new_name);
+ tree decl = SSA_NAME_VAR (name);
+ if (decl)
+ {
+ replace_by_duplicate_decl (&decl, vars_map, to_context);
+ new_name = make_ssa_name_fn (DECL_STRUCT_FUNCTION (to_context),
+ decl, SSA_NAME_DEF_STMT (name));
+ if (SSA_NAME_IS_DEFAULT_DEF (name))
+ set_ssa_default_def (DECL_STRUCT_FUNCTION (to_context),
+ decl, new_name);
+ }
+ else
+ new_name = copy_ssa_name_fn (DECL_STRUCT_FUNCTION (to_context),
+ name, SSA_NAME_DEF_STMT (name));
loc = pointer_map_insert (vars_map, name);
*loc = new_name;
any_var = true;
}
+ if (gimple_in_ssa_p (cfun))
+ for (ix = 1; ix < num_ssa_names; ++ix)
+ {
+ tree name = ssa_name (ix);
+ if (name && !SSA_NAME_VAR (name))
+ {
+ fprintf (file, " ");
+ print_generic_expr (file, TREE_TYPE (name), flags);
+ fprintf (file, " ");
+ print_generic_expr (file, name, flags);
+ fprintf (file, ";\n");
+ }
+ }
}
if (cfun && cfun->decl == fn && cfun->cfg && basic_block_info)
ret = VEC_index (tree, complex_ssa_name_components, ssa_name_index);
if (ret == NULL)
{
- ret = get_component_var (SSA_NAME_VAR (ssa_name), imag_p);
+ if (SSA_NAME_VAR (ssa_name))
+ ret = get_component_var (SSA_NAME_VAR (ssa_name), imag_p);
+ else
+ ret = TREE_TYPE (TREE_TYPE (ssa_name));
ret = make_ssa_name (ret, NULL);
/* Copy some properties from the original. In particular, whether it
{
/* Replace an anonymous base value with the variable from cvc_lookup.
This should result in better debug info. */
- if (DECL_IGNORED_P (SSA_NAME_VAR (value))
+ if (SSA_NAME_VAR (ssa_name)
+ && (!SSA_NAME_VAR (value) || DECL_IGNORED_P (SSA_NAME_VAR (value)))
&& !DECL_IGNORED_P (SSA_NAME_VAR (ssa_name)))
{
comp = get_component_var (SSA_NAME_VAR (ssa_name), imag_p);
return duplicate_ssa_name_fn (cfun, var, stmt);
}
+/* Return an anonymous SSA_NAME node for type TYPE defined in statement STMT
+ in function cfun. Arrange so that it uses NAME in dumps. */
+
+static inline tree
+make_temp_ssa_name (tree type, gimple stmt, const char *name)
+{
+ tree ssa_name;
+ gcc_checking_assert (TYPE_P (type));
+ ssa_name = make_ssa_name_fn (cfun, type, stmt);
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (ssa_name, get_identifier (name));
+ return ssa_name;
+}
/* Returns the base object and a constant BITS_PER_UNIT offset in *POFFSET that
denotes the starting address of the memory access EXP.
static tree
remap_ssa_name (tree name, copy_body_data *id)
{
- tree new_tree;
+ tree new_tree, var;
tree *n;
gcc_assert (TREE_CODE (name) == SSA_NAME);
return name;
}
+ /* Remap anonymous SSA names or SSA names of anonymous decls. */
+ var = SSA_NAME_VAR (name);
+ if (!var
+ || (!SSA_NAME_IS_DEFAULT_DEF (name)
+ && TREE_CODE (var) == VAR_DECL
+ && !VAR_DECL_IS_VIRTUAL_OPERAND (var)
+ && DECL_ARTIFICIAL (var)
+ && DECL_IGNORED_P (var)
+ && !DECL_NAME (var)))
+ {
+ struct ptr_info_def *pi;
+ new_tree = make_ssa_name (remap_type (TREE_TYPE (name), id), NULL);
+ if (!var && SSA_NAME_IDENTIFIER (name))
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (new_tree, SSA_NAME_IDENTIFIER (name));
+ insert_decl_map (id, name, new_tree);
+ SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_tree)
+ = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name);
+ /* At least IPA points-to info can be directly transferred. */
+ if (id->src_cfun->gimple_df
+ && id->src_cfun->gimple_df->ipa_pta
+ && (pi = SSA_NAME_PTR_INFO (name))
+ && !pi->pt.anything)
+ {
+ struct ptr_info_def *new_pi = get_ptr_info (new_tree);
+ new_pi->pt = pi->pt;
+ }
+ return new_tree;
+ }
+
/* Do not set DEF_STMT yet as statement is not copied yet. We do that
in copy_bb. */
- new_tree = remap_decl (SSA_NAME_VAR (name), id);
+ new_tree = remap_decl (var, id);
/* We might've substituted constant or another SSA_NAME for
the variable.
inlining: this saves us from need to introduce PHI node in a case
return value is just partly initialized. */
if ((TREE_CODE (new_tree) == VAR_DECL || TREE_CODE (new_tree) == PARM_DECL)
- && (TREE_CODE (SSA_NAME_VAR (name)) != RESULT_DECL
+ && (!SSA_NAME_VAR (name)
+ || TREE_CODE (SSA_NAME_VAR (name)) != RESULT_DECL
|| !id->transform_return_to_modify))
{
struct ptr_info_def *pi;
regions of the CFG, but this is expensive to test. */
if (id->entry_bb
&& SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name)
- && TREE_CODE (SSA_NAME_VAR (name)) != PARM_DECL
+ && (!SSA_NAME_VAR (name)
+ || TREE_CODE (SSA_NAME_VAR (name)) != PARM_DECL)
&& (id->entry_bb != EDGE_SUCC (ENTRY_BLOCK_PTR, 0)->dest
|| EDGE_COUNT (id->entry_bb->preds) != 1))
{
if (retval
&& (TREE_CODE (retval) != RESULT_DECL
&& (TREE_CODE (retval) != SSA_NAME
+ || ! SSA_NAME_VAR (retval)
|| TREE_CODE (SSA_NAME_VAR (retval)) != RESULT_DECL)))
{
copy = gimple_build_assign (id->retvar, retval);
if (!is_gimple_debug (init_stmt) && MAY_HAVE_DEBUG_STMTS)
{
- tree var, def = gimple_assign_lhs (init_stmt);
-
- if (TREE_CODE (def) == SSA_NAME)
- var = SSA_NAME_VAR (def);
- else
- var = def;
-
- insert_init_debug_bind (id, bb, var, def, init_stmt);
+ tree def = gimple_assign_lhs (init_stmt);
+ insert_init_debug_bind (id, bb, def, def, init_stmt);
}
}
}
static bool
marked_for_renaming (tree sym)
{
- if (!symbols_to_rename_set)
+ if (!symbols_to_rename_set || sym == NULL_TREE)
return false;
return bitmap_bit_p (symbols_to_rename_set, DECL_UID (sym));
}
{
bitmap_head *dfs;
basic_block bb;
+ unsigned i;
/* Initialize operand data structures. */
init_ssa_operands (cfun);
fini_ssa_renamer ();
+ /* Try to get rid of all gimplifier generated temporaries by making
+ its SSA names anonymous. This way we can garbage collect them
+ all after removing unused locals which we do in our TODO. */
+ for (i = 1; i < num_ssa_names; ++i)
+ {
+ tree decl, name = ssa_name (i);
+ if (!name
+ || SSA_NAME_IS_DEFAULT_DEF (name))
+ continue;
+ decl = SSA_NAME_VAR (name);
+ if (decl
+ && TREE_CODE (decl) == VAR_DECL
+ && !VAR_DECL_IS_VIRTUAL_OPERAND (decl)
+ && DECL_ARTIFICIAL (decl)
+ && DECL_IGNORED_P (decl)
+ && !DECL_NAME (decl))
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (name, NULL_TREE);
+ }
+
return 0;
}
break;
case GIMPLE_NOP:
- {
- tree decl = SSA_NAME_VAR (var);
-
- if (TREE_CODE (decl) != PARM_DECL && DECL_INITIAL (decl))
- expr_object_size (osi, var, DECL_INITIAL (decl));
- else
- expr_object_size (osi, var, decl);
- }
+ if (SSA_NAME_VAR (var)
+ && TREE_CODE (SSA_NAME_VAR (var)) == PARM_DECL)
+ expr_object_size (osi, var, SSA_NAME_VAR (var));
+ else
+ /* Uninitialized SSA names point nowhere. */
+ object_sizes[object_size_type][varno] = unknown[object_size_type];
break;
case GIMPLE_PHI:
if (slot && *slot)
return ((struct name_to_copy_elt *) *slot)->new_name;
+ if (copy_name_p)
+ {
+ copy = duplicate_ssa_name (name, NULL);
+ nelt = XNEW (struct name_to_copy_elt);
+ nelt->version = idx;
+ nelt->new_name = copy;
+ nelt->field = NULL_TREE;
+ *slot = nelt;
+ }
+ else
+ {
+ gcc_assert (!slot);
+ copy = name;
+ }
+
var = SSA_NAME_VAR (name);
+ if (!var)
+ return copy;
+
uid = DECL_UID (var);
ielt.uid = uid;
dslot = htab_find_slot_with_hash (decl_copies, &ielt, uid, INSERT);
else
var_copy = ((struct int_tree_map *) *dslot)->to;
- if (copy_name_p)
- {
- copy = duplicate_ssa_name (name, NULL);
- nelt = XNEW (struct name_to_copy_elt);
- nelt->version = idx;
- nelt->new_name = copy;
- nelt->field = NULL_TREE;
- *slot = nelt;
- }
- else
- {
- gcc_assert (!slot);
- copy = name;
- }
-
replace_ssa_name_symbol (copy, var_copy);
return copy;
}
struct name_to_copy_elt *const elt = (struct name_to_copy_elt *) *slot;
tree type = (tree) data;
tree name = ssa_name (elt->version);
- tree var = SSA_NAME_VAR (name);
- tree field = build_decl (DECL_SOURCE_LOCATION (var),
- FIELD_DECL, DECL_NAME (var), TREE_TYPE (var));
+ tree field = build_decl (UNKNOWN_LOCATION,
+ FIELD_DECL, SSA_NAME_IDENTIFIER (name),
+ TREE_TYPE (name));
insert_field_into_struct (type, field);
elt->field = field;
phi = gsi_stmt (psi);
name = PHI_RESULT (phi);
var = SSA_NAME_VAR (name);
- if (!bitmap_bit_p (tmp_vars, DECL_UID (var)))
+ if (!var || !bitmap_bit_p (tmp_vars, DECL_UID (var)))
continue;
use = PHI_ARG_DEF_FROM_EDGE (phi, e);
gcc_assert (TREE_CODE (use) == SSA_NAME);
break;
case SSA_NAME:
- dump_generic_node (buffer, SSA_NAME_VAR (node), spc, flags, false);
+ if (SSA_NAME_IDENTIFIER (node))
+ dump_generic_node (buffer, SSA_NAME_IDENTIFIER (node),
+ spc, flags, false);
pp_string (buffer, "_");
pp_decimal_int (buffer, SSA_NAME_VERSION (node));
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (node))
{
char *pretty_name = make_fancy_name (access->expr);
tree debug_expr = unshare_expr (access->expr), d;
+ bool fail = false;
DECL_NAME (repl) = get_identifier (pretty_name);
obstack_free (&name_obstack, pretty_name);
used SSA_NAMEs and thus they could be freed. All debug info
generation cares is whether something is constant or variable
and that get_ref_base_and_extent works properly on the
- expression. */
- for (d = debug_expr; handled_component_p (d); d = TREE_OPERAND (d, 0))
+ expression. It cannot handle accesses at a non-constant offset
+ though, so just give up in those cases. */
+ for (d = debug_expr; !fail && handled_component_p (d);
+ d = TREE_OPERAND (d, 0))
switch (TREE_CODE (d))
{
case ARRAY_REF:
case ARRAY_RANGE_REF:
if (TREE_OPERAND (d, 1)
- && TREE_CODE (TREE_OPERAND (d, 1)) == SSA_NAME)
- TREE_OPERAND (d, 1) = SSA_NAME_VAR (TREE_OPERAND (d, 1));
+ && TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
+ fail = true;
if (TREE_OPERAND (d, 3)
- && TREE_CODE (TREE_OPERAND (d, 3)) == SSA_NAME)
- TREE_OPERAND (d, 3) = SSA_NAME_VAR (TREE_OPERAND (d, 3));
+ && TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
+ fail = true;
/* FALLTHRU */
case COMPONENT_REF:
if (TREE_OPERAND (d, 2)
- && TREE_CODE (TREE_OPERAND (d, 2)) == SSA_NAME)
- TREE_OPERAND (d, 2) = SSA_NAME_VAR (TREE_OPERAND (d, 2));
+ && TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
+ fail = true;
break;
default:
break;
}
- SET_DECL_DEBUG_EXPR (repl, debug_expr);
- DECL_DEBUG_EXPR_IS_FROM (repl) = 1;
+ if (!fail)
+ {
+ SET_DECL_DEBUG_EXPR (repl, debug_expr);
+ DECL_DEBUG_EXPR_IS_FROM (repl) = 1;
+ }
if (access->grp_no_warning)
TREE_NO_WARNING (repl) = 1;
else
if (TREE_CODE (lhs) != SSA_NAME)
return false;
+
decl = SSA_NAME_VAR (lhs);
- if (TREE_CODE (decl) != PARM_DECL)
+ if (decl == NULL_TREE
+ || TREE_CODE (decl) != PARM_DECL)
return false;
adj = get_adjustment_for_base (adjustments, decl);
}
-/* Called if a coalesce across and abnormal edge cannot be performed. PHI is
- the phi node at fault, I is the argument index at fault. A message is
- printed and compilation is then terminated. */
-
-static inline void
-abnormal_corrupt (gimple phi, int i)
-{
- edge e = gimple_phi_arg_edge (phi, i);
- tree res = gimple_phi_result (phi);
- tree arg = gimple_phi_arg_def (phi, i);
-
- fprintf (stderr, " Corrupt SSA across abnormal edge BB%d->BB%d\n",
- e->src->index, e->dest->index);
- fprintf (stderr, "Argument %d (", i);
- print_generic_expr (stderr, arg, TDF_SLIM);
- if (TREE_CODE (arg) != SSA_NAME)
- fprintf (stderr, ") is not an SSA_NAME.\n");
- else
- {
- gcc_assert (SSA_NAME_VAR (res) != SSA_NAME_VAR (arg));
- fprintf (stderr, ") does not have the same base variable as the result ");
- print_generic_stmt (stderr, res, TDF_SLIM);
- }
-
- internal_error ("SSA corruption");
-}
-
-
/* Print a failure to coalesce a MUST_COALESCE pair X and Y. */
static inline void
{
edge e = gimple_phi_arg_edge (phi, i);
arg = PHI_ARG_DEF (phi, i);
- if (TREE_CODE (arg) == SSA_NAME)
- register_ssa_partition (map, arg);
- if (TREE_CODE (arg) == SSA_NAME
- && SSA_NAME_VAR (arg) == SSA_NAME_VAR (res))
- {
+ if (TREE_CODE (arg) != SSA_NAME)
+ continue;
+
+ register_ssa_partition (map, arg);
+ if ((SSA_NAME_VAR (arg) == SSA_NAME_VAR (res)
+ && TREE_TYPE (arg) == TREE_TYPE (res))
+ || (e->flags & EDGE_ABNORMAL))
+ {
saw_copy = true;
bitmap_set_bit (used_in_copy, SSA_NAME_VERSION (arg));
if ((e->flags & EDGE_ABNORMAL) == 0)
{
int cost = coalesce_cost_edge (e);
if (cost == 1 && has_single_use (arg))
- add_cost_one_coalesce (cl, ver, SSA_NAME_VERSION (arg));
+ add_cost_one_coalesce (cl, ver, SSA_NAME_VERSION (arg));
else
add_coalesce (cl, ver, SSA_NAME_VERSION (arg), cost);
}
}
- else
- if (e->flags & EDGE_ABNORMAL)
- abnormal_corrupt (phi, i);
}
if (saw_copy)
bitmap_set_bit (used_in_copy, ver);
if (gimple_assign_copy_p (stmt)
&& TREE_CODE (lhs) == SSA_NAME
&& TREE_CODE (rhs1) == SSA_NAME
- && SSA_NAME_VAR (lhs) == SSA_NAME_VAR (rhs1))
+ && SSA_NAME_VAR (lhs) == SSA_NAME_VAR (rhs1)
+ && TREE_TYPE (lhs) == TREE_TYPE (rhs1))
{
v1 = SSA_NAME_VERSION (lhs);
v2 = SSA_NAME_VERSION (rhs1);
v1 = SSA_NAME_VERSION (outputs[match]);
v2 = SSA_NAME_VERSION (input);
- if (SSA_NAME_VAR (outputs[match]) == SSA_NAME_VAR (input))
+ if (SSA_NAME_VAR (outputs[match]) == SSA_NAME_VAR (input)
+ && TREE_TYPE (outputs[match]) == TREE_TYPE (input))
{
cost = coalesce_cost (REG_BR_PROB_BASE,
optimize_bb_for_size_p (bb));
if (var != NULL_TREE && is_gimple_reg (var))
{
/* Add coalesces between all the result decls. */
- if (TREE_CODE (SSA_NAME_VAR (var)) == RESULT_DECL)
+ if (SSA_NAME_VAR (var)
+ && TREE_CODE (SSA_NAME_VAR (var)) == RESULT_DECL)
{
if (first == NULL_TREE)
first = var;
else
{
- gcc_assert (SSA_NAME_VAR (var) == SSA_NAME_VAR (first));
+ gcc_assert (SSA_NAME_VAR (var) == SSA_NAME_VAR (first)
+ && TREE_TYPE (var) == TREE_TYPE (first));
v1 = SSA_NAME_VERSION (first);
v2 = SSA_NAME_VERSION (var);
bitmap_set_bit (used_in_copy, v1);
int v1 = SSA_NAME_VERSION (res);
int v2 = SSA_NAME_VERSION (arg);
- if (SSA_NAME_VAR (arg) != SSA_NAME_VAR (res))
- abnormal_corrupt (phi, e->dest_idx);
-
if (debug)
fprintf (debug, "Abnormal coalesce: ");
var2 = ssa_name (y);
/* Assert the coalesces have the same base variable. */
- gcc_assert (SSA_NAME_VAR (var1) == SSA_NAME_VAR (var2));
+ gcc_assert (SSA_NAME_VAR (var1) == SSA_NAME_VAR (var2)
+ && TREE_TYPE (var1) == TREE_TYPE (var2));
if (debug)
fprintf (debug, "Coalesce list: ");
gcc_assert (p1 != NO_PARTITION);
gcc_assert (p2 != NO_PARTITION);
- rep1 = partition_to_var (map, p1);
- rep2 = partition_to_var (map, p2);
- root1 = SSA_NAME_VAR (rep1);
- root2 = SSA_NAME_VAR (rep2);
-
if (p1 == p2)
{
if (debug)
return false;
}
+ rep1 = partition_to_var (map, p1);
+ rep2 = partition_to_var (map, p2);
+ root1 = SSA_NAME_VAR (rep1);
+ root2 = SSA_NAME_VAR (rep2);
+ if (!root1 && !root2)
+ return false;
+
/* Don't coalesce if one of the variables occurs in an abnormal PHI. */
abnorm = (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rep1)
|| SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rep2));
}
/* Never attempt to coalesce 2 different parameters. */
- if (TREE_CODE (root1) == PARM_DECL && TREE_CODE (root2) == PARM_DECL)
+ if ((root1 && TREE_CODE (root1) == PARM_DECL)
+ && (root2 && TREE_CODE (root2) == PARM_DECL))
{
if (debug)
fprintf (debug, " : 2 different PARM_DECLS. No coalesce.\n");
return false;
}
- if ((TREE_CODE (root1) == RESULT_DECL) != (TREE_CODE (root2) == RESULT_DECL))
+ if ((root1 && TREE_CODE (root1) == RESULT_DECL)
+ != (root2 && TREE_CODE (root2) == RESULT_DECL))
{
if (debug)
fprintf (debug, " : One root a RESULT_DECL. No coalesce.\n");
return false;
}
- ign1 = TREE_CODE (root1) == VAR_DECL && DECL_IGNORED_P (root1);
- ign2 = TREE_CODE (root2) == VAR_DECL && DECL_IGNORED_P (root2);
+ ign1 = !root1 || (TREE_CODE (root1) == VAR_DECL && DECL_IGNORED_P (root1));
+ ign2 = !root2 || (TREE_CODE (root2) == VAR_DECL && DECL_IGNORED_P (root2));
/* Refrain from coalescing user variables, if requested. */
if (!ign1 && !ign2)
/* If both values have default defs, we can't coalesce. If only one has a
tag, make sure that variable is the new root partition. */
- if (ssa_default_def (cfun, root1))
+ if (root1 && ssa_default_def (cfun, root1))
{
- if (ssa_default_def (cfun, root2))
+ if (root2 && ssa_default_def (cfun, root2))
{
if (debug)
fprintf (debug, " : 2 default defs. No coalesce.\n");
ign1 = false;
}
}
- else if (ssa_default_def (cfun, root2))
+ else if (root2 && ssa_default_def (cfun, root2))
{
ign1 = true;
ign2 = false;
}
+ /* Do not coalesce if we cannot assign a symbol to the partition. */
+ if (!(!ign2 && root2)
+ && !(!ign1 && root1))
+ {
+ if (debug)
+ fprintf (debug, " : Choosen variable has no root. No coalesce.\n");
+ return false;
+ }
+
/* Don't coalesce if the new chosen root variable would be read-only.
If both ign1 && ign2, then the root var of the larger partition
wins, so reject in that case if any of the root vars is TREE_READONLY.
Otherwise reject only if the root var, on which replace_ssa_name_symbol
will be called below, is readonly. */
- if ((TREE_READONLY (root1) && ign2) || (TREE_READONLY (root2) && ign1))
+ if (((root1 && TREE_READONLY (root1)) && ign2)
+ || ((root2 && TREE_READONLY (root2)) && ign1))
{
if (debug)
fprintf (debug, " : Readonly variable. No coalesce.\n");
}
/* Don't coalesce if the two variables aren't type compatible . */
- if (!types_compatible_p (TREE_TYPE (root1), TREE_TYPE (root2))
+ if (!types_compatible_p (TREE_TYPE (var1), TREE_TYPE (var2))
/* There is a disconnect between the middle-end type-system and
VRP, avoid coalescing enum types with different bounds. */
- || ((TREE_CODE (TREE_TYPE (root1)) == ENUMERAL_TYPE
- || TREE_CODE (TREE_TYPE (root2)) == ENUMERAL_TYPE)
- && TREE_TYPE (root1) != TREE_TYPE (root2)))
+ || ((TREE_CODE (TREE_TYPE (var1)) == ENUMERAL_TYPE
+ || TREE_CODE (TREE_TYPE (var2)) == ENUMERAL_TYPE)
+ && TREE_TYPE (var1) != TREE_TYPE (var2)))
{
if (debug)
fprintf (debug, " : Incompatible types. No coalesce.\n");
/* Set the root variable of the partition to the better choice, if there is
one. */
- if (!ign2)
+ if (!ign2 && root2)
replace_ssa_name_symbol (partition_to_var (map, p3), root2);
- else if (!ign1)
+ else if (!ign1 && root1)
replace_ssa_name_symbol (partition_to_var (map, p3), root1);
+ else
+ gcc_unreachable ();
if (debug)
{
{
int x, num_part;
tree var;
- htab_t decl_to_index;
+ htab_t tree_to_index;
struct tree_int_map *m, *mapstorage;
num_part = num_var_partitions (map);
- decl_to_index = htab_create (num_part, tree_decl_map_hash,
+ tree_to_index = htab_create (num_part, tree_map_base_hash,
tree_int_map_eq, NULL);
/* We can have at most num_part entries in the hash tables, so it's
enough to allocate so many map elements once, saving some malloc
struct tree_int_map **slot;
unsigned baseindex;
var = partition_to_var (map, x);
- var = SSA_NAME_VAR (var);
+ if (SSA_NAME_VAR (var))
+ m->base.from = SSA_NAME_VAR (var);
+ else
+ /* This restricts what anonymous SSA names we can coalesce
+ as it restricts the sets we compute conflicts for.
+ Using TREE_TYPE to generate sets is the easies as
+ type equivalency also holds for SSA names with the same
+ underlying decl. */
+ m->base.from = TREE_TYPE (var);
/* If base variable hasn't been seen, set it up. */
- m->base.from = var;
- slot = (struct tree_int_map **) htab_find_slot (decl_to_index, m, INSERT);
+ slot = (struct tree_int_map **) htab_find_slot (tree_to_index,
+ m, INSERT);
if (!*slot)
{
baseindex = m - mapstorage;
map->num_basevars = m - mapstorage;
free (mapstorage);
- htab_delete (decl_to_index);
+ htab_delete (tree_to_index);
}
tree b;
if (TREE_CODE (t) == SSA_NAME)
- t = SSA_NAME_VAR (t);
+ {
+ *walk_subtrees = 0;
+ t = SSA_NAME_VAR (t);
+ if (!t)
+ return NULL;
+ }
if (IS_EXPR_CODE_CLASS (c)
&& (b = TREE_BLOCK (t)) != NULL)
for (i = 0; i < (unsigned)num_var_partitions (map); i++)
{
basic_block tmp;
- tree d;
+ tree d = NULL_TREE;
bitmap loe;
var = partition_to_var (map, i);
stmt = SSA_NAME_DEF_STMT (var);
tmp = gimple_bb (stmt);
- d = ssa_default_def (cfun, SSA_NAME_VAR (var));
+ if (SSA_NAME_VAR (var))
+ d = ssa_default_def (cfun, SSA_NAME_VAR (var));
loe = live_on_entry (live, e->dest);
if (loe && bitmap_bit_p (loe, i))
break;
case SSA_NAME:
- ref = SSA_NAME_VAR (ref);
- /* Fallthru. */
-
case VAR_DECL:
case PARM_DECL:
name = get_name (ref);
case SSA_NAME:
*ws = 0;
obj = SSA_NAME_VAR (*expr_p);
+ /* Defer handling of anonymous SSA_NAMEs to the expander. */
+ if (!obj)
+ return NULL_TREE;
if (!DECL_RTL_SET_P (obj))
x = gen_raw_REG (DECL_MODE (obj), (*regno)++);
break;
The reason is to make debugging simpler; so this is not relevant for
artificial ivs created by other optimization passes. */
if (cand->pos != IP_ORIGINAL
+ || !SSA_NAME_VAR (cand->var_before)
|| DECL_ARTIFICIAL (SSA_NAME_VAR (cand->var_before)))
cost++;
enum tree_code exit_cmp;
gimple phi_old_loop, phi_new_loop, phi_rest;
gimple_stmt_iterator psi_old_loop, psi_new_loop;
- tree init, next, new_init, var;
+ tree init, next, new_init;
struct loop *new_loop;
basic_block rest, exit_bb;
edge old_entry, new_entry, old_latch, precond_edge, new_exit;
if (TREE_CODE (next) == SSA_NAME
&& useless_type_conversion_p (TREE_TYPE (next),
TREE_TYPE (init)))
- var = SSA_NAME_VAR (next);
+ new_init = copy_ssa_name (next, NULL);
else if (TREE_CODE (init) == SSA_NAME
&& useless_type_conversion_p (TREE_TYPE (init),
TREE_TYPE (next)))
- var = SSA_NAME_VAR (init);
+ new_init = copy_ssa_name (init, NULL);
else if (useless_type_conversion_p (TREE_TYPE (next), TREE_TYPE (init)))
- var = create_tmp_var (TREE_TYPE (next), "unrinittmp");
+ new_init = make_temp_ssa_name (TREE_TYPE (next), NULL, "unrinittmp");
else
- var = create_tmp_var (TREE_TYPE (init), "unrinittmp");
+ new_init = make_temp_ssa_name (TREE_TYPE (init), NULL, "unrinittmp");
- new_init = make_ssa_name (var, NULL);
phi_rest = create_phi_node (new_init, rest);
add_phi_arg (phi_rest, init, precond_edge, UNKNOWN_LOCATION);
a new SSA_NAME we create. */
if (!result)
{
- result = make_ssa_name (SSA_NAME_VAR (lhs), gimple_build_nop ());
+ result = make_temp_ssa_name (TREE_TYPE (lhs), gimple_build_nop (),
+ "vntemp");
/* Initialize value-number information properly. */
VN_INFO_GET (result)->valnum = result;
VN_INFO (result)->value_id = get_next_value_id ();
static const char *
alias_get_name (tree decl)
{
- const char *res;
+ const char *res = NULL;
char *temp;
int num_printed = 0;
- if (DECL_ASSEMBLER_NAME_SET_P (decl))
- res = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- else
- res= get_name (decl);
- if (res != NULL)
- return res;
-
- res = "NULL";
if (!dump_file)
- return res;
+ return "NULL";
if (TREE_CODE (decl) == SSA_NAME)
{
- num_printed = asprintf (&temp, "%s_%u",
- alias_get_name (SSA_NAME_VAR (decl)),
- SSA_NAME_VERSION (decl));
+ res = get_name (decl);
+ if (res)
+ num_printed = asprintf (&temp, "%s_%u", res, SSA_NAME_VERSION (decl));
+ else
+ num_printed = asprintf (&temp, "_%u", SSA_NAME_VERSION (decl));
+ if (num_printed > 0)
+ {
+ res = ggc_strdup (temp);
+ free (temp);
+ }
}
else if (DECL_P (decl))
{
- num_printed = asprintf (&temp, "D.%u", DECL_UID (decl));
- }
- if (num_printed > 0)
- {
- res = ggc_strdup (temp);
- free (temp);
+ if (DECL_ASSEMBLER_NAME_SET_P (decl))
+ res = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ else
+ {
+ res = get_name (decl);
+ if (!res)
+ {
+ num_printed = asprintf (&temp, "D.%u", DECL_UID (decl));
+ if (num_printed > 0)
+ {
+ res = ggc_strdup (temp);
+ free (temp);
+ }
+ }
+ }
}
- return res;
+ if (res != NULL)
+ return res;
+
+ return "NULL";
}
/* Find the variable id for tree T in the map.
def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
version = SSA_NAME_VERSION (def);
- basevar = SSA_NAME_VAR (def);
def_vars = BITMAP_ALLOC (NULL);
- bitmap_set_bit (def_vars, DECL_UID (basevar));
+ basevar = SSA_NAME_VAR (def);
+ if (basevar)
+ bitmap_set_bit (def_vars, DECL_UID (basevar));
/* Add this expression to the dependency list for each use partition. */
FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
bitmap_ior_into (def_vars, use_vars);
BITMAP_FREE (tab->expr_decl_uids[var_version]);
}
- else
+ else if (SSA_NAME_VAR (var))
bitmap_set_bit (def_vars, DECL_UID (SSA_NAME_VAR (var)));
}
tab->expr_decl_uids[version] = def_vars;
if (!bitmap_empty_p (vars))
FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter2, SSA_OP_DEF)
{
- if (bitmap_bit_p (vars, DECL_UID (SSA_NAME_VAR (def))))
+ if (SSA_NAME_VAR (def)
+ && bitmap_bit_p (vars, DECL_UID (SSA_NAME_VAR (def))))
{
same_root_var = true;
break;
{
gimple phi = gsi_stmt (gsi);
tree arg = PHI_ARG_DEF (phi, e->dest_idx);
+ tree res = PHI_RESULT (phi);
struct equiv_hash_elt equiv_hash_elt;
void **slot;
- /* If the argument is not an invariant, or refers to the same
+ /* If the argument is not an invariant, and refers to the same
underlying variable as the PHI result, then there's no
point in un-propagating the argument. */
if (!is_gimple_min_invariant (arg)
- && SSA_NAME_VAR (arg) != SSA_NAME_VAR (PHI_RESULT (phi)))
+ && (SSA_NAME_VAR (arg) == SSA_NAME_VAR (res)
+ && TREE_TYPE (arg) == TREE_TYPE (res)))
continue;
/* Lookup this argument's value in the hash table. */
{
tree equiv = VEC_index (tree, elt->equivalences, j);
- if (SSA_NAME_VAR (equiv) == SSA_NAME_VAR (PHI_RESULT (phi)))
+ if (SSA_NAME_VAR (equiv) == SSA_NAME_VAR (res)
+ && TREE_TYPE (equiv) == TREE_TYPE (res))
{
SET_PHI_ARG_DEF (phi, e->dest_idx, equiv);
break;
{
tree var = SSA_NAME_VAR (t);
+ if (!var)
+ ;
/* Parameters get their initial value from the function entry. */
- if (TREE_CODE (var) == PARM_DECL)
+ else if (TREE_CODE (var) == PARM_DECL)
return false;
-
/* When returning by reference the return address is actually a hidden
parameter. */
- if (TREE_CODE (SSA_NAME_VAR (t)) == RESULT_DECL
- && DECL_BY_REFERENCE (SSA_NAME_VAR (t)))
+ else if (TREE_CODE (var) == RESULT_DECL && DECL_BY_REFERENCE (var))
return false;
-
/* Hard register variables get their initial value from the ether. */
- if (TREE_CODE (var) == VAR_DECL && DECL_HARD_REGISTER (var))
+ else if (TREE_CODE (var) == VAR_DECL && DECL_HARD_REGISTER (var))
return false;
/* The value is undefined iff its definition statement is empty. */
return;
uninit_op = gimple_phi_arg_def (phi, MASK_FIRST_SET_BIT (uninit_opnds));
+ if (SSA_NAME_VAR (uninit_op) == NULL_TREE)
+ return;
warn_uninit (OPT_Wmaybe_uninitialized, uninit_op, SSA_NAME_VAR (uninit_op),
SSA_NAME_VAR (uninit_op),
"%qD may be used uninitialized in this function",
if (!MAY_HAVE_DEBUG_STMTS)
return NULL_TREE;
+ if (TREE_CODE (var) == SSA_NAME)
+ {
+ var = SSA_NAME_VAR (var);
+ if (var == NULL_TREE)
+ return NULL_TREE;
+ }
+
if ((TREE_CODE (var) != VAR_DECL
|| VAR_DECL_IS_VIRTUAL_OPERAND (var))
&& TREE_CODE (var) != PARM_DECL)
return true;
}
- if (TREE_TYPE (ssa_name) != TREE_TYPE (SSA_NAME_VAR (ssa_name)))
+ if (SSA_NAME_VAR (ssa_name) != NULL_TREE
+ && TREE_TYPE (ssa_name) != TREE_TYPE (ssa_name))
{
error ("type mismatch between an SSA_NAME and its symbol");
return true;
if (verify_ssa_name (ssa_name, is_virtual))
goto err;
- if (TREE_CODE (SSA_NAME_VAR (ssa_name)) == RESULT_DECL
+ if (SSA_NAME_VAR (ssa_name)
+ && TREE_CODE (SSA_NAME_VAR (ssa_name)) == RESULT_DECL
&& DECL_BY_REFERENCE (SSA_NAME_VAR (ssa_name)))
{
error ("RESULT_DECL should be read only when DECL_BY_REFERENCE is set");
gcc_assert (TREE_CODE (var) == VAR_DECL
|| TREE_CODE (var) == PARM_DECL
- || TREE_CODE (var) == RESULT_DECL);
+ || TREE_CODE (var) == RESULT_DECL
+ || (TYPE_P (var) && is_gimple_reg_type (var)));
/* If our free list has an element, then use it. */
if (!VEC_empty (tree, FREE_SSANAMES (fn)))
ssa_name_nodes_created++;
}
- TREE_TYPE (t) = TREE_TYPE (var);
- SSA_NAME_VAR (t) = var;
+ if (TYPE_P (var))
+ {
+ TREE_TYPE (t) = var;
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (t, NULL_TREE);
+ }
+ else
+ {
+ TREE_TYPE (t) = TREE_TYPE (var);
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (t, var);
+ }
SSA_NAME_DEF_STMT (t) = stmt;
SSA_NAME_PTR_INFO (t) = NULL;
SSA_NAME_IN_FREE_LIST (t) = 0;
/* Hopefully this can go away once we have the new incremental
SSA updating code installed. */
- SSA_NAME_VAR (var) = saved_ssa_name_var;
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (var, saved_ssa_name_var);
/* Note this SSA_NAME is now in the first list. */
SSA_NAME_IN_FREE_LIST (var) = 1;
tree
copy_ssa_name_fn (struct function *fn, tree name, gimple stmt)
{
- return make_ssa_name_fn (fn, SSA_NAME_VAR (name), stmt);
+ tree new_name;
+
+ if (SSA_NAME_VAR (name))
+ new_name = make_ssa_name_fn (fn, SSA_NAME_VAR (name), stmt);
+ else
+ {
+ new_name = make_ssa_name_fn (fn, TREE_TYPE (name), stmt);
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (new_name, SSA_NAME_IDENTIFIER (name));
+ }
+
+ return new_name;
}
void
replace_ssa_name_symbol (tree ssa_name, tree sym)
{
- SSA_NAME_VAR (ssa_name) = sym;
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (ssa_name, sym);
TREE_TYPE (ssa_name) = TREE_TYPE (sym);
}
STRIP_NOPS (stripped_decl);
if (DECL_P (stripped_decl) && DECL_NAME (stripped_decl))
return IDENTIFIER_POINTER (DECL_NAME (stripped_decl));
+ else if (TREE_CODE (stripped_decl) == SSA_NAME)
+ {
+ tree name = SSA_NAME_IDENTIFIER (stripped_decl);
+ if (!name)
+ return NULL;
+ return IDENTIFIER_POINTER (name);
+ }
else
{
switch (TREE_CODE (stripped_decl))
\f
/* SSA_NAME accessors. */
-/* Returns the variable being referenced. Once released, this is the
- only field that can be relied upon. */
-#define SSA_NAME_VAR(NODE) SSA_NAME_CHECK (NODE)->ssa_name.var
+/* Returns the IDENTIFIER_NODE giving the SSA name a name or NULL_TREE
+ if there is no name associated with it. */
+#define SSA_NAME_IDENTIFIER(NODE) \
+ (SSA_NAME_CHECK (NODE)->ssa_name.var != NULL_TREE \
+ ? (TREE_CODE ((NODE)->ssa_name.var) == IDENTIFIER_NODE \
+ ? (NODE)->ssa_name.var \
+ : DECL_NAME ((NODE)->ssa_name.var)) \
+ : NULL_TREE)
+
+/* Returns the variable being referenced. This can be NULL_TREE for
+ temporaries not associated with any user variable.
+ Once released, this is the only field that can be relied upon. */
+#define SSA_NAME_VAR(NODE) \
+ (SSA_NAME_CHECK (NODE)->ssa_name.var == NULL_TREE \
+ || TREE_CODE ((NODE)->ssa_name.var) == IDENTIFIER_NODE \
+ ? NULL_TREE : (NODE)->ssa_name.var)
+
+#define SET_SSA_NAME_VAR_OR_IDENTIFIER(NODE,VAR) \
+ do { SSA_NAME_CHECK (NODE)->ssa_name.var = (VAR); } while (0)
/* Returns the statement which defines this SSA name. */
#define SSA_NAME_DEF_STMT(NODE) SSA_NAME_CHECK (NODE)->ssa_name.def_stmt