This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix ASM_EXPR handling in tree-nested.c and omp-low.c (PRs middle-end/30262, middle-end/30263)


Hi!

The following testcases ICE (or some subset of them is just rejected valid
code).  The problem is that walk_stmts (which is used by both tree-nested.c
changes as well as omp lowering) isn't ASM_EXPR aware.  Even when output
operands of ASM_EXPR aren't LHS of a GIMPLE_MODIFY_STMT, they are lvalues
the ASM_EXPR modifies, also for constraints which don't allow a reg and
allow a mem we can't allow setting a temporary variable and later copying
that value to its final location, as ASM_EXPR implicitly takes address
of the "m" operand.  Similarly, input "m" operands, eventhough they aren't
really written into, need to be lvalues and ASM_EXPR is taking their
address.  The following patch fixes this.

Ok for trunk/4.2?

2006-12-20  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/30262
	PR middle-end/30263
	* tree-nested.c (walk_asm_expr): New function.
	(walk_stmts): Use it for ASM_EXPR.

	* gcc.c-torture/execute/20061220-1.c: New test.
	* gcc.dg/gomp/asm-1.c: New test.

--- gcc/tree-nested.c.jj	2006-12-08 15:58:09.000000000 +0100
+++ gcc/tree-nested.c	2006-12-20 16:28:35.000000000 +0100
@@ -546,6 +546,47 @@ get_nl_goto_field (struct nesting_info *
   return field;
 }
 
+/* Helper function for walk_stmts.  Walk output operands of an ASM_EXPR.  */
+
+static void
+walk_asm_expr (struct walk_stmt_info *wi, tree stmt)
+{
+  int noutputs = list_length (ASM_OUTPUTS (stmt));
+  const char **oconstraints
+    = (const char **) alloca ((noutputs) * sizeof (const char *));
+  int i;
+  tree link;
+  const char *constraint;
+  bool allows_mem, allows_reg, is_inout;
+
+  wi->is_lhs = true;
+  for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
+    {
+      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);
+
+      wi->val_only = (allows_reg || !allows_mem);
+      walk_tree (&TREE_VALUE (link), wi->callback, wi, NULL);
+    }
+
+  for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
+    {
+      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+      parse_input_constraint (&constraint, 0, 0, noutputs, 0,
+			      oconstraints, &allows_mem, &allows_reg);
+
+      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;
+      walk_tree (&TREE_VALUE (link), wi->callback, wi, NULL);
+    }
+
+  wi->is_lhs = false;
+  wi->val_only = true;
+}
+
 /* Iterate over all sub-statements of *TP calling walk_tree with
    WI->CALLBACK for every sub-expression in each statement found.  */
 
@@ -628,6 +669,10 @@ walk_stmts (struct walk_stmt_info *wi, t
       wi->is_lhs = false;
       break;
 
+    case ASM_EXPR:
+      walk_asm_expr (wi, *tp);
+      break;
+
     default:
       wi->val_only = true;
       walk_tree (tp, wi->callback, wi, NULL);
--- gcc/testsuite/gcc.c-torture/execute/20061220-1.c.jj	2006-12-20 15:40:09.000000000 +0100
+++ gcc/testsuite/gcc.c-torture/execute/20061220-1.c	2006-12-20 15:39:33.000000000 +0100
@@ -0,0 +1,72 @@
+/* PR middle-end/30262 */
+extern void abort (void);
+
+int
+foo (void)
+{
+  unsigned int x = 0;
+
+  void nested (void)
+  {
+    x = 254;
+  }
+
+  nested ();
+  asm volatile ("" :: "r" (x));
+  asm volatile ("" :: "m" (x));
+  asm volatile ("" :: "mr" (x));
+  asm volatile ("" : "=r" (x) : "0" (x));
+  asm volatile ("" : "=m" (x) : "m" (x));
+  return x;
+}
+
+int
+bar (void)
+{
+  unsigned int x = 0;
+
+  void nested (void)
+  {
+    asm volatile ("" :: "r" (x));
+    asm volatile ("" :: "m" (x));
+    asm volatile ("" :: "mr" (x));
+    x += 4;
+    asm volatile ("" : "=r" (x) : "0" (x));
+    asm volatile ("" : "=m" (x) : "m" (x));
+  }
+
+  nested ();
+  return x;
+}
+
+int
+baz (void)
+{
+  unsigned int x = 0;
+
+  void nested (void)
+  {
+    void nested2 (void)
+    {
+      asm volatile ("" :: "r" (x));
+      asm volatile ("" :: "m" (x));
+      asm volatile ("" :: "mr" (x));
+      x += 4;
+      asm volatile ("" : "=r" (x) : "0" (x));
+      asm volatile ("" : "=m" (x) : "m" (x));
+    }
+    nested2 ();
+    nested2 ();
+  }
+
+  nested ();
+  return x;
+}
+
+int
+main (void)
+{
+  if (foo () != 254 || bar () != 4 || baz () != 8)
+    abort ();
+  return 0;
+}
--- gcc/testsuite/gcc.dg/gomp/asm-1.c.jj	2006-12-20 16:35:57.000000000 +0100
+++ gcc/testsuite/gcc.dg/gomp/asm-1.c	2006-12-20 16:36:41.000000000 +0100
@@ -0,0 +1,19 @@
+/* PR middle-end/30263 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fopenmp" } */
+
+void
+foo (void)
+{
+  int s0, s1 = 5, s2 = 6;
+  int p0, p1, p2;
+  int f0 = 4, f1 = 5, f2 = 6;
+#pragma omp parallel shared (s0, s1, s2) private (p0, p1, p2) \
+	    firstprivate (f0, f1, f2)
+  {
+    asm ("" : "=m" (p0) : "m" (p1), "mr" (p2));
+    if (omp_get_thread_num () == 0)
+      asm ("" : "=m" (s0) : "m" (s1), "mr" (s2));
+    asm ("" : "=m" (f0) : "m" (f1), "mr" (f2));
+  }
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]