diff mbox

[1/3] Create gimple-iterator.h and gimple-walk.[ch]

Message ID 528390AF.5080505@redhat.com
State New
Headers show

Commit Message

Andrew MacLeod Nov. 13, 2013, 2:46 p.m. UTC
This set of 3 patches creates gimple-iterator.h to hold the prototypes 
for the existing gimple-iterator.c.  It also extracts the gimple-stmt 
'walker' routines into their own file. I didn't originally intend to do 
that, but I discovered that the include dependencies between statements, 
iterators and walkers made the separation occur naturally, so went with it.

There were a couple of routines that got moved from .h to .c files.    
tree-phinodes.h::set_phi_nodes()  and 
gimple.h::gimple_seq_set_location() were moved into their .c files 
because the inlined function made use of statement iterators, and by 
moving them into the .c file, it removes the requirement on 
gimple-iterator.h being needed so simply parse the header file.  I do 
not believe either will have any measurable impact.

patch 1 has the core changes.
patch 2 updates the core compiler files to include one or both .h files 
as needed.
patch 3 updates a few other files.. 2 target config files and 2 
testsuite plugin tests which require the new includes.

Note that at this moment, gimple.h still has "enum 
gsi_iterator_update".  I can't move that out until I split gimplfy.h 
into the gimplfy-be.h component mentioned in the previous patch set 
(gimplify-be.h will require gimple-iterator.h and contain only 
gimplification routines that the back end uses).  That'll be the next 
patch set...  and then once that is out, I'll clean up the remaining 
gimple.h prototypes and then see about flattening all the #includes in 
gimple.h and gimplfy.h

bootstraps on x86_64-unknown-linux-gnu with no new regressions.

I built stage 1 successfully for aarch64-elf, aarch64-linux-gnu, 
powerpc-darwin8, powerpc-eabi, and  rs6000-ibm-aix6.0 to verify the 
config changes compile for those targets.   I'm also currently building 
the other targets I built when gimplify.h was split out just to make 
sure I didn't miss anything there.... but I don't think there are any 
dependencies in those targets.

OK for mainline?

Andrew

Comments

Jeff Law Nov. 13, 2013, 10:29 p.m. UTC | #1
On 11/13/13 07:46, Andrew MacLeod wrote:
> This set of 3 patches creates gimple-iterator.h to hold the prototypes
> for the existing gimple-iterator.c.  It also extracts the gimple-stmt
> 'walker' routines into their own file. I didn't originally intend to do
> that, but I discovered that the include dependencies between statements,
> iterators and walkers made the separation occur naturally, so went with it.
>
> There were a couple of routines that got moved from .h to .c files.
> tree-phinodes.h::set_phi_nodes()  and
> gimple.h::gimple_seq_set_location() were moved into their .c files
> because the inlined function made use of statement iterators, and by
> moving them into the .c file, it removes the requirement on
> gimple-iterator.h being needed so simply parse the header file.  I do
> not believe either will have any measurable impact.
>
> patch 1 has the core changes.
> patch 2 updates the core compiler files to include one or both .h files
> as needed.
> patch 3 updates a few other files.. 2 target config files and 2
> testsuite plugin tests which require the new includes.
>
> Note that at this moment, gimple.h still has "enum
> gsi_iterator_update".  I can't move that out until I split gimplfy.h
> into the gimplfy-be.h component mentioned in the previous patch set
> (gimplify-be.h will require gimple-iterator.h and contain only
> gimplification routines that the back end uses).  That'll be the next
> patch set...  and then once that is out, I'll clean up the remaining
> gimple.h prototypes and then see about flattening all the #includes in
> gimple.h and gimplfy.h
>
> bootstraps on x86_64-unknown-linux-gnu with no new regressions.
>
> I built stage 1 successfully for aarch64-elf, aarch64-linux-gnu,
> powerpc-darwin8, powerpc-eabi, and  rs6000-ibm-aix6.0 to verify the
> config changes compile for those targets.   I'm also currently building
> the other targets I built when gimplify.h was split out just to make
> sure I didn't miss anything there.... but I don't think there are any
> dependencies in those targets.
>
> OK for mainline?
All 3 patches in the series are fine.

Thanks,
jeff
diff mbox

Patch


	* gimple-walk.h: New File.  Relocate prototypes from gimple.h.
	(struct walk_stmt_info):  Relocate here from gimple.h.
	* gimple-iterator.h: New File.  Relocate prototypes from gimple.h.
	(struct gimple_stmt_iterator_d): Relocate here from gimple.h.
	(gsi_start_1, gsi_none, gsi_start_bb, gsi_last_1, gsi_last_bb,
	gsi_end_p, gsi_one_before_end_p, gsi_next, gsi_prev, gsi_stmt,
	gsi_after_labels, gsi_next_nondebug, gsi_prev_nondebug,
	gsi_start_nondebug_bb, gsi_start_nondebug_after_labels_bb,
	gsi_last_nondebug_bb, gsi_bb, gsi_seq): Relocate here from gimple.h.
	* gimple.h (struct gimple_stmt_iterator_d): Move to gimple-iterator.h.
	(gsi_start_1, gsi_none, gsi_start_bb, gsi_last_1, gsi_last_bb,
	gsi_end_p, gsi_one_before_end_p, gsi_next, gsi_prev, gsi_stmt,
	gsi_after_labels, gsi_next_nondebug, gsi_prev_nondebug,
	gsi_start_nondebug_bb, gsi_start_nondebug_after_labels_bb,
	gsi_last_nondebug_bb, gsi_bb, gsi_seq): Move to gimple-iterator.h.
	(struct walk_stmt_info): Move to gimple-walk.h.
	(gimple_seq_set_location): Move to gimple.c
	* gimple-walk.c: New File.
	(walk_gimple_seq_mod, walk_gimple_seq, walk_gimple_asm, walk_gimple_op,
	walk_gimple_stmt, get_base_loadstore, walk_stmt_load_store_addr_ops,
	walk_stmt_load_store_ops): Relocate here from gimple.c.
	* gimple-iterator.c: Include gimple-iterator.h.
	* gimple.c (walk_gimple_seq_mod, walk_gimple_seq, walk_gimple_asm,
	walk_gimple_op, walk_gimple_stmt, get_base_loadstore,
	walk_stmt_load_store_addr_ops, walk_stmt_load_store_ops): Move to
	gimple-walk.c.
	(gimple_seq_set_location): Relocate from gimple.h.
	* tree-phinodes.h (set_phi_nodes): Move to tree-phinodes.c.
	* tree-phinodes.c (set_phi_nodes): Relocate from tree-phinodes.h.
	* gengtype.c (open_base_files): Add gimple-iterator.h to include list.
	* Makefile.in (OBJS): Add gimple-walk.o

