diff mbox

Perform some kind of special TER for asm input operands that don't allow regs nor memory (PR inline-asm/23200)

Message ID 20110204131953.GB30899@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Feb. 4, 2011, 1:19 p.m. UTC
On Thu, Feb 03, 2011 at 11:22:49AM -0800, Richard Henderson wrote:
> On 02/03/2011 10:21 AM, Jakub Jelinek wrote:
> > Perhaps we want to limit it some more, e.g. don't look at SSA_NAME_DEF_STMT
> > if it sets a SSA_NAME for user variable at -O0
> > If we'd avoid user variables (!DECL_IGNORED_P or something similar), then
> > pr27528.c testcase wouldn't need to be adjusted.

The updated patch below adds the above

> The is_replaceable_p change lacks documentation for the TER argument,
> and reading the patch I wasn't sure precisely what it is supposed to mean.

and adds a comment above is_replaceable_p documenting the new parameter.
The patch fixes e.g.
static char c;

void
foo (int i, int j, int k)
{
  asm volatile ("" : : "i" (&c + 1), "r" (i > 56 ? j * 18 : k + 34));
}
with -O2 -fno-tree-ccp too (which TER normally doesn't optimize because
&c + 1 is assigned into temporary in a different bb), though of course one
could say that it is user's fault to turn off ccp.

Bootstrapped/regtested again on x86_64-linux and i686-linux.

2011-02-04  Jakub Jelinek  <jakub@redhat.com>

	PR inline-asm/23200
	* tree-ssa-ter.c (is_replaceable_p): Add TER argument.  Don't
	do bb, locus and block comparison and disallow loads if it is
	not set.
	(stmt_is_replaceable_p): New function.
	(process_replaceable, find_replaceable_in_bb): Adjust is_replaceable_p
	callers.
	* expr.c (expand_expr_real_1) <case SSA_NAME>: If
	get_gimple_for_ssa_name try for EXPAND_INITIALIZER harder to use
	SSA_NAME_DEF_STMT.
	* tree-flow.h (stmt_is_replaceable_p): New prototype.

	* gcc.dg/pr23200.c: New test.



	Jakub

Comments

Richard Henderson Feb. 4, 2011, 3:43 p.m. UTC | #1
On 02/04/2011 05:19 AM, Jakub Jelinek wrote:
> 	PR inline-asm/23200
> 	* tree-ssa-ter.c (is_replaceable_p): Add TER argument.  Don't
> 	do bb, locus and block comparison and disallow loads if it is
> 	not set.
> 	(stmt_is_replaceable_p): New function.
> 	(process_replaceable, find_replaceable_in_bb): Adjust is_replaceable_p
> 	callers.
> 	* expr.c (expand_expr_real_1) <case SSA_NAME>: If
> 	get_gimple_for_ssa_name try for EXPAND_INITIALIZER harder to use
> 	SSA_NAME_DEF_STMT.
> 	* tree-flow.h (stmt_is_replaceable_p): New prototype.
> 
> 	* gcc.dg/pr23200.c: New test.

Ok.


r~
diff mbox

Patch

--- gcc/tree-ssa-ter.c.jj	2011-02-03 20:06:47.599536223 +0100
+++ gcc/tree-ssa-ter.c	2011-02-04 08:27:55.656433821 +0100
@@ -357,10 +357,17 @@  add_dependence (temp_expr_table_p tab, i
 }
 
 
-/* Return TRUE if expression STMT is suitable for replacement.  */
+/* Return TRUE if expression STMT is suitable for replacement.
+   TER is true if is_replaceable_p is called from within TER, false
+   when used from within stmt_is_replaceable_p, i.e. EXPAND_INITIALIZER
+   expansion.  The differences are that with !TER some tests are skipped
+   to make it more aggressive (doesn't require the same bb, or for -O0
+   same locus and same BLOCK), on the other side never considers memory
+   loads as replaceable, because those don't ever lead into constant
+   expressions.  */
 
 static inline bool
