diff mbox

Perform anonymous constant propagation during inlining

Message ID 1538996.TcTA0zy8bB@polaris
State New
Headers show

Commit Message

Eric Botcazou May 1, 2015, 6:09 p.m. UTC
> OK, how aggressive then?  We could as well do the substitution for all
> copies:
> 
>       /* For EXPAND_INITIALIZER try harder to get something simpler.
> 	 Otherwise, substitute copies on the RHS, this can propagate
> 	 constants at -O0 and thus simplify arithmetic operations.  */
>       if (g == NULL
> 	  && !SSA_NAME_IS_DEFAULT_DEF (exp)
> 	  && (optimize || DECL_IGNORED_P (SSA_NAME_VAR (exp)))
> 	  && (modifier == EXPAND_INITIALIZER
> 
> 	      || (modifier != EXPAND_WRITE
> 
> 		  && gimple_assign_copy_p (SSA_NAME_DEF_STMT (exp))))
> 	  && stmt_is_replaceable_p (SSA_NAME_DEF_STMT (exp)))
> 	g = SSA_NAME_DEF_STMT (exp);

This doesn't work (this generates wrong code because this creates overlapping 
live ranges for SSA_NAMEs with the same base variable).  Here's the latest 
working version, all the predicates and accessors used are inlined.

Tested on x86_64-suse-linux, OK for the mainline?


2015-05-01  Eric Botcazou  <ebotcazou@adacore.com>

	* expr.c (expand_expr_real_1) <SSA_NAME>: Try to substitute constants
	on the RHS of expressions.
	* gimple-expr.h (is_gimple_constant): Reorder.

Comments

Richard Biener May 4, 2015, 8:46 a.m. UTC | #1
On Fri, May 1, 2015 at 8:09 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> OK, how aggressive then?  We could as well do the substitution for all
>> copies:
>>
>>       /* For EXPAND_INITIALIZER try harder to get something simpler.
>>        Otherwise, substitute copies on the RHS, this can propagate
>>        constants at -O0 and thus simplify arithmetic operations.  */
>>       if (g == NULL
>>         && !SSA_NAME_IS_DEFAULT_DEF (exp)
>>         && (optimize || DECL_IGNORED_P (SSA_NAME_VAR (exp)))
>>         && (modifier == EXPAND_INITIALIZER
>>
>>             || (modifier != EXPAND_WRITE
>>
>>                 && gimple_assign_copy_p (SSA_NAME_DEF_STMT (exp))))
>>         && stmt_is_replaceable_p (SSA_NAME_DEF_STMT (exp)))
>>       g = SSA_NAME_DEF_STMT (exp);
>
> This doesn't work (this generates wrong code because this creates overlapping
> live ranges for SSA_NAMEs with the same base variable).  Here's the latest
> working version, all the predicates and accessors used are inlined.

Hum, the fact that your earlier version created wrong code
(get_gimple_for_ssa_name
already returned false here) points at some issues with
EXPAND_INITIALIZER as well, no...?