Index: gimple-walk.h
===================================================================
*** gimple-walk.h	(revision 0)
--- gimple-walk.h	(working copy)
***************
*** 0 ****
--- 1,99 ----
+ /* Header file for gimple statement walk support.
+    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_WALK_H
+ #define GCC_GIMPLE_WALK_H
+ 
+ /* Convenience routines to walk all statements of a gimple function.
+    Note that this is useful exclusively before the code is converted
+    into SSA form.  Once the program is in SSA form, the standard
+    operand interface should be used to analyze/modify statements.  */
+ struct walk_stmt_info
+ {
+   /* Points to the current statement being walked.  */
+   gimple_stmt_iterator gsi;
+ 
+   /* Additional data that the callback functions may want to carry
+      through the recursion.  */
+   void *info;
+ 
+   /* Pointer map used to mark visited tree nodes when calling
+      walk_tree on each operand.  If set to NULL, duplicate tree nodes
+      will be visited more than once.  */
+   struct pointer_set_t *pset;
+ 
+   /* Operand returned by the callbacks.  This is set when calling
+      walk_gimple_seq.  If the walk_stmt_fn or walk_tree_fn callback
+      returns non-NULL, this field will contain the tree returned by
+      the last callback.  */
+   tree callback_result;
+ 
+   /* Indicates whether the operand being examined may be replaced
+      with something that matches is_gimple_val (if true) or something
+      slightly more complicated (if false).  "Something" technically
+      means the common subset of is_gimple_lvalue and is_gimple_rhs,
+      but we never try to form anything more complicated than that, so
+      we don't bother checking.
+ 
+      Also note that CALLBACK should update this flag while walking the
+      sub-expressions of a statement.  For instance, when walking the
+      statement 'foo (&var)', the flag VAL_ONLY will initially be set
+      to true, however, when walking &var, the operand of that
+      ADDR_EXPR does not need to be a GIMPLE value.  */
+   BOOL_BITFIELD val_only : 1;
+ 
+   /* True if we are currently walking the LHS of an assignment.  */
+   BOOL_BITFIELD is_lhs : 1;
+ 
+   /* Optional.  Set to true by the callback functions if they made any
+      changes.  */
+   BOOL_BITFIELD changed : 1;
+ 
+   /* True if we're interested in location information.  */
+   BOOL_BITFIELD want_locations : 1;
+ 
+   /* True if we've removed the statement that was processed.  */
+   BOOL_BITFIELD removed_stmt : 1;
+ };
+ 
+ /* Callback for walk_gimple_stmt.  Called for every statement found
+    during traversal.  The first argument points to the statement to
+    walk.  The second argument is a flag that the callback sets to
+    'true' if it the callback handled all the operands and
+    sub-statements of the statement (the default value of this flag is
+    'false').  The third argument is an anonymous pointer to data
+    to be used by the callback.  */
+ typedef tree (*walk_stmt_fn) (gimple_stmt_iterator *, bool *,
+ 			      struct walk_stmt_info *);
+ 
+ extern gimple walk_gimple_seq_mod (gimple_seq *, walk_stmt_fn, walk_tree_fn,
+ 				   struct walk_stmt_info *);
+ extern gimple walk_gimple_seq (gimple_seq, walk_stmt_fn, walk_tree_fn,
+ 			       struct walk_stmt_info *);
+ extern tree walk_gimple_op (gimple, walk_tree_fn, struct walk_stmt_info *);
+ extern tree walk_gimple_stmt (gimple_stmt_iterator *, walk_stmt_fn,
+ 			      walk_tree_fn, struct walk_stmt_info *);
+ extern bool walk_stmt_load_store_addr_ops (gimple, void *,
+ 					   bool (*)(gimple, tree, void *),
+ 					   bool (*)(gimple, tree, void *),
+ 					   bool (*)(gimple, tree, void *));
+ extern bool walk_stmt_load_store_ops (gimple, void *,
+ 				      bool (*)(gimple, tree, void *),
+ 				      bool (*)(gimple, tree, void *));
+ #endif /* GCC_GIMPLE_WALK_H */
Index: gimple-iterator.h
===================================================================
*** gimple-iterator.h	(revision 0)
--- gimple-iterator.h	(working copy)
***************
*** 0 ****
--- 1,288 ----
+ /* Header file for gimple iterators.
+    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_ITERATOR_H
+ #define GCC_GIMPLE_ITERATOR_H
+ 
+ /* Iterator object for GIMPLE statement sequences.  */
+ 
+ typedef struct gimple_stmt_iterator_d
+ {
+   /* Sequence node holding the current statement.  */
+   gimple_seq_node ptr;
+ 
+   /* Sequence and basic block holding the statement.  These fields
+      are necessary to handle edge cases such as when statement is
+      added to an empty basic block or when the last statement of a
+      block/sequence is removed.  */
+   gimple_seq *seq;
+   basic_block bb;
+ } gimple_stmt_iterator;
+  
+ extern void gsi_insert_seq_before_without_update (gimple_stmt_iterator *,
+ 						  gimple_seq,
+ 						  enum gsi_iterator_update);
+ extern void gsi_insert_seq_before (gimple_stmt_iterator *, gimple_seq,
+ 				   enum gsi_iterator_update);
+ extern void gsi_insert_seq_after_without_update (gimple_stmt_iterator *,
+ 						 gimple_seq,
+ 						 enum gsi_iterator_update);
+ extern void gsi_insert_seq_after (gimple_stmt_iterator *, gimple_seq,
+ 				  enum gsi_iterator_update);
+ extern gimple_seq gsi_split_seq_after (gimple_stmt_iterator);
+ extern void gsi_set_stmt (gimple_stmt_iterator *, gimple);
+ extern void gsi_split_seq_before (gimple_stmt_iterator *, gimple_seq *);
+ extern void gsi_replace (gimple_stmt_iterator *, gimple, bool);
+ extern void gsi_replace_with_seq (gimple_stmt_iterator *, gimple_seq, bool);
+ extern void gsi_insert_before_without_update (gimple_stmt_iterator *, gimple,
+ 					      enum gsi_iterator_update);
+ extern void gsi_insert_before (gimple_stmt_iterator *, gimple,
+ 			       enum gsi_iterator_update);
+ extern void gsi_insert_after_without_update (gimple_stmt_iterator *, gimple,
+ 					     enum gsi_iterator_update);
+ extern void gsi_insert_after (gimple_stmt_iterator *, gimple,
+ 			      enum gsi_iterator_update);
+ extern bool gsi_remove (gimple_stmt_iterator *, bool);
+ extern gimple_stmt_iterator gsi_for_stmt (gimple);
+ extern void gsi_move_after (gimple_stmt_iterator *, gimple_stmt_iterator *);
+ extern void gsi_move_before (gimple_stmt_iterator *, gimple_stmt_iterator *);
+ extern void gsi_move_to_bb_end (gimple_stmt_iterator *, basic_block);
+ extern void gsi_insert_on_edge (edge, gimple);
+ extern void gsi_insert_seq_on_edge (edge, gimple_seq);
+ extern basic_block gsi_insert_on_edge_immediate (edge, gimple);
+ extern basic_block gsi_insert_seq_on_edge_immediate (edge, gimple_seq);
+ extern void gsi_commit_edge_inserts (void);
+ extern void gsi_commit_one_edge_insert (edge, basic_block *);
+ extern gimple_stmt_iterator gsi_start_phis (basic_block);
+ 
+ /* Return a new iterator pointing to GIMPLE_SEQ's first statement.  */
+ 
+ static inline gimple_stmt_iterator
+ gsi_start_1 (gimple_seq *seq)
+ {
+   gimple_stmt_iterator i;
+ 
+   i.ptr = gimple_seq_first (*seq);
+   i.seq = seq;
+   i.bb = i.ptr ? gimple_bb (i.ptr) : NULL;
+ 
+   return i;
+ }
+ 
+ #define gsi_start(x) gsi_start_1 (&(x))
+ 
+ static inline gimple_stmt_iterator
+ gsi_none (void)
+ {
+   gimple_stmt_iterator i;
+   i.ptr = NULL;
+   i.seq = NULL;
+   i.bb = NULL;
+   return i;
+ }
+ 
+ /* Return a new iterator pointing to the first statement in basic block BB.  */
+ 
+ static inline gimple_stmt_iterator
+ gsi_start_bb (basic_block bb)
+ {
+   gimple_stmt_iterator i;
+   gimple_seq *seq;
+ 
+   seq = bb_seq_addr (bb);
+   i.ptr = gimple_seq_first (*seq);
+   i.seq = seq;
+   i.bb = bb;
+ 
+   return i;
+ }
+ 
+ /* Return a new iterator initially pointing to GIMPLE_SEQ's last statement.  */
+ 
+ static inline gimple_stmt_iterator
+ gsi_last_1 (gimple_seq *seq)
+ {
+   gimple_stmt_iterator i;
+ 
+   i.ptr = gimple_seq_last (*seq);
+   i.seq = seq;
+   i.bb = i.ptr ? gimple_bb (i.ptr) : NULL;
+ 
+   return i;
+ }
+ 
+ #define gsi_last(x) gsi_last_1 (&(x))
+ 
+ /* Return a new iterator pointing to the last statement in basic block BB.  */
+ 
+ static inline gimple_stmt_iterator
+ gsi_last_bb (basic_block bb)
+ {
+   gimple_stmt_iterator i;
+   gimple_seq *seq;
+ 
+   seq = bb_seq_addr (bb);
+   i.ptr = gimple_seq_last (*seq);
+   i.seq = seq;
+   i.bb = bb;
+ 
+   return i;
+ }
+ 
+ /* Return true if I is at the end of its sequence.  */
+ 
+ static inline bool
+ gsi_end_p (gimple_stmt_iterator i)
+ {
+   return i.ptr == NULL;
+ }
+ 
+ /* Return true if I is one statement before the end of its sequence.  */
+ 
+ static inline bool
+ gsi_one_before_end_p (gimple_stmt_iterator i)
+ {
+   return i.ptr != NULL && i.ptr->gsbase.next == NULL;
+ }
+ 
+ /* Advance the iterator to the next gimple statement.  */
+ 
+ static inline void
+ gsi_next (gimple_stmt_iterator *i)
+ {
+   i->ptr = i->ptr->gsbase.next;
+ }
+ 
+ /* Advance the iterator to the previous gimple statement.  */
+ 
+ static inline void
+ gsi_prev (gimple_stmt_iterator *i)
+ {
+   gimple prev = i->ptr->gsbase.prev;
+   if (prev->gsbase.next)
+     i->ptr = prev;
+   else
+     i->ptr = NULL;
+ }
+ 
+ /* Return the current stmt.  */
+ 
+ static inline gimple
+ gsi_stmt (gimple_stmt_iterator i)
+ {
+   return i.ptr;
+ }
+ 
+ /* Return a block statement iterator that points to the first non-label
+    statement in block BB.  */
+ 
+ static inline gimple_stmt_iterator
+ gsi_after_labels (basic_block bb)
+ {
+   gimple_stmt_iterator gsi = gsi_start_bb (bb);
+ 
+   while (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL)
+     gsi_next (&gsi);
+ 
+   return gsi;
+ }
+ 
+ /* Advance the iterator to the next non-debug gimple statement.  */
+ 
+ static inline void
+ gsi_next_nondebug (gimple_stmt_iterator *i)
+ {
+   do
+     {
+       gsi_next (i);
+     }
+   while (!gsi_end_p (*i) && is_gimple_debug (gsi_stmt (*i)));
+ }
+ 
+ /* Advance the iterator to the next non-debug gimple statement.  */
+ 
+ static inline void
+ gsi_prev_nondebug (gimple_stmt_iterator *i)
+ {
+   do
+     {
+       gsi_prev (i);
+     }
+   while (!gsi_end_p (*i) && is_gimple_debug (gsi_stmt (*i)));
+ }
+ 
+ /* Return a new iterator pointing to the first non-debug statement in
+    basic block BB.  */
+ 
+ static inline gimple_stmt_iterator
+ gsi_start_nondebug_bb (basic_block bb)
+ {
+   gimple_stmt_iterator i = gsi_start_bb (bb);
+ 
+   if (!gsi_end_p (i) && is_gimple_debug (gsi_stmt (i)))
+     gsi_next_nondebug (&i);
+ 
+   return i;
+ }
+ 
+ /* Return a new iterator pointing to the first non-debug non-label statement in
+    basic block BB.  */
+ 
+ static inline gimple_stmt_iterator
+ gsi_start_nondebug_after_labels_bb (basic_block bb)
+ {
+   gimple_stmt_iterator i = gsi_after_labels (bb);
+ 
+   if (!gsi_end_p (i) && is_gimple_debug (gsi_stmt (i)))
+     gsi_next_nondebug (&i);
+ 
+   return i;
+ }
+ 
+ /* Return a new iterator pointing to the last non-debug statement in
+    basic block BB.  */
+ 
+ static inline gimple_stmt_iterator
+ gsi_last_nondebug_bb (basic_block bb)
+ {
+   gimple_stmt_iterator i = gsi_last_bb (bb);
+ 
+   if (!gsi_end_p (i) && is_gimple_debug (gsi_stmt (i)))
+     gsi_prev_nondebug (&i);
+ 
+   return i;
+ }
+ 
+ /* Return the basic block associated with this iterator.  */
+ 
+ static inline basic_block
+ gsi_bb (gimple_stmt_iterator i)
+ {
+   return i.bb;
+ }
+ 
+ /* Return the sequence associated with this iterator.  */
+ 
+ static inline gimple_seq
+ gsi_seq (gimple_stmt_iterator i)
+ {
+   return *i.seq;
+ }
+ 
+ #endif /* GCC_GIMPLE_ITERATOR_H */
Index: gimple.h
===================================================================
*** gimple.h	(revision 204721)
--- gimple.h	(working copy)
*************** enum plf_mask {
*** 141,161 ****
      GF_PLF_2	= 1 << 1
  };
  
- /* Iterator object for GIMPLE statement sequences.  */
- 
- struct gimple_stmt_iterator_d
- {
-   /* Sequence node holding the current statement.  */
-   gimple_seq_node ptr;
- 
-   /* Sequence and basic block holding the statement.  These fields
-      are necessary to handle edge cases such as when statement is
-      added to an empty basic block or when the last statement of a
-      block/sequence is removed.  */
-   gimple_seq *seq;
-   basic_block bb;
- };
- 
  /* Data structure definitions for GIMPLE tuples.  NOTE: word markers
     are for 64 bit hosts.  */
  
--- 141,146 ----
*************** extern bool gimple_compare_field_offset
*** 847,859 ****
  extern tree gimple_unsigned_type (tree);
  extern tree gimple_signed_type (tree);
  extern alias_set_type gimple_get_alias_set (tree);
- extern bool walk_stmt_load_store_addr_ops (gimple, void *,
- 					   bool (*)(gimple, tree, void *),
- 					   bool (*)(gimple, tree, void *),
- 					   bool (*)(gimple, tree, void *));
- extern bool walk_stmt_load_store_ops (gimple, void *,
- 				      bool (*)(gimple, tree, void *),
- 				      bool (*)(gimple, tree, void *));
  extern bool gimple_ior_addresses_taken (bitmap, gimple);
  extern bool gimple_call_builtin_p (gimple, enum built_in_class);
  extern bool gimple_call_builtin_p (gimple, enum built_in_function);
--- 832,837 ----
*************** gimple_expr_type (const_gimple stmt)
*** 5223,5449 ****
      return void_type_node;
  }
  
