diff mbox

gimple build interface

Message ID 523B2CC4.6050007@redhat.com
State New
Headers show

Commit Message

Andrew MacLeod Sept. 19, 2013, 4:56 p.m. UTC
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?

Andrew

Comments

Richard Biener Sept. 20, 2013, 8:08 a.m. UTC | #1
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?

Anyway, it looks ok to me modulo the pre-existing broken builder stuff
(whether it's in tree-ssa.h or gimple.h doesn't really matter for that fact).

Thanks,
Richard.

> Andrew
Jakub Jelinek Sept. 20, 2013, 8:13 a.m. UTC | #2
On Fri, Sep 20, 2013 at 10:08:20AM +0200, Richard Biener wrote:
> 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).

Moving them to asan.c looks wrong.  If we don't want them, the change
that introduced them should be just reverted.  There is nothing special
in asan.c that would require using different APIs than everything else.

	Jakub
Diego Novillo Sept. 20, 2013, 1:07 p.m. UTC | #3
On Fri, Sep 20, 2013 at 4:08 AM, Richard Biener
<richard.guenther@gmail.com> 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?

No.  They don't belong there.  This is a high-level wrapper for the
low-level instruction builders.

> to have various issues so it shouldn't be used (I wonder who approved them
> in the end ... maybe it was even me).

Not really. I put it in and still need to flush it out a bit more.
I'll work on it.


Diego.
Richard Biener Sept. 20, 2013, 1:28 p.m. UTC | #4
On Fri, Sep 20, 2013 at 3:07 PM, Diego Novillo <dnovillo@google.com> wrote:
> On Fri, Sep 20, 2013 at 4:08 AM, Richard Biener
> <richard.guenther@gmail.com> 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?
>
> No.  They don't belong there.  This is a high-level wrapper for the
> low-level instruction builders.
>
>> to have various issues so it shouldn't be used (I wonder who approved them
>> in the end ... maybe it was even me).
>
> Not really. I put it in and still need to flush it out a bit more.
> I'll work on it.

Maybe put it into a separate .c/.h file combo then?

Richard.

>
> Diego.
Andrew MacLeod Sept. 23, 2013, 4:21 p.m. UTC | #5
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?

Andrew
David Malcolm Sept. 23, 2013, 5:05 p.m. UTC | #6
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?
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 tree-ssa.c
	* tree-ssa.c (struct count_ptr_d, count_ptr_derefs,
	count_uses_and_derefs): Relocate from gimple.c.
	(get_expr_type): Relocate from gimple.c.
	(build_assign, build_type_cast): Change to only create ssanames.
	(ssa_replace_lhs): Renamed gimple_replace_ssa from gimple.c
	* gimple.h: Move prototypes to...
	* tree-ssa.h: Here.
	* tree-ssa-reassoc.c (repropagate_negates): Use ssa_replace_lhs.
	* tree-ssa-math-opts (execute_cse_reciprocals): Use ssa_replace_lhs.


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: tree-ssa.c
===================================================================
*** tree-ssa.c	(revision 202720)
--- tree-ssa.c	(working copy)
*************** flush_pending_stmts (edge e)
*** 231,236 ****
--- 231,456 ----
    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);
+ }
+ 
+ 
+ /* 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);
+ }
+ 
+ 
+ 
+ /* 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
+ ssa_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);
+ }
+ 
+ 
  /* 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: 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: tree-ssa.h
===================================================================
*** tree-ssa.h	(revision 202720)
--- tree-ssa.h	(working copy)
*************** extern edge_var_map_vector *redirect_edg
*** 42,47 ****
--- 42,61 ----
  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 *);
+ /* Helper functions to build SSA statements.  */
+ 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);
+ 
+ extern void ssa_replace_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-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;
! 	      ssa_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);
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;
  
! 		  ssa_replace_lhs (stmt1, arg1);
  		  gimple_call_set_fndecl (stmt1, fndecl);
  		  update_stmt (stmt1);
  		  reciprocal_stats.rfuncs_inserted++;