diff mbox

gimple build interface

Message ID 52407780.4080005@redhat.com
State New
Headers show

Commit Message

Andrew MacLeod Sept. 23, 2013, 5:16 p.m. UTC
On 09/23/2013 01:05 PM, David Malcolm wrote:
> On Mon, 2013-09-23 at 12:21 -0400, Andrew MacLeod wrote:
>> On 09/20/2013 04:08 AM, Richard Biener wrote:
>>> On Thu, Sep 19, 2013 at 6:56 PM, Andrew MacLeod <amacleod@redhat.com> wrote:
>>>> On 09/19/2013 09:24 AM, Andrew MacLeod wrote:
>>>>> I think this is of most use to ssa passes that need to construct code
>>>>> snippets, so I propose we make this ssa specific and put it in tree-ssa.c
>>>>> (renaming it ssa_build_assign),  *OR* we could leave it general purpose and
>>>>> put it in its own set of files, gimple-ssa-build.[ch] or something that
>>>>> crosses the border between the two representations.
>>>>>
>>>>> I'd also suggest that the final optional parameter be changed to tree *lhs
>>>>> = NULL_TREE,  which would allow the caller to specify the LHS if they want,
>>>>> otherwise make_ssa_name would be called. If we want to leave it supporting
>>>>> both gimple and ssa, then anyone from gimple land could pass in a gimple LHS
>>>>> variable thus avoiding the call to make_ssa_name....
>>>>>
>>>>> Thoughts?
>>>>> Andrew
>>>> Anyway, here is a patch which does that and a bit more.  I didn't rename
>>>> build_assign() to ssa_build_assign()..   even though those are the only kind
>>>> actually created right now.   we can leave that for the day someone actually
>>>> decides to flush this interface out, and maybe we'll want to pass in
>>>> gimple_tmps and call them from front ends or other places... then it would
>>>> have to be renamed again. So I just left it as is for the moment, but that
>>>> could be changed.
>>>>
>>>> I also moved gimple_replace_lhs() to tree-ssa.c and renamed it
>>>> ssa_replace_lhs(). It calls insert_debug_temp_for_var_def() from tree-ssa.c
>>>> and that only works with the immediate use operands.. so that is an SSA
>>>> specific routine, which makes this one SSA specific as well.
>>>>
>>>> Those 2 changes allow tree-ssa.h to no longer be included, it is replaced
>>>> with tree-flow.h.   Some preliminary work to enable removing immediate use
>>>> routines out of tree-flow.h include:
>>>>
>>>> struct count_ptr_d, count_ptr_derefs(), count_uses_and_derefs() also get
>>>> moved to tree-ssa.c since those are also require the immediate use
>>>> mechanism, and thus is also SSA dependent.
>>>>
>>>> This bootstraps on x86_64-unknown-linux-gnu and has no new regressions.
>>>> OK?
>>> Can you move the builders to asan.c please?  From a quick glance it seems
>>> to have various issues so it shouldn't be used (I wonder who approved them
>>> in the end ... maybe it was even me).
>>>
>>> ssa_replace_lhs sounds odd (a 'SSA' has a lhs?), but maybe it's just me.
>>> I'd have chosen gimple_replace_ssa_lhs?
>> That sounds better.  done.
>>
>> And I also think a seperate file for those builders is probably best...
>> here's a patch with those changes.. New files called
>> gimple-builder.[ch]...    Then diego can eventually do whatever his
>> grand vision for them is.  I minimized the includes.
>>
>> bootstraps and rerunning tests.  OK?
> Did you forget to attach the patch?
>
Of course not!  :-P

Oh how I hate mondays.

Andrew

Comments