- /* Return a new iterator pointing to GIMPLE_SEQ's first statement.  */
- 
- static inline gimple_stmt_iterator
- gsi_start_1 (gimple_seq *seq)
- {
-   gimple_stmt_iterator i;
- 
-   i.ptr = gimple_seq_first (*seq);
-   i.seq = seq;
-   i.bb = i.ptr ? gimple_bb (i.ptr) : NULL;
- 
-   return i;
- }
- 
- #define gsi_start(x) gsi_start_1 (&(x))
- 
- static inline gimple_stmt_iterator
- gsi_none (void)
- {
-   gimple_stmt_iterator i;
-   i.ptr = NULL;
-   i.seq = NULL;
-   i.bb = NULL;
-   return i;
- }
- 
- /* Return a new iterator pointing to the first statement in basic block BB.  */
- 
- static inline gimple_stmt_iterator
- gsi_start_bb (basic_block bb)
- {
-   gimple_stmt_iterator i;
-   gimple_seq *seq;
- 
-   seq = bb_seq_addr (bb);
-   i.ptr = gimple_seq_first (*seq);
-   i.seq = seq;
-   i.bb = bb;
- 
-   return i;
- }
- 
- 
- /* Return a new iterator initially pointing to GIMPLE_SEQ's last statement.  */
- 
- static inline gimple_stmt_iterator
- gsi_last_1 (gimple_seq *seq)
- {
-   gimple_stmt_iterator i;
- 
-   i.ptr = gimple_seq_last (*seq);
-   i.seq = seq;
-   i.bb = i.ptr ? gimple_bb (i.ptr) : NULL;
- 
-   return i;
- }
- 
- #define gsi_last(x) gsi_last_1 (&(x))
- 
- /* Return a new iterator pointing to the last statement in basic block BB.  */
- 
- static inline gimple_stmt_iterator
- gsi_last_bb (basic_block bb)
- {
-   gimple_stmt_iterator i;
-   gimple_seq *seq;
- 
-   seq = bb_seq_addr (bb);
-   i.ptr = gimple_seq_last (*seq);
-   i.seq = seq;
-   i.bb = bb;
- 
-   return i;
- }
- 
- 
- /* Return true if I is at the end of its sequence.  */
- 
- static inline bool
- gsi_end_p (gimple_stmt_iterator i)
- {
-   return i.ptr == NULL;
- }
- 
- 
- /* Return true if I is one statement before the end of its sequence.  */
- 
- static inline bool
- gsi_one_before_end_p (gimple_stmt_iterator i)
- {
-   return i.ptr != NULL && i.ptr->gsbase.next == NULL;
- }
- 
- 
- /* Advance the iterator to the next gimple statement.  */
- 
- static inline void
- gsi_next (gimple_stmt_iterator *i)
- {
-   i->ptr = i->ptr->gsbase.next;
- }
- 
- /* Advance the iterator to the previous gimple statement.  */
- 
- static inline void
- gsi_prev (gimple_stmt_iterator *i)
- {
-   gimple prev = i->ptr->gsbase.prev;
-   if (prev->gsbase.next)
-     i->ptr = prev;
-   else
-     i->ptr = NULL;
- }
- 
- /* Return the current stmt.  */
- 
- static inline gimple
- gsi_stmt (gimple_stmt_iterator i)
- {
-   return i.ptr;
- }
- 
- /* Return a block statement iterator that points to the first non-label
-    statement in block BB.  */
- 
- static inline gimple_stmt_iterator
- gsi_after_labels (basic_block bb)
- {
-   gimple_stmt_iterator gsi = gsi_start_bb (bb);
- 
-   while (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL)
-     gsi_next (&gsi);
- 
-   return gsi;
- }
- 
- /* Advance the iterator to the next non-debug gimple statement.  */
- 
- static inline void
- gsi_next_nondebug (gimple_stmt_iterator *i)
- {
-   do
-     {
-       gsi_next (i);
-     }
-   while (!gsi_end_p (*i) && is_gimple_debug (gsi_stmt (*i)));
- }
- 
- /* Advance the iterator to the next non-debug gimple statement.  */
- 
- static inline void
- gsi_prev_nondebug (gimple_stmt_iterator *i)
- {
-   do
-     {
-       gsi_prev (i);
-     }
-   while (!gsi_end_p (*i) && is_gimple_debug (gsi_stmt (*i)));
- }
- 
- /* Return a new iterator pointing to the first non-debug statement in
-    basic block BB.  */
- 
- static inline gimple_stmt_iterator
- gsi_start_nondebug_bb (basic_block bb)
- {
-   gimple_stmt_iterator i = gsi_start_bb (bb);
- 
-   if (!gsi_end_p (i) && is_gimple_debug (gsi_stmt (i)))
-     gsi_next_nondebug (&i);
- 
-   return i;
- }
- 
- /* Return a new iterator pointing to the first non-debug non-label statement in
-    basic block BB.  */
- 
- static inline gimple_stmt_iterator
- gsi_start_nondebug_after_labels_bb (basic_block bb)
- {
-   gimple_stmt_iterator i = gsi_after_labels (bb);
- 
-   if (!gsi_end_p (i) && is_gimple_debug (gsi_stmt (i)))
-     gsi_next_nondebug (&i);
- 
-   return i;
- }
- 
- /* Return a new iterator pointing to the last non-debug statement in
-    basic block BB.  */
- 
- static inline gimple_stmt_iterator
- gsi_last_nondebug_bb (basic_block bb)
- {
-   gimple_stmt_iterator i = gsi_last_bb (bb);
- 
-   if (!gsi_end_p (i) && is_gimple_debug (gsi_stmt (i)))
-     gsi_prev_nondebug (&i);
- 
-   return i;
- }
- 
- 
- /* Return the basic block associated with this iterator.  */
- 
- static inline basic_block
- gsi_bb (gimple_stmt_iterator i)
- {
-   return i.bb;
- }
- 
- 
- /* Return the sequence associated with this iterator.  */
- 
- static inline gimple_seq
- gsi_seq (gimple_stmt_iterator i)
- {
-   return *i.seq;
- }
- 
- 
  enum gsi_iterator_update
  {
    GSI_NEW_STMT,		/* Only valid when single statement is added, move
--- 5201,5206 ----
*************** enum gsi_iterator_update
*** 5454,5565 ****
  			   direction.  */
  };
  
- /* In gimple-iterator.c  */
- gimple_stmt_iterator gsi_start_phis (basic_block);
- gimple_seq gsi_split_seq_after (gimple_stmt_iterator);
- void gsi_split_seq_before (gimple_stmt_iterator *, gimple_seq *);
- void gsi_set_stmt (gimple_stmt_iterator *, gimple);
- void gsi_replace (gimple_stmt_iterator *, gimple, bool);
- void gsi_replace_with_seq (gimple_stmt_iterator *, gimple_seq, bool);
- void gsi_insert_before (gimple_stmt_iterator *, gimple,
- 			enum gsi_iterator_update);
- void gsi_insert_before_without_update (gimple_stmt_iterator *, gimple,
-                                        enum gsi_iterator_update);
- void gsi_insert_seq_before (gimple_stmt_iterator *, gimple_seq,
-                             enum gsi_iterator_update);
- void gsi_insert_seq_before_without_update (gimple_stmt_iterator *, gimple_seq,
-                                            enum gsi_iterator_update);
- void gsi_insert_after (gimple_stmt_iterator *, gimple,
- 		       enum gsi_iterator_update);
- void gsi_insert_after_without_update (gimple_stmt_iterator *, gimple,
-                                       enum gsi_iterator_update);
- void gsi_insert_seq_after (gimple_stmt_iterator *, gimple_seq,
- 			   enum gsi_iterator_update);
- void gsi_insert_seq_after_without_update (gimple_stmt_iterator *, gimple_seq,
-                                           enum gsi_iterator_update);
- bool gsi_remove (gimple_stmt_iterator *, bool);
- gimple_stmt_iterator gsi_for_stmt (gimple);
- void gsi_move_after (gimple_stmt_iterator *, gimple_stmt_iterator *);
- void gsi_move_before (gimple_stmt_iterator *, gimple_stmt_iterator *);
- void gsi_move_to_bb_end (gimple_stmt_iterator *, basic_block);
- void gsi_insert_on_edge (edge, gimple);
- void gsi_insert_seq_on_edge (edge, gimple_seq);
- basic_block gsi_insert_on_edge_immediate (edge, gimple);
- basic_block gsi_insert_seq_on_edge_immediate (edge, gimple_seq);
- void gsi_commit_one_edge_insert (edge, basic_block *);
- void gsi_commit_edge_inserts (void);
  gimple gimple_call_copy_skip_args (gimple, bitmap);
  
- /* Convenience routines to walk all statements of a gimple function.
-    Note that this is useful exclusively before the code is converted
-    into SSA form.  Once the program is in SSA form, the standard
-    operand interface should be used to analyze/modify statements.  */
- struct walk_stmt_info
- {
-   /* Points to the current statement being walked.  */
-   gimple_stmt_iterator gsi;
- 
-   /* Additional data that the callback functions may want to carry
-      through the recursion.  */
-   void *info;
- 
-   /* Pointer map used to mark visited tree nodes when calling
-      walk_tree on each operand.  If set to NULL, duplicate tree nodes
-      will be visited more than once.  */
-   struct pointer_set_t *pset;
- 
-   /* Operand returned by the callbacks.  This is set when calling
-      walk_gimple_seq.  If the walk_stmt_fn or walk_tree_fn callback
-      returns non-NULL, this field will contain the tree returned by
-      the last callback.  */
-   tree callback_result;
- 
-   /* Indicates whether the operand being examined may be replaced
-      with something that matches is_gimple_val (if true) or something
-      slightly more complicated (if false).  "Something" technically
-      means the common subset of is_gimple_lvalue and is_gimple_rhs,
-      but we never try to form anything more complicated than that, so
-      we don't bother checking.
- 
-      Also note that CALLBACK should update this flag while walking the
-      sub-expressions of a statement.  For instance, when walking the
-      statement 'foo (&var)', the flag VAL_ONLY will initially be set
-      to true, however, when walking &var, the operand of that
-      ADDR_EXPR does not need to be a GIMPLE value.  */
-   BOOL_BITFIELD val_only : 1;
- 
-   /* True if we are currently walking the LHS of an assignment.  */
-   BOOL_BITFIELD is_lhs : 1;
- 
-   /* Optional.  Set to true by the callback functions if they made any
-      changes.  */
-   BOOL_BITFIELD changed : 1;
- 
-   /* True if we're interested in location information.  */
-   BOOL_BITFIELD want_locations : 1;
- 
-   /* True if we've removed the statement that was processed.  */
-   BOOL_BITFIELD removed_stmt : 1;
- };
- 
- /* Callback for walk_gimple_stmt.  Called for every statement found
-    during traversal.  The first argument points to the statement to
-    walk.  The second argument is a flag that the callback sets to
-    'true' if it the callback handled all the operands and
-    sub-statements of the statement (the default value of this flag is
-    'false').  The third argument is an anonymous pointer to data
-    to be used by the callback.  */
- typedef tree (*walk_stmt_fn) (gimple_stmt_iterator *, bool *,
- 			      struct walk_stmt_info *);
- 
- gimple walk_gimple_seq (gimple_seq, walk_stmt_fn, walk_tree_fn,
- 		        struct walk_stmt_info *);
- gimple walk_gimple_seq_mod (gimple_seq *, walk_stmt_fn, walk_tree_fn,
- 			    struct walk_stmt_info *);
- tree walk_gimple_stmt (gimple_stmt_iterator *, walk_stmt_fn, walk_tree_fn,
- 		       struct walk_stmt_info *);
- tree walk_gimple_op (gimple, walk_tree_fn, struct walk_stmt_info *);
- 
  /* Enum and arrays used for allocation stats.  Keep in sync with
     gimple.c:gimple_alloc_kind_names.  */
  enum gimple_alloc_kind