That said, the path you add is certainly safe (though maybe we want to change
get_gimple_for_ssa_name to return tcc_constant single-use defs even if
TER is disabled
(thus at -O0 - and only at -O0, otherwise it shouldn't happen).  That
would cover
more cases of get_gimple_for_ssa_name uses (I can see
optimize_bitfield_expansion
for example...)

So, your patch is ok for trunk unless you want to explore the
get_gimple_for_ssa_name
improvement suggestion.

I also wonder about EXPAND_INITIALIZER creating overlapping
life-ranges (or moving
loads across stores).

Thanks,
Richard.

> Tested on x86_64-suse-linux, OK for the mainline?
>
>
> 2015-05-01  Eric Botcazou  <ebotcazou@adacore.com>
>
>         * expr.c (expand_expr_real_1) <SSA_NAME>: Try to substitute constants
>         on the RHS of expressions.
>         * gimple-expr.h (is_gimple_constant): Reorder.
>
>
> --
> Eric Botcazou
Eric Botcazou May 4, 2015, 9:30 a.m. UTC | #2
> Hum, the fact that your earlier version created wrong code
> (get_gimple_for_ssa_name
> already returned false here) points at some issues with
> EXPAND_INITIALIZER as well, no...?

Theoritically yes but, in practice, EXPAND_INITIALIZER is used in varasm.c and 
for debugging stuff only, so I don't think that's a real concern.

> That said, the path you add is certainly safe (though maybe we want to
> change get_gimple_for_ssa_name to return tcc_constant single-use defs even
> if TER is disabled
> (thus at -O0 - and only at -O0, otherwise it shouldn't happen).  That
> would cover
> more cases of get_gimple_for_ssa_name uses (I can see
> optimize_bitfield_expansion
> for example...)

optimize_bitfield_assignment_op is only interested in loads from bitfields 
though.  The get_gimple_for_ssa_name route would be interesting to bypass the 
stmt_is_replaceable_p test, i.e. to bypass the single-use test, but this could 
be counter-productive at -O0 so I'm not sure it's worth the trouble.
Eric Botcazou May 4, 2015, 9:38 p.m. UTC | #3
> 2015-05-01  Eric Botcazou  <ebotcazou@adacore.com>
> 
> 	* expr.c (expand_expr_real_1) <SSA_NAME>: Try to substitute constants
> 	on the RHS of expressions.
> 	* gimple-expr.h (is_gimple_constant): Reorder.

Bummer.  This breaks C++ debugging:

+FAIL: gdb.cp/class2.exp: print alpha at marker return 0
+FAIL: gdb.cp/class2.exp: print beta at marker return 0
+FAIL: gdb.cp/class2.exp: print * aap at marker return 0
+FAIL: gdb.cp/class2.exp: print * bbp at marker return 0
+FAIL: gdb.cp/class2.exp: print * abp at marker return 0, s-p-o off
+FAIL: gdb.cp/class2.exp: print * (B *) abp at marker return 0
+FAIL: gdb.cp/class2.exp: p acp
+FAIL: gdb.cp/class2.exp: p acp->c1
+FAIL: gdb.cp/class2.exp: p acp->c2

because C++ is apparently relying on the assignment to the anonymous return 
object to preserve the debug info attached to a return statement.

Would you be OK with a slight variation of your earlier idea, i.e. calling 
fold_stmt with a specific valueizer from fold_marked_statements instead of the 
implicit no_follow_ssa_edges in the inliner?  Something like:

tree
follow_anonymous_single_use_edges (tree val)
{
  if (TREE_CODE (val) == SSA_NAME
      && (!SSA_NAME_VAR (val) || DECL_IGNORED_P (SSA_NAME_VAR (var)))
      && has_single_use (val))
    return val
  return NULL_TREE;
}
Richard Biener May 5, 2015, 5:43 a.m. UTC | #4
On May 4, 2015 11:38:42 PM GMT+02:00, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> 2015-05-01  Eric Botcazou  <ebotcazou@adacore.com>
>> 
>> 	* expr.c (expand_expr_real_1) <SSA_NAME>: Try to substitute
>constants
>> 	on the RHS of expressions.
>> 	* gimple-expr.h (is_gimple_constant): Reorder.
>
>Bummer.  This breaks C++ debugging:
>
>+FAIL: gdb.cp/class2.exp: print alpha at marker return 0
>+FAIL: gdb.cp/class2.exp: print beta at marker return 0
>+FAIL: gdb.cp/class2.exp: print * aap at marker return 0
>+FAIL: gdb.cp/class2.exp: print * bbp at marker return 0
>+FAIL: gdb.cp/class2.exp: print * abp at marker return 0, s-p-o off
>+FAIL: gdb.cp/class2.exp: print * (B *) abp at marker return 0
>+FAIL: gdb.cp/class2.exp: p acp
>+FAIL: gdb.cp/class2.exp: p acp->c1
>+FAIL: gdb.cp/class2.exp: p acp->c2
>
>because C++ is apparently relying on the assignment to the anonymous
>return 
>object to preserve the debug info attached to a return statement.
>
>Would you be OK with a slight variation of your earlier idea, i.e.
>calling 
>fold_stmt with a specific valueizer from fold_marked_statements instead
>of the 
>implicit no_follow_ssa_edges in the inliner?  Something like:
>
>tree
>follow_anonymous_single_use_edges (tree val)
>{
>  if (TREE_CODE (val) == SSA_NAME
>      && (!SSA_NAME_VAR (val) || DECL_IGNORED_P (SSA_NAME_VAR (var)))
>      && has_single_use (val))
>    return val
>  return NULL_TREE;
>}

Yes, that works for me as well.

Richard.
diff mbox

Patch

Index: expr.c
===================================================================
--- expr.c	(revision 222673)
+++ expr.c	(working copy)
@@ -9511,11 +9511,17 @@  expand_expr_real_1 (tree exp, rtx target
 	}
 
       g = get_gimple_for_ssa_name (exp);
-      /* For EXPAND_INITIALIZER try harder to get something simpler.  */
+      /* For EXPAND_INITIALIZER try harder to get something simpler.
+	 Otherwise, substitute constants on the RHS, this can make
+	 it possible to simplify arithmetic operations at -O0.  */
       if (g == NULL
-	  && modifier == EXPAND_INITIALIZER
 	  && !SSA_NAME_IS_DEFAULT_DEF (exp)
 	  && (optimize || DECL_IGNORED_P (SSA_NAME_VAR (exp)))
+	  && (modifier == EXPAND_INITIALIZER
+	      || (modifier != EXPAND_WRITE
+		  && gimple_assign_single_p (SSA_NAME_DEF_STMT (exp))
+		  && is_gimple_constant
+		     (gimple_assign_rhs1 (SSA_NAME_DEF_STMT (exp)))))
 	  && stmt_is_replaceable_p (SSA_NAME_DEF_STMT (exp)))
 	g = SSA_NAME_DEF_STMT (exp);
       if (g)
Index: gimple-expr.h
===================================================================
--- gimple-expr.h	(revision 222673)
+++ gimple-expr.h	(working copy)
@@ -136,9 +136,9 @@  is_gimple_constant (const_tree t)
     case INTEGER_CST:
     case REAL_CST:
     case FIXED_CST:
-    case STRING_CST:
     case COMPLEX_CST:
     case VECTOR_CST:
+    case STRING_CST:
       return true;
 
     default: