]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gimple.c (gimple_replace_lhs): Move to tree-ssa.c and rename.
authorAndrew MacLeod <amacleod@redhat.com>
Thu, 26 Sep 2013 13:23:31 +0000 (13:23 +0000)
committerAndrew Macleod <amacleod@gcc.gnu.org>
Thu, 26 Sep 2013 13:23:31 +0000 (13:23 +0000)
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

gcc/ChangeLog
gcc/Makefile.in
gcc/asan.c
gcc/gimple-builder.c [new file with mode: 0644]
gcc/gimple-builder.h [new file with mode: 0644]
gcc/gimple.c
gcc/gimple.h
gcc/tree-ssa-math-opts.c
gcc/tree-ssa-reassoc.c
gcc/tree-ssa.c
gcc/tree-ssa.h

index 7d5e2c5a25991830f4f3737f650da6359bcc60a3..eb83ea893232364f7611ea1846936a5f4a9f17f0 100644 (file)
@@ -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
index d10e48a147a372f919b56db41d5da1e7e257e9e1..f55f1d15a9ceba85e0897b84fb7eb2b6049466b0 100644 (file)
@@ -1220,6 +1220,7 @@ OBJS = \
        gcse.o \
        ggc-common.o \
        gimple.o \
+       gimple-builder.o \
        gimple-iterator.o \
        gimple-fold.o \
        gimple-low.o \
index 32f183775cdfd89a0624b175b770b3654084bbdb..2e1fb0e4082538ae0404a1fe511057b3c52c8b7c 100644 (file)
@@ -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 (file)
index 0000000..665c802
--- /dev/null
@@ -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 (file)
index 0000000..532c04e
--- /dev/null
@@ -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 */
index 59fcf4335a3ac6f82e198908e9e3f0fb04636793..6a182700cfd5eefe227f55176c78f053338f8b47 100644 (file)
@@ -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.
 
index 5f1280586d2614a448909c2a82e57d327c081b91..3047ab4b66780696ca4a168ee4cf86c7ff2e7815 100644 (file)
@@ -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 *),
index 54445beee7c5b60dbd4e7ba2b32f37affd0ab2ce..149e080ff194693adfcfdb15ea783bb3e5d62c47 100644 (file)
@@ -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++;
index 6dffe7e9a8186ff7cbaf5a33f3d8858a3288f325..b378f57e8f5fdccb00c895bb8d24f4f4555be77b 100644 (file)
@@ -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);
index 8146e1fed1d46ed1ba1bb01c612ecb86c3de597c..8c340ded1af18e41ab9ff818a1c7d53a229be9b9 100644 (file)
@@ -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
index 1808b1c447a5affbebd4d7bc6a7b9f00a4935312..7ffb332252bf4813247641b7e5f3bbeea9ee36d0 100644 (file)
@@ -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 *);