--- 5211,5218 ----
*************** gimple_alloc_kind (enum gimple_code code
*** 5593,5607 ****
  
  extern void dump_gimple_statistics (void);
  
- /* Set the location of all statements in SEQ to LOC.  */
- 
- static inline void
- gimple_seq_set_location (gimple_seq seq, location_t loc)
- {
-   for (gimple_stmt_iterator i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
-     gimple_set_location (gsi_stmt (i), loc);
- }
- 
  /* Return true if a location should not be emitted for this statement
     by annotate_all_with_location.  */
  
--- 5246,5251 ----
*************** gimple_set_do_not_emit_location (gimple
*** 5636,5640 ****
--- 5280,5285 ----
  
  extern void sort_case_labels (vec<tree> );
  extern void preprocess_case_label_vec_for_gimple (vec<tree> , tree, tree *);
+ extern void gimple_seq_set_location (gimple_seq , location_t);
  
  #endif  /* GCC_GIMPLE_H */
Index: gimple-walk.c
===================================================================
*** gimple-walk.c	(revision 0)
--- gimple-walk.c	(working copy)
***************
*** 0 ****
--- 1,871 ----
+ /* Gimple walk support.
+ 
+    Copyright (C) 2007-2013 Free Software Foundation, Inc.
+    Contributed by Aldy Hernandez <aldyh@redhat.com>
+ 
+ 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 "tm.h"
+ #include "tree.h"
+ #include "gimple.h"
+ #include "gimple-iterator.h"
+ #include "gimple-walk.h"
+ #include "gimple-walk.h"
+ #include "demangle.h"
+ 
+ /* Walk all the statements in the sequence *PSEQ calling walk_gimple_stmt
+    on each one.  WI is as in walk_gimple_stmt.
+ 
+    If walk_gimple_stmt returns non-NULL, the walk is stopped, and the
+    value is stored in WI->CALLBACK_RESULT.  Also, the statement that
+    produced the value is returned if this statement has not been
+    removed by a callback (wi->removed_stmt).  If the statement has
+    been removed, NULL is returned.
+ 
+    Otherwise, all the statements are walked and NULL returned.  */
+ 
+ gimple
+ walk_gimple_seq_mod (gimple_seq *pseq, walk_stmt_fn callback_stmt,
+ 		     walk_tree_fn callback_op, struct walk_stmt_info *wi)
+ {
+   gimple_stmt_iterator gsi;
+ 
+   for (gsi = gsi_start (*pseq); !gsi_end_p (gsi); )
+     {
+       tree ret = walk_gimple_stmt (&gsi, callback_stmt, callback_op, wi);
+       if (ret)
+ 	{
+ 	  /* If CALLBACK_STMT or CALLBACK_OP return a value, WI must exist
+ 	     to hold it.  */
+ 	  gcc_assert (wi);
+ 	  wi->callback_result = ret;
+ 
+ 	  return wi->removed_stmt ? NULL : gsi_stmt (gsi);
+ 	}
+ 
+       if (!wi->removed_stmt)
+ 	gsi_next (&gsi);
+     }
+ 
+   if (wi)
+     wi->callback_result = NULL_TREE;
+ 
+   return NULL;
+ }
+ 
+ 
+ /* Like walk_gimple_seq_mod, but ensure that the head of SEQ isn't
+    changed by the callbacks.  */
+ 
+ gimple
+ walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt,
+ 		 walk_tree_fn callback_op, struct walk_stmt_info *wi)
+ {
+   gimple_seq seq2 = seq;
+   gimple ret = walk_gimple_seq_mod (&seq2, callback_stmt, callback_op, wi);
+   gcc_assert (seq2 == seq);
+   return ret;
+ }
+ 
+ 
+ /* Helper function for walk_gimple_stmt.  Walk operands of a GIMPLE_ASM.  */
+ 
+ static tree
+ walk_gimple_asm (gimple stmt, walk_tree_fn callback_op,
+ 		 struct walk_stmt_info *wi)
+ {
+   tree ret, op;
+   unsigned noutputs;
+   const char **oconstraints;
+   unsigned i, n;
+   const char *constraint;
+   bool allows_mem, allows_reg, is_inout;
+ 
+   noutputs = gimple_asm_noutputs (stmt);
+   oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
+ 
+   if (wi)
+     wi->is_lhs = true;
+ 
+   for (i = 0; i < noutputs; i++)
+     {
+       op = gimple_asm_output_op (stmt, i);
+       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
+       oconstraints[i] = constraint;
+       parse_output_constraint (&constraint, i, 0, 0, &allows_mem, &allows_reg,
+ 	                       &is_inout);
+       if (wi)
+ 	wi->val_only = (allows_reg || !allows_mem);
+       ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
+       if (ret)
+ 	return ret;
+     }
+ 
+   n = gimple_asm_ninputs (stmt);
+   for (i = 0; i < n; i++)
+     {
+       op = gimple_asm_input_op (stmt, i);
+       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
+       parse_input_constraint (&constraint, 0, 0, noutputs, 0,
+ 			      oconstraints, &allows_mem, &allows_reg);
+       if (wi)
+ 	{
+ 	  wi->val_only = (allows_reg || !allows_mem);
+           /* Although input "m" is not really a LHS, we need a lvalue.  */
+ 	  wi->is_lhs = !wi->val_only;
+ 	}
+       ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
+       if (ret)
+ 	return ret;
+     }
+ 
+   if (wi)
+     {
+       wi->is_lhs = false;
+       wi->val_only = true;
+     }
+ 
+   n = gimple_asm_nlabels (stmt);
+   for (i = 0; i < n; i++)
+     {
+       op = gimple_asm_label_op (stmt, i);
+       ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
+       if (ret)
+ 	return ret;
+     }
+ 
+   return NULL_TREE;
+ }
+ 
+ 
+ /* Helper function of WALK_GIMPLE_STMT.  Walk every tree operand in
+    STMT.  CALLBACK_OP and WI are as in WALK_GIMPLE_STMT.
+ 
+    CALLBACK_OP is called on each operand of STMT via walk_tree.
+    Additional parameters to walk_tree must be stored in WI.  For each operand
+    OP, walk_tree is called as:
+ 
+ 	walk_tree (&OP, CALLBACK_OP, WI, WI->PSET)
+ 
+    If CALLBACK_OP returns non-NULL for an operand, the remaining
+    operands are not scanned.
+ 
+    The return value is that returned by the last call to walk_tree, or
+    NULL_TREE if no CALLBACK_OP is specified.  */
+ 
+ tree
+ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
+ 		struct walk_stmt_info *wi)
+ {
+   struct pointer_set_t *pset = (wi) ? wi->pset : NULL;
+   unsigned i;
+   tree ret = NULL_TREE;
+ 
+   switch (gimple_code (stmt))
+     {
+     case GIMPLE_ASSIGN:
+       /* Walk the RHS operands.  If the LHS is of a non-renamable type or
+          is a register variable, we may use a COMPONENT_REF on the RHS.  */
+       if (wi)
+ 	{
+ 	  tree lhs = gimple_assign_lhs (stmt);
+ 	  wi->val_only
+ 	    = (is_gimple_reg_type (TREE_TYPE (lhs)) && !is_gimple_reg (lhs))
+ 	      || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
+ 	}
+ 
+       for (i = 1; i < gimple_num_ops (stmt); i++)
+ 	{
+ 	  ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi,
+ 			   pset);
+ 	  if (ret)
+ 	    return ret;
+ 	}
+ 
+       /* Walk the LHS.  If the RHS is appropriate for a memory, we
+ 	 may use a COMPONENT_REF on the LHS.  */
+       if (wi)
+ 	{
+           /* If the RHS is of a non-renamable type or is a register variable,
+ 	     we may use a COMPONENT_REF on the LHS.  */
+ 	  tree rhs1 = gimple_assign_rhs1 (stmt);
+ 	  wi->val_only
+ 	    = (is_gimple_reg_type (TREE_TYPE (rhs1)) && !is_gimple_reg (rhs1))
+ 	      || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
+ 	  wi->is_lhs = true;
+ 	}
+ 
+       ret = walk_tree (gimple_op_ptr (stmt, 0), callback_op, wi, pset);
+       if (ret)
+ 	return ret;
+ 
+       if (wi)
+ 	{
+ 	  wi->val_only = true;
+ 	  wi->is_lhs = false;
+ 	}
+       break;
+ 
+     case GIMPLE_CALL:
+       if (wi)
+ 	{
+ 	  wi->is_lhs = false;
+ 	  wi->val_only = true;
+ 	}
+ 
+       ret = walk_tree (gimple_call_chain_ptr (stmt), callback_op, wi, pset);
+       if (ret)
+         return ret;
+ 
+       ret = walk_tree (gimple_call_fn_ptr (stmt), callback_op, wi, pset);
+       if (ret)
+         return ret;
+ 
+       for (i = 0; i < gimple_call_num_args (stmt); i++)
+ 	{
+ 	  if (wi)
+ 	    wi->val_only
+ 	      = is_gimple_reg_type (TREE_TYPE (gimple_call_arg (stmt, i)));
+ 	  ret = walk_tree (gimple_call_arg_ptr (stmt, i), callback_op, wi,
+ 			   pset);
+ 	  if (ret)
+ 	    return ret;
+ 	}
+ 
+       if (gimple_call_lhs (stmt))
+ 	{
+ 	  if (wi)
+ 	    {
+ 	      wi->is_lhs = true;
+ 	      wi->val_only
+ 		= is_gimple_reg_type (TREE_TYPE (gimple_call_lhs (stmt)));
+ 	    }
+ 
+ 	  ret = walk_tree (gimple_call_lhs_ptr (stmt), callback_op, wi, pset);
+ 	  if (ret)
+ 	    return ret;
+ 	}
+ 
+       if (wi)
+ 	{
+ 	  wi->is_lhs = false;
+ 	  wi->val_only = true;
+ 	}
+       break;
+ 
+     case GIMPLE_CATCH:
+       ret = walk_tree (gimple_catch_types_ptr (stmt), callback_op, wi,
+ 		       pset);
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_EH_FILTER:
+       ret = walk_tree (gimple_eh_filter_types_ptr (stmt), callback_op, wi,
+ 		       pset);
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_ASM:
+       ret = walk_gimple_asm (stmt, callback_op, wi);
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_OMP_CONTINUE:
+       ret = walk_tree (gimple_omp_continue_control_def_ptr (stmt),
+ 	  	       callback_op, wi, pset);
+       if (ret)
+ 	return ret;
+ 
+       ret = walk_tree (gimple_omp_continue_control_use_ptr (stmt),
+ 	  	       callback_op, wi, pset);
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_OMP_CRITICAL:
+       ret = walk_tree (gimple_omp_critical_name_ptr (stmt), callback_op, wi,
+ 		       pset);
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_OMP_FOR:
+       ret = walk_tree (gimple_omp_for_clauses_ptr (stmt), callback_op, wi,
+ 		       pset);
+       if (ret)
+ 	return ret;
+       for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
+ 	{
+ 	  ret = walk_tree (gimple_omp_for_index_ptr (stmt, i), callback_op,
+ 			   wi, pset);
+ 	  if (ret)
+ 	    return ret;
+ 	  ret = walk_tree (gimple_omp_for_initial_ptr (stmt, i), callback_op,
+ 			   wi, pset);
+ 	  if (ret)
+ 	    return ret;
+ 	  ret = walk_tree (gimple_omp_for_final_ptr (stmt, i), callback_op,
+ 			   wi, pset);
+ 	  if (ret)
+ 	    return ret;
+ 	  ret = walk_tree (gimple_omp_for_incr_ptr (stmt, i), callback_op,
+ 			   wi, pset);
+ 	}
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_OMP_PARALLEL:
+       ret = walk_tree (gimple_omp_parallel_clauses_ptr (stmt), callback_op,
+ 		       wi, pset);
+       if (ret)
+ 	return ret;
+       ret = walk_tree (gimple_omp_parallel_child_fn_ptr (stmt), callback_op,
+ 		       wi, pset);
+       if (ret)
+ 	return ret;
+       ret = walk_tree (gimple_omp_parallel_data_arg_ptr (stmt), callback_op,
+ 		       wi, pset);
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_OMP_TASK:
+       ret = walk_tree (gimple_omp_task_clauses_ptr (stmt), callback_op,
+ 		       wi, pset);
+       if (ret)
+ 	return ret;
+       ret = walk_tree (gimple_omp_task_child_fn_ptr (stmt), callback_op,
+ 		       wi, pset);
+       if (ret)
+ 	return ret;
+       ret = walk_tree (gimple_omp_task_data_arg_ptr (stmt), callback_op,
+ 		       wi, pset);
+       if (ret)
+ 	return ret;
+       ret = walk_tree (gimple_omp_task_copy_fn_ptr (stmt), callback_op,
+ 		       wi, pset);
+       if (ret)
+ 	return ret;
+       ret = walk_tree (gimple_omp_task_arg_size_ptr (stmt), callback_op,
+ 		       wi, pset);
+       if (ret)
+ 	return ret;
+       ret = walk_tree (gimple_omp_task_arg_align_ptr (stmt), callback_op,
+ 		       wi, pset);
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_OMP_SECTIONS:
+       ret = walk_tree (gimple_omp_sections_clauses_ptr (stmt), callback_op,
+ 		       wi, pset);
+       if (ret)
+ 	return ret;
+ 
+       ret = walk_tree (gimple_omp_sections_control_ptr (stmt), callback_op,
+ 		       wi, pset);
+       if (ret)
+ 	return ret;
+ 
+       break;
+ 
+     case GIMPLE_OMP_SINGLE:
+       ret = walk_tree (gimple_omp_single_clauses_ptr (stmt), callback_op, wi,
+ 		       pset);
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_OMP_TARGET:
+       ret = walk_tree (gimple_omp_target_clauses_ptr (stmt), callback_op, wi,
+ 		       pset);
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_OMP_TEAMS:
+       ret = walk_tree (gimple_omp_teams_clauses_ptr (stmt), callback_op, wi,
+ 		       pset);
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_OMP_ATOMIC_LOAD:
+       ret = walk_tree (gimple_omp_atomic_load_lhs_ptr (stmt), callback_op, wi,
+ 		       pset);
+       if (ret)
+ 	return ret;
+ 
+       ret = walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt), callback_op, wi,
+ 		       pset);
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_OMP_ATOMIC_STORE:
+       ret = walk_tree (gimple_omp_atomic_store_val_ptr (stmt), callback_op,
+ 		       wi, pset);
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_TRANSACTION:
+       ret = walk_tree (gimple_transaction_label_ptr (stmt), callback_op,
+ 		       wi, pset);
+       if (ret)
+ 	return ret;
+       break;
+ 
+     case GIMPLE_OMP_RETURN:
+       ret = walk_tree (gimple_omp_return_lhs_ptr (stmt), callback_op, wi,
+ 		       pset);
+       if (ret)
+ 	return ret;
+       break;
+ 
+       /* Tuples that do not have operands.  */
+     case GIMPLE_NOP:
+     case GIMPLE_RESX:
+     case GIMPLE_PREDICT:
+       break;
+ 
+     default:
+       {
+ 	enum gimple_statement_structure_enum gss;
+ 	gss = gimple_statement_structure (stmt);
+ 	if (gss == GSS_WITH_OPS || gss == GSS_WITH_MEM_OPS)
+ 	  for (i = 0; i < gimple_num_ops (stmt); i++)
+ 	    {
+ 	      ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi, pset);
+ 	      if (ret)
+ 		return ret;
+ 	    }
+       }
+       break;
+     }
+ 
+   return NULL_TREE;
+ }
+ 
+ 
+ /* Walk the current statement in GSI (optionally using traversal state
+    stored in WI).  If WI is NULL, no state is kept during traversal.
+    The callback CALLBACK_STMT is called.  If CALLBACK_STMT indicates
+    that it has handled all the operands of the statement, its return
+    value is returned.  Otherwise, the return value from CALLBACK_STMT
+    is discarded and its operands are scanned.
+ 
+    If CALLBACK_STMT is NULL or it didn't handle the operands,
+    CALLBACK_OP is called on each operand of the statement via
+    walk_gimple_op.  If walk_gimple_op returns non-NULL for any
+    operand, the remaining operands are not scanned.  In this case, the
+    return value from CALLBACK_OP is returned.
+ 
+    In any other case, NULL_TREE is returned.  */
+ 
+ tree
+ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
+ 		  walk_tree_fn callback_op, struct walk_stmt_info *wi)
+ {
+   gimple ret;
+   tree tree_ret;
+   gimple stmt = gsi_stmt (*gsi);
+ 
+   if (wi)
+     {
+       wi->gsi = *gsi;
+       wi->removed_stmt = false;
+ 
+       if (wi->want_locations && gimple_has_location (stmt))
+ 	input_location = gimple_location (stmt);
+     }
+ 
+   ret = NULL;
+ 
+   /* Invoke the statement callback.  Return if the callback handled
+      all of STMT operands by itself.  */
+   if (callback_stmt)
+     {
+       bool handled_ops = false;
+       tree_ret = callback_stmt (gsi, &handled_ops, wi);
+       if (handled_ops)
+ 	return tree_ret;
+ 
+       /* If CALLBACK_STMT did not handle operands, it should not have
+ 	 a value to return.  */
+       gcc_assert (tree_ret == NULL);
+ 
+       if (wi && wi->removed_stmt)
+ 	return NULL;
+ 
+       /* Re-read stmt in case the callback changed it.  */
+       stmt = gsi_stmt (*gsi);
+     }
+ 
+   /* If CALLBACK_OP is defined, invoke it on every operand of STMT.  */
+   if (callback_op)
+     {
+       tree_ret = walk_gimple_op (stmt, callback_op, wi);
+       if (tree_ret)
+ 	return tree_ret;
+     }
+ 
+   /* If STMT can have statements inside (e.g. GIMPLE_BIND), walk them.  */
+   switch (gimple_code (stmt))
+     {
+     case GIMPLE_BIND:
+       ret = walk_gimple_seq_mod (gimple_bind_body_ptr (stmt), callback_stmt,
+ 				 callback_op, wi);
+       if (ret)
+ 	return wi->callback_result;
+       break;
+ 
+     case GIMPLE_CATCH:
+       ret = walk_gimple_seq_mod (gimple_catch_handler_ptr (stmt), callback_stmt,
+ 				 callback_op, wi);
+       if (ret)
+ 	return wi->callback_result;
+       break;
+ 
+     case GIMPLE_EH_FILTER:
+       ret = walk_gimple_seq_mod (gimple_eh_filter_failure_ptr (stmt), callback_stmt,
+ 		             callback_op, wi);
+       if (ret)
+ 	return wi->callback_result;
+       break;
+ 
+     case GIMPLE_EH_ELSE:
+       ret = walk_gimple_seq_mod (gimple_eh_else_n_body_ptr (stmt),
+ 			     callback_stmt, callback_op, wi);
+       if (ret)
+ 	return wi->callback_result;
+       ret = walk_gimple_seq_mod (gimple_eh_else_e_body_ptr (stmt),
+ 			     callback_stmt, callback_op, wi);
+       if (ret)
+ 	return wi->callback_result;
+       break;
+ 
+     case GIMPLE_TRY:
+       ret = walk_gimple_seq_mod (gimple_try_eval_ptr (stmt), callback_stmt, callback_op,
+ 	                     wi);
+       if (ret)
+ 	return wi->callback_result;
+ 
+       ret = walk_gimple_seq_mod (gimple_try_cleanup_ptr (stmt), callback_stmt,
+ 	                     callback_op, wi);
+       if (ret)
+ 	return wi->callback_result;
+       break;
+ 
+     case GIMPLE_OMP_FOR:
+       ret = walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt), callback_stmt,
+ 		             callback_op, wi);
+       if (ret)
+ 	return wi->callback_result;
+ 
+       /* FALL THROUGH.  */
+     case GIMPLE_OMP_CRITICAL:
+     case GIMPLE_OMP_MASTER:
+     case GIMPLE_OMP_TASKGROUP:
+     case GIMPLE_OMP_ORDERED:
+     case GIMPLE_OMP_SECTION:
+     case GIMPLE_OMP_PARALLEL:
+     case GIMPLE_OMP_TASK:
+     case GIMPLE_OMP_SECTIONS:
+     case GIMPLE_OMP_SINGLE:
+     case GIMPLE_OMP_TARGET:
+     case GIMPLE_OMP_TEAMS:
+       ret = walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), callback_stmt,
+ 			     callback_op, wi);
+       if (ret)
+ 	return wi->callback_result;
+       break;
+ 
+     case GIMPLE_WITH_CLEANUP_EXPR:
+       ret = walk_gimple_seq_mod (gimple_wce_cleanup_ptr (stmt), callback_stmt,
+ 			     callback_op, wi);
+       if (ret)
+ 	return wi->callback_result;
+       break;
+ 
+     case GIMPLE_TRANSACTION:
+       ret = walk_gimple_seq_mod (gimple_transaction_body_ptr (stmt),
+ 			     callback_stmt, callback_op, wi);
+       if (ret)
+ 	return wi->callback_result;
+       break;
+ 
+     default:
+       gcc_assert (!gimple_has_substatements (stmt));
+       break;
+     }
+ 
+   return NULL;
+ }
+ 
+ /* 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.  */
+ 
+ static tree
+ get_base_loadstore (tree op)
+ {
+   while (handled_component_p (op))
+     op = TREE_OPERAND (op, 0);
+   if (DECL_P (op)
+       || INDIRECT_REF_P (op)
+       || TREE_CODE (op) == MEM_REF
+       || TREE_CODE (op) == TARGET_MEM_REF)
+     return op;
+   return NULL_TREE;
+ }
+ 
+ 
+ /* For the statement STMT call the callbacks VISIT_LOAD, VISIT_STORE and
+    VISIT_ADDR if non-NULL on loads, store and address-taken operands
+    passing the STMT, the base of the operand and DATA to it.  The base
+    will be either a decl, an indirect reference (including TARGET_MEM_REF)
+    or the argument of an address expression.
+    Returns the results of these callbacks or'ed.  */
+ 
+ bool
+ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
+ 			       bool (*visit_load)(gimple, tree, void *),
+ 			       bool (*visit_store)(gimple, tree, void *),
+ 			       bool (*visit_addr)(gimple, tree, void *))
+ {
+   bool ret = false;
+   unsigned i;
+   if (gimple_assign_single_p (stmt))
+     {
+       tree lhs, rhs;
+       if (visit_store)
+ 	{
+ 	  lhs = get_base_loadstore (gimple_assign_lhs (stmt));
+ 	  if (lhs)
+ 	    ret |= visit_store (stmt, lhs, data);
+ 	}
+       rhs = gimple_assign_rhs1 (stmt);
+       while (handled_component_p (rhs))
+ 	rhs = TREE_OPERAND (rhs, 0);
+       if (visit_addr)
+ 	{
+ 	  if (TREE_CODE (rhs) == ADDR_EXPR)
+ 	    ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
+ 	  else if (TREE_CODE (rhs) == TARGET_MEM_REF
+ 		   && TREE_CODE (TMR_BASE (rhs)) == ADDR_EXPR)
+ 	    ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), data);
+ 	  else if (TREE_CODE (rhs) == OBJ_TYPE_REF
+ 		   && TREE_CODE (OBJ_TYPE_REF_OBJECT (rhs)) == ADDR_EXPR)
+ 	    ret |= visit_addr (stmt, TREE_OPERAND (OBJ_TYPE_REF_OBJECT (rhs),
+ 						   0), data);
+ 	  else if (TREE_CODE (rhs) == CONSTRUCTOR)
+ 	    {
+ 	      unsigned int ix;
+ 	      tree val;
+ 
+ 	      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), ix, val)
+ 		if (TREE_CODE (val) == ADDR_EXPR)
+ 		  ret |= visit_addr (stmt, TREE_OPERAND (val, 0), data);
+ 		else if (TREE_CODE (val) == OBJ_TYPE_REF
+ 			 && TREE_CODE (OBJ_TYPE_REF_OBJECT (val)) == ADDR_EXPR)
+ 		  ret |= visit_addr (stmt,
+ 				     TREE_OPERAND (OBJ_TYPE_REF_OBJECT (val),
+ 						   0), data);
+ 	    }
+           lhs = gimple_assign_lhs (stmt);
+ 	  if (TREE_CODE (lhs) == TARGET_MEM_REF
+               && TREE_CODE (TMR_BASE (lhs)) == ADDR_EXPR)
+             ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 0), data);
+ 	}
+       if (visit_load)
+ 	{
+ 	  rhs = get_base_loadstore (rhs);
+ 	  if (rhs)
+ 	    ret |= visit_load (stmt, rhs, data);
+ 	}
+     }
+   else if (visit_addr
+ 	   && (is_gimple_assign (stmt)
+ 	       || gimple_code (stmt) == GIMPLE_COND))
+     {
+       for (i = 0; i < gimple_num_ops (stmt); ++i)
+ 	{
+ 	  tree op = gimple_op (stmt, i);
+ 	  if (op == NULL_TREE)
+ 	    ;
+ 	  else if (TREE_CODE (op) == ADDR_EXPR)
+ 	    ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+ 	  /* COND_EXPR and VCOND_EXPR rhs1 argument is a comparison
+ 	     tree with two operands.  */
+ 	  else if (i == 1 && COMPARISON_CLASS_P (op))
+ 	    {
+ 	      if (TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
+ 		ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 0),
+ 						       0), data);
+ 	      if (TREE_CODE (TREE_OPERAND (op, 1)) == ADDR_EXPR)
+ 		ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 1),
+ 						       0), data);
+ 	    }
+ 	}
+     }
+   else if (is_gimple_call (stmt))
+     {
+       if (visit_store)
+ 	{
+ 	  tree lhs = gimple_call_lhs (stmt);
+ 	  if (lhs)
+ 	    {
+ 	      lhs = get_base_loadstore (lhs);
+ 	      if (lhs)
+ 		ret |= visit_store (stmt, lhs, data);
+ 	    }
+ 	}
+       if (visit_load || visit_addr)
+ 	for (i = 0; i < gimple_call_num_args (stmt); ++i)
+ 	  {
+ 	    tree rhs = gimple_call_arg (stmt, i);
+ 	    if (visit_addr
+ 		&& TREE_CODE (rhs) == ADDR_EXPR)
+ 	      ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
+ 	    else if (visit_load)
+ 	      {
+ 		rhs = get_base_loadstore (rhs);
+ 		if (rhs)
+ 		  ret |= visit_load (stmt, rhs, data);
+ 	      }
+ 	  }
+       if (visit_addr
+ 	  && gimple_call_chain (stmt)
+ 	  && TREE_CODE (gimple_call_chain (stmt)) == ADDR_EXPR)
+ 	ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (stmt), 0),
+ 			   data);
+       if (visit_addr
+ 	  && gimple_call_return_slot_opt_p (stmt)
+ 	  && gimple_call_lhs (stmt) != NULL_TREE
+ 	  && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt))))
+ 	ret |= visit_addr (stmt, gimple_call_lhs (stmt), data);
+     }
+   else if (gimple_code (stmt) == GIMPLE_ASM)
+     {
+       unsigned noutputs;
+       const char *constraint;
+       const char **oconstraints;
+       bool allows_mem, allows_reg, is_inout;
+       noutputs = gimple_asm_noutputs (stmt);
+       oconstraints = XALLOCAVEC (const char *, noutputs);
+       if (visit_store || visit_addr)
+ 	for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
+ 	  {
+ 	    tree link = gimple_asm_output_op (stmt, i);
+ 	    tree op = get_base_loadstore (TREE_VALUE (link));
+ 	    if (op && visit_store)
+ 	      ret |= visit_store (stmt, op, data);
+ 	    if (visit_addr)
+ 	      {
+ 		constraint = TREE_STRING_POINTER
+ 		    (TREE_VALUE (TREE_PURPOSE (link)));
+ 		oconstraints[i] = constraint;
+ 		parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
+ 					 &allows_reg, &is_inout);
+ 		if (op && !allows_reg && allows_mem)
+ 		  ret |= visit_addr (stmt, op, data);
+ 	      }
+ 	  }
+       if (visit_load || visit_addr)
+ 	for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
+ 	  {
+ 	    tree link = gimple_asm_input_op (stmt, i);
+ 	    tree op = TREE_VALUE (link);
+ 	    if (visit_addr
+ 		&& TREE_CODE (op) == ADDR_EXPR)
+ 	      ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+ 	    else if (visit_load || visit_addr)
+ 	      {
+ 		op = get_base_loadstore (op);
+ 		if (op)
+ 		  {
+ 		    if (visit_load)
+ 		      ret |= visit_load (stmt, op, data);
+ 		    if (visit_addr)
+ 		      {
+ 			constraint = TREE_STRING_POINTER
+ 			    (TREE_VALUE (TREE_PURPOSE (link)));
+ 			parse_input_constraint (&constraint, 0, 0, noutputs,
+ 						0, oconstraints,
+ 						&allows_mem, &allows_reg);
+ 			if (!allows_reg && allows_mem)
+ 			  ret |= visit_addr (stmt, op, data);
+ 		      }
+ 		  }
+ 	      }
+ 	  }
+     }
+   else if (gimple_code (stmt) == GIMPLE_RETURN)
+     {
+       tree op = gimple_return_retval (stmt);
+       if (op)
+ 	{
+ 	  if (visit_addr
+ 	      && TREE_CODE (op) == ADDR_EXPR)
+ 	    ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+ 	  else if (visit_load)
+ 	    {
+ 	      op = get_base_loadstore (op);
+ 	      if (op)
+ 		ret |= visit_load (stmt, op, data);
+ 	    }
+ 	}
+     }
+   else if (visit_addr
+ 	   && gimple_code (stmt) == GIMPLE_PHI)
+     {
+       for (i = 0; i < gimple_phi_num_args (stmt); ++i)
+ 	{
+ 	  tree op = gimple_phi_arg_def (stmt, i);
+ 	  if (TREE_CODE (op) == ADDR_EXPR)
+ 	    ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+ 	}
+     }
+   else if (visit_addr
+ 	   && gimple_code (stmt) == GIMPLE_GOTO)
+     {
+       tree op = gimple_goto_dest (stmt);
+       if (TREE_CODE (op) == ADDR_EXPR)
+ 	ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+     }
+ 
+   return ret;
+ }
+ 
+ /* Like walk_stmt_load_store_addr_ops but with NULL visit_addr.  IPA-CP
+    should make a faster clone for this case.  */
+ 
+ bool
+ walk_stmt_load_store_ops (gimple stmt, void *data,
+ 			  bool (*visit_load)(gimple, tree, void *),
+ 			  bool (*visit_store)(gimple, tree, void *))
+ {
+   return walk_stmt_load_store_addr_ops (stmt, data,
+ 					visit_load, visit_store, NULL);
+ }
Index: gimple-iterator.c
===================================================================
*** gimple-iterator.c	(revision 204721)
--- gimple-iterator.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 24,29 ****
--- 24,30 ----
  #include "tm.h"
  #include "tree.h"
  #include "gimple.h"
