Re: [PATCH] Don't reject TER unnecessarily (PRs middle-end/58956, middle-end/59470)

2013-12-23 Thread Hans-Peter Nilsson
On Sat, 14 Dec 2013, Jakub Jelinek wrote:
> 2013-12-14  Jakub Jelinek  
>
>   PR middle-end/58956
>   PR middle-end/59470
>   * gimple-walk.h (walk_stmt_load_store_addr_fn): New typedef.
>   (walk_stmt_load_store_addr_ops, walk_stmt_load_store_ops): Use it
>   for callback params.
>   * gimple-walk.c (walk_stmt_load_store_ops): Likewise.
>   (walk_stmt_load_store_addr_ops): Likewise.  Adjust all callback
>   calls to supply the gimple operand containing the base tree
>   as an extra argument.
>   * tree-ssa-ter.c: Include gimple-walk.h.
>   (find_ssaname, find_ssaname_in_store): New helper functions.
>   (find_replaceable_in_bb): For calls or GIMPLE_ASM, only set
>   same_root_var if USE is used somewhere in the stores of the stmt.
>   * ipa-prop.c (visit_ref_for_mod_analysis): Remove name of the stmt
>   argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
>   * ipa-pure-const.c (check_load, check_store, check_ipa_load,
>   check_ipa_store): Likewise.
>   * gimple.c (gimple_ior_addresses_taken_1, check_loadstore): Likewise.
>   * ipa-split.c (test_nonssa_use, mark_nonssa_use): Likewise.
>   (verify_non_ssa_vars, visit_bb): Adjust their callers.
>   * cfgexpand.c (add_scope_conflicts_1): Use
>   walk_stmt_load_store_addr_fn type for visit variable.
>   (visit_op, visit_conflict): Remove name of the stmt
>   argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
>   * tree-sra.c (asm_visit_addr): Likewise.  Remove name of the data
>   argument and ATTRIBUTE_UNUSED.
>   * cgraphbuild.c (mark_address, mark_load, mark_store): Add another
>   unnamed tree argument.
>   * gimple-ssa-isolate-paths.c (check_loadstore): Likewise.  Remove
>   ATTRIBUTE_UNUSED from stmt parameter.

Caused PR59584, an ICE.

(I'm going to fix the define_split bug that this exposed, but I
don't think that bug - allowing SP as a temporary - is the cause
of the hiccup.)

brgds, H-P


Re: [PATCH] Don't reject TER unnecessarily (PRs middle-end/58956, middle-end/59470)

2013-12-16 Thread Richard Biener
Jakub Jelinek  wrote:
>On Sat, Dec 14, 2013 at 06:51:35PM +0100, Richard Biener wrote:
>> >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>> 
>> Ok.
>
>Thanks, committed.  For 4.8, do you prefer this larger (thus more
>risky?)
>patch, or the smaller tree-ssa-ter.c change only?

I prefer the larger one, after a few days.

Thanks,
Richard.

>   Jakub




Re: [PATCH] Don't reject TER unnecessarily (PRs middle-end/58956, middle-end/59470)

2013-12-16 Thread Jakub Jelinek
On Sat, Dec 14, 2013 at 06:51:35PM +0100, Richard Biener wrote:
> >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> Ok.

Thanks, committed.  For 4.8, do you prefer this larger (thus more risky?)
patch, or the smaller tree-ssa-ter.c change only?

Jakub


Re: [PATCH] Don't reject TER unnecessarily (PRs middle-end/58956, middle-end/59470)

