diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2013-09-26 13:23:31 +0000 |
---|---|---|
committer | Andrew Macleod <amacleod@gcc.gnu.org> | 2013-09-26 13:23:31 +0000 |
commit | ff2a63a749c386637ef085f7bc3102a8d8d2aab3 (patch) | |
tree | 0bdac19cc1c197b2e326293eb4c1344554b4e7b5 /gcc/tree-ssa.c | |
parent | a2544177b989c29fe893e55d422c8d9e6f27c6b3 (diff) | |
download | gcc-ff2a63a749c386637ef085f7bc3102a8d8d2aab3.zip gcc-ff2a63a749c386637ef085f7bc3102a8d8d2aab3.tar.gz gcc-ff2a63a749c386637ef085f7bc3102a8d8d2aab3.tar.bz2 |
gimple.c (gimple_replace_lhs): Move to tree-ssa.c and rename.
2013-09-26 Andrew MacLeod <amacleod@redhat.com>
* gimple.c (gimple_replace_lhs): Move to tree-ssa.c and rename.
(struct count_ptr_d, count_ptr_derefs, count_uses_and_derefs): Move to
tree-ssa.c
(create_gimple_tmp): Delete.
(get_expr_type, build_assign, build_type_cast): Move to...
* gimple-builder.c: New File.
(get_expr_type): Relocate from gimple.c.
(build_assign, build_type_cast): Change to only create ssanames.
* gimple.h: Move prototypes to...
* gimple-builder.h: New File. Here.
* tree-ssa.h: And here.
* tree-ssa.c (struct count_ptr_d, count_ptr_derefs,
count_uses_and_derefs): Relocate from gimple.c.
(gimple_replace_ssa_lhs): Renamed gimple_replace_ssa from gimple.c
* tree-ssa-reassoc.c (repropagate_negates): Use gimple_replace_ssa_lhs.
* tree-ssa-math-opts (execute_cse_reciprocals): Use
gimple_replace_ssa_lhs.
* asan.c: Include gimple-builder.h.
* Makefile.in: Add gimple-builder.o.
From-SVN: r202945
Diffstat (limited to 'gcc/tree-ssa.c')
-rw-r--r-- | gcc/tree-ssa.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 8146e1f..8c340de 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -231,6 +231,135 @@ flush_pending_stmts (edge e) redirect_edge_var_map_clear (e); } + +/* Data structure used to count the number of dereferences to PTR + inside an expression. */ +struct count_ptr_d +{ + tree ptr; + unsigned num_stores; + unsigned num_loads; +}; + + +/* Helper for count_uses_and_derefs. Called by walk_tree to look for + (ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA. */ + +static tree +count_ptr_derefs (tree *tp, int *walk_subtrees, void *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 + the address of 'fld' as 'ptr + offsetof(fld)'. */ + if (TREE_CODE (*tp) == ADDR_EXPR) + { + *walk_subtrees = 0; + return NULL_TREE; + } + + if (TREE_CODE (*tp) == MEM_REF && TREE_OPERAND (*tp, 0) == count_p->ptr) + { + if (wi_p->is_lhs) + count_p->num_stores++; + else + count_p->num_loads++; + } + + return NULL_TREE; +} + + +/* Count the number of direct and indirect uses for pointer PTR in + statement STMT. The number of direct uses is stored in + *NUM_USES_P. Indirect references are counted separately depending + on whether they are store or load operations. The counts are + stored in *NUM_STORES_P and *NUM_LOADS_P. */ + +void +count_uses_and_derefs (tree ptr, gimple stmt, unsigned *num_uses_p, + unsigned *num_loads_p, unsigned *num_stores_p) +{ + ssa_op_iter i; + tree use; + + *num_uses_p = 0; + *num_loads_p = 0; + *num_stores_p = 0; + + /* Find out the total number of uses of PTR in STMT. */ + FOR_EACH_SSA_TREE_OPERAND (use, stmt, i, SSA_OP_USE) + if (use == ptr) + (*num_uses_p)++; + + /* Now count the number of indirect references to PTR. This is + truly awful, but we don't have much choice. There are no parent + pointers inside INDIRECT_REFs, so an expression like + '*x_1 = foo (x_1, *x_1)' needs to be traversed piece by piece to + 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 (is_gimple_assign (stmt) + || gimple_code (stmt) == GIMPLE_RETURN + || gimple_code (stmt) == GIMPLE_ASM + || is_gimple_call (stmt)) + { + struct walk_stmt_info wi; + struct count_ptr_d count; + + count.ptr = ptr; + count.num_stores = 0; + count.num_loads = 0; + + memset (&wi, 0, sizeof (wi)); + wi.info = &count; + walk_gimple_op (stmt, count_ptr_derefs, &wi); + + *num_stores_p = count.num_stores; + *num_loads_p = count.num_loads; + } + + gcc_assert (*num_uses_p >= *num_loads_p + *num_stores_p); +} + + +/* Replace the LHS of STMT, an assignment, either a GIMPLE_ASSIGN or a + GIMPLE_CALL, with NLHS, in preparation for modifying the RHS to an + expression with a different value. + + This will update any annotations (say debug bind stmts) referring + to the original LHS, so that they use the RHS instead. This is + done even if NLHS and LHS are the same, for it is understood that + the RHS will be modified afterwards, and NLHS will not be assigned + an equivalent value. + + Adjusting any non-annotation uses of the LHS, if needed, is a + responsibility of the caller. + + The effect of this call should be pretty much the same as that of + inserting a copy of STMT before STMT, and then removing the + original stmt, at which time gsi_remove() would have update + annotations, but using this function saves all the inserting, + copying and removing. */ + +void +gimple_replace_ssa_lhs (gimple stmt, tree nlhs) +{ + if (MAY_HAVE_DEBUG_STMTS) + { + tree lhs = gimple_get_lhs (stmt); + + gcc_assert (SSA_NAME_DEF_STMT (lhs) == stmt); + + insert_debug_temp_for_var_def (NULL, lhs); + } + + gimple_set_lhs (stmt, nlhs); +} + + /* Given a tree for an expression for which we might want to emit locations or values in debug information (generally a variable, but we might deal with other kinds of trees in the future), return the |