+ #include "gimple-iterator.h"
  #include "gimple-ssa.h"
  #include "cgraph.h"
  #include "tree-cfg.h"
Index: gimple.c
===================================================================
*** gimple.c	(revision 204721)
--- gimple.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 29,34 ****
--- 29,36 ----
  #include "hard-reg-set.h"
  #include "basic-block.h"
  #include "gimple.h"
+ #include "gimple-iterator.h"
+ #include "gimple-walk.h"
  #include "gimplify.h"
  #include "diagnostic.h"
  #include "value-prof.h"
*************** gimple_seq_copy (gimple_seq src)
*** 1297,1896 ****
  }
  
  
- /* Walk all the statements in the sequence *PSEQ calling walk_gimple_stmt
-    on each one.  WI is as in walk_gimple_stmt.
- 
-    If walk_gimple_stmt returns non-NULL, the walk is stopped, and the
-    value is stored in WI->CALLBACK_RESULT.  Also, the statement that
-    produced the value is returned if this statement has not been
-    removed by a callback (wi->removed_stmt).  If the statement has
-    been removed, NULL is returned.
- 
-    Otherwise, all the statements are walked and NULL returned.  */
- 
- gimple
- walk_gimple_seq_mod (gimple_seq *pseq, walk_stmt_fn callback_stmt,
- 		     walk_tree_fn callback_op, struct walk_stmt_info *wi)
- {
-   gimple_stmt_iterator gsi;
- 
-   for (gsi = gsi_start (*pseq); !gsi_end_p (gsi); )
-     {
-       tree ret = walk_gimple_stmt (&gsi, callback_stmt, callback_op, wi);
-       if (ret)
- 	{
- 	  /* If CALLBACK_STMT or CALLBACK_OP return a value, WI must exist
- 	     to hold it.  */
- 	  gcc_assert (wi);
- 	  wi->callback_result = ret;
- 
- 	  return wi->removed_stmt ? NULL : gsi_stmt (gsi);
- 	}
- 
-       if (!wi->removed_stmt)
- 	gsi_next (&gsi);
-     }
- 
-   if (wi)
-     wi->callback_result = NULL_TREE;
- 
-   return NULL;
- }
- 
- 
- /* Like walk_gimple_seq_mod, but ensure that the head of SEQ isn't
-    changed by the callbacks.  */
- 
- gimple
- walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt,
- 		 walk_tree_fn callback_op, struct walk_stmt_info *wi)
- {
-   gimple_seq seq2 = seq;
-   gimple ret = walk_gimple_seq_mod (&seq2, callback_stmt, callback_op, wi);
-   gcc_assert (seq2 == seq);
-   return ret;
- }
- 
- 
- /* Helper function for walk_gimple_stmt.  Walk operands of a GIMPLE_ASM.  */
- 
- static tree
- walk_gimple_asm (gimple stmt, walk_tree_fn callback_op,
- 		 struct walk_stmt_info *wi)
- {
-   tree ret, op;
-   unsigned noutputs;
-   const char **oconstraints;
-   unsigned i, n;
-   const char *constraint;
-   bool allows_mem, allows_reg, is_inout;
- 
-   noutputs = gimple_asm_noutputs (stmt);
-   oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
- 
-   if (wi)
-     wi->is_lhs = true;
- 
-   for (i = 0; i < noutputs; i++)
-     {
-       op = gimple_asm_output_op (stmt, i);
-       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
-       oconstraints[i] = constraint;
-       parse_output_constraint (&constraint, i, 0, 0, &allows_mem, &allows_reg,
- 	                       &is_inout);
-       if (wi)
- 	wi->val_only = (allows_reg || !allows_mem);
-       ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
-       if (ret)
- 	return ret;
-     }
- 
-   n = gimple_asm_ninputs (stmt);
-   for (i = 0; i < n; i++)
-     {
-       op = gimple_asm_input_op (stmt, i);
-       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
-       parse_input_constraint (&constraint, 0, 0, noutputs, 0,
- 			      oconstraints, &allows_mem, &allows_reg);
-       if (wi)
- 	{
- 	  wi->val_only = (allows_reg || !allows_mem);
-           /* Although input "m" is not really a LHS, we need a lvalue.  */
- 	  wi->is_lhs = !wi->val_only;
- 	}
-       ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
-       if (ret)
- 	return ret;
-     }
- 
-   if (wi)
-     {
-       wi->is_lhs = false;
-       wi->val_only = true;
-     }
- 
-   n = gimple_asm_nlabels (stmt);
-   for (i = 0; i < n; i++)
-     {
-       op = gimple_asm_label_op (stmt, i);
-       ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL);
-       if (ret)
- 	return ret;
-     }
- 
-   return NULL_TREE;
- }
- 
- 
- /* Helper function of WALK_GIMPLE_STMT.  Walk every tree operand in
-    STMT.  CALLBACK_OP and WI are as in WALK_GIMPLE_STMT.
- 
-    CALLBACK_OP is called on each operand of STMT via walk_tree.
-    Additional parameters to walk_tree must be stored in WI.  For each operand
-    OP, walk_tree is called as:
- 
- 	walk_tree (&OP, CALLBACK_OP, WI, WI->PSET)
- 
-    If CALLBACK_OP returns non-NULL for an operand, the remaining
-    operands are not scanned.
- 
-    The return value is that returned by the last call to walk_tree, or
-    NULL_TREE if no CALLBACK_OP is specified.  */
- 
- tree
- walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
- 		struct walk_stmt_info *wi)
- {
-   struct pointer_set_t *pset = (wi) ? wi->pset : NULL;
-   unsigned i;
-   tree ret = NULL_TREE;
- 
-   switch (gimple_code (stmt))
-     {
-     case GIMPLE_ASSIGN:
-       /* Walk the RHS operands.  If the LHS is of a non-renamable type or
-          is a register variable, we may use a COMPONENT_REF on the RHS.  */
-       if (wi)
- 	{
- 	  tree lhs = gimple_assign_lhs (stmt);
- 	  wi->val_only
- 	    = (is_gimple_reg_type (TREE_TYPE (lhs)) && !is_gimple_reg (lhs))
- 	      || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
- 	}
- 
-       for (i = 1; i < gimple_num_ops (stmt); i++)
- 	{
- 	  ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi,
- 			   pset);
- 	  if (ret)
- 	    return ret;
- 	}
- 
-       /* Walk the LHS.  If the RHS is appropriate for a memory, we
- 	 may use a COMPONENT_REF on the LHS.  */
-       if (wi)
- 	{
-           /* If the RHS is of a non-renamable type or is a register variable,
- 	     we may use a COMPONENT_REF on the LHS.  */
- 	  tree rhs1 = gimple_assign_rhs1 (stmt);
- 	  wi->val_only
- 	    = (is_gimple_reg_type (TREE_TYPE (rhs1)) && !is_gimple_reg (rhs1))
- 	      || gimple_assign_rhs_class (stmt) != GIMPLE_SINGLE_RHS;
- 	  wi->is_lhs = true;
- 	}
- 
-       ret = walk_tree (gimple_op_ptr (stmt, 0), callback_op, wi, pset);
-       if (ret)
- 	return ret;
- 
-       if (wi)
- 	{
- 	  wi->val_only = true;
- 	  wi->is_lhs = false;
- 	}
-       break;
- 
-     case GIMPLE_CALL:
-       if (wi)
- 	{
- 	  wi->is_lhs = false;
- 	  wi->val_only = true;
- 	}
- 
-       ret = walk_tree (gimple_call_chain_ptr (stmt), callback_op, wi, pset);
-       if (ret)
-         return ret;
- 
-       ret = walk_tree (gimple_call_fn_ptr (stmt), callback_op, wi, pset);
-       if (ret)
-         return ret;
- 
-       for (i = 0; i < gimple_call_num_args (stmt); i++)
- 	{
- 	  if (wi)
- 	    wi->val_only
- 	      = is_gimple_reg_type (TREE_TYPE (gimple_call_arg (stmt, i)));
- 	  ret = walk_tree (gimple_call_arg_ptr (stmt, i), callback_op, wi,
- 			   pset);
- 	  if (ret)
- 	    return ret;
- 	}
- 
-       if (gimple_call_lhs (stmt))
- 	{
- 	  if (wi)
- 	    {
- 	      wi->is_lhs = true;
- 	      wi->val_only
- 		= is_gimple_reg_type (TREE_TYPE (gimple_call_lhs (stmt)));
- 	    }
- 
- 	  ret = walk_tree (gimple_call_lhs_ptr (stmt), callback_op, wi, pset);
- 	  if (ret)
- 	    return ret;
- 	}
- 
-       if (wi)
- 	{
- 	  wi->is_lhs = false;
- 	  wi->val_only = true;
- 	}
-       break;
- 
-     case GIMPLE_CATCH:
-       ret = walk_tree (gimple_catch_types_ptr (stmt), callback_op, wi,
- 		       pset);
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_EH_FILTER:
-       ret = walk_tree (gimple_eh_filter_types_ptr (stmt), callback_op, wi,
- 		       pset);
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_ASM:
-       ret = walk_gimple_asm (stmt, callback_op, wi);
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_OMP_CONTINUE:
-       ret = walk_tree (gimple_omp_continue_control_def_ptr (stmt),
- 	  	       callback_op, wi, pset);
-       if (ret)
- 	return ret;
- 
-       ret = walk_tree (gimple_omp_continue_control_use_ptr (stmt),
- 	  	       callback_op, wi, pset);
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_OMP_CRITICAL:
-       ret = walk_tree (gimple_omp_critical_name_ptr (stmt), callback_op, wi,
- 		       pset);
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_OMP_FOR:
-       ret = walk_tree (gimple_omp_for_clauses_ptr (stmt), callback_op, wi,
- 		       pset);
-       if (ret)
- 	return ret;
-       for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
- 	{
- 	  ret = walk_tree (gimple_omp_for_index_ptr (stmt, i), callback_op,
- 			   wi, pset);
- 	  if (ret)
- 	    return ret;
- 	  ret = walk_tree (gimple_omp_for_initial_ptr (stmt, i), callback_op,
- 			   wi, pset);
- 	  if (ret)
- 	    return ret;
- 	  ret = walk_tree (gimple_omp_for_final_ptr (stmt, i), callback_op,
- 			   wi, pset);
- 	  if (ret)
- 	    return ret;
- 	  ret = walk_tree (gimple_omp_for_incr_ptr (stmt, i), callback_op,
- 			   wi, pset);
- 	}
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_OMP_PARALLEL:
-       ret = walk_tree (gimple_omp_parallel_clauses_ptr (stmt), callback_op,
- 		       wi, pset);
-       if (ret)
- 	return ret;
-       ret = walk_tree (gimple_omp_parallel_child_fn_ptr (stmt), callback_op,
- 		       wi, pset);
-       if (ret)
- 	return ret;
-       ret = walk_tree (gimple_omp_parallel_data_arg_ptr (stmt), callback_op,
- 		       wi, pset);
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_OMP_TASK:
-       ret = walk_tree (gimple_omp_task_clauses_ptr (stmt), callback_op,
- 		       wi, pset);
-       if (ret)
- 	return ret;
-       ret = walk_tree (gimple_omp_task_child_fn_ptr (stmt), callback_op,
- 		       wi, pset);
-       if (ret)
- 	return ret;
-       ret = walk_tree (gimple_omp_task_data_arg_ptr (stmt), callback_op,
- 		       wi, pset);
-       if (ret)
- 	return ret;
-       ret = walk_tree (gimple_omp_task_copy_fn_ptr (stmt), callback_op,
- 		       wi, pset);
-       if (ret)
- 	return ret;
-       ret = walk_tree (gimple_omp_task_arg_size_ptr (stmt), callback_op,
- 		       wi, pset);
-       if (ret)
- 	return ret;
-       ret = walk_tree (gimple_omp_task_arg_align_ptr (stmt), callback_op,
- 		       wi, pset);
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_OMP_SECTIONS:
-       ret = walk_tree (gimple_omp_sections_clauses_ptr (stmt), callback_op,
- 		       wi, pset);
-       if (ret)
- 	return ret;
- 
-       ret = walk_tree (gimple_omp_sections_control_ptr (stmt), callback_op,
- 		       wi, pset);
-       if (ret)
- 	return ret;
- 
-       break;
- 
-     case GIMPLE_OMP_SINGLE:
-       ret = walk_tree (gimple_omp_single_clauses_ptr (stmt), callback_op, wi,
- 		       pset);
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_OMP_TARGET:
-       ret = walk_tree (gimple_omp_target_clauses_ptr (stmt), callback_op, wi,
- 		       pset);
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_OMP_TEAMS:
-       ret = walk_tree (gimple_omp_teams_clauses_ptr (stmt), callback_op, wi,
- 		       pset);
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_OMP_ATOMIC_LOAD:
-       ret = walk_tree (gimple_omp_atomic_load_lhs_ptr (stmt), callback_op, wi,
- 		       pset);
-       if (ret)
- 	return ret;
- 
-       ret = walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt), callback_op, wi,
- 		       pset);
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_OMP_ATOMIC_STORE:
-       ret = walk_tree (gimple_omp_atomic_store_val_ptr (stmt), callback_op,
- 		       wi, pset);
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_TRANSACTION:
-       ret = walk_tree (gimple_transaction_label_ptr (stmt), callback_op,
- 		       wi, pset);
-       if (ret)
- 	return ret;
-       break;
- 
-     case GIMPLE_OMP_RETURN:
-       ret = walk_tree (gimple_omp_return_lhs_ptr (stmt), callback_op, wi,
- 		       pset);
-       if (ret)
- 	return ret;
-       break;
- 
-       /* Tuples that do not have operands.  */
-     case GIMPLE_NOP:
-     case GIMPLE_RESX:
-     case GIMPLE_PREDICT:
-       break;
- 
-     default:
-       {
- 	enum gimple_statement_structure_enum gss;
- 	gss = gimple_statement_structure (stmt);
- 	if (gss == GSS_WITH_OPS || gss == GSS_WITH_MEM_OPS)
- 	  for (i = 0; i < gimple_num_ops (stmt); i++)
- 	    {
- 	      ret = walk_tree (gimple_op_ptr (stmt, i), callback_op, wi, pset);
- 	      if (ret)
- 		return ret;
- 	    }
-       }
-       break;
-     }
- 
-   return NULL_TREE;
- }
- 
- 
- /* Walk the current statement in GSI (optionally using traversal state
-    stored in WI).  If WI is NULL, no state is kept during traversal.
-    The callback CALLBACK_STMT is called.  If CALLBACK_STMT indicates
-    that it has handled all the operands of the statement, its return
-    value is returned.  Otherwise, the return value from CALLBACK_STMT
-    is discarded and its operands are scanned.
- 
-    If CALLBACK_STMT is NULL or it didn't handle the operands,
-    CALLBACK_OP is called on each operand of the statement via
-    walk_gimple_op.  If walk_gimple_op returns non-NULL for any
-    operand, the remaining operands are not scanned.  In this case, the
-    return value from CALLBACK_OP is returned.
- 
-    In any other case, NULL_TREE is returned.  */
- 
- tree
- walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
- 		  walk_tree_fn callback_op, struct walk_stmt_info *wi)
- {
-   gimple ret;
-   tree tree_ret;
-   gimple stmt = gsi_stmt (*gsi);
- 
-   if (wi)
-     {
-       wi->gsi = *gsi;
-       wi->removed_stmt = false;
- 
-       if (wi->want_locations && gimple_has_location (stmt))
- 	input_location = gimple_location (stmt);
-     }
- 
-   ret = NULL;
- 
-   /* Invoke the statement callback.  Return if the callback handled
-      all of STMT operands by itself.  */
-   if (callback_stmt)
-     {
-       bool handled_ops = false;
-       tree_ret = callback_stmt (gsi, &handled_ops, wi);
-       if (handled_ops)
- 	return tree_ret;
- 
-       /* If CALLBACK_STMT did not handle operands, it should not have
- 	 a value to return.  */
-       gcc_assert (tree_ret == NULL);
- 
-       if (wi && wi->removed_stmt)
- 	return NULL;
- 
-       /* Re-read stmt in case the callback changed it.  */
-       stmt = gsi_stmt (*gsi);
-     }
- 
-   /* If CALLBACK_OP is defined, invoke it on every operand of STMT.  */
-   if (callback_op)
-     {
-       tree_ret = walk_gimple_op (stmt, callback_op, wi);
-       if (tree_ret)
- 	return tree_ret;
-     }
- 
-   /* If STMT can have statements inside (e.g. GIMPLE_BIND), walk them.  */
-   switch (gimple_code (stmt))
-     {
-     case GIMPLE_BIND:
-       ret = walk_gimple_seq_mod (gimple_bind_body_ptr (stmt), callback_stmt,
- 				 callback_op, wi);
-       if (ret)
- 	return wi->callback_result;
-       break;
- 
-     case GIMPLE_CATCH:
-       ret = walk_gimple_seq_mod (gimple_catch_handler_ptr (stmt), callback_stmt,
- 				 callback_op, wi);
-       if (ret)
- 	return wi->callback_result;
-       break;
- 
-     case GIMPLE_EH_FILTER:
-       ret = walk_gimple_seq_mod (gimple_eh_filter_failure_ptr (stmt), callback_stmt,
- 		             callback_op, wi);
-       if (ret)
- 	return wi->callback_result;
-       break;
- 
-     case GIMPLE_EH_ELSE:
-       ret = walk_gimple_seq_mod (gimple_eh_else_n_body_ptr (stmt),
- 			     callback_stmt, callback_op, wi);
-       if (ret)
- 	return wi->callback_result;
-       ret = walk_gimple_seq_mod (gimple_eh_else_e_body_ptr (stmt),
- 			     callback_stmt, callback_op, wi);
-       if (ret)
- 	return wi->callback_result;
-       break;
- 
-     case GIMPLE_TRY:
-       ret = walk_gimple_seq_mod (gimple_try_eval_ptr (stmt), callback_stmt, callback_op,
- 	                     wi);
-       if (ret)
- 	return wi->callback_result;
- 
-       ret = walk_gimple_seq_mod (gimple_try_cleanup_ptr (stmt), callback_stmt,
- 	                     callback_op, wi);
-       if (ret)
- 	return wi->callback_result;
-       break;
- 
-     case GIMPLE_OMP_FOR:
-       ret = walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt), callback_stmt,
- 		             callback_op, wi);
-       if (ret)
- 	return wi->callback_result;
- 
-       /* FALL THROUGH.  */
-     case GIMPLE_OMP_CRITICAL:
-     case GIMPLE_OMP_MASTER:
-     case GIMPLE_OMP_TASKGROUP:
-     case GIMPLE_OMP_ORDERED:
-     case GIMPLE_OMP_SECTION:
-     case GIMPLE_OMP_PARALLEL:
-     case GIMPLE_OMP_TASK:
-     case GIMPLE_OMP_SECTIONS:
-     case GIMPLE_OMP_SINGLE:
-     case GIMPLE_OMP_TARGET:
-     case GIMPLE_OMP_TEAMS:
-       ret = walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), callback_stmt,
- 			     callback_op, wi);
-       if (ret)
- 	return wi->callback_result;
-       break;
- 
-     case GIMPLE_WITH_CLEANUP_EXPR:
-       ret = walk_gimple_seq_mod (gimple_wce_cleanup_ptr (stmt), callback_stmt,
- 			     callback_op, wi);
-       if (ret)
- 	return wi->callback_result;
-       break;
- 
-     case GIMPLE_TRANSACTION:
-       ret = walk_gimple_seq_mod (gimple_transaction_body_ptr (stmt),
- 			     callback_stmt, callback_op, wi);
-       if (ret)
- 	return wi->callback_result;
-       break;
- 
-     default:
-       gcc_assert (!gimple_has_substatements (stmt));
-       break;
-     }
- 
-   return NULL;
- }
- 
  
  /* Return true if calls C1 and C2 are known to go to the same function.  */
  