2013-12-14 Thread Richard Biener
Jakub Jelinek  wrote:
>On Fri, Dec 13, 2013 at 09:47:20AM +0100, Richard Biener wrote:
>> Jakub Jelinek  wrote:
>> >On Fri, Dec 13, 2013 at 07:30:12AM +0100, Richard Biener wrote:
>> >> Jakub Jelinek  wrote:
>> >> >lhs of a call for calls or somewhere in output arguments of
>inline
>> >asm.
>> >> 
>> >> Can you please simply use walk_stmt_load_store_ops to get at the
>stmt
>> >outputs?
>> >
>> >No, unfortunately.  The problem is that
>> >walk_stmt_load_store_{addr_,}ops first
>> >calls and get_base_loadstore on the operand and thus effectively
>strips
>> >all the
>> >handled components from it. 
>> 
>> That's a defficiency of that function then which we should fix, for
>> example with either passing both to the callback or by adding a flag.
>
>Ok, this patch implements the former (passing both the base (as before)
>and
>the gimple operand tree that is either equal to the base or contains
>the
>base.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok.

Thanks,
Richard.

>2013-12-14  Jakub Jelinek  
>
>   PR middle-end/58956
>   PR middle-end/59470
>   * gimple-walk.h (walk_stmt_load_store_addr_fn): New typedef.
>   (walk_stmt_load_store_addr_ops, walk_stmt_load_store_ops): Use it
>   for callback params.
>   * gimple-walk.c (walk_stmt_load_store_ops): Likewise.
>   (walk_stmt_load_store_addr_ops): Likewise.  Adjust all callback
>   calls to supply the gimple operand containing the base tree
>   as an extra argument.
>   * tree-ssa-ter.c: Include gimple-walk.h.
>   (find_ssaname, find_ssaname_in_store): New helper functions.
>   (find_replaceable_in_bb): For calls or GIMPLE_ASM, only set
>   same_root_var if USE is used somewhere in the stores of the stmt.
>   * ipa-prop.c (visit_ref_for_mod_analysis): Remove name of the stmt
>   argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
>   * ipa-pure-const.c (check_load, check_store, check_ipa_load,
>   check_ipa_store): Likewise.
>   * gimple.c (gimple_ior_addresses_taken_1, check_loadstore): Likewise.
>   * ipa-split.c (test_nonssa_use, mark_nonssa_use): Likewise.
>   (verify_non_ssa_vars, visit_bb): Adjust their callers.
>   * cfgexpand.c (add_scope_conflicts_1): Use
>   walk_stmt_load_store_addr_fn type for visit variable.
>   (visit_op, visit_conflict): Remove name of the stmt
>   argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
>   * tree-sra.c (asm_visit_addr): Likewise.  Remove name of the data
>   argument and ATTRIBUTE_UNUSED.
>   * cgraphbuild.c (mark_address, mark_load, mark_store): Add another
>   unnamed tree argument.
>   * gimple-ssa-isolate-paths.c (check_loadstore): Likewise.  Remove
>   ATTRIBUTE_UNUSED from stmt parameter.
>
>   * gcc.target/i386/pr59470.c: New test.
>
>--- gcc/gimple-walk.h.jj   2013-11-14 09:10:01.0 +0100
>+++ gcc/gimple-walk.h  2013-12-13 17:11:15.446033263 +0100
>@@ -89,11 +89,12 @@ extern gimple walk_gimple_seq (gimple_se
>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 *);
>+typedef bool (*walk_stmt_load_store_addr_fn) (gimple, tree, tree, void
>*);
> extern bool walk_stmt_load_store_addr_ops (gimple, void *,
>- bool (*)(gimple, tree, void *),
>- bool (*)(gimple, tree, void *),
>- bool (*)(gimple, tree, void *));
>+ walk_stmt_load_store_addr_fn,
>+ walk_stmt_load_store_addr_fn,
>+ walk_stmt_load_store_addr_fn);
> extern bool walk_stmt_load_store_ops (gimple, void *,
>-bool (*)(gimple, tree, void *),
>-bool (*)(gimple, tree, void *));
>+walk_stmt_load_store_addr_fn,
>+walk_stmt_load_store_addr_fn);
> #endif /* GCC_GIMPLE_WALK_H */
>--- gcc/gimple-walk.c.jj   2013-11-22 21:03:03.0 +0100
>+++ gcc/gimple-walk.c  2013-12-13 17:11:15.452033280 +0100
>@@ -649,42 +649,46 @@ get_base_loadstore (tree op)
> 
>/* 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.
>+   passing the STMT, the base of the operand, the operand itself
>containing
>+   the base 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.
>Ret

Re: [PATCH] Don't reject TER unnecessarily (PRs middle-end/58956, middle-end/59470)

2013-12-14 Thread Jakub Jelinek
On Fri, Dec 13, 2013 at 09:47:20AM +0100, Richard Biener wrote:
> Jakub Jelinek  wrote:
> >On Fri, Dec 13, 2013 at 07:30:12AM +0100, Richard Biener wrote:
> >> Jakub Jelinek  wrote:
> >> >lhs of a call for calls or somewhere in output arguments of inline
> >asm.
> >> 
> >> Can you please simply use walk_stmt_load_store_ops to get at the stmt
> >outputs?
> >
> >No, unfortunately.  The problem is that
> >walk_stmt_load_store_{addr_,}ops first
> >calls and get_base_loadstore on the operand and thus effectively strips
> >all the
> >handled components from it. 
> 
> That's a defficiency of that function then which we should fix, for
> example with either passing both to the callback or by adding a flag.

Ok, this patch implements the former (passing both the base (as before) and
the gimple operand tree that is either equal to the base or contains the
base.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2013-12-14  Jakub Jelinek  

PR middle-end/58956
PR middle-end/59470
* gimple-walk.h (walk_stmt_load_store_addr_fn): New typedef.
(walk_stmt_load_store_addr_ops, walk_stmt_load_store_ops): Use it
for callback params.
* gimple-walk.c (walk_stmt_load_store_ops): Likewise.
(walk_stmt_load_store_addr_ops): Likewise.  Adjust all callback
calls to supply the gimple operand containing the base tree
as an extra argument.
* tree-ssa-ter.c: Include gimple-walk.h.
(find_ssaname, find_ssaname_in_store): New helper functions.
(find_replaceable_in_bb): For calls or GIMPLE_ASM, only set
same_root_var if USE is used somewhere in the stores of the stmt.
* ipa-prop.c (visit_ref_for_mod_analysis): Remove name of the stmt
argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
* ipa-pure-const.c (check_load, check_store, check_ipa_load,
check_ipa_store): Likewise.
* gimple.c (gimple_ior_addresses_taken_1, check_loadstore): Likewise.
* ipa-split.c (test_nonssa_use, mark_nonssa_use): Likewise.
(verify_non_ssa_vars, visit_bb): Adjust their callers.
* cfgexpand.c (add_scope_conflicts_1): Use
walk_stmt_load_store_addr_fn type for visit variable.
(visit_op, visit_conflict): Remove name of the stmt
argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
* tree-sra.c (asm_visit_addr): Likewise.  Remove name of the data
argument and ATTRIBUTE_UNUSED.
* cgraphbuild.c (mark_address, mark_load, mark_store): Add another
unnamed tree argument.
* gimple-ssa-isolate-paths.c (check_loadstore): Likewise.  Remove
ATTRIBUTE_UNUSED from stmt parameter.

* gcc.target/i386/pr59470.c: New test.

--- gcc/gimple-walk.h.jj2013-11-14 09:10:01.0 +0100
+++ gcc/gimple-walk.h   2013-12-13 17:11:15.446033263 +0100
@@ -89,11 +89,12 @@ extern gimple walk_gimple_seq (gimple_se
 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 *);
+typedef bool (*walk_stmt_load_store_addr_fn) (gimple, tree, tree, void *);
 extern bool walk_stmt_load_store_addr_ops (gimple, void *,
-  bool (*)(gimple, tree, void *),
-  bool (*)(gimple, tree, void *),
-  bool (*)(gimple, tree, void *));
+  walk_stmt_load_store_addr_fn,
+  walk_stmt_load_store_addr_fn,
+  walk_stmt_load_store_addr_fn);
 extern bool walk_stmt_load_store_ops (gimple, void *,
- bool (*)(gimple, tree, void *),
- bool (*)(gimple, tree, void *));
+ walk_stmt_load_store_addr_fn,
+ walk_stmt_load_store_addr_fn);
 #endif /* GCC_GIMPLE_WALK_H */