Richard Biener Sept. 24, 2013, 9:50 a.m. UTC | #1
On Mon, Sep 23, 2013 at 7:16 PM, Andrew MacLeod <amacleod@redhat.com> wrote:
> On 09/23/2013 01:05 PM, David Malcolm wrote:
>>
>> On Mon, 2013-09-23 at 12:21 -0400, Andrew MacLeod wrote:
>>>
>>> On 09/20/2013 04:08 AM, Richard Biener wrote:
>>>>
>>>> On Thu, Sep 19, 2013 at 6:56 PM, Andrew MacLeod <amacleod@redhat.com>
>>>> wrote:
>>>>>
>>>>> On 09/19/2013 09:24 AM, Andrew MacLeod wrote:
>>>>>>
>>>>>> I think this is of most use to ssa passes that need to construct code
>>>>>> snippets, so I propose we make this ssa specific and put it in
>>>>>> tree-ssa.c
>>>>>> (renaming it ssa_build_assign),  *OR* we could leave it general
>>>>>> purpose and
>>>>>> put it in its own set of files, gimple-ssa-build.[ch] or something
>>>>>> that
>>>>>> crosses the border between the two representations.
>>>>>>
>>>>>> I'd also suggest that the final optional parameter be changed to tree
>>>>>> *lhs
>>>>>> = NULL_TREE,  which would allow the caller to specify the LHS if they
>>>>>> want,
>>>>>> otherwise make_ssa_name would be called. If we want to leave it
>>>>>> supporting
>>>>>> both gimple and ssa, then anyone from gimple land could pass in a
>>>>>> gimple LHS
>>>>>> variable thus avoiding the call to make_ssa_name....
>>>>>>
>>>>>> Thoughts?
>>>>>> Andrew
>>>>>
>>>>> Anyway, here is a patch which does that and a bit more.  I didn't
>>>>> rename
>>>>> build_assign() to ssa_build_assign()..   even though those are the only
>>>>> kind
>>>>> actually created right now.   we can leave that for the day someone
>>>>> actually
>>>>> decides to flush this interface out, and maybe we'll want to pass in
>>>>> gimple_tmps and call them from front ends or other places... then it
>>>>> would
>>>>> have to be renamed again. So I just left it as is for the moment, but
>>>>> that
>>>>> could be changed.
>>>>>
>>>>> I also moved gimple_replace_lhs() to tree-ssa.c and renamed it
>>>>> ssa_replace_lhs(). It calls insert_debug_temp_for_var_def() from
>>>>> tree-ssa.c
>>>>> and that only works with the immediate use operands.. so that is an SSA
>>>>> specific routine, which makes this one SSA specific as well.
>>>>>
>>>>> Those 2 changes allow tree-ssa.h to no longer be included, it is
>>>>> replaced
>>>>> with tree-flow.h.   Some preliminary work to enable removing immediate
>>>>> use
>>>>> routines out of tree-flow.h include:
>>>>>
>>>>> struct count_ptr_d, count_ptr_derefs(), count_uses_and_derefs() also
>>>>> get
>>>>> moved to tree-ssa.c since those are also require the immediate use
>>>>> mechanism, and thus is also SSA dependent.
>>>>>
>>>>> This bootstraps on x86_64-unknown-linux-gnu and has no new regressions.
>>>>> OK?
>>>>
>>>> Can you move the builders to asan.c please?  From a quick glance it
>>>> seems
>>>> to have various issues so it shouldn't be used (I wonder who approved
>>>> them
>>>> in the end ... maybe it was even me).
>>>>
>>>> ssa_replace_lhs sounds odd (a 'SSA' has a lhs?), but maybe it's just me.
>>>> I'd have chosen gimple_replace_ssa_lhs?
>>>
>>> That sounds better.  done.
>>>
>>> And I also think a seperate file for those builders is probably best...
>>> here's a patch with those changes.. New files called
>>> gimple-builder.[ch]...    Then diego can eventually do whatever his
>>> grand vision for them is.  I minimized the includes.
>>>
>>> bootstraps and rerunning tests.  OK?
>>
>> Did you forget to attach the patch?
>>
> Of course not!  :-P
>
> Oh how I hate mondays.

Old patch attached?

Richard.

> Andrew
Andrew MacLeod Sept. 24, 2013, 11:31 a.m. UTC | #2
On 09/24/2013 05:50 AM, Richard Biener wrote:
>
>>> Did you forget to attach the patch?
>>>
>> Of course not!  :-P
>>
>> Oh how I hate mondays.
> Old patch attached?
>
> Richard.
>
>
Errr..... no.  that last one has gimple-builder.[ch] and the 
ssa_replace_lhs renamed to gimple_replace_ssa_lhs..

I'll also wait for Tromey's auto dependency patch, and then just add the 
.o to the list to be built in Makefile.in.

Andrew
Richard Biener Sept. 24, 2013, 11:35 a.m. UTC | #3
On Tue, Sep 24, 2013 at 1:31 PM, Andrew MacLeod <amacleod@redhat.com> wrote:
> On 09/24/2013 05:50 AM, Richard Biener wrote:
>>
>>
>>>> Did you forget to attach the patch?
>>>>
>>> Of course not!  :-P
>>>
>>> Oh how I hate mondays.
>>
>> Old patch attached?
>>
>> Richard.
>>
>>
> Errr..... no.  that last one has gimple-builder.[ch] and the ssa_replace_lhs
> renamed to gimple_replace_ssa_lhs..
>
> I'll also wait for Tromey's auto dependency patch, and then just add the .o
> to the list to be built in Makefile.in.

Ah, stupid firefox saving as gimp(1).patch.

This looks ok.
Thanks,
Richard.

> Andrew
diff mbox

Patch


	* 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.
	* Makefile.in: Add gimple-builder.o and dependencies.


Index: gimple.c
===================================================================
*** gimple.c	(revision 202720)
--- gimple.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 30,36 ****
  #include "basic-block.h"
  #include "gimple.h"
  #include "diagnostic.h"