--- 1299,1304 ----
*************** gimple_get_alias_set (tree t)
*** 2996,3246 ****
  }
  
  
- /* 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.  */
- 
- static tree
- get_base_loadstore (tree op)
- {
-   while (handled_component_p (op))
-     op = TREE_OPERAND (op, 0);
-   if (DECL_P (op)
-       || INDIRECT_REF_P (op)
-       || TREE_CODE (op) == MEM_REF
-       || TREE_CODE (op) == TARGET_MEM_REF)
-     return op;
-   return NULL_TREE;
- }
- 
- /* For the statement STMT call the callbacks VISIT_LOAD, VISIT_STORE and
-    VISIT_ADDR if non-NULL on loads, store and address-taken operands
-    passing the STMT, the base of the operand and DATA to it.  The base
-    will be either a decl, an indirect reference (including TARGET_MEM_REF)
-    or the argument of an address expression.
-    Returns the results of these callbacks or'ed.  */
- 
- bool
- walk_stmt_load_store_addr_ops (gimple stmt, void *data,
- 			       bool (*visit_load)(gimple, tree, void *),
- 			       bool (*visit_store)(gimple, tree, void *),
- 			       bool (*visit_addr)(gimple, tree, void *))
- {
-   bool ret = false;
-   unsigned i;
-   if (gimple_assign_single_p (stmt))
-     {
-       tree lhs, rhs;
-       if (visit_store)
- 	{
- 	  lhs = get_base_loadstore (gimple_assign_lhs (stmt));
- 	  if (lhs)
- 	    ret |= visit_store (stmt, lhs, data);
- 	}
-       rhs = gimple_assign_rhs1 (stmt);
-       while (handled_component_p (rhs))
- 	rhs = TREE_OPERAND (rhs, 0);
-       if (visit_addr)
- 	{
- 	  if (TREE_CODE (rhs) == ADDR_EXPR)
- 	    ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
- 	  else if (TREE_CODE (rhs) == TARGET_MEM_REF
- 		   && TREE_CODE (TMR_BASE (rhs)) == ADDR_EXPR)
- 	    ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), data);
- 	  else if (TREE_CODE (rhs) == OBJ_TYPE_REF
- 		   && TREE_CODE (OBJ_TYPE_REF_OBJECT (rhs)) == ADDR_EXPR)
- 	    ret |= visit_addr (stmt, TREE_OPERAND (OBJ_TYPE_REF_OBJECT (rhs),
- 						   0), data);
- 	  else if (TREE_CODE (rhs) == CONSTRUCTOR)
- 	    {
- 	      unsigned int ix;
- 	      tree val;
- 
- 	      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), ix, val)
- 		if (TREE_CODE (val) == ADDR_EXPR)
- 		  ret |= visit_addr (stmt, TREE_OPERAND (val, 0), data);
- 		else if (TREE_CODE (val) == OBJ_TYPE_REF
- 			 && TREE_CODE (OBJ_TYPE_REF_OBJECT (val)) == ADDR_EXPR)
- 		  ret |= visit_addr (stmt,
- 				     TREE_OPERAND (OBJ_TYPE_REF_OBJECT (val),
- 						   0), data);
- 	    }
-           lhs = gimple_assign_lhs (stmt);
- 	  if (TREE_CODE (lhs) == TARGET_MEM_REF
-               && TREE_CODE (TMR_BASE (lhs)) == ADDR_EXPR)
-             ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 0), data);
- 	}
-       if (visit_load)
- 	{
- 	  rhs = get_base_loadstore (rhs);
- 	  if (rhs)
- 	    ret |= visit_load (stmt, rhs, data);
- 	}
-     }
-   else if (visit_addr
- 	   && (is_gimple_assign (stmt)
- 	       || gimple_code (stmt) == GIMPLE_COND))
-     {
-       for (i = 0; i < gimple_num_ops (stmt); ++i)
- 	{
- 	  tree op = gimple_op (stmt, i);
- 	  if (op == NULL_TREE)
- 	    ;
- 	  else if (TREE_CODE (op) == ADDR_EXPR)
- 	    ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
- 	  /* COND_EXPR and VCOND_EXPR rhs1 argument is a comparison
- 	     tree with two operands.  */
- 	  else if (i == 1 && COMPARISON_CLASS_P (op))
- 	    {
- 	      if (TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
- 		ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 0),
- 						       0), data);
- 	      if (TREE_CODE (TREE_OPERAND (op, 1)) == ADDR_EXPR)
- 		ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 1),
- 						       0), data);
- 	    }
- 	}
-     }
-   else if (is_gimple_call (stmt))
-     {
-       if (visit_store)
- 	{
- 	  tree lhs = gimple_call_lhs (stmt);
- 	  if (lhs)
- 	    {
- 	      lhs = get_base_loadstore (lhs);
- 	      if (lhs)
- 		ret |= visit_store (stmt, lhs, data);
- 	    }
- 	}
-       if (visit_load || visit_addr)
- 	for (i = 0; i < gimple_call_num_args (stmt); ++i)
- 	  {
- 	    tree rhs = gimple_call_arg (stmt, i);
- 	    if (visit_addr
- 		&& TREE_CODE (rhs) == ADDR_EXPR)
- 	      ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
- 	    else if (visit_load)
- 	      {
- 		rhs = get_base_loadstore (rhs);
- 		if (rhs)
- 		  ret |= visit_load (stmt, rhs, data);
- 	      }
- 	  }
-       if (visit_addr
- 	  && gimple_call_chain (stmt)
- 	  && TREE_CODE (gimple_call_chain (stmt)) == ADDR_EXPR)
- 	ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (stmt), 0),
- 			   data);
-       if (visit_addr
- 	  && gimple_call_return_slot_opt_p (stmt)
- 	  && gimple_call_lhs (stmt) != NULL_TREE
- 	  && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt))))
- 	ret |= visit_addr (stmt, gimple_call_lhs (stmt), data);
-     }
-   else if (gimple_code (stmt) == GIMPLE_ASM)
-     {
-       unsigned noutputs;
-       const char *constraint;
-       const char **oconstraints;
-       bool allows_mem, allows_reg, is_inout;
-       noutputs = gimple_asm_noutputs (stmt);
-       oconstraints = XALLOCAVEC (const char *, noutputs);
-       if (visit_store || visit_addr)
- 	for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
- 	  {
- 	    tree link = gimple_asm_output_op (stmt, i);
- 	    tree op = get_base_loadstore (TREE_VALUE (link));
- 	    if (op && visit_store)
- 	      ret |= visit_store (stmt, op, data);
- 	    if (visit_addr)
- 	      {
- 		constraint = TREE_STRING_POINTER
- 		    (TREE_VALUE (TREE_PURPOSE (link)));
- 		oconstraints[i] = constraint;
- 		parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
- 					 &allows_reg, &is_inout);
- 		if (op && !allows_reg && allows_mem)
- 		  ret |= visit_addr (stmt, op, data);
- 	      }
- 	  }
-       if (visit_load || visit_addr)
- 	for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
- 	  {
- 	    tree link = gimple_asm_input_op (stmt, i);
- 	    tree op = TREE_VALUE (link);
- 	    if (visit_addr
- 		&& TREE_CODE (op) == ADDR_EXPR)
- 	      ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
- 	    else if (visit_load || visit_addr)
- 	      {
- 		op = get_base_loadstore (op);
- 		if (op)
- 		  {
- 		    if (visit_load)
- 		      ret |= visit_load (stmt, op, data);
- 		    if (visit_addr)
- 		      {
- 			constraint = TREE_STRING_POINTER
- 			    (TREE_VALUE (TREE_PURPOSE (link)));
- 			parse_input_constraint (&constraint, 0, 0, noutputs,
- 						0, oconstraints,
- 						&allows_mem, &allows_reg);
- 			if (!allows_reg && allows_mem)
- 			  ret |= visit_addr (stmt, op, data);
- 		      }
- 		  }
- 	      }
- 	  }
-     }
-   else if (gimple_code (stmt) == GIMPLE_RETURN)
-     {
-       tree op = gimple_return_retval (stmt);
-       if (op)
- 	{
- 	  if (visit_addr
- 	      && TREE_CODE (op) == ADDR_EXPR)
- 	    ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
- 	  else if (visit_load)
- 	    {
- 	      op = get_base_loadstore (op);
- 	      if (op)
- 		ret |= visit_load (stmt, op, data);
- 	    }
- 	}
-     }
-   else if (visit_addr
- 	   && gimple_code (stmt) == GIMPLE_PHI)
-     {
-       for (i = 0; i < gimple_phi_num_args (stmt); ++i)
- 	{
- 	  tree op = gimple_phi_arg_def (stmt, i);
- 	  if (TREE_CODE (op) == ADDR_EXPR)
- 	    ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
- 	}
-     }
-   else if (visit_addr
- 	   && gimple_code (stmt) == GIMPLE_GOTO)
-     {
-       tree op = gimple_goto_dest (stmt);
-       if (TREE_CODE (op) == ADDR_EXPR)
- 	ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
-     }
- 
-   return ret;
- }
- 
- /* Like walk_stmt_load_store_addr_ops but with NULL visit_addr.  IPA-CP
-    should make a faster clone for this case.  */
- 
- bool
- walk_stmt_load_store_ops (gimple stmt, void *data,
- 			  bool (*visit_load)(gimple, tree, void *),
- 			  bool (*visit_store)(gimple, tree, void *))
- {
-   return walk_stmt_load_store_addr_ops (stmt, data,
- 					visit_load, visit_store, NULL);
- }
- 
  /* Helper for gimple_ior_addresses_taken_1.  */
  
  static bool
