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 | |
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')
-rw-r--r-- | gcc/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/Makefile.in | 1 | ||||
-rw-r--r-- | gcc/asan.c | 1 | ||||
-rw-r--r-- | gcc/gimple-builder.c | 118 | ||||
-rw-r--r-- | gcc/gimple-builder.h | 34 | ||||
-rw-r--r-- | gcc/gimple.c | 225 | ||||
-rw-r--r-- | gcc/gimple.h | 15 | ||||
-rw-r--r-- | gcc/tree-ssa-math-opts.c | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-reassoc.c | 2 | ||||
-rw-r--r-- | gcc/tree-ssa.c | 129 | ||||
-rw-r--r-- | gcc/tree-ssa.h | 3 |
11 files changed, 311 insertions, 241 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7d5e2c5..eb83ea8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +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. + 2013-09-26 Richard Biener <rguenther@suse.de> * tree-ssa-live.c (var_map_base_init): Handle SSA names with diff --git a/gcc/Makefile.in b/gcc/Makefile.in index d10e48a..f55f1d1 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1220,6 +1220,7 @@ OBJS = \ gcse.o \ ggc-common.o \ gimple.o \ + gimple-builder.o \ gimple-iterator.o \ gimple-fold.o \ gimple-low.o \ @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see #include "hash-table.h" #include "alloc-pool.h" #include "cfgloop.h" +#include "gimple-builder.h" /* AddressSanitizer finds out-of-bounds and use-after-free bugs with <2x slowdown on average. diff --git a/gcc/gimple-builder.c b/gcc/gimple-builder.c new file mode 100644 index 0000000..665c802 --- /dev/null +++ b/gcc/gimple-builder.c @@ -0,0 +1,118 @@ +/* Functions for high level gimple building routines. + Copyright (C) 2013 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "gimple.h" +#include "tree-ssa.h" + + +/* Return the expression type to use based on the CODE and type of + the given operand OP. If the expression CODE is a comparison, + the returned type is boolean_type_node. Otherwise, it returns + the type of OP. */ + +static tree +get_expr_type (enum tree_code code, tree op) +{ + return (TREE_CODE_CLASS (code) == tcc_comparison) + ? boolean_type_node + : TREE_TYPE (op); +} + + +/* Build a new gimple assignment. The LHS of the assignment is a new + temporary whose type matches the given expression. MODE indicates + whether the LHS should be an SSA or a normal temporary. CODE is + the expression code for the RHS. OP1 is the first operand and VAL + is an integer value to be used as the second operand. */ + +gimple +build_assign (enum tree_code code, tree op1, int val, tree lhs) +{ + tree op2 = build_int_cst (TREE_TYPE (op1), val); + if (lhs == NULL_TREE) + lhs = make_ssa_name (get_expr_type (code, op1), NULL); + return gimple_build_assign_with_ops (code, lhs, op1, op2); +} + +gimple +build_assign (enum tree_code code, gimple g, int val, tree lhs ) +{ + return build_assign (code, gimple_assign_lhs (g), val, lhs); +} + + +/* Build and return a new GIMPLE assignment. The new assignment will + have the opcode CODE and operands OP1 and OP2. The type of the + expression on the RHS is inferred to be the type of OP1. + + The LHS of the statement will be an SSA name or a GIMPLE temporary + in normal form depending on the type of builder invoking this + function. */ + +gimple +build_assign (enum tree_code code, tree op1, tree op2, tree lhs) +{ + if (lhs == NULL_TREE) + lhs = make_ssa_name (get_expr_type (code, op1), NULL); + return gimple_build_assign_with_ops (code, lhs, op1, op2); +} + +gimple +build_assign (enum tree_code code, gimple op1, tree op2, tree lhs) +{ + return build_assign (code, gimple_assign_lhs (op1), op2, lhs); +} + +gimple +build_assign (enum tree_code code, tree op1, gimple op2, tree lhs) +{ + return build_assign (code, op1, gimple_assign_lhs (op2), lhs); +} + +gimple +build_assign (enum tree_code code, gimple op1, gimple op2, tree lhs) +{ + return build_assign (code, gimple_assign_lhs (op1), gimple_assign_lhs (op2), + lhs); +} + + +/* Create and return a type cast assignment. This creates a NOP_EXPR + that converts OP to TO_TYPE. */ + +gimple +build_type_cast (tree to_type, tree op, tree lhs) +{ + if (lhs == NULL_TREE) + lhs = make_ssa_name (to_type, NULL); + return gimple_build_assign_with_ops (NOP_EXPR, lhs, op, NULL_TREE); +} + +gimple +build_type_cast (tree to_type, gimple op, tree lhs) +{ + return build_type_cast (to_type, gimple_assign_lhs (op), lhs); +} + + + diff --git a/gcc/gimple-builder.h b/gcc/gimple-builder.h new file mode 100644 index 0000000..532c04e --- /dev/null +++ b/gcc/gimple-builder.h @@ -0,0 +1,34 @@ +/* Header file for high level statement building routines. + Copyright (C) 2013 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + + +#ifndef GCC_GIMPLE_BUILDER_H +#define GCC_GIMPLE_BUILDER_H + +tree create_gimple_tmp (tree, tree lhs = NULL_TREE); +gimple build_assign (enum tree_code, tree, int, tree lhs = NULL_TREE); +gimple build_assign (enum tree_code, gimple, int, tree lhs = NULL_TREE); +gimple build_assign (enum tree_code, tree, tree, tree lhs = NULL_TREE); +gimple build_assign (enum tree_code, gimple, tree, tree lhs = NULL_TREE); +gimple build_assign (enum tree_code, tree, gimple, tree lhs = NULL_TREE); +gimple build_assign (enum tree_code, gimple, gimple, tree lhs = NULL_TREE); +gimple build_type_cast (tree, tree, tree lhs = NULL_TREE); +gimple build_type_cast (tree, gimple, tree lhs = NULL_TREE); + +#endif /* GCC_GIMPLE_BUILDER_H */ diff --git a/gcc/gimple.c b/gcc/gimple.c index 59fcf43..6a18270 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -30,7 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple.h" #include "diagnostic.h" -#include "tree-ssa.h" +#include "tree-flow.h" #include "value-prof.h" #include "flags.h" #include "alias.h" @@ -2156,39 +2156,6 @@ gimple_set_lhs (gimple stmt, tree lhs) gcc_unreachable(); } -/* 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_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); -} /* Return a deep copy of statement STMT. All the operands from STMT are reallocated and copied using unshare_expr. The DEF, USE, VDEF @@ -3739,96 +3706,6 @@ gimple_get_alias_set (tree t) } -/* 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); -} - /* From a tree operand OP return the base of a load or store operation or NULL_TREE if OP is not a load or a store. */ @@ -4225,106 +4102,6 @@ gimple_asm_clobbers_memory_p (const_gimple stmt) } -/* Create and return an unnamed temporary. MODE indicates whether - this should be an SSA or NORMAL temporary. TYPE is the type to use - for the new temporary. */ - -tree -create_gimple_tmp (tree type, enum ssa_mode mode) -{ - return (mode == M_SSA) - ? make_ssa_name (type, NULL) - : create_tmp_var (type, NULL); -} - - -/* Return the expression type to use based on the CODE and type of - the given operand OP. If the expression CODE is a comparison, - the returned type is boolean_type_node. Otherwise, it returns - the type of OP. */ - -static tree -get_expr_type (enum tree_code code, tree op) -{ - return (TREE_CODE_CLASS (code) == tcc_comparison) - ? boolean_type_node - : TREE_TYPE (op); -} - - -/* Build a new gimple assignment. The LHS of the assignment is a new - temporary whose type matches the given expression. MODE indicates - whether the LHS should be an SSA or a normal temporary. CODE is - the expression code for the RHS. OP1 is the first operand and VAL - is an integer value to be used as the second operand. */ - -gimple -build_assign (enum tree_code code, tree op1, int val, enum ssa_mode mode) -{ - tree op2 = build_int_cst (TREE_TYPE (op1), val); - tree lhs = create_gimple_tmp (get_expr_type (code, op1), mode); - return gimple_build_assign_with_ops (code, lhs, op1, op2); -} - -gimple -build_assign (enum tree_code code, gimple g, int val, enum ssa_mode mode) -{ - return build_assign (code, gimple_assign_lhs (g), val, mode); -} - - -/* Build and return a new GIMPLE assignment. The new assignment will - have the opcode CODE and operands OP1 and OP2. The type of the - expression on the RHS is inferred to be the type of OP1. - - The LHS of the statement will be an SSA name or a GIMPLE temporary - in normal form depending on the type of builder invoking this - function. */ - -gimple -build_assign (enum tree_code code, tree op1, tree op2, enum ssa_mode mode) -{ - tree lhs = create_gimple_tmp (get_expr_type (code, op1), mode); - return gimple_build_assign_with_ops (code, lhs, op1, op2); -} - -gimple -build_assign (enum tree_code code, gimple op1, tree op2, enum ssa_mode mode) -{ - return build_assign (code, gimple_assign_lhs (op1), op2, mode); -} - -gimple -build_assign (enum tree_code code, tree op1, gimple op2, enum ssa_mode mode) -{ - return build_assign (code, op1, gimple_assign_lhs (op2), mode); -} - -gimple -build_assign (enum tree_code code, gimple op1, gimple op2, enum ssa_mode mode) -{ - return build_assign (code, gimple_assign_lhs (op1), gimple_assign_lhs (op2), - mode); -} - - -/* Create and return a type cast assignment. This creates a NOP_EXPR - that converts OP to TO_TYPE. */ - -gimple -build_type_cast (tree to_type, tree op, enum ssa_mode mode) -{ - tree lhs = create_gimple_tmp (to_type, mode); - return gimple_build_assign_with_ops (NOP_EXPR, lhs, op, NULL_TREE); -} - -gimple -build_type_cast (tree to_type, gimple op, enum ssa_mode mode) -{ - return build_type_cast (to_type, gimple_assign_lhs (op), mode); -} - - /* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a useless type conversion, otherwise return false. diff --git a/gcc/gimple.h b/gcc/gimple.h index 5f12805..3047ab4 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -730,19 +730,6 @@ union GTY ((desc ("gimple_statement_structure (&%h)"), struct gimple_statement_transaction GTY((tag ("GSS_TRANSACTION"))) gimple_transaction; }; -/* In gimple.c. */ - -/* Helper functions to build GIMPLE statements. */ -tree create_gimple_tmp (tree, enum ssa_mode = M_SSA); -gimple build_assign (enum tree_code, tree, int, enum ssa_mode = M_SSA); -gimple build_assign (enum tree_code, gimple, int, enum ssa_mode = M_SSA); -gimple build_assign (enum tree_code, tree, tree, enum ssa_mode = M_SSA); -gimple build_assign (enum tree_code, gimple, tree, enum ssa_mode = M_SSA); -gimple build_assign (enum tree_code, tree, gimple, enum ssa_mode = M_SSA); -gimple build_assign (enum tree_code, gimple, gimple, enum ssa_mode = M_SSA); -gimple build_type_cast (tree, tree, enum ssa_mode = M_SSA); -gimple build_type_cast (tree, gimple, enum ssa_mode = M_SSA); - /* Offset in bytes to the location of the operand vector. Zero if there is no operand vector for this tuple structure. */ extern size_t const gimple_ops_offset_[]; @@ -909,8 +896,6 @@ extern void free_gimple_type_tables (void); extern tree gimple_unsigned_type (tree); extern tree gimple_signed_type (tree); extern alias_set_type gimple_get_alias_set (tree); -extern void count_uses_and_derefs (tree, gimple, unsigned *, unsigned *, - unsigned *); extern bool walk_stmt_load_store_addr_ops (gimple, void *, bool (*)(gimple, tree, void *), bool (*)(gimple, tree, void *), diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index 54445be..149e080 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -608,7 +608,7 @@ execute_cse_reciprocals (void) if (fail) continue; - gimple_replace_lhs (stmt1, arg1); + gimple_replace_ssa_lhs (stmt1, arg1); gimple_call_set_fndecl (stmt1, fndecl); update_stmt (stmt1); reciprocal_stats.rfuncs_inserted++; diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index 6dffe7e..b378f57 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -3682,7 +3682,7 @@ repropagate_negates (void) tree a = gimple_assign_rhs1 (feed); tree rhs2 = gimple_assign_rhs2 (user); gimple_stmt_iterator gsi = gsi_for_stmt (feed), gsi2; - gimple_replace_lhs (feed, negate); + gimple_replace_ssa_lhs (feed, negate); gimple_assign_set_rhs_with_ops (&gsi, PLUS_EXPR, a, rhs2); update_stmt (gsi_stmt (gsi)); gsi2 = gsi_for_stmt (user); 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 diff --git a/gcc/tree-ssa.h b/gcc/tree-ssa.h index 1808b1c..7ffb332 100644 --- a/gcc/tree-ssa.h +++ b/gcc/tree-ssa.h @@ -42,6 +42,9 @@ extern edge_var_map_vector *redirect_edge_var_map_vector (edge); extern void redirect_edge_var_map_destroy (void); extern edge ssa_redirect_edge (edge, basic_block); extern void flush_pending_stmts (edge); +extern void count_uses_and_derefs (tree, gimple, unsigned *, unsigned *, + unsigned *); +extern void gimple_replace_ssa_lhs (gimple, tree); extern tree target_for_debug_bind (tree); extern void insert_debug_temp_for_var_def (gimple_stmt_iterator *, tree); extern void insert_debug_temps_for_defs (gimple_stmt_iterator *); |