This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tuples] Re-enable alias and optimization (2/3)
- From: Diego Novillo <dnovillo at google dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Cc: Oleg Ryjkov <olegr at google dot com>, William Maddox <maddox at google dot com>, Rafael Espindola <espindola at google dot com>, Aldy Hernandez <aldyh at redhat dot com>
- Date: Sun, 10 Feb 2008 18:40:42 -0500
- Subject: [tuples] Re-enable alias and optimization (2/3)
Part 2 converts the alias analysis bits.
2008-02-10 Diego Novillo <dnovillo@google.com>
* gimple-dummy.c (ipa_type_escape_field_does_not_clobber_p):
Remove.
* tree-ssa-alias.c: Convert to tuples.
* opts.c (decode_options): Re-enable optimization.
* gimple-pretty-print.c (dump_gimple_mem_ops): New.
(dump_gimple_stmt): Handle TDF_STMTADDR, TDF_LINENO.
Call dump_gimple_mem_ops if GS has memory operands.
* ipa-type-escape.c: Convert to tuples.
* ipa-type-escape.h: Likewise.
* Makefile.in (tree-ssa-structalias.o): Add dependency on
gt-tree-ssa-structalias.h.
(GTFILES): Add tree-ssa-structalias.c and
tree-ssa-structalias.h.
* tree-ssa-structalias.c: Convert to tuples.
* tree-ssa-structalias.h: Likewise.
* passes.c (init_optimization_passes): Enable
pass_create_structure_vars.
2008-02-10 Diego Novillo <dnovillo@google.com>
* gimple-dummy.c (ipa_type_escape_field_does_not_clobber_p):
Remove.
* tree-ssa-alias.c: Convert to tuples.
* opts.c (decode_options): Re-enable optimization.
* gimple-pretty-print.c (dump_gimple_mem_ops): New.
(dump_gimple_stmt): Handle TDF_STMTADDR, TDF_LINENO.
Call dump_gimple_mem_ops if GS has memory operands.
* ipa-type-escape.c: Convert to tuples.
* ipa-type-escape.h: Likewise.
* Makefile.in (tree-ssa-structalias.o): Add dependency on
gt-tree-ssa-structalias.h.
(GTFILES): Add tree-ssa-structalias.c and
tree-ssa-structalias.h.
* tree-ssa-structalias.c: Convert to tuples.
* tree-ssa-structalias.h: Likewise.
* passes.c (init_optimization_passes): Enable
pass_create_structure_vars.
Index: tree-gimple.c
===================================================================
--- tree-gimple.c (revision 132202)
+++ tree-gimple.c (working copy)
@@ -81,8 +81,6 @@ get_gimple_rhs_class (enum tree_code cod
case TRUTH_NOT_EXPR:
return GIMPLE_UNARY_RHS;
- /* FIXME tuples. We are not allowing CALL_EXPR on the RHS
- anymore. Watch out for random failures. */
case COND_EXPR:
case CONSTRUCTOR:
case OBJ_TYPE_REF:
Index: gimple-dummy.c
===================================================================
--- gimple-dummy.c (revision 132202)
+++ gimple-dummy.c (working copy)
@@ -63,7 +63,6 @@ DUMMY_FN (ipa_node_create);
DUMMY_FN (ipa_nodes_create);
DUMMY_FN (ipa_nodes_free);
DUMMY_FN (ipa_remove_method);
-DUMMY_FN (ipa_type_escape_field_does_not_clobber_p);
DUMMY_FN (multiplier_allowed_in_address_p);
DUMMY_FN (multiply_by_cost);
DUMMY_FN (nowrap_type_p);
Index: tree-ssa-alias.c
===================================================================
--- tree-ssa-alias.c (revision 132202)
+++ tree-ssa-alias.c (working copy)
@@ -49,8 +49,6 @@ along with GCC; see the file COPYING3.
#include "pointer-set.h"
#include "alloc-pool.h"
-/* FIXME tuples. */
-#if 0
/* Broad overview of how aliasing works:
First we compute points-to sets, which is done in
@@ -757,7 +755,7 @@ static void
count_mem_refs (long *num_vuses_p, long *num_vdefs_p,
long *num_partitioned_p, long *num_unpartitioned_p)
{
- block_stmt_iterator bsi;
+ gimple_stmt_iterator gsi;
basic_block bb;
long num_vdefs, num_vuses, num_partitioned, num_unpartitioned;
referenced_var_iterator rvi;
@@ -767,9 +765,9 @@ count_mem_refs (long *num_vuses_p, long
if (num_vuses_p || num_vdefs_p)
FOR_EACH_BB (bb)
- for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
- tree stmt = bsi_stmt (bsi);
+ gimple stmt = gsi_stmt (gsi);
if (stmt_references_memory_p (stmt))
{
num_vuses += NUM_SSA_OPERANDS (stmt, SSA_OP_VUSE);
@@ -1018,7 +1016,7 @@ debug_mp_info (VEC(mem_sym_stats_t,heap)
recorded by this function, see compute_memory_partitions). */
void
-update_mem_sym_stats_from_stmt (tree var, tree stmt, long num_direct_reads,
+update_mem_sym_stats_from_stmt (tree var, gimple stmt, long num_direct_reads,
long num_direct_writes)
{
mem_sym_stats_t stats;
@@ -1175,13 +1173,8 @@ find_partition_for (mem_sym_stats_t mp_p
mp_p->partitioned_p = true;
- /* FIXME tuples. */
-#if 0
mark_sym_for_renaming (mp_p->var);
mark_sym_for_renaming (mpt);
-#else
- gimple_unreachable ();
-#endif
return mpt;
}
@@ -1431,19 +1424,9 @@ build_mp_info (struct mem_ref_stats_d *m
marked for renaming. */
if ((old_mpt = memory_partition (var)) != NULL)
{
- /* FIXME tuples. */
-#if 0
mark_sym_for_renaming (old_mpt);
-#else
- gimple_unreachable ();
-#endif
set_memory_partition (var, NULL_TREE);
- /* FIXME tuples. */
-#if 0
mark_sym_for_renaming (var);
-#else
- gimple_unreachable ();
-#endif
}
sym_stats = get_mem_sym_stats_for (var);
@@ -1664,7 +1647,6 @@ done:
timevar_pop (TV_MEMORY_PARTITIONING);
}
-#endif
/* Compute may-alias information for every variable referenced in function
FNDECL.
@@ -1779,8 +1761,6 @@ done:
unsigned int
compute_may_aliases (void)
{
- /* FIXME tuples. */
-#if 0
struct alias_info *ai;
timevar_push (TV_TREE_MAY_ALIAS);
@@ -1851,11 +1831,11 @@ compute_may_aliases (void)
/* Populate all virtual operands and newly promoted register operands. */
{
- block_stmt_iterator bsi;
+ gimple_stmt_iterator gsi;
basic_block bb;
FOR_EACH_BB (bb)
- for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- update_stmt_if_modified (bsi_stmt (bsi));
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ update_stmt_if_modified (gsi_stmt (gsi));
}
/* Debugging dumps. */
@@ -1878,30 +1858,21 @@ compute_may_aliases (void)
/* Deallocate memory used by aliasing data structures. */
delete_alias_info (ai);
- /* FIXME tuples. */
-#if 0
if (need_ssa_update_p ())
update_ssa (TODO_update_ssa);
-#else
- gimple_unreachable ();
-#endif
timevar_pop (TV_TREE_MAY_ALIAS);
return 0;
-#else
- gimple_unreachable ();
-#endif
}
-/* FIXME tuples. */
-#if 0
/* Data structure used to count the number of dereferences to PTR
inside an expression. */
struct count_ptr_d
{
tree ptr;
- unsigned count;
+ unsigned num_stores;
+ unsigned num_loads;
};
@@ -1911,7 +1882,8 @@ struct count_ptr_d
static tree
count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
{
- struct count_ptr_d *count_p = (struct count_ptr_d *) data;
+ struct walk_stmt_info *wi_p = (struct walk_stmt_info *) data;
+ struct count_ptr_d *count_p = (struct count_ptr_d *) wi_p->info;
/* Do not walk inside ADDR_EXPR nodes. In the expression &ptr->fld,
pointer 'ptr' is *not* dereferenced, it is simply used to compute
@@ -1923,7 +1895,12 @@ count_ptr_derefs (tree *tp, int *walk_su
}
if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
- count_p->count++;
+ {
+ if (wi_p->is_lhs)
+ count_p->num_stores++;
+ else
+ count_p->num_loads++;
+ }
return NULL_TREE;
}
@@ -1936,7 +1913,7 @@ count_ptr_derefs (tree *tp, int *walk_su
stored in *NUM_STORES_P and *NUM_LOADS_P. */
void
-count_uses_and_derefs (tree ptr, tree stmt, unsigned *num_uses_p,
+count_uses_and_derefs (tree ptr, gimple stmt, unsigned *num_uses_p,
unsigned *num_loads_p, unsigned *num_stores_p)
{
ssa_op_iter i;
@@ -1958,59 +1935,24 @@ count_uses_and_derefs (tree ptr, tree st
find all the indirect and direct uses of x_1 inside. The only
shortcut we can take is the fact that GIMPLE only allows
INDIRECT_REFs inside the expressions below. */
- if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
- || (TREE_CODE (stmt) == RETURN_EXPR
- && TREE_CODE (TREE_OPERAND (stmt, 0)) == GIMPLE_MODIFY_STMT)
- || TREE_CODE (stmt) == ASM_EXPR
- || TREE_CODE (stmt) == CALL_EXPR)
+ if (gimple_code (stmt) == GIMPLE_ASSIGN
+ || gimple_code (stmt) == GIMPLE_RETURN
+ || gimple_code (stmt) == GIMPLE_ASM
+ || gimple_code (stmt) == GIMPLE_CALL)
{
- tree lhs, rhs;
+ struct walk_stmt_info wi;
+ struct count_ptr_d count;
- if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
- {
- lhs = GIMPLE_STMT_OPERAND (stmt, 0);
- rhs = GIMPLE_STMT_OPERAND (stmt, 1);
- }
- else if (TREE_CODE (stmt) == RETURN_EXPR)
- {
- tree e = TREE_OPERAND (stmt, 0);
- lhs = GIMPLE_STMT_OPERAND (e, 0);
- rhs = GIMPLE_STMT_OPERAND (e, 1);
- }
- else if (TREE_CODE (stmt) == ASM_EXPR)
- {
- lhs = ASM_OUTPUTS (stmt);
- rhs = ASM_INPUTS (stmt);
- }
- else
- {
- lhs = NULL_TREE;
- rhs = stmt;
- }
+ count.ptr = ptr;
+ count.num_stores = 0;
+ count.num_loads = 0;
- if (lhs
- && (TREE_CODE (lhs) == TREE_LIST
- || EXPR_P (lhs)
- || GIMPLE_STMT_P (lhs)))
- {
- struct count_ptr_d count;
- count.ptr = ptr;
- count.count = 0;
- walk_tree (&lhs, count_ptr_derefs, &count, NULL);
- *num_stores_p = count.count;
- }
+ memset (&wi, 0, sizeof (wi));
+ wi.info = &count;
+ walk_gimple_stmt (stmt, NULL, count_ptr_derefs, &wi);
- if (rhs
- && (TREE_CODE (rhs) == TREE_LIST
- || EXPR_P (rhs)
- || GIMPLE_STMT_P (rhs)))
- {
- struct count_ptr_d count;
- count.ptr = ptr;
- count.count = 0;
- walk_tree (&rhs, count_ptr_derefs, &count, NULL);
- *num_loads_p = count.count;
- }
+ *num_stores_p = count.num_stores;
+ *num_loads_p = count.num_loads;
}
gcc_assert (*num_uses_p >= *num_loads_p + *num_stores_p);
@@ -2920,7 +2862,7 @@ may_alias_p (tree ptr, alias_set_type me
/* The star count is -1 if the type at the end of the
pointer_to chain is not a record or union type. */
if ((!alias_set_only) &&
- ipa_type_escape_star_count_of_interesting_type (var_type) >= 0)
+ 0 /* FIXME tuples ipa_type_escape_star_count_of_interesting_type (var_type) >= 0*/)
{
int ptr_star_count = 0;
@@ -3027,21 +2969,20 @@ set_pt_anything (tree ptr)
if none. */
enum escape_type
-is_escape_site (tree stmt)
+is_escape_site (gimple stmt)
{
- tree call = get_call_expr_in (stmt);
- if (call != NULL_TREE)
+ if (gimple_code (stmt) == GIMPLE_CALL)
{
- if (!TREE_SIDE_EFFECTS (call))
+ if (!(gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST)))
return ESCAPE_TO_PURE_CONST;
return ESCAPE_TO_CALL;
}
- else if (TREE_CODE (stmt) == ASM_EXPR)
+ else if (gimple_code (stmt) == GIMPLE_ASM)
return ESCAPE_TO_ASM;
- else if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
+ else if (gimple_code (stmt) == GIMPLE_ASSIGN)
{
- tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
+ tree lhs = gimple_assign_lhs (stmt);
/* Get to the base of _REF nodes. */
if (TREE_CODE (lhs) != SSA_NAME)
@@ -3052,13 +2993,12 @@ is_escape_site (tree stmt)
if (lhs == NULL_TREE)
return ESCAPE_UNKNOWN;
- if (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == NOP_EXPR
- || TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == CONVERT_EXPR
- || TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == VIEW_CONVERT_EXPR)
+ if (gimple_subcode (stmt) == NOP_EXPR
+ || gimple_subcode (stmt) == CONVERT_EXPR
+ || gimple_subcode (stmt) == VIEW_CONVERT_EXPR)
{
- tree from
- = TREE_TYPE (TREE_OPERAND (GIMPLE_STMT_OPERAND (stmt, 1), 0));
- tree to = TREE_TYPE (GIMPLE_STMT_OPERAND (stmt, 1));
+ tree from = TREE_TYPE (gimple_assign_rhs1 (stmt));
+ tree to = TREE_TYPE (lhs);
/* If the RHS is a conversion between a pointer and an integer, the
pointer escapes since we can't track the integer. */
@@ -3088,7 +3028,7 @@ is_escape_site (tree stmt)
Applications (OOPSLA), pp. 1-19, 1999. */
return ESCAPE_STORED_IN_GLOBAL;
}
- else if (TREE_CODE (stmt) == RETURN_EXPR)
+ else if (gimple_code (stmt) == RETURN_EXPR)
return ESCAPE_TO_RETURN;
return NO_ESCAPE;
@@ -3386,7 +3326,6 @@ get_ptr_info (tree t)
return pi;
}
-#endif
/* Dump points-to information for SSA_NAME PTR into FILE. */
@@ -3443,10 +3382,8 @@ debug_points_to_info_for (tree var)
void
dump_points_to_info (FILE *file ATTRIBUTE_UNUSED)
{
- /* FIXME tuples. */
-#if 0
basic_block bb;
- block_stmt_iterator si;
+ gimple_stmt_iterator si;
ssa_op_iter iter;
const char *fname =
lang_hooks.decl_printable_name (current_function_decl, 2);
@@ -3471,18 +3408,17 @@ dump_points_to_info (FILE *file ATTRIBUT
/* Dump points-to information for every pointer defined in the program. */
FOR_EACH_BB (bb)
{
- tree phi;
-
- for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+ for (si = gsi_start (phi_nodes (bb)); !gsi_end_p (si); gsi_next (&si))
{
+ gimple phi = gsi_stmt (si);
tree ptr = PHI_RESULT (phi);
if (POINTER_TYPE_P (TREE_TYPE (ptr)))
dump_points_to_info_for (file, ptr);
}
- for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
{
- tree stmt = bsi_stmt (si);
+ gimple stmt = gsi_stmt (si);
tree def;
FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)
if (TREE_CODE (def) == SSA_NAME
@@ -3492,14 +3428,9 @@ dump_points_to_info (FILE *file ATTRIBUT
}
fprintf (file, "\n");
-#else
- gimple_unreachable ();
-#endif
}
-/* FIXME tuples. */
-#if 0
/* Dump points-to info pointed to by PTO into STDERR. */
void
@@ -3507,7 +3438,6 @@ debug_points_to_info (void)
{
dump_points_to_info (stderr);
}
-#endif
/* Dump to FILE the list of variables that may be aliasing VAR. */
@@ -3535,8 +3465,6 @@ dump_may_aliases_for (FILE *file, tree v
}
-/* FIXME tuples. */
-#if 0
/* Dump to stderr the list of variables that may be aliasing VAR. */
void
@@ -3544,7 +3472,6 @@ debug_may_aliases_for (tree var)
{
dump_may_aliases_for (stderr, var);
}
-#endif
/* Return true if VAR may be aliased. */
@@ -3583,8 +3510,6 @@ may_be_aliased (tree var)
return true;
}
-/* FIXME tuples. */
-#if 0
/* The following is based on code in add_stmt_operand to ensure that the
same defs/uses/vdefs/vuses will be found after replacing a reference
to var (or ARRAY_REF to var) with an INDIRECT_REF to ptr whose value
@@ -4016,12 +3941,6 @@ find_used_portions (tree *tp, int *walk_
{
switch (TREE_CODE (*tp))
{
- case GIMPLE_MODIFY_STMT:
- /* Recurse manually here to track whether the use is in the
- LHS of an assignment. */
- find_used_portions (&GIMPLE_STMT_OPERAND (*tp, 0), walk_subtrees, tp);
- return find_used_portions (&GIMPLE_STMT_OPERAND (*tp, 1),
- walk_subtrees, NULL);
case REALPART_EXPR:
case IMAGPART_EXPR:
case COMPONENT_REF:
@@ -4059,12 +3978,14 @@ find_used_portions (tree *tp, int *walk_
}
}
break;
- /* This is here to make sure we mark the entire base variable as used
- when you take its address. Because our used portion analysis is
- simple, we aren't looking at casts or pointer arithmetic to see what
- happens when you take the address. */
+
case ADDR_EXPR:
{
+ /* This is here to make sure we mark the entire base variable
+ as used when you take its address. Because our used
+ portion analysis is simple, we aren't looking at casts or
+ pointer arithmetic to see what happens when you take the
+ address. */
tree var = get_base_address (TREE_OPERAND (*tp, 0));
if (var
@@ -4090,19 +4011,7 @@ find_used_portions (tree *tp, int *walk_
}
}
break;
- case CALL_EXPR:
- {
- int i;
- int nargs = call_expr_nargs (*tp);
- for (i = 0; i < nargs; i++)
- {
- tree *arg = &CALL_EXPR_ARG (*tp, i);
- if (TREE_CODE (*arg) != ADDR_EXPR)
- find_used_portions (arg, walk_subtrees, NULL);
- }
- *walk_subtrees = 0;
- return NULL_TREE;
- }
+
case VAR_DECL:
case PARM_DECL:
case RESULT_DECL:
@@ -4132,17 +4041,15 @@ find_used_portions (tree *tp, int *walk_
break;
}
+
return NULL_TREE;
}
-#endif
/* Create structure field variables for structures used in this function. */
static unsigned int
create_structure_vars (void)
{
- /* FIXME tuples. */
-#if 0
basic_block bb;
safe_referenced_var_iterator rvi;
VEC (tree, heap) *varvec = NULL;
@@ -4153,14 +4060,16 @@ create_structure_vars (void)
FOR_EACH_BB (bb)
{
- block_stmt_iterator bsi;
- tree phi;
+ gimple_stmt_iterator gsi;
+ gimple phi;
- for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+ for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
{
use_operand_p use;
ssa_op_iter iter;
+ phi = gsi_stmt (gsi);
+
FOR_EACH_PHI_ARG (use, phi, iter, SSA_OP_USE)
{
tree op = USE_FROM_PTR (use);
@@ -4169,13 +4078,46 @@ create_structure_vars (void)
}
}
- for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
- walk_tree_without_duplicates (bsi_stmt_ptr (bsi),
- find_used_portions,
- NULL);
+ gimple stmt;
+ size_t i, start;
+
+ stmt = gsi_stmt (gsi);
+
+ if (gimple_code (stmt) == GIMPLE_CALL)
+ {
+ walk_tree_without_duplicates (gimple_call_lhs_ptr (stmt),
+ find_used_portions, stmt);
+
+ /* When an address escapes, assume that the whole
+ structure is used. So, ignore ADDR_EXPR arguments. */
+ for (i = 0; i < gimple_call_num_args (stmt); i++)
+ {
+ int walk_subtrees = 1;
+ tree *arg = gimple_call_arg_ptr (stmt, i);
+ if (TREE_CODE (*arg) != ADDR_EXPR)
+ find_used_portions (arg, &walk_subtrees, 0);
+ }
+ }
+ else
+ {
+ start = 0;
+
+ if (gimple_code (stmt) == GIMPLE_ASSIGN)
+ {
+ walk_tree_without_duplicates (gimple_op_ptr (stmt, 0),
+ find_used_portions, stmt);
+ start = 1;
+ }
+
+ for (i = start; i < gimple_num_ops (stmt); i++)
+ walk_tree_without_duplicates (gimple_op_ptr (stmt, i),
+ find_used_portions, 0);
+ }
}
}
+
FOR_EACH_REFERENCED_VAR_SAFE (var, varvec, rvi)
{
/* The C++ FE creates vars without DECL_SIZE set, for some reason. */
@@ -4193,10 +4135,11 @@ create_structure_vars (void)
if (gimple_in_ssa_p (cfun))
FOR_EACH_BB (bb)
{
- block_stmt_iterator bsi;
- for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ gimple_stmt_iterator gsi;
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
- tree stmt = bsi_stmt (bsi);
+ gimple stmt = gsi_stmt (gsi);
bool update = false;
unsigned int i;
bitmap_iterator bi;
@@ -4223,8 +4166,8 @@ create_structure_vars (void)
}
}
- if (stmt_ann (stmt)->addresses_taken && !update)
- EXECUTE_IF_SET_IN_BITMAP (stmt_ann (stmt)->addresses_taken,
+ if (gimple_addresses_taken (stmt) && !update)
+ EXECUTE_IF_SET_IN_BITMAP (gimple_addresses_taken (stmt),
0, i, bi)
{
tree sym = referenced_var_lookup (i);
@@ -4241,9 +4184,6 @@ create_structure_vars (void)
}
return TODO_rebuild_alias;
-#else
- gimple_unreachable ();
-#endif
}
static bool
@@ -4265,7 +4205,8 @@ struct tree_opt_pass pass_create_structu
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func, /* todo_flags_finish */
+ TODO_dump_func
+ | TODO_rebuild_alias,/* todo_flags_finish */
0 /* letter */
};
Index: opts.c
===================================================================
--- opts.c (revision 132202)
+++ opts.c (working copy)
@@ -775,16 +775,6 @@ decode_options (unsigned int argc, const
}
}
- /* FIXME tuples. Force optimization level to 0 until alias analysis
- and complex lowering at O1+ is fully enabled. */
- if (flag_gimple_conversion == 0)
- {
- optimize = 0;
- optimize_size = 0;
- }
- else
- gimple_unreachable ();
-
if (!optimize)
{
flag_merge_constants = 0;
Index: gimple-pretty-print.c
===================================================================
--- gimple-pretty-print.c (revision 132202)
+++ gimple-pretty-print.c (working copy)
@@ -552,6 +552,106 @@ dump_gimple_phi (pretty_printer *buffer,
dump_symbols (buffer, gimple_stored_syms (phi), flags);
}
+
+
+/* Dump all the memory operands for statement GS. BUFFER, SPC and
+ FLAGS are as in dump_gimple_stmt. */
+
+static void
+dump_gimple_mem_ops (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+ struct voptype_d *vdefs;
+ struct voptype_d *vuses;
+ int i, n;
+
+ if (!ssa_operands_active () || !stmt_references_memory_p (gs))
+ return;
+
+ /* Even if the statement doesn't have virtual operators yet, it may
+ contain symbol information (this happens before aliases have been
+ computed). */
+ if ((flags & TDF_MEMSYMS)
+ && gimple_vuse_ops (gs) == NULL
+ && gimple_vdef_ops (gs) == NULL)
+ {
+ if (gimple_loaded_syms (gs))
+ {
+ pp_string (buffer, "# LOADS: ");
+ dump_symbols (buffer, gimple_loaded_syms (gs), flags);
+ newline_and_indent (buffer, spc);
+ }
+
+ if (gimple_stored_syms (gs))
+ {
+ pp_string (buffer, "# STORES: ");
+ dump_symbols (buffer, gimple_stored_syms (gs), flags);
+ newline_and_indent (buffer, spc);
+ }
+
+ return;
+ }
+
+ vuses = gimple_vuse_ops (gs);
+ while (vuses)
+ {
+ pp_string (buffer, "# VUSE <");
+
+ n = VUSE_NUM (vuses);
+ for (i = 0; i < n; i++)
+ {
+ dump_generic_node (buffer, VUSE_OP (vuses, i), spc + 2, flags, false);
+ if (i < n - 1)
+ pp_string (buffer, ", ");
+ }
+
+ pp_string (buffer, ">");
+
+ if (flags & TDF_MEMSYMS)
+ dump_symbols (buffer, gimple_loaded_syms (gs), flags);
+
+ newline_and_indent (buffer, spc);
+ vuses = vuses->next;
+ }
+
+ vdefs = gimple_vdef_ops (gs);
+ while (vdefs)
+ {
+ pp_string (buffer, "# ");
+ dump_generic_node (buffer, VDEF_RESULT (vdefs), spc + 2, flags, false);
+ pp_string (buffer, " = VDEF <");
+
+ n = VDEF_NUM (vdefs);
+ for (i = 0; i < n; i++)
+ {
+ dump_generic_node (buffer, VDEF_OP (vdefs, i), spc + 2, flags, 0);
+ if (i < n - 1)
+ pp_string (buffer, ", ");
+ }
+
+ pp_string (buffer, ">");
+
+ if ((flags & TDF_MEMSYMS) && vdefs->next == NULL)
+ dump_symbols (buffer, gimple_stored_syms (gs), flags);
+
+ newline_and_indent (buffer, spc);
+ vdefs = vdefs->next;
+ }
+}
+
+
/* Dump the gimple statement GS on the pretty printer BUFFER, SPC
spaces of indent. FLAGS specifies details to show in the dump (see
TDF_* in tree.h). */
@@ -562,6 +662,25 @@ dump_gimple_stmt (pretty_printer *buffer
if (!gs)
return;
+ if (flags & TDF_STMTADDR)
+ pp_printf (buffer, "<&%p> ", (void *) gs);
+
+ if ((flags & TDF_LINENO) && !gimple_locus_empty_p (gs))
+ {
+ expanded_location xloc = expand_location (gimple_locus (gs));
+ pp_character (buffer, '[');
+ if (xloc.file)
+ {
+ pp_string (buffer, xloc.file);
+ pp_string (buffer, " : ");
+ }
+ pp_decimal_int (buffer, xloc.line);
+ pp_string (buffer, "] ");
+ }
+
+ if (gimple_has_mem_ops (gs))
+ dump_gimple_mem_ops (buffer, gs, spc, flags);
+
switch (gimple_code (gs))
{
case GIMPLE_ASM:
Index: ipa-type-escape.c
===================================================================
--- ipa-type-escape.c (revision 132202)
+++ ipa-type-escape.c (working copy)
@@ -54,8 +54,6 @@ along with GCC; see the file COPYING3.
#include "diagnostic.h"
#include "langhooks.h"
-/* FIXME tuples. */
-#if 0
/* Some of the aliasing is called very early, before this phase is
called. To assure that this is not a problem, we keep track of if
this phase has been run. */
@@ -137,8 +135,8 @@ static bitmap_obstack ipa_obstack;
/* Static functions from this file that are used
before being defined. */
-static unsigned int look_for_casts (tree lhs ATTRIBUTE_UNUSED, tree);
-static bool is_cast_from_non_pointer (tree, tree, void *);
+static unsigned int look_for_casts (tree);
+static bool is_cast_from_non_pointer (tree, gimple, void *);
/* Get the name of TYPE or return the string "<UNNAMED>". */
static const char*
@@ -309,7 +307,7 @@ get_canon_type (tree type, bool see_thru
while (POINTER_TYPE_P (type))
type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- result = splay_tree_lookup(type_to_canon_type, (splay_tree_key) type);
+ result = splay_tree_lookup (type_to_canon_type, (splay_tree_key) type);
if (result == NULL)
return discover_unique_type (type);
@@ -664,9 +662,7 @@ check_cast_type (tree to_type, tree from
static bool
is_malloc_result (tree var)
{
- tree def_stmt;
- tree rhs;
- int flags;
+ gimple def_stmt;
if (!var)
return false;
@@ -676,20 +672,13 @@ is_malloc_result (tree var)
def_stmt = SSA_NAME_DEF_STMT (var);
- if (TREE_CODE (def_stmt) != GIMPLE_MODIFY_STMT)
- return false;
-
- if (var != GIMPLE_STMT_OPERAND (def_stmt, 0))
+ if (gimple_code (def_stmt) != GIMPLE_CALL)
return false;
- rhs = get_call_expr_in (def_stmt);
-
- if (!rhs)
+ if (var != gimple_call_lhs (def_stmt))
return false;
- flags = call_expr_flags (rhs);
-
- return ((flags & ECF_MALLOC) != 0);
+ return ((gimple_call_flags (def_stmt) & ECF_MALLOC) != 0);
}
@@ -770,118 +759,98 @@ check_cast (tree to_type, tree from)
return cast;
}
-typedef struct cast
-{
- int type;
- tree stmt;
-}cast_t;
-
-/* This function is a callback for walk_tree called from
- is_cast_from_non_pointer. The data->type is set to be:
-
- 0 - if there is no cast
- number - the number of casts from non-pointer type
- -1 - if there is a cast that makes the type to escape
- If data->type = number, then data->stmt will contain the
- last casting stmt met in traversing. */
+/* Scan assignment statement S to see if there are any casts within it. */
-static tree
-is_cast_from_non_pointer_1 (tree *tp, int *walk_subtrees, void *data)
+static unsigned int
+look_for_casts_stmt (gimple s)
{
- tree def_stmt = *tp;
+ unsigned int cast = 0;
+ gcc_assert (gimple_code (s) == GIMPLE_ASSIGN);
- if (pointer_set_insert (visited_stmts, def_stmt))
+ if (gimple_assign_cast_p (s))
{
- *walk_subtrees = 0;
- return NULL;
+ tree castfromvar = gimple_assign_rhs1 (s);
+ cast |= check_cast (TREE_TYPE (gimple_assign_lhs (s)), castfromvar);
}
-
- switch (TREE_CODE (def_stmt))
+ else
{
- case GIMPLE_MODIFY_STMT:
- {
- use_operand_p use_p;
- ssa_op_iter iter;
- tree lhs = GIMPLE_STMT_OPERAND (def_stmt, 0);
- tree rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
-
- unsigned int cast = look_for_casts (lhs, rhs);
- /* Check that only one cast happened, and it's of
- non-pointer type. */
- if ((cast & CT_FROM_NON_P) == (CT_FROM_NON_P)
- && (cast & ~(CT_FROM_NON_P)) == 0)
- {
- ((cast_t *)data)->stmt = def_stmt;
- ((cast_t *)data)->type++;
-
- FOR_EACH_SSA_USE_OPERAND (use_p, def_stmt, iter, SSA_OP_ALL_USES)
- {
- walk_use_def_chains (USE_FROM_PTR (use_p), is_cast_from_non_pointer,
- data, false);
- if (((cast_t*)data)->type == -1)
- return def_stmt;
- }
- }
-
- /* Check that there is no cast, or cast is not harmful. */
- else if ((cast & CT_NO_CAST) == (CT_NO_CAST)
- || (cast & CT_DOWN) == (CT_DOWN)
- || (cast & CT_UP) == (CT_UP)
- || (cast & CT_USELESS) == (CT_USELESS)
- || (cast & CT_FROM_MALLOC) == (CT_FROM_MALLOC))
- {
- FOR_EACH_SSA_USE_OPERAND (use_p, def_stmt, iter, SSA_OP_ALL_USES)
- {
- walk_use_def_chains (USE_FROM_PTR (use_p), is_cast_from_non_pointer,
- data, false);
- if (((cast_t*)data)->type == -1)
- return def_stmt;
- }
- }
+ size_t i;
+ for (i = 0; i < gimple_num_ops (s); i++)
+ cast |= look_for_casts (gimple_op (s, i));
+ }
- /* The cast is harmful. */
- else
- {
- ((cast_t *)data)->type = -1;
- return def_stmt;
- }
+ if (!cast)
+ cast = CT_NO_CAST;
- *walk_subtrees = 0;
- }
- break;
+ return cast;
+}
- default:
- {
- *walk_subtrees = 0;
- break;
- }
- }
- return NULL;
-}
+typedef struct cast
+{
+ int type;
+ gimple stmt;
+} cast_t;
/* This function is a callback for walk_use_def_chains function called
from is_array_access_through_pointer_and_index. */
static bool
-is_cast_from_non_pointer (tree var, tree def_stmt, void *data)
+is_cast_from_non_pointer (tree var, gimple def_stmt, void *data)
{
-
if (!def_stmt || !var)
return false;
- /* FIXME tuples. */
-#if 0
- if (TREE_CODE (def_stmt) == PHI_NODE)
+ if (gimple_code (def_stmt) == GIMPLE_PHI)
return false;
-#endif
if (SSA_NAME_IS_DEFAULT_DEF (var))
return false;
- walk_tree (&def_stmt, is_cast_from_non_pointer_1, data, NULL);
+ if (gimple_code (def_stmt) == GIMPLE_ASSIGN)
+ {
+ use_operand_p use_p;
+ ssa_op_iter iter;
+ unsigned int cast = look_for_casts_stmt (def_stmt);
+
+ /* Check that only one cast happened, and it's of non-pointer
+ type. */
+ if ((cast & CT_FROM_NON_P) == (CT_FROM_NON_P)
+ && (cast & ~(CT_FROM_NON_P)) == 0)
+ {
+ ((cast_t *)data)->stmt = def_stmt;
+ ((cast_t *)data)->type++;
+
+ FOR_EACH_SSA_USE_OPERAND (use_p, def_stmt, iter, SSA_OP_ALL_USES)
+ {
+ walk_use_def_chains (USE_FROM_PTR (use_p),
+ is_cast_from_non_pointer, data, false);
+ if (((cast_t*)data)->type == -1)
+ break;
+ }
+ }
+ /* Check that there is no cast, or cast is not harmful. */
+ else if ((cast & CT_NO_CAST) == (CT_NO_CAST)
+ || (cast & CT_DOWN) == (CT_DOWN)
+ || (cast & CT_UP) == (CT_UP)
+ || (cast & CT_USELESS) == (CT_USELESS)
+ || (cast & CT_FROM_MALLOC) == (CT_FROM_MALLOC))
+ {
+ FOR_EACH_SSA_USE_OPERAND (use_p, def_stmt, iter, SSA_OP_ALL_USES)
+ {
+ walk_use_def_chains (USE_FROM_PTR (use_p),
+ is_cast_from_non_pointer, data, false);
+ if (((cast_t*)data)->type == -1)
+ break;
+ }
+ }
+ /* The cast is harmful. */
+ else
+ ((cast_t *)data)->type = -1;
+ }
+
if (((cast_t*)data)->type == -1)
return true;
@@ -934,9 +903,10 @@ is_cast_from_non_pointer (tree var, tree
bool
is_array_access_through_pointer_and_index (enum tree_code code, tree op0,
tree op1, tree *base, tree *offset,
- tree *offset_cast_stmt)
+ gimple *offset_cast_stmt)
{
- tree before_cast, before_cast_def_stmt;
+ tree before_cast;
+ gimple before_cast_def_stmt;
cast_t op0_cast, op1_cast;
*base = NULL;
@@ -1018,26 +988,23 @@ is_array_access_through_pointer_and_inde
/* before_cast_def_stmt should be of the form:
D.1605_6 = i.1_5 * 16; */
- if (TREE_CODE (before_cast_def_stmt) == GIMPLE_MODIFY_STMT)
+ if (gimple_code (before_cast_def_stmt) == GIMPLE_ASSIGN)
{
- tree lhs = GIMPLE_STMT_OPERAND (before_cast_def_stmt,0);
- tree rhs = GIMPLE_STMT_OPERAND (before_cast_def_stmt,1);
-
/* We expect temporary here. */
- if (!is_gimple_reg (lhs))
+ if (!is_gimple_reg (gimple_assign_lhs (before_cast_def_stmt)))
return false;
- if (TREE_CODE (rhs) == MULT_EXPR)
+ if (gimple_subcode (before_cast_def_stmt) == MULT_EXPR)
{
- tree arg0 = TREE_OPERAND (rhs, 0);
- tree arg1 = TREE_OPERAND (rhs, 1);
+ tree arg0 = gimple_assign_rhs1 (before_cast_def_stmt);
+ tree arg1 = gimple_assign_rhs2 (before_cast_def_stmt);
tree unit_size =
TYPE_SIZE_UNIT (TREE_TYPE (TYPE_MAIN_VARIANT (TREE_TYPE (op0))));
if (!(CONSTANT_CLASS_P (arg0)
- && simple_cst_equal (arg0,unit_size))
+ && simple_cst_equal (arg0, unit_size))
&& !(CONSTANT_CLASS_P (arg1)
- && simple_cst_equal (arg1,unit_size)))
+ && simple_cst_equal (arg1, unit_size)))
return false;
}
else
@@ -1177,7 +1144,11 @@ check_tree (tree t)
check_tree (TREE_OPERAND (t, 0));
if (SSA_VAR_P (t) || (TREE_CODE (t) == FUNCTION_DECL))
- check_operand (t);
+ {
+ check_operand (t);
+ if (DECL_INITIAL (t))
+ check_tree (DECL_INITIAL (t));
+ }
}
/* Create an address_of edge FROM_TYPE.TO_TYPE. */
@@ -1264,15 +1235,13 @@ look_for_address_of (tree t)
}
-/* Scan tree T to see if there are any casts within it.
- LHS Is the LHS of the expression involving the cast. */
+/* Scan tree T to see if there are any casts within it. */
static unsigned int
-look_for_casts (tree lhs ATTRIBUTE_UNUSED, tree t)
+look_for_casts (tree t)
{
unsigned int cast = 0;
-
if (is_gimple_cast (t) || TREE_CODE (t) == VIEW_CONVERT_EXPR)
{
tree castfromvar = TREE_OPERAND (t, 0);
@@ -1306,7 +1275,7 @@ static void
check_rhs_var (tree t)
{
look_for_address_of (t);
- check_tree(t);
+ check_tree (t);
}
/* Check to see if T is an assignment to a static var we are
@@ -1315,7 +1284,7 @@ check_rhs_var (tree t)
static void
check_lhs_var (tree t)
{
- check_tree(t);
+ check_tree (t);
}
/* This is a scaled down version of get_asm_expr_operands from
@@ -1326,35 +1295,15 @@ check_lhs_var (tree t)
analyzed and STMT is the actual asm statement. */
static void
-get_asm_expr_operands (tree stmt)
+check_asm (gimple stmt)
{
- int noutputs = list_length (ASM_OUTPUTS (stmt));
- const char **oconstraints
- = (const char **) alloca ((noutputs) * sizeof (const char *));
- int i;
- tree link;
- const char *constraint;
- bool allows_mem, allows_reg, is_inout;
-
- for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
- {
- oconstraints[i] = constraint
- = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
- parse_output_constraint (&constraint, i, 0, 0,
- &allows_mem, &allows_reg, &is_inout);
-
- check_lhs_var (TREE_VALUE (link));
- }
+ size_t i;
- for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
- {
- constraint
- = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
- parse_input_constraint (&constraint, 0, 0, noutputs, 0,
- oconstraints, &allows_mem, &allows_reg);
-
- check_rhs_var (TREE_VALUE (link));
- }
+ for (i = 0; i < gimple_asm_noutputs (stmt); i++)
+ check_lhs_var (gimple_asm_output_op (stmt, i));
+
+ for (i = 0; i < gimple_asm_ninputs (stmt); i++)
+ check_rhs_var (gimple_asm_input_op (stmt, i));
/* There is no code here to check for asm memory clobbers. The
casual maintainer might think that such code would be necessary,
@@ -1364,22 +1313,22 @@ get_asm_expr_operands (tree stmt)
assumed to already escape. So, we are protected here. */
}
-/* Check the parameters of a function call to CALL_EXPR to mark the
+
+/* Check the parameters of function call to CALL to mark the
types that pass across the function boundary. Also check to see if
this is either an indirect call, a call outside the compilation
unit. */
static void
-check_call (tree call_expr)
+check_call (gimple call)
{
- tree operand;
- tree callee_t = get_callee_fndecl (call_expr);
+ tree callee_t = gimple_call_fndecl (call);
struct cgraph_node* callee;
enum availability avail = AVAIL_NOT_AVAILABLE;
- call_expr_arg_iterator iter;
+ size_t i;
- FOR_EACH_CALL_EXPR_ARG (operand, iter, call_expr)
- check_rhs_var (operand);
+ for (i = 0; i < gimple_call_num_args (call); i++)
+ check_rhs_var (gimple_call_arg (call, i));
if (callee_t)
{
@@ -1392,12 +1341,11 @@ check_call (tree call_expr)
parameters. */
if (TYPE_ARG_TYPES (TREE_TYPE (callee_t)))
{
- for (arg_type = TYPE_ARG_TYPES (TREE_TYPE (callee_t)),
- operand = first_call_expr_arg (call_expr, &iter);
+ for (arg_type = TYPE_ARG_TYPES (TREE_TYPE (callee_t)), i = 0;
arg_type && TREE_VALUE (arg_type) != void_type_node;
- arg_type = TREE_CHAIN (arg_type),
- operand = next_call_expr_arg (&iter))
+ arg_type = TREE_CHAIN (arg_type), i++)
{
+ tree operand = gimple_call_arg (call, i);
if (operand)
{
last_arg_type = TREE_VALUE(arg_type);
@@ -1415,15 +1363,14 @@ check_call (tree call_expr)
/* FIXME - According to Geoff Keating, we should never
have to do this; the front ends should always process
the arg list from the TYPE_ARG_LIST. */
- for (arg_type = DECL_ARGUMENTS (callee_t),
- operand = first_call_expr_arg (call_expr, &iter);
+ for (arg_type = DECL_ARGUMENTS (callee_t), i = 0;
arg_type;
- arg_type = TREE_CHAIN (arg_type),
- operand = next_call_expr_arg (&iter))
+ arg_type = TREE_CHAIN (arg_type), i++)
{
+ tree operand = gimple_call_arg (call, i);
if (operand)
{
- last_arg_type = TREE_TYPE(arg_type);
+ last_arg_type = TREE_TYPE (arg_type);
check_cast (last_arg_type, operand);
}
else
@@ -1437,10 +1384,9 @@ check_call (tree call_expr)
/* In the case where we have a var_args function, we need to
check the remaining parameters against the last argument. */
arg_type = last_arg_type;
- for (;
- operand != NULL_TREE;
- operand = next_call_expr_arg (&iter))
+ for ( ; i < gimple_call_num_args (call); i++)
{
+ tree operand = gimple_call_arg (call, i);
if (arg_type)
check_cast (arg_type, operand);
else
@@ -1461,16 +1407,16 @@ check_call (tree call_expr)
are any bits available for the callee (such as by declaration or
because it is builtin) and process solely on the basis of those
bits. */
-
if (avail == AVAIL_NOT_AVAILABLE || avail == AVAIL_OVERWRITABLE)
{
/* If this is a direct call to an external function, mark all of
the parameter and return types. */
- FOR_EACH_CALL_EXPR_ARG (operand, iter, call_expr)
+ for (i = 0; i < gimple_call_num_args (call); i++)
{
+ tree operand = gimple_call_arg (call, i);
tree type = get_canon_type (TREE_TYPE (operand), false, false);
mark_interesting_type (type, EXPOSED_PARAMETER);
- }
+ }
if (callee_t)
{
@@ -1498,7 +1444,8 @@ okay_pointer_operation (enum tree_code c
case PLUS_EXPR:
case POINTER_PLUS_EXPR:
{
- tree base, offset, offset_cast_stmt;
+ tree base, offset;
+ gimple offset_cast_stmt;
if (POINTER_TYPE_P (op0type)
&& TREE_CODE (op0) == SSA_NAME
@@ -1532,150 +1479,126 @@ okay_pointer_operation (enum tree_code c
return false;
}
-/* TP is the part of the tree currently under the microscope.
- WALK_SUBTREES is part of the walk_tree api but is unused here.
- DATA is cgraph_node of the function being walked. */
-/* FIXME: When this is converted to run over SSA form, this code
- should be converted to use the operand scanner. */
-static tree
-scan_for_refs (tree *tp, int *walk_subtrees, void *data)
+/* Helper for scan_for_refs. Check the operands of an assignment to
+ mark types that may escape. */
+
+static void
+check_assign (gimple t)
{
- struct cgraph_node *fn = (struct cgraph_node *) data;
- tree t = *tp;
+ /* First look on the lhs and see what variable is stored to */
+ check_lhs_var (gimple_assign_lhs (t));
- switch (TREE_CODE (t))
+ /* For the purposes of figuring out what the cast affects */
+
+ /* Next check the operands on the rhs to see if they are ok. */
+ switch (TREE_CODE_CLASS (gimple_subcode (t)))
{
- case VAR_DECL:
- if (DECL_INITIAL (t))
- walk_tree (&DECL_INITIAL (t), scan_for_refs, fn, visited_nodes);
- *walk_subtrees = 0;
+ case tcc_binary:
+ {
+ tree op0 = gimple_assign_rhs1 (t);
+ tree type0 = get_canon_type (TREE_TYPE (op0), false, false);
+ tree op1 = gimple_assign_rhs2 (t);
+ tree type1 = get_canon_type (TREE_TYPE (op1), false, false);
+
+ /* If this is pointer arithmetic of any bad sort, then
+ we need to mark the types as bad. For binary
+ operations, no binary operator we currently support
+ is always "safe" in regard to what it would do to
+ pointers for purposes of determining which types
+ escape, except operations of the size of the type.
+ It is possible that min and max under the right set
+ of circumstances and if the moon is in the correct
+ place could be safe, but it is hard to see how this
+ is worth the effort. */
+ if (type0 && POINTER_TYPE_P (type0)
+ && !okay_pointer_operation (gimple_subcode (t), op0, op1))
+ mark_interesting_type (type0, FULL_ESCAPE);
+
+ if (type1 && POINTER_TYPE_P (type1)
+ && !okay_pointer_operation (gimple_subcode (t), op1, op0))
+ mark_interesting_type (type1, FULL_ESCAPE);
+
+ look_for_casts (op0);
+ look_for_casts (op1);
+ check_rhs_var (op0);
+ check_rhs_var (op1);
+ }
break;
- case GIMPLE_MODIFY_STMT:
+ case tcc_unary:
{
- /* First look on the lhs and see what variable is stored to */
- tree lhs = GIMPLE_STMT_OPERAND (t, 0);
- tree rhs = GIMPLE_STMT_OPERAND (t, 1);
+ tree rhs = gimple_assign_rhs1 (t);
+ tree op0 = TREE_OPERAND (rhs, 0);
+ tree type0 = get_canon_type (TREE_TYPE (op0), false, false);
- check_lhs_var (lhs);
- check_cast (TREE_TYPE (lhs), rhs);
+ /* For unary operations, if the operation is NEGATE or ABS on
+ a pointer, this is also considered pointer arithmetic and
+ thus, bad for business. */
+ if (type0
+ && POINTER_TYPE_P (type0)
+ && (TREE_CODE (op0) == NEGATE_EXPR
+ || TREE_CODE (op0) == ABS_EXPR))
+ mark_interesting_type (type0, FULL_ESCAPE);
- /* For the purposes of figuring out what the cast affects */
+ check_rhs_var (op0);
+ look_for_casts (op0);
+ look_for_casts (rhs);
+ }
+ break;
- /* Next check the operands on the rhs to see if they are ok. */
- switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
- {
- case tcc_binary:
- {
- tree op0 = TREE_OPERAND (rhs, 0);
- tree type0 = get_canon_type (TREE_TYPE (op0), false, false);
- tree op1 = TREE_OPERAND (rhs, 1);
- tree type1 = get_canon_type (TREE_TYPE (op1), false, false);
-
- /* If this is pointer arithmetic of any bad sort, then
- we need to mark the types as bad. For binary
- operations, no binary operator we currently support
- is always "safe" in regard to what it would do to
- pointers for purposes of determining which types
- escape, except operations of the size of the type.
- It is possible that min and max under the right set
- of circumstances and if the moon is in the correct
- place could be safe, but it is hard to see how this
- is worth the effort. */
-
- if (type0 && POINTER_TYPE_P (type0)
- && !okay_pointer_operation (TREE_CODE (rhs), op0, op1))
- mark_interesting_type (type0, FULL_ESCAPE);
- if (type1 && POINTER_TYPE_P (type1)
- && !okay_pointer_operation (TREE_CODE (rhs), op1, op0))
- mark_interesting_type (type1, FULL_ESCAPE);
-
- look_for_casts (lhs, op0);
- look_for_casts (lhs, op1);
- check_rhs_var (op0);
- check_rhs_var (op1);
- }
- break;
- case tcc_unary:
- {
- tree op0 = TREE_OPERAND (rhs, 0);
- tree type0 = get_canon_type (TREE_TYPE (op0), false, false);
- /* For unary operations, if the operation is NEGATE or
- ABS on a pointer, this is also considered pointer
- arithmetic and thus, bad for business. */
- if (type0 && (TREE_CODE (op0) == NEGATE_EXPR
- || TREE_CODE (op0) == ABS_EXPR)
- && POINTER_TYPE_P (type0))
- {
- mark_interesting_type (type0, FULL_ESCAPE);
- }
- check_rhs_var (op0);
- look_for_casts (lhs, op0);
- look_for_casts (lhs, rhs);
- }
+ case tcc_reference:
+ look_for_casts (gimple_assign_rhs1 (t));
+ check_rhs_var (gimple_assign_rhs1 (t));
+ break;
- break;
- case tcc_reference:
- look_for_casts (lhs, rhs);
- check_rhs_var (rhs);
- break;
- case tcc_declaration:
- check_rhs_var (rhs);
- break;
- case tcc_expression:
- switch (TREE_CODE (rhs))
- {
- case ADDR_EXPR:
- look_for_casts (lhs, TREE_OPERAND (rhs, 0));
- check_rhs_var (rhs);
- break;
- default:
- break;
- }
- break;
- case tcc_vl_exp:
- switch (TREE_CODE (rhs))
- {
- case CALL_EXPR:
- /* If this is a call to malloc, squirrel away the
- result so we do mark the resulting cast as being
- bad. */
- check_call (rhs);
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- *walk_subtrees = 0;
- }
+ case tcc_declaration:
+ check_rhs_var (gimple_assign_rhs1 (t));
break;
- case ADDR_EXPR:
- /* This case is here to find addresses on rhs of constructors in
- decl_initial of static variables. */
- check_rhs_var (t);
- *walk_subtrees = 0;
+ case tcc_expression:
+ if (gimple_subcode (t) == ADDR_EXPR)
+ {
+ tree rhs = gimple_assign_rhs1 (t);
+ look_for_casts (TREE_OPERAND (rhs, 0));
+ check_rhs_var (rhs);
+ }
break;
- case CALL_EXPR:
+ default:
+ break;
+ }
+}
+
+
+/* Scan statement T for references to types and mark anything
+ interesting. */
+
+static void
+scan_for_refs (gimple t)
+{
+ switch (gimple_code (t))
+ {
+ case GIMPLE_ASSIGN:
+ check_assign (t);
+ break;
+
+ case GIMPLE_CALL:
+ /* If this is a call to malloc, squirrel away the result so we
+ do mark the resulting cast as being bad. */
check_call (t);
- *walk_subtrees = 0;
break;
- case ASM_EXPR:
- get_asm_expr_operands (t);
- *walk_subtrees = 0;
+ case GIMPLE_ASM:
+ check_asm (t);
break;
default:
break;
}
- return NULL;
+
+ return;
}
@@ -1725,7 +1648,7 @@ analyze_variable (struct varpool_node *v
gcc_assert (TREE_CODE (global) == VAR_DECL);
if (DECL_INITIAL (global))
- walk_tree (&DECL_INITIAL (global), scan_for_refs, NULL, visited_nodes);
+ check_tree (DECL_INITIAL (global));
}
/* This is the main routine for finding the reference patterns for
@@ -1746,10 +1669,9 @@ analyze_function (struct cgraph_node *fn
FOR_EACH_BB_FN (this_block, this_cfun)
{
- block_stmt_iterator bsi;
- for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
- walk_tree (bsi_stmt_ptr (bsi), scan_for_refs,
- fn, visited_nodes);
+ gimple_stmt_iterator gsi;
+ for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
+ scan_for_refs (gsi_stmt (gsi));
}
}
@@ -1765,8 +1687,7 @@ analyze_function (struct cgraph_node *fn
if (TREE_CODE (var) == VAR_DECL
&& DECL_INITIAL (var)
&& !TREE_STATIC (var))
- walk_tree (&DECL_INITIAL (var), scan_for_refs,
- fn, visited_nodes);
+ check_tree (DECL_INITIAL (var));
get_canon_type (TREE_TYPE (var), false, false);
}
}
@@ -2217,5 +2138,3 @@ struct tree_opt_pass pass_ipa_type_escap
0, /* todo_flags_finish */
0 /* letter */
};
-
-#endif
Index: ipa-type-escape.h
===================================================================
--- ipa-type-escape.h (revision 132202)
+++ ipa-type-escape.h (working copy)
@@ -23,11 +23,11 @@ along with GCC; see the file COPYING3.
#include "tree.h"
bool ipa_type_escape_type_contained_p (tree type);
-bool ipa_type_escape_field_does_not_clobber_p (tree record_type, tree field_type);
+bool ipa_type_escape_field_does_not_clobber_p (tree, tree);
int ipa_type_escape_star_count_of_interesting_type (tree type);
int ipa_type_escape_star_count_of_interesting_or_array_type (tree type);
bool is_array_access_through_pointer_and_index (enum tree_code, tree, tree,
- tree *, tree *, tree *);
+ tree *, tree *, gimple *);
#endif /* GCC_IPA_TYPE_ESCAPE_H */
Index: tree-outof-ssa.c
===================================================================
--- tree-outof-ssa.c (revision 132202)
+++ tree-outof-ssa.c (working copy)
@@ -617,7 +617,7 @@ eliminate_virtual_phis (void)
FOR_EACH_BB (bb)
{
- for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
+ for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); )
{
gimple phi = gsi_stmt (gsi);
if (!is_gimple_reg (SSA_NAME_VAR (gimple_phi_result (phi))))
@@ -640,8 +640,10 @@ eliminate_virtual_phis (void)
}
}
#endif
- remove_phi_node (phi, true);
+ remove_phi_node (&gsi, true);
}
+ else
+ gsi_next (&gsi);
}
}
}
@@ -1292,7 +1294,6 @@ static void
remove_ssa_form (bool perform_ter)
{
basic_block bb;
- gimple phi;
tree *values = NULL;
var_map map;
gimple_stmt_iterator gsi;
@@ -1338,17 +1339,8 @@ remove_ssa_form (bool perform_ter)
/* Remove PHI nodes which have been translated back to real variables. */
FOR_EACH_BB (bb)
- {
- for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi);)
- {
- phi = gsi_stmt (gsi);
-
- /* Update iterator before removing phi */
- gsi_next (&gsi);
-
- remove_phi_node (phi, true);
- }
- }
+ for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi);)
+ remove_phi_node (&gsi, true);
/* If any copies were inserted on edges, analyze and insert them now. */
perform_edge_inserts ();
Index: tree-flow.h
===================================================================
--- tree-flow.h (revision 132202)
+++ tree-flow.h (working copy)
@@ -780,7 +780,7 @@ extern void reserve_phi_args_for_new_edg
extern gimple create_phi_node (tree, basic_block);
extern void add_phi_arg (gimple, tree, edge);
extern void remove_phi_args (edge);
-extern void remove_phi_node (gimple, bool);
+extern void remove_phi_node (gimple_stmt_iterator *, bool);
/* In gimple-low.c */
extern void record_vars_into (tree, tree);
@@ -802,7 +802,7 @@ extern void debug_points_to_info_for (tr
extern bool may_be_aliased (tree);
extern struct ptr_info_def *get_ptr_info (tree);
extern void new_type_alias (tree, tree, tree);
-extern void count_uses_and_derefs (tree, tree, unsigned *, unsigned *,
+extern void count_uses_and_derefs (tree, gimple, unsigned *, unsigned *,
unsigned *);
static inline subvar_t get_subvars_for_var (tree);
static inline tree get_subvar_at (tree, unsigned HOST_WIDE_INT);
Index: Makefile.in
===================================================================
--- Makefile.in (revision 132202)
+++ Makefile.in (working copy)
@@ -1995,12 +1995,10 @@ stor-layout.o : stor-layout.c $(CONFIG_H
$(TREE_H) $(PARAMS_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) $(RTL_H) \
$(GGC_H) $(TM_P_H) $(TARGET_H) langhooks.h $(REGS_H) gt-stor-layout.h \
toplev.h
-# FIXME tuples. Do not merge.
-# gt-tree-ssa-structalias.h
tree-ssa-structalias.o: tree-ssa-structalias.c tree-ssa-structalias.h \
$(SYSTEM_H) $(CONFIG_H) $(GGC_H) $(TREE_H) $(TREE_FLOW_H) \
$(TM_H) coretypes.h $(CGRAPH_H) tree-pass.h $(TIMEVAR_H) \
- $(PARAMS_H) $(ALIAS_H) pointer-set.h $(FUNCTION_H)
+ $(PARAMS_H) $(ALIAS_H) pointer-set.h $(FUNCTION_H) gt-tree-ssa-structalias.h
tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
toplev.h $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
@@ -3115,8 +3113,6 @@ s-constrs-h: $(MD_DEPS) build/genpreds$(
# FIXME tuples. Do not merge.
# $(srcdir)/tree-scalar-evolution.c
-# $(srcdir)/tree-ssa-structalias.h
-# $(srcdir)/tree-ssa-structalias.c
# $(srcdir)/ipa-reference.h
# $(srcdir)/omp-low.c
# $(srcdir)/ipa-reference.c
@@ -3156,6 +3152,8 @@ GTFILES = $(srcdir)/input.h $(srcdir)/co
$(srcdir)/targhooks.c $(out_file) $(srcdir)/passes.c $(srcdir)/cgraphunit.c \
$(srcdir)/tree-ssa-propagate.c \
$(srcdir)/tree-phinodes.c \
+ $(srcdir)/tree-ssa-structalias.h \
+ $(srcdir)/tree-ssa-structalias.c \
@all_gtfiles@
GTFILES_H = $(subst /,-, $(patsubst $(srcdir)/%,gt-%, $(patsubst %.c,%.h, \
Index: tree-ssa-structalias.c
===================================================================
--- tree-ssa-structalias.c (revision 132202)
+++ tree-ssa-structalias.c (working copy)
@@ -53,8 +53,6 @@
#include "alias.h"
#include "pointer-set.h"
-/* FIXME tuples. */
-#if 0
/* The idea behind this analyzer is to generate set constraints from the
program, then solve the resulting constraints in order to generate the
points-to sets.
@@ -2854,45 +2852,6 @@ get_constraint_for (tree t, VEC (ce_s, h
return;
}
break;
- case CALL_EXPR:
- /* XXX: In interprocedural mode, if we didn't have the
- body, we would need to do *each pointer argument =
- &ANYTHING added. */
- if (call_expr_flags (t) & (ECF_MALLOC | ECF_MAY_BE_ALLOCA))
- {
- varinfo_t vi;
- tree heapvar = heapvar_lookup (t);
-
- if (heapvar == NULL)
- {
- heapvar = create_tmp_var_raw (ptr_type_node, "HEAP");
- DECL_EXTERNAL (heapvar) = 1;
- get_var_ann (heapvar)->is_heapvar = 1;
- if (gimple_referenced_vars (cfun))
- add_referenced_var (heapvar);
- heapvar_insert (t, heapvar);
- }
-
- temp.var = create_variable_info_for (heapvar,
- alias_get_name (heapvar));
-
- vi = get_varinfo (temp.var);
- vi->is_artificial_var = 1;
- vi->is_heap_var = 1;
- temp.type = ADDRESSOF;
- temp.offset = 0;
- VEC_safe_push (ce_s, heap, *results, &temp);
- return;
- }
- else
- {
- temp.var = anything_id;
- temp.type = SCALAR;
- temp.offset = 0;
- VEC_safe_push (ce_s, heap, *results, &temp);
- return;
- }
- break;
default:
{
temp.type = ADDRESSOF;
@@ -2963,12 +2922,6 @@ get_constraint_for (tree t, VEC (ce_s, h
{
switch (TREE_CODE (t))
{
- case PHI_NODE:
- {
- get_constraint_for (PHI_RESULT (t), results);
- return;
- }
- break;
case SSA_NAME:
{
struct constraint_expr temp;
@@ -3284,7 +3237,7 @@ do_structure_copy (tree lhsop, tree rhso
ADDRESSABLE_VARS. */
static void
-update_alias_info (tree stmt, struct alias_info *ai)
+update_alias_info (gimple stmt, struct alias_info *ai)
{
bitmap addr_taken;
use_operand_p use_p;
@@ -3306,7 +3259,7 @@ update_alias_info (tree stmt, struct ali
mem_ref_stats->num_asm_sites++;
/* Mark all the variables whose address are taken by the statement. */
- addr_taken = addresses_taken (stmt);
+ addr_taken = gimple_addresses_taken (stmt);
if (addr_taken)
{
bitmap_ior_into (gimple_addressable_vars (cfun), addr_taken);
@@ -3365,7 +3318,7 @@ update_alias_info (tree stmt, struct ali
/* If STMT is a PHI node, then it will not have pointer
dereferences and it will not be an escape point. */
- if (TREE_CODE (stmt) == PHI_NODE)
+ if (gimple_code (stmt) == GIMPLE_PHI)
continue;
/* Determine whether OP is a dereferenced pointer, and if STMT
@@ -3393,13 +3346,13 @@ update_alias_info (tree stmt, struct ali
are not GIMPLE invariants), they can only appear on the RHS
of an assignment and their base address is always an
INDIRECT_REF expression. */
- if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
- && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == ADDR_EXPR
- && !is_gimple_val (GIMPLE_STMT_OPERAND (stmt, 1)))
+ if (gimple_code (stmt) == GIMPLE_ASSIGN
+ && gimple_subcode (stmt) == ADDR_EXPR
+ && !is_gimple_val (gimple_assign_rhs1 (stmt)))
{
/* If the RHS if of the form &PTR->FLD and PTR == OP, then
this represents a potential dereference of PTR. */
- tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
+ tree rhs = gimple_assign_rhs1 (stmt);
tree base = get_base_address (TREE_OPERAND (rhs, 0));
if (TREE_CODE (base) == INDIRECT_REF
&& TREE_OPERAND (base, 0) == op)
@@ -3442,7 +3395,7 @@ update_alias_info (tree stmt, struct ali
/* If the statement makes a function call, assume
that pointer OP will be dereferenced in a store
operation inside the called function. */
- if (get_call_expr_in (stmt)
+ if (gimple_code (stmt) == GIMPLE_CALL
|| stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
{
pointer_set_insert (ai->dereferenced_ptrs_store, var);
@@ -3451,7 +3404,7 @@ update_alias_info (tree stmt, struct ali
}
}
- if (TREE_CODE (stmt) == PHI_NODE)
+ if (gimple_code (stmt) == GIMPLE_PHI)
return;
/* Mark stored variables in STMT as being written to and update the
@@ -3509,6 +3462,9 @@ update_alias_info (tree stmt, struct ali
/* Handle pointer arithmetic EXPR when creating aliasing constraints.
+ EXPR is assumed to be an assignment with a pointer arithmetic
+ expression on the RHS.
+
Expressions of the type PTR + CST can be handled in two ways:
1- If the constraint for PTR is ADDRESSOF for a non-structure
@@ -3527,7 +3483,7 @@ update_alias_info (tree stmt, struct ali
separate constraint by the caller. */
static bool
-handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr)
+handle_ptr_arith (VEC (ce_s, heap) *lhsc, gimple expr)
{
tree op0, op1;
struct constraint_expr *c, *c2;
@@ -3537,11 +3493,11 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc
unsigned int rhsoffset = 0;
bool unknown_addend = false;
- if (TREE_CODE (expr) != POINTER_PLUS_EXPR)
+ if (gimple_assign_subcode (expr) != POINTER_PLUS_EXPR)
return false;
- op0 = TREE_OPERAND (expr, 0);
- op1 = TREE_OPERAND (expr, 1);
+ op0 = gimple_assign_rhs1 (expr);
+ op1 = gimple_assign_rhs2 (expr);
gcc_assert (POINTER_TYPE_P (TREE_TYPE (op0)));
get_constraint_for (op0, &temp);
@@ -3605,18 +3561,18 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc
RHS. */
static void
-handle_rhs_call (tree rhs)
+handle_rhs_call (gimple rhs)
{
- tree arg;
- call_expr_arg_iterator iter;
+ size_t i;
struct constraint_expr rhsc;
rhsc.var = anything_id;
rhsc.offset = 0;
rhsc.type = ADDRESSOF;
- FOR_EACH_CALL_EXPR_ARG (arg, iter, rhs)
+ for (i = 0; i < gimple_call_num_args (rhs); i++)
{
+ tree arg = gimple_call_arg (rhs, i);
VEC(ce_s, heap) *lhsc = NULL;
/* Find those pointers being passed, and make sure they end up
@@ -3662,39 +3618,36 @@ handle_lhs_call (tree lhs)
when building alias sets and computing alias grouping heuristics. */
static void
-find_func_aliases (tree origt)
+find_func_aliases (gimple origt)
{
- tree t = origt;
+ gimple t = origt;
VEC(ce_s, heap) *lhsc = NULL;
VEC(ce_s, heap) *rhsc = NULL;
struct constraint_expr *c;
- if (TREE_CODE (t) == RETURN_EXPR && TREE_OPERAND (t, 0))
- t = TREE_OPERAND (t, 0);
-
/* Now build constraints expressions. */
- if (TREE_CODE (t) == PHI_NODE)
+ if (gimple_code (t) == GIMPLE_PHI)
{
- gcc_assert (!AGGREGATE_TYPE_P (TREE_TYPE (PHI_RESULT (t))));
+ gcc_assert (!AGGREGATE_TYPE_P (TREE_TYPE (gimple_phi_result (t))));
/* Only care about pointers and structures containing
pointers. */
- if (could_have_pointers (PHI_RESULT (t)))
+ if (could_have_pointers (gimple_phi_result (t)))
{
- int i;
+ size_t i;
unsigned int j;
/* For a phi node, assign all the arguments to
the result. */
- get_constraint_for (PHI_RESULT (t), &lhsc);
- for (i = 0; i < PHI_NUM_ARGS (t); i++)
+ get_constraint_for (gimple_phi_result (t), &lhsc);
+ for (i = 0; i < gimple_phi_num_args (t); i++)
{
tree rhstype;
tree strippedrhs = PHI_ARG_DEF (t, i);
STRIP_NOPS (strippedrhs);
rhstype = TREE_TYPE (strippedrhs);
- get_constraint_for (PHI_ARG_DEF (t, i), &rhsc);
+ get_constraint_for (gimple_phi_arg_def (t, i), &rhsc);
for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
{
@@ -3709,130 +3662,151 @@ find_func_aliases (tree origt)
}
}
}
- /* In IPA mode, we need to generate constraints to pass call
- arguments through their calls. There are two cases, either a
- GIMPLE_MODIFY_STMT when we are returning a value, or just a plain
- CALL_EXPR when we are not.
-
- In non-ipa mode, we need to generate constraints for each
- pointer passed by address. */
- else if (((TREE_CODE (t) == GIMPLE_MODIFY_STMT
- && TREE_CODE (GIMPLE_STMT_OPERAND (t, 1)) == CALL_EXPR
- && !(call_expr_flags (GIMPLE_STMT_OPERAND (t, 1))
- & (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))
- || (TREE_CODE (t) == CALL_EXPR
- && !(call_expr_flags (t)
- & (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))))
+ else if (gimple_code (t) == GIMPLE_CALL)
{
- if (!in_ipa_mode)
- {
- if (TREE_CODE (t) == GIMPLE_MODIFY_STMT)
- {
- handle_rhs_call (GIMPLE_STMT_OPERAND (t, 1));
- if (POINTER_TYPE_P (TREE_TYPE (GIMPLE_STMT_OPERAND (t, 1))))
- handle_lhs_call (GIMPLE_STMT_OPERAND (t, 0));
- }
- else
- handle_rhs_call (t);
- }
- else
+ if (!(gimple_call_flags (t) & (ECF_MALLOC | ECF_MAY_BE_ALLOCA)))
{
- tree lhsop;
- tree rhsop;
- tree arg;
- call_expr_arg_iterator iter;
- varinfo_t fi;
- int i = 1;
- tree decl;
- if (TREE_CODE (t) == GIMPLE_MODIFY_STMT)
- {
- lhsop = GIMPLE_STMT_OPERAND (t, 0);
- rhsop = GIMPLE_STMT_OPERAND (t, 1);
- }
- else
- {
- lhsop = NULL;
- rhsop = t;
- }
- decl = get_callee_fndecl (rhsop);
+ /* In IPA mode, we need to generate constraints to pass call
+ arguments through their calls. There are two cases,
+ either a GIMPLE_CALL returning a value, or just a plain
+ GIMPLE_CALL when we are not.
- /* If we can directly resolve the function being called, do so.
- Otherwise, it must be some sort of indirect expression that
- we should still be able to handle. */
- if (decl)
+ In non-ipa mode, we need to generate constraints for each
+ pointer passed by address. */
+ if (!in_ipa_mode)
{
- fi = get_vi_for_tree (decl);
+ if (gimple_call_lhs (t))
+ {
+ handle_rhs_call (t);
+ if (POINTER_TYPE_P (gimple_call_return_type (t)))
+ handle_lhs_call (gimple_call_lhs (t));
+ }
+ else
+ handle_rhs_call (t);
}
else
{
- decl = CALL_EXPR_FN (rhsop);
- fi = get_vi_for_tree (decl);
- }
-
- /* Assign all the passed arguments to the appropriate incoming
- parameters of the function. */
+ tree lhsop;
+ varinfo_t fi;
+ int i = 1;
+ size_t j;
+ tree decl;
- FOR_EACH_CALL_EXPR_ARG (arg, iter, rhsop)
- {
- struct constraint_expr lhs ;
- struct constraint_expr *rhsp;
+ lhsop = gimple_call_lhs (t);
+ decl = gimple_call_fndecl (t);
- get_constraint_for (arg, &rhsc);
- if (TREE_CODE (decl) != FUNCTION_DECL)
+ /* If we can directly resolve the function being called, do so.
+ Otherwise, it must be some sort of indirect expression that
+ we should still be able to handle. */
+ if (decl)
+ fi = get_vi_for_tree (decl);
+ else
{
- lhs.type = DEREF;
- lhs.var = fi->id;
- lhs.offset = i;
+ decl = gimple_call_fn (t);
+ fi = get_vi_for_tree (decl);
}
- else
+
+ /* Assign all the passed arguments to the appropriate incoming
+ parameters of the function. */
+ for (j = 0; j < gimple_call_num_args (t); j++)
{
- lhs.type = SCALAR;
- lhs.var = first_vi_for_offset (fi, i)->id;
- lhs.offset = 0;
+ struct constraint_expr lhs ;
+ struct constraint_expr *rhsp;
+ tree arg = gimple_call_arg (t, j);
+
+ get_constraint_for (arg, &rhsc);
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ lhs.type = DEREF;
+ lhs.var = fi->id;
+ lhs.offset = i;
+ }
+ else
+ {
+ lhs.type = SCALAR;
+ lhs.var = first_vi_for_offset (fi, i)->id;
+ lhs.offset = 0;
+ }
+ while (VEC_length (ce_s, rhsc) != 0)
+ {
+ rhsp = VEC_last (ce_s, rhsc);
+ process_constraint (new_constraint (lhs, *rhsp));
+ VEC_pop (ce_s, rhsc);
+ }
+ i++;
}
- while (VEC_length (ce_s, rhsc) != 0)
+
+ /* If we are returning a value, assign it to the result. */
+ if (lhsop)
{
- rhsp = VEC_last (ce_s, rhsc);
- process_constraint (new_constraint (lhs, *rhsp));
- VEC_pop (ce_s, rhsc);
+ struct constraint_expr rhs;
+ struct constraint_expr *lhsp;
+ unsigned int j = 0;
+
+ get_constraint_for (lhsop, &lhsc);
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ rhs.type = DEREF;
+ rhs.var = fi->id;
+ rhs.offset = i;
+ }
+ else
+ {
+ rhs.type = SCALAR;
+ rhs.var = first_vi_for_offset (fi, i)->id;
+ rhs.offset = 0;
+ }
+ for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
+ process_constraint (new_constraint (*lhsp, rhs));
}
- i++;
}
+ }
+ else
+ {
+ /* Handle calls to malloc(). */
+ struct constraint_expr temp;
+ unsigned int j;
+ varinfo_t vi;
+ struct constraint_expr *lhsp;
+ tree heapvar = heapvar_lookup ((tree) t);
- /* If we are returning a value, assign it to the result. */
- if (lhsop)
+ /* XXX: In interprocedural mode, if we didn't have the
+ body, we would need to do *each pointer argument =
+ &ANYTHING added. */
+ if (heapvar == NULL)
{
- struct constraint_expr rhs;
- struct constraint_expr *lhsp;
- unsigned int j = 0;
-
- get_constraint_for (lhsop, &lhsc);
- if (TREE_CODE (decl) != FUNCTION_DECL)
- {
- rhs.type = DEREF;
- rhs.var = fi->id;
- rhs.offset = i;
- }
- else
- {
- rhs.type = SCALAR;
- rhs.var = first_vi_for_offset (fi, i)->id;
- rhs.offset = 0;
- }
- for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
- process_constraint (new_constraint (*lhsp, rhs));
+ heapvar = create_tmp_var_raw (ptr_type_node, "HEAP");
+ DECL_EXTERNAL (heapvar) = 1;
+ get_var_ann (heapvar)->is_heapvar = 1;
+ if (gimple_referenced_vars (cfun))
+ add_referenced_var (heapvar);
+ heapvar_insert ((tree) t, heapvar);
}
+
+ temp.var = create_variable_info_for (heapvar,
+ alias_get_name (heapvar));
+
+ vi = get_varinfo (temp.var);
+ vi->is_artificial_var = 1;
+ vi->is_heap_var = 1;
+ temp.type = ADDRESSOF;
+ temp.offset = 0;
+ VEC_safe_push (ce_s, heap, rhsc, &temp);
+
+ for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
+ process_constraint (new_constraint (*lhsp, temp));
}
}
- /* Otherwise, just a regular assignment statement. */
- else if (TREE_CODE (t) == GIMPLE_MODIFY_STMT)
+ else if (gimple_code (t) == GIMPLE_ASSIGN)
{
- tree lhsop = GIMPLE_STMT_OPERAND (t, 0);
- tree rhsop = GIMPLE_STMT_OPERAND (t, 1);
- int i;
+ /* Otherwise, just a regular assignment statement. */
+ tree lhsop = gimple_assign_lhs (t);
+ tree rhsop = (gimple_num_ops (t) == 2) ? gimple_assign_rhs1 (t) : NULL;
+ size_t i;
- if ((AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
- || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE)
+ if (rhsop
+ && (AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
+ || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE)
&& (AGGREGATE_TYPE_P (TREE_TYPE (rhsop))
|| TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE))
{
@@ -3841,16 +3815,15 @@ find_func_aliases (tree origt)
else
{
/* Only care about operations with pointers, structures
- containing pointers, dereferences, and call expressions. */
- if (could_have_pointers (lhsop)
- || TREE_CODE (rhsop) == CALL_EXPR)
+ containing pointers and dereferences. */
+ if (could_have_pointers (lhsop))
{
get_constraint_for (lhsop, &lhsc);
- switch (TREE_CODE_CLASS (TREE_CODE (rhsop)))
+ switch (TREE_CODE_CLASS (gimple_subcode (t)))
{
- /* RHS that consist of unary operations,
- exceptional types, or bare decls/constants, get
- handled directly by get_constraint_for. */
+ /* RHS that consist of unary operations, exceptional
+ types, or bare decls/constants, get handled
+ directly by get_constraint_for. */
case tcc_reference:
case tcc_declaration:
case tcc_constant:
@@ -3880,7 +3853,7 @@ find_func_aliases (tree origt)
PTR + CST, we can simply use PTR's
constraint because pointer arithmetic is
not allowed to go out of bounds. */
- if (handle_ptr_arith (lhsc, rhsop))
+ if (handle_ptr_arith (lhsc, t))
break;
}
/* FALLTHRU */
@@ -3890,9 +3863,9 @@ find_func_aliases (tree origt)
to process expressions other than simple operands
(e.g. INDIRECT_REF, ADDR_EXPR, CALL_EXPR). */
default:
- for (i = 0; i < TREE_OPERAND_LENGTH (rhsop); i++)
+ for (i = 1; i < gimple_num_ops (t); i++)
{
- tree op = TREE_OPERAND (rhsop, i);
+ tree op = gimple_op (t, i);
unsigned int j;
gcc_assert (VEC_length (ce_s, rhsc) == 0);
@@ -3912,11 +3885,11 @@ find_func_aliases (tree origt)
}
}
}
- else if (TREE_CODE (t) == CHANGE_DYNAMIC_TYPE_EXPR)
+ else if (gimple_code (t) == GIMPLE_CHANGE_DYNAMIC_TYPE)
{
unsigned int j;
- get_constraint_for (CHANGE_DYNAMIC_TYPE_LOCATION (t), &lhsc);
+ get_constraint_for (gimple_cdt_location (t), &lhsc);
for (j = 0; VEC_iterate (ce_s, lhsc, j, c); ++j)
get_varinfo (c->var)->no_tbaa_pruning = true;
}
@@ -5380,12 +5353,13 @@ compute_points_to_sets (struct alias_inf
/* Now walk all statements and derive aliases. */
FOR_EACH_BB (bb)
{
- block_stmt_iterator bsi;
- tree phi;
+ gimple_stmt_iterator gsi;
- for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+ for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
{
- if (is_gimple_reg (PHI_RESULT (phi)))
+ gimple phi = gsi_stmt (gsi);
+
+ if (is_gimple_reg (gimple_phi_result (phi)))
{
find_func_aliases (phi);
@@ -5397,9 +5371,9 @@ compute_points_to_sets (struct alias_inf
}
}
- for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
{
- tree stmt = bsi_stmt (bsi);
+ gimple stmt = gsi_stmt (gsi);
find_func_aliases (stmt);
@@ -5409,12 +5383,12 @@ compute_points_to_sets (struct alias_inf
sets. */
update_alias_info (stmt, ai);
- /* The information in CHANGE_DYNAMIC_TYPE_EXPR nodes has now
- been captured, and we can remove them. */
- if (TREE_CODE (stmt) == CHANGE_DYNAMIC_TYPE_EXPR)
- bsi_remove (&bsi, true);
+ /* The information in GIMPLE_CHANGE_DYNAMIC_TYPE statements
+ has now been captured, and we can remove them. */
+ if (gimple_code (stmt) == GIMPLE_CHANGE_DYNAMIC_TYPE)
+ gsi_remove (&gsi, true);
else
- bsi_next (&bsi);
+ gsi_next (&gsi);
}
}
@@ -5511,7 +5485,6 @@ delete_points_to_sets (void)
free_alloc_pool (constraint_pool);
have_alias_info = false;
}
-#endif
/* Return true if we should execute IPA PTA. */
static bool
@@ -5527,8 +5500,6 @@ gate_ipa_pta (void)
static unsigned int
ipa_pta_execute (void)
{
- /* FIXME tuples. */
-#if 0
struct cgraph_node *node;
struct scc_info *si;
@@ -5568,22 +5539,19 @@ ipa_pta_execute (void)
FOR_EACH_BB_FN (bb, func)
{
- block_stmt_iterator bsi;
- tree phi;
+ gimple_stmt_iterator gsi;
- for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+ for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi);
+ gsi_next (&gsi))
{
- if (is_gimple_reg (PHI_RESULT (phi)))
- {
- find_func_aliases (phi);
- }
- }
+ gimple phi = gsi_stmt (gsi);
- for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- {
- tree stmt = bsi_stmt (bsi);
- find_func_aliases (stmt);
+ if (is_gimple_reg (gimple_phi_result (phi)))
+ find_func_aliases (phi);
}
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ find_func_aliases (gsi_stmt (gsi));
}
current_function_decl = old_func_decl;
pop_cfun ();
@@ -5632,9 +5600,6 @@ ipa_pta_execute (void)
delete_alias_heapvars ();
delete_points_to_sets ();
return 0;
-#else
- gimple_unreachable ();
-#endif
}
struct tree_opt_pass pass_ipa_pta =
@@ -5654,8 +5619,6 @@ struct tree_opt_pass pass_ipa_pta =
0 /* letter */
};
-/* FIXME tuples. */
-#if 0
/* Initialize the heapvar for statement mapping. */
void
init_alias_heapvars (void)
@@ -5673,4 +5636,3 @@ delete_alias_heapvars (void)
}
#include "gt-tree-ssa-structalias.h"
-#endif
Index: tree-ssa-structalias.h
===================================================================
--- tree-ssa-structalias.h (revision 132202)
+++ tree-ssa-structalias.h (working copy)
@@ -63,8 +63,8 @@ struct alias_info
};
/* In tree-ssa-alias.c. */
-enum escape_type is_escape_site (tree);
-void update_mem_sym_stats_from_stmt (tree, tree, long, long);
+enum escape_type is_escape_site (gimple);
+void update_mem_sym_stats_from_stmt (tree, gimple, long, long);
/* In tree-ssa-structalias.c. */
extern void compute_points_to_sets (struct alias_info *);
Index: tree-cfg.c
===================================================================
--- tree-cfg.c (revision 132202)
+++ tree-cfg.c (working copy)
@@ -1330,7 +1330,7 @@ gimple_merge_blocks (basic_block a, basi
/* Remove all single-valued PHI nodes from block B of the form
V_i = PHI <V_j> by propagating V_j to all the uses of V_i. */
gsi = gsi_last_bb (a);
- for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
+ for (gsi = gsi_start (phis); !gsi_end_p (gsi); )
{
gimple phi = gsi_stmt (gsi);
tree def = gimple_phi_result (phi), use = gimple_phi_arg_def (phi, 0);
@@ -1357,7 +1357,7 @@ gimple_merge_blocks (basic_block a, basi
copy = gimple_build_assign (def, use);
gsi_insert_after (&gsi, copy, GSI_NEW_STMT);
SSA_NAME_DEF_STMT (def) = copy;
- remove_phi_node (phi, false);
+ remove_phi_node (&gsi, false);
}
else
{
@@ -1376,7 +1376,8 @@ gimple_merge_blocks (basic_block a, basi
}
else
replace_uses_by (def, use);
- remove_phi_node (phi, true);
+
+ remove_phi_node (&gsi, true);
}
}
@@ -2018,17 +2019,12 @@ struct tree_opt_pass pass_remove_useless
static void
remove_phi_nodes_and_edges_for_unreachable_block (basic_block bb)
{
- gimple phi;
+ gimple_stmt_iterator gsi;
/* Since this block is no longer reachable, we can just delete all
of its PHI nodes. */
- phi = gimple_seq_first (phi_nodes (bb));
- while (phi)
- {
- gimple next = gimple_next (phi);
- remove_phi_node (phi, true);
- phi = next;
- }
+ for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); )
+ remove_phi_node (&gsi, true);
set_phi_nodes (bb, NULL);
Index: passes.c
===================================================================
--- passes.c (revision 132202)
+++ passes.c (working copy)
@@ -582,9 +582,9 @@ init_optimization_passes (void)
NEXT_PASS (pass_all_optimizations);
{
struct tree_opt_pass **p = &pass_all_optimizations.sub;
+ NEXT_PASS (pass_create_structure_vars);
/* FIXME tuples. */
#if 0
- NEXT_PASS (pass_create_structure_vars);
NEXT_PASS (pass_return_slot);
NEXT_PASS (pass_rename_ssa_copies);