--- 2404,2409 ----
*************** preprocess_case_label_vec_for_gimple (ve
*** 3688,3690 ****
--- 2851,2862 ----
    if (default_casep)
      *default_casep = default_case;
  }
+ 
+ /* Set the location of all statements in SEQ to LOC.  */
+ 
+ void
+ gimple_seq_set_location (gimple_seq seq, location_t loc)
+ {
+   for (gimple_stmt_iterator i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
+     gimple_set_location (gsi_stmt (i), loc);
+ }
Index: tree-phinodes.h
===================================================================
*** tree-phinodes.h	(revision 204721)
--- tree-phinodes.h	(working copy)
*************** extern void remove_phi_args (edge);
*** 30,50 ****
  extern void remove_phi_node (gimple_stmt_iterator *, bool);
  extern void remove_phi_nodes (basic_block);
  extern tree degenerate_phi_result (gimple);
! 
! /* Set PHI nodes of a basic block BB to SEQ.  */
! 
! static inline void
! set_phi_nodes (basic_block bb, gimple_seq seq)
! {
!   gimple_stmt_iterator i;
! 
!   gcc_checking_assert (!(bb->flags & BB_RTL));
!   bb->il.gimple.phi_nodes = seq;
!   if (seq)
!     for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
!       gimple_set_bb (gsi_stmt (i), bb);
! }
! 
  
  static inline use_operand_p
  gimple_phi_arg_imm_use_ptr (gimple gs, int i)
--- 30,36 ----
  extern void remove_phi_node (gimple_stmt_iterator *, bool);
  extern void remove_phi_nodes (basic_block);
  extern tree degenerate_phi_result (gimple);
! extern void set_phi_nodes (basic_block, gimple_seq);
  
  static inline use_operand_p
  gimple_phi_arg_imm_use_ptr (gimple gs, int i)
Index: tree-phinodes.c
===================================================================
*** tree-phinodes.c	(revision 204721)
--- tree-phinodes.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 25,30 ****
--- 25,31 ----
  #include "ggc.h"
  #include "basic-block.h"
  #include "gimple.h"
+ #include "gimple-iterator.h"
  #include "gimple-ssa.h"
  #include "tree-phinodes.h"
  #include "ssa-iterators.h"
*************** degenerate_phi_result (gimple phi)
*** 504,508 ****
--- 505,522 ----
    return (i == gimple_phi_num_args (phi) ? val : NULL);
  }
  