--- gcc/gimple-walk.c.jj2013-11-22 21:03:03.0 +0100
+++ gcc/gimple-walk.c   2013-12-13 17:11:15.452033280 +0100
@@ -649,42 +649,46 @@ get_base_loadstore (tree op)
 
 /* 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.
+   passing the STMT, the base of the operand, the operand itself containing
+   the base 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, v

Re: [PATCH] Don't reject TER unnecessarily (PRs middle-end/58956, middle-end/59470)

2013-12-13 Thread Richard Biener
Jakub Jelinek  wrote:
>On Fri, Dec 13, 2013 at 07:30:12AM +0100, Richard Biener wrote:
>> Jakub Jelinek  wrote:
>> >lhs of a call for calls or somewhere in output arguments of inline
>asm.
>> 
>> Can you please simply use walk_stmt_load_store_ops to get at the stmt
>outputs?
>
>No, unfortunately.  The problem is that
>walk_stmt_load_store_{addr_,}ops first
>calls and get_base_loadstore on the operand and thus effectively strips
>all the
>handled components from it. 

That's a defficiency of that function then which we should fix, for example 
with either passing both to the callback or by adding a flag.

Richard.

 But we need to look at any uses of
>SSA_NAMEs
>in the whole operand, not only if it is based on *MEM_REF with SSA_NAME
>operand.  I.e., a change of the patch to use walk_stmt_load_store_ops
>will keep the pr58956.c testcase fixed, because there is *i, but will
>make pr59470.c (the new one in the patch) broken, because there the
>SSA_NAME is used as ARRAY_REF index and base is some VAR_DECL.
>It guess it wouldn't be hard to make similar testcase even for the call
>case, though it is unclear if it would be miscompiled or not.
>
>   Jakub




Re: [PATCH] Don't reject TER unnecessarily (PRs middle-end/58956, middle-end/59470)

2013-12-12 Thread Jakub Jelinek
On Fri, Dec 13, 2013 at 07:30:12AM +0100, Richard Biener wrote:
> Jakub Jelinek  wrote:
> >lhs of a call for calls or somewhere in output arguments of inline asm.
> 
> Can you please simply use walk_stmt_load_store_ops to get at the stmt outputs?

No, unfortunately.  The problem is that walk_stmt_load_store_{addr_,}ops first
calls and get_base_loadstore on the operand and thus effectively strips all the
handled components from it.  But we need to look at any uses of SSA_NAMEs
in the whole operand, not only if it is based on *MEM_REF with SSA_NAME
operand.  I.e., a change of the patch to use walk_stmt_load_store_ops
will keep the pr58956.c testcase fixed, because there is *i, but will
make pr59470.c (the new one in the patch) broken, because there the
SSA_NAME is used as ARRAY_REF index and base is some VAR_DECL.
It guess it wouldn't be hard to make similar testcase even for the call
case, though it is unclear if it would be miscompiled or not.

Jakub


Re: [PATCH] Don't reject TER unnecessarily (PRs middle-end/58956, middle-end/59470)

2013-12-12 Thread Richard Biener
Jakub Jelinek  wrote:
>Hi!
>
>Before the PR58956 fix find_replaceable_in_bb only gave up TER if
>stmt was gimple_assign_single_p that was storing something that
>could alias with TERed load, but now it also punts on calls (a lot of
>them
>apparently) and inline asm (all of them, because stmt_may_clobber_ref_p
>always returns true for GIMPLE_ASM).  I believe we can restore TERing
>most of the cases for calls and inline asm though, because for calls
>all arguments are necessarily evaluated before the call and the only
>memory side effects of the call are the call itself and perhaps storing
>of non-SSA_NAME return value afterwards.  And for inline asm again
>all input operands have to be evaluated before the inline asm, and the
>only storing side-effects are again inside of the inline asm and
>perhaps
>storing of the output operands.
>
>Thus, this patch will only stop TERing if USE is used somewhere in
>lhs of a call for calls or somewhere in output arguments of inline asm.

Can you please simply use walk_stmt_load_store_ops to get at the stmt outputs?

Thanks,
Richard.

>Bootstrapped/regtested on x86_64-linux and i686-linux (both on trunk
>and 4.8
>branch), ok for trunk/4.8?
>
>The reason I'd like to see this for 4.8 is to decrease the amount of
>code
>generation changes from pre-r205709 to minimum, as it can uncover other
>latent bugs than just PR59470.
>
>2013-12-12  Jakub Jelinek  
>
>   PR middle-end/58956
>   PR middle-end/59470
>   * tree-ssa-ter.c (find_ssa_name): New helper function.
>   (find_replaceable_in_bb): For calls, only set same_root_var
>   if USE is used somewhere in gimple_call_lhs, for GIMPLE_ASM,
>   only set same_root_var if USE is used somewhere in output operand
>   trees.
>
>   * gcc.target/i386/pr59470.c: New test.
>
>--- gcc/tree-ssa-ter.c.jj  2013-12-10 08:52:13.0 +0100
>+++ gcc/tree-ssa-ter.c 2013-12-12 10:43:26.177866960 +0100
>@@ -554,6 +554,20 @@ mark_replaceable (temp_expr_table_p tab,
> }
> 
> 
>+/* Helper function for find_replaceable_in_bb.  Called via walk_tree
>to
>+   find a SSA_NAME DATA somewhere in *TP.  */
>+
>+static tree
>+find_ssa_name (tree *tp, int *walk_subtrees, void *data)
>+{
>+  tree var = (tree) data;
>+  if (*tp == var)
>+return var;
>+  else if (IS_TYPE_OR_DECL_P (*tp))
>+*walk_subtrees = 0;
>+  return NULL_TREE;
>+}
>+
>/* This function processes basic block BB, and looks for variables
>which can
>be replaced by their expressions.  Results are stored in the table TAB.
> */
> 
>@@ -618,7 +632,42 @@ find_replaceable_in_bb (temp_expr_table_
> && gimple_assign_single_p (def_stmt)
> && stmt_may_clobber_ref_p (stmt,
>gimple_assign_rhs1 (def_stmt)))
>-  same_root_var = true;
>+  {
>+if (is_gimple_call (stmt))
>+  {
>+/* For calls, it is not a problem if USE is among
>+   call's arguments or say OBJ_TYPE_REF argument,
>+   all those necessarily need to be evaluated before
>+   the call that may clobber the memory.  But if
>+   LHS of the call refers to USE, expansion might
>+   evaluate it after the call, prevent TER in that
>+   case.  */
>+if (gimple_call_lhs (stmt)
>+&& TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME
>+&& walk_tree (gimple_call_lhs_ptr (stmt),
>+  find_ssa_name, use, NULL))
>+  same_root_var = true;
>+  }
>+else if (gimple_code (stmt) == GIMPLE_ASM)
>+  {
>+/* For inline asm, allow TER of loads into input
>+   arguments, but disallow TER for USEs that occur
>+   somewhere in outputs.  */
>+unsigned int i;
>+for (i = 0; i < gimple_asm_noutputs (stmt); i++)
>+  if (TREE_CODE (gimple_asm_output_op (stmt, i))
>+  != SSA_NAME
>+  && walk_tree (gimple_asm_output_op_ptr (stmt,
>+  i),
>+find_ssa_name, use, NULL))
>+{
>+  same_root_var = true;
>+  break;
>+}
>+  }
>+else
>+  same_root_var = true;
>+  }
>   }
> 
> /* Mark expression as replaceable unless stmt is volatile, or
>the
>--- gcc/testsuite/gcc.target/i386/pr59470.c.jj 2013-12-12
>10:31:54.746517544 +0100

[PATCH] Don't reject TER unnecessarily (PRs middle-end/58956, middle-end/59470)

2013-12-12 Thread Jakub Jelinek
Hi!

Before the PR58956 fix find_replaceable_in_bb only gave up TER if
stmt was gimple_assign_single_p that was storing something that
could alias with TERed load, but now it also punts on calls (a lot of them
apparently) and inline asm (all of them, because stmt_may_clobber_ref_p
always returns true for GIMPLE_ASM).  I believe we can restore TERing
most of the cases for calls and inline asm though, because for calls
all arguments are necessarily evaluated before the call and the only
memory side effects of the call are the call itself and perhaps storing
of non-SSA_NAME return value afterwards.  And for inline asm again
all input operands have to be evaluated before the inline asm, and the
only storing side-effects are again inside of the inline asm and perhaps
storing of the output operands.

Thus, this patch will only stop TERing if USE is used somewhere in
lhs of a call for calls or somewhere in output arguments of inline asm.

Bootstrapped/regtested on x86_64-linux and i686-linux (both on trunk and 4.8
branch), ok for trunk/4.8?

The reason I'd like to see this for 4.8 is to decrease the amount of code
generation changes from pre-r205709 to minimum, as it can uncover other
latent bugs than just PR59470.

2013-12-12  Jakub Jelinek  

PR middle-end/58956
PR middle-end/59470
* tree-ssa-ter.c (find_ssa_name): New helper function.
(find_replaceable_in_bb): For calls, only set same_root_var
if USE is used somewhere in gimple_call_lhs, for GIMPLE_ASM,
only set same_root_var if USE is used somewhere in output operand
trees.

* gcc.target/i386/pr59470.c: New test.

--- gcc/tree-ssa-ter.c.jj   2013-12-10 08:52:13.0 +0100
+++ gcc/tree-ssa-ter.c  2013-12-12 10:43:26.177866960 +0100
@@ -554,6 +554,20 @@ mark_replaceable (temp_expr_table_p tab,
 }
 
 
+/* Helper function for find_replaceable_in_bb.  Called via walk_tree to
+   find a SSA_NAME DATA somewhere in *TP.  */
+
+static tree
+find_ssa_name (tree *tp, int *walk_subtrees, void *data)
+{
+  tree var = (tree) data;
+  if (*tp == var)
+return var;
+  else if (IS_TYPE_OR_DECL_P (*tp))
+*walk_subtrees = 0;
+  return NULL_TREE;
+}
+
 /* This function processes basic block BB, and looks for variables which can
be replaced by their expressions.  Results are stored in the table TAB.  */
 