-is_replaceable_p (gimple stmt)
+is_replaceable_p (gimple stmt, bool ter)
 {
   use_operand_p use_p;
   tree def;
@@ -386,7 +393,7 @@  is_replaceable_p (gimple stmt)
     return false;
 
   /* If the use isn't in this block, it wont be replaced either.  */
-  if (gimple_bb (use_stmt) != gimple_bb (stmt))
+  if (ter && gimple_bb (use_stmt) != gimple_bb (stmt))
     return false;
 
   locus1 = gimple_location (stmt);
@@ -404,6 +411,7 @@  is_replaceable_p (gimple stmt)
     }
 
   if (!optimize
+      && ter
       && ((locus1 && locus1 != locus2) || (block1 && block1 != block2)))
     return false;
 
@@ -416,7 +424,7 @@  is_replaceable_p (gimple stmt)
     return false;
 
   /* Without alias info we can't move around loads.  */
-  if (!optimize
+  if ((!optimize || !ter)
       && gimple_assign_single_p (stmt)
       && !is_gimple_val (gimple_assign_rhs1 (stmt)))
     return false;
@@ -444,6 +452,16 @@  is_replaceable_p (gimple stmt)
 }
 
 
+/* Variant of is_replaceable_p test for use in EXPAND_INITIALIZER
+   expansion.  */
+
+bool
+stmt_is_replaceable_p (gimple stmt)
+{
+  return is_replaceable_p (stmt, false);
+}
+
+
 /* This function will remove the expression for VERSION from replacement
    consideration in table TAB.  If FREE_EXPR is true, then remove the
    expression from consideration as well by freeing the decl uid bitmap.  */
@@ -477,7 +495,7 @@  process_replaceable (temp_expr_table_p t
   ssa_op_iter iter;
   bitmap def_vars, use_vars;
 
-  gcc_checking_assert (is_replaceable_p (stmt));
+  gcc_checking_assert (is_replaceable_p (stmt, true));
 
   def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
   version = SSA_NAME_VERSION (def);
@@ -589,7 +607,7 @@  find_replaceable_in_bb (temp_expr_table_
       if (is_gimple_debug (stmt))
 	continue;
 
-      stmt_replaceable = is_replaceable_p (stmt);
+      stmt_replaceable = is_replaceable_p (stmt, true);
 
       /* Determine if this stmt finishes an existing expression.  */
       FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
--- gcc/expr.c.jj	2011-02-03 20:06:47.578420074 +0100
+++ gcc/expr.c	2011-02-04 08:25:40.599546425 +0100
@@ -8387,6 +8387,13 @@  expand_expr_real_1 (tree exp, rtx target
 				   NULL);
 
       g = get_gimple_for_ssa_name (exp);
+      /* For EXPAND_INITIALIZER try harder to get something simpler.  */
+      if (g == NULL
+	  && modifier == EXPAND_INITIALIZER
+	  && !SSA_NAME_IS_DEFAULT_DEF (exp)
+	  && (optimize || DECL_IGNORED_P (SSA_NAME_VAR (exp)))
+	  && stmt_is_replaceable_p (SSA_NAME_DEF_STMT (exp)))
+	g = SSA_NAME_DEF_STMT (exp);
       if (g)
 	return expand_expr_real (gimple_assign_rhs_to_tree (g), target, tmode,
 				 modifier, NULL);
--- gcc/tree-flow.h.jj	2011-02-03 20:06:47.611407214 +0100
+++ gcc/tree-flow.h	2011-02-04 08:20:38.032392656 +0100
@@ -852,6 +852,9 @@  bool fixup_noreturn_call (gimple stmt);
 /* In ipa-pure-const.c  */
 void warn_function_noreturn (tree);
 
+/* In tree-ssa-ter.c  */
+bool stmt_is_replaceable_p (gimple);
+
 #include "tree-flow-inline.h"
 
 void swap_tree_operands (gimple, tree *, tree *);
--- gcc/testsuite/gcc.dg/pr23200.c.jj	2011-02-04 08:20:38.033545824 +0100
+++ gcc/testsuite/gcc.dg/pr23200.c	2011-02-04 08:20:38.033545824 +0100
@@ -0,0 +1,22 @@ 
+/* PR inline-asm/23200 */
+/* { dg-do compile { target nonpic } } */
+/* { dg-options "-O0" } */
+
+static char var;
+
+void
+foo (void)
+{
+  asm volatile ("" :: "i" (&var + 1));
+}
+
+typedef int T[];
+typedef T *P;
+
+int var2;
+
+void
+bar (void)
+{
+  asm volatile ("" :: "i"(&(*(P)&var2)[1]));
+}