+ /* Set PHI nodes of a basic block BB to SEQ.  */
+ 
+ void
+ set_phi_nodes (basic_block bb, gimple_seq seq)
+ {
+   gimple_stmt_iterator i;
+ 
+   gcc_checking_assert (!(bb->flags & BB_RTL));
+   bb->il.gimple.phi_nodes = seq;
+   if (seq)
+     for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
+       gimple_set_bb (gsi_stmt (i), bb);
+ }
  
  #include "gt-tree-phinodes.h"
Index: gengtype.c
===================================================================
*** gengtype.c	(revision 204721)
--- gengtype.c	(working copy)
*************** open_base_files (void)
*** 1769,1777 ****
        "tree.h", "rtl.h", "function.h", "insn-config.h", "expr.h",
        "hard-reg-set.h", "basic-block.h", "cselib.h", "insn-addr.h",
        "optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h",
!       "gimple.h", "gimple-ssa.h", "tree-cfg.h", "tree-phinodes.h",
!       "ssa-iterators.h", "tree-ssanames.h", "tree-ssa-loop.h",
!       "tree-ssa-loop-ivopts.h", "tree-ssa-loop-manip.h",
        "tree-ssa-loop-niter.h", "tree-into-ssa.h", "tree-dfa.h", 
        "tree-ssa.h", "reload.h", "cpp-id-data.h", "tree-chrec.h",
        "except.h", "output.h",  "cfgloop.h",
--- 1769,1777 ----
        "tree.h", "rtl.h", "function.h", "insn-config.h", "expr.h",
        "hard-reg-set.h", "basic-block.h", "cselib.h", "insn-addr.h",
        "optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h",
!       "gimple.h", "gimple-iterator.h", "gimple-ssa.h", "tree-cfg.h",
!       "tree-phinodes.h", "ssa-iterators.h", "tree-ssanames.h",
!       "tree-ssa-loop.h", "tree-ssa-loop-ivopts.h", "tree-ssa-loop-manip.h",
        "tree-ssa-loop-niter.h", "tree-into-ssa.h", "tree-dfa.h", 
        "tree-ssa.h", "reload.h", "cpp-id-data.h", "tree-chrec.h",
        "except.h", "output.h",  "cfgloop.h",
Index: Makefile.in
===================================================================
*** Makefile.in	(revision 204721)
--- Makefile.in	(working copy)
*************** OBJS = \
*** 1240,1245 ****
--- 1240,1246 ----
  	gimple-ssa-strength-reduction.o \
  	gimple-streamer-in.o \
  	gimple-streamer-out.o \
+ 	gimple-walk.o \
  	gimplify.o \
  	godump.o \
  	graph.o \