@@ -618,7 +632,42 @@ find_replaceable_in_bb (temp_expr_table_
  && gimple_assign_single_p (def_stmt)
  && stmt_may_clobber_ref_p (stmt,
 gimple_assign_rhs1 (def_stmt)))
-   same_root_var = true;
+   {
+ if (is_gimple_call (stmt))
+   {
+ /* For calls, it is not a problem if USE is among
+call's arguments or say OBJ_TYPE_REF argument,
+all those necessarily need to be evaluated before
+the call that may clobber the memory.  But if
+LHS of the call refers to USE, expansion might
+evaluate it after the call, prevent TER in that
+case.  */
+ if (gimple_call_lhs (stmt)
+ && TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME
+ && walk_tree (gimple_call_lhs_ptr (stmt),
+   find_ssa_name, use, NULL))
+   same_root_var = true;
+   }
+ else if (gimple_code (stmt) == GIMPLE_ASM)
+   {
+ /* For inline asm, allow TER of loads into input
+arguments, but disallow TER for USEs that occur
+somewhere in outputs.  */
+ unsigned int i;
+ for (i = 0; i < gimple_asm_noutputs (stmt); i++)
+   if (TREE_CODE (gimple_asm_output_op (stmt, i))
+   != SSA_NAME
+   && walk_tree (gimple_asm_output_op_ptr (stmt,
+   i),
+ find_ssa_name, use, NULL))
+ {
+   same_root_var = true;
+   break;
+ }
+   }
+ else
+   same_root_var = true;
+   }
}
 
  /* Mark expression as replaceable unless stmt is volatile, or the
--- gcc/testsuite/gcc.target/i386/pr59470.c.jj  2013-12-12 10:31:54.746517544 
+0100
+++ gcc/testsuite/gcc.target/i386/pr59470.c 2013-12-12 10:32:42.045273313 
+0100
@@ -0,0 +1,17 @@
+/* PR middle-end/58956 */
+/* PR middle-end/59470 */
+/* { dg-do run }