! #include "tree-ssa.h"
  #include "value-prof.h"
  #include "flags.h"
  #include "alias.h"
--- 30,36 ----
  #include "basic-block.h"
  #include "gimple.h"
  #include "diagnostic.h"
! #include "tree-flow.h"
  #include "value-prof.h"
  #include "flags.h"
  #include "alias.h"
*************** gimple_set_lhs (gimple stmt, tree lhs)
*** 2156,2194 ****
      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
--- 2156,2161 ----
*************** gimple_get_alias_set (tree t)
*** 3739,3834 ****
  }
  
  
- /* 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.  */
  
--- 3706,3711 ----
*************** gimple_asm_clobbers_memory_p (const_gimp
*** 4225,4330 ****
  }
  
  
- /* 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.
  
--- 4102,4107 ----
Index: gimple-builder.c
===================================================================
*** gimple-builder.c	(revision 0)
--- gimple-builder.c	(revision 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);
+ }
+ 
+ 
+ 
Index: gimple.h
===================================================================
*** gimple.h	(revision 202720)
--- gimple.h	(working copy)
*************** union GTY ((desc ("gimple_statement_stru
*** 730,748 ****
    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_[];
--- 730,735 ----
*************** extern void free_gimple_type_tables (voi
*** 909,916 ****
  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 *),
--- 896,901 ----
Index: gimple-builder.h
===================================================================
*** gimple-builder.h	(revision 0)
--- gimple-builder.h	(revision 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: tree-ssa.h
===================================================================
*** tree-ssa.h	(revision 202720)
--- tree-ssa.h	(working copy)
*************** extern edge_var_map_vector *redirect_edg
*** 42,47 ****
--- 42,50 ----
  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 *);
Index: tree-ssa.c
===================================================================
*** tree-ssa.c	(revision 202720)
--- tree-ssa.c	(working copy)
*************** flush_pending_stmts (edge e)
*** 231,236 ****
--- 231,365 ----
    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: tree-ssa-reassoc.c
===================================================================
*** tree-ssa-reassoc.c	(revision 202720)
--- tree-ssa-reassoc.c	(working copy)
*************** repropagate_negates (void)
*** 3682,3688 ****
  	      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_assign_set_rhs_with_ops (&gsi, PLUS_EXPR, a, rhs2);
  	      update_stmt (gsi_stmt (gsi));
  	      gsi2 = gsi_for_stmt (user);
--- 3682,3688 ----
  	      tree a = gimple_assign_rhs1 (feed);
  	      tree rhs2 = gimple_assign_rhs2 (user);
  	      gimple_stmt_iterator gsi = gsi_for_stmt (feed), gsi2;
! 	      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: tree-ssa-math-opts.c
===================================================================
*** tree-ssa-math-opts.c	(revision 202720)
--- tree-ssa-math-opts.c	(working copy)
*************** execute_cse_reciprocals (void)
*** 608,614 ****
  		  if (fail)
  		    continue;
  
! 		  gimple_replace_lhs (stmt1, arg1);
  		  gimple_call_set_fndecl (stmt1, fndecl);
  		  update_stmt (stmt1);
  		  reciprocal_stats.rfuncs_inserted++;
--- 608,614 ----
  		  if (fail)
  		    continue;
  
! 		  gimple_replace_ssa_lhs (stmt1, arg1);
  		  gimple_call_set_fndecl (stmt1, fndecl);
  		  update_stmt (stmt1);
  		  reciprocal_stats.rfuncs_inserted++;
Index: Makefile.in
===================================================================
*** Makefile.in	(revision 202720)
--- Makefile.in	(working copy)
*************** OBJS = \
*** 1248,1253 ****
--- 1248,1254 ----
  	gcse.o \
  	ggc-common.o \
  	gimple.o \
+ 	gimple-builder.o \
  	gimple-iterator.o \
  	gimple-fold.o \
  	gimple-low.o \
*************** gimple.o : gimple.c $(CONFIG_H) $(SYSTEM
*** 2678,2683 ****
--- 2679,2686 ----
     $(GGC_H) $(GIMPLE_H) $(DIAGNOSTIC_CORE_H) $(DIAGNOSTIC_H) gt-gimple.h \
     $(TREE_SSA_H) value-prof.h $(FLAGS_H) $(DEMANGLE_H) \
     $(TARGET_H) $(ALIAS_H)
+ gimple-builder.o : gimple-builder.c gimple-builder.h $(CONFIG_H) $(SYSTEM_H) \
+    coretypes.h $(TREE_H) $(GIMPLE_H) $(TREE_SSA_H)
  gimple-pretty-print.o : gimple-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \
     coretypes.h $(DUMPFILE_H) \
     $(TREE_H) $(DIAGNOSTIC_H) $(HASHTAB_H) $(TREE_SSA_H) \