]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/39804 (internal compiler error: in propagate_necessity, at...
authorRichard Guenther <rguenther@suse.de>
Sat, 18 Apr 2009 13:02:00 +0000 (13:02 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Sat, 18 Apr 2009 13:02:00 +0000 (13:02 +0000)
2009-04-18  Richard Guenther  <rguenther@suse.de>

PR middle-end/39804
* tree-ssa-ccp.c (fold_stmt_1): New function factored from ...
(fold_stmt): ... this and ...
(fold_stmt_inplace): ... this.
(fold_stmt_1): Fold references in calls and asms.
* tree-cfg.c (remove_useless_stmts_cond): Use fold_stmt.

* gcc.target/i386/pr39804.c: New testcase.

From-SVN: r146314

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr39804.c [new file with mode: 0644]
gcc/tree-cfg.c
gcc/tree-ssa-ccp.c

index 49608da89abdc748ffe80bb7ad7b32e6cd1e6b0a..19806f5544618c6df97781022878e3010bdc0446 100644 (file)
@@ -1,3 +1,12 @@
+2009-04-18  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/39804
+       * tree-ssa-ccp.c (fold_stmt_1): New function factored from ...
+       (fold_stmt): ... this and ...
+       (fold_stmt_inplace): ... this.
+       (fold_stmt_1): Fold references in calls and asms.
+       * tree-cfg.c (remove_useless_stmts_cond): Use fold_stmt.
+
 2009-04-18  Kazu Hirata  <kazu@codesourcery.com>
 
        * tree-vrp.c (ssa_name_nonzero_p): Remove.
index 4085037d3544bd8c6f15c1846f3cc735a7c2369b..846725e1daa6be4529c8029947f3dd8f34f899f6 100644 (file)
@@ -1,3 +1,8 @@
+2009-04-18  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/39804
+       * gcc.target/i386/pr39804.c: New testcase.
+
 2009-04-18  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc.target/i386/pr39496.c: Compile with -mtune=i686.
diff --git a/gcc/testsuite/gcc.target/i386/pr39804.c b/gcc/testsuite/gcc.target/i386/pr39804.c
new file mode 100644 (file)
index 0000000..3ff2479
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O" } */
+
+typedef unsigned char u8;
+struct __large_struct { unsigned long buf[100]; };
+static inline __attribute__((always_inline)) unsigned long
+__copy_from_user_inatomic(void *to, const void *from, unsigned long n)
+{
+  unsigned long ret = 0;
+  asm volatile("1:     mov""b"" %2,%""b""1\n" "2:\n"
+              ".section .fixup,\"ax\"\n"
+              "3:      mov %3,%0\n"
+              "        xor""b"" %""b""1,%""b""1\n"
+              "        jmp 2b\n"
+              ".previous\n"
+              " .section __ex_table,\"a\"\n"
+              " " ".balign 4" " " "\n"
+              " " ".long" " " "1b" "," "3b" "\n"
+              " .previous\n"
+              : "=r" (ret), "=q"(*(u8 *)to)
+              : "m" ((*(struct __large_struct *)(from))), "i" (1), "0" (ret));
+  return ret;
+}
+void romchecksum(const unsigned char *rom, unsigned char c)
+{
+  unsigned char sum;
+  for (sum = 0;
+       !__copy_from_user_inatomic(&(c), ( typeof(c) *)(rom++), sizeof(c));)
+    sum += c;
+}
index 9862af82aaecf225b07557ae3ecf0f68553babd4..d4aa935e1f69ffe3d0c79f845e15ee6c1122f0aa 100644 (file)
@@ -1574,7 +1574,8 @@ remove_useless_stmts_cond (gimple_stmt_iterator *gsi, struct rus_data *data)
   gimple stmt = gsi_stmt (*gsi);
 
   /* The folded result must still be a conditional statement.  */
-  fold_stmt_inplace (stmt);
+  fold_stmt (gsi);
+  gcc_assert (gsi_stmt (*gsi) == stmt);
 
   data->may_branch = true;
 
index 0bbc0f04325f9dd500feadaa7349cb74b244173a..9cf2f83546b70a2618395d6c4de4618b3d2f53cd 100644 (file)
@@ -2836,43 +2836,81 @@ fold_gimple_call (gimple_stmt_iterator *gsi)
   return false;
 }
 
-/* Fold the statement pointed to by GSI.  In some cases, this function may
-   replace the whole statement with a new one.  Returns true iff folding
-   makes any changes.
-   The statement pointed to by GSI should be in valid gimple form but may
-   be in unfolded state as resulting from for example constant propagation
-   which can produce *&x = 0.  */
+/* Worker for both fold_stmt and fold_stmt_inplace.  The INPLACE argument
+   distinguishes both cases.  */
 
-bool
-fold_stmt (gimple_stmt_iterator *gsi)
+static bool
+fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace)
 {
   bool changed = false;
   gimple stmt = gsi_stmt (*gsi);
+  unsigned i;
 
   /* Fold the main computation performed by the statement.  */
   switch (gimple_code (stmt))
     {
     case GIMPLE_ASSIGN:
       {
+       unsigned old_num_ops = gimple_num_ops (stmt);
        tree new_rhs = fold_gimple_assign (gsi);
-       if (new_rhs != NULL_TREE)
+       if (new_rhs != NULL_TREE
+           && (!inplace
+               || get_gimple_rhs_num_ops (TREE_CODE (new_rhs)) < old_num_ops))
          {
            gimple_assign_set_rhs_from_tree (gsi, new_rhs);
            changed = true;
          }
        break;
       }
+
     case GIMPLE_COND:
       changed |= fold_gimple_cond (stmt);
       break;
+
     case GIMPLE_CALL:
+      /* Fold *& in call arguments.  */
+      for (i = 0; i < gimple_call_num_args (stmt); ++i)
+       if (REFERENCE_CLASS_P (gimple_call_arg (stmt, i)))
+         {
+           tree tmp = maybe_fold_reference (gimple_call_arg (stmt, i), false);
+           if (tmp)
+             {
+               gimple_call_set_arg (stmt, i, tmp);
+               changed = true;
+             }
+         }
       /* The entire statement may be replaced in this case.  */
-      changed |= fold_gimple_call (gsi);
+      if (!inplace)
+       changed |= fold_gimple_call (gsi);
       break;
 
-    default:
-      return changed;
+    case GIMPLE_ASM:
+      /* Fold *& in asm operands.  */
+      for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
+       {
+         tree link = gimple_asm_output_op (stmt, i);
+         tree op = TREE_VALUE (link);
+         if (REFERENCE_CLASS_P (op)
+             && (op = maybe_fold_reference (op, true)) != NULL_TREE)
+           {
+             TREE_VALUE (link) = op;
+             changed = true;
+           }
+       }
+      for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
+       {
+         tree link = gimple_asm_input_op (stmt, i);
+         tree op = TREE_VALUE (link);
+         if (REFERENCE_CLASS_P (op)
+             && (op = maybe_fold_reference (op, false)) != NULL_TREE)
+           {
+             TREE_VALUE (link) = op;
+             changed = true;
+           }
+       }
       break;
+
+    default:;
     }
 
   stmt = gsi_stmt (*gsi);
@@ -2895,6 +2933,19 @@ fold_stmt (gimple_stmt_iterator *gsi)
   return changed;
 }
 
+/* Fold the statement pointed to by GSI.  In some cases, this function may
+   replace the whole statement with a new one.  Returns true iff folding
+   makes any changes.
+   The statement pointed to by GSI should be in valid gimple form but may
+   be in unfolded state as resulting from for example constant propagation
+   which can produce *&x = 0.  */
+
+bool
+fold_stmt (gimple_stmt_iterator *gsi)
+{
+  return fold_stmt_1 (gsi, false);
+}
+
 /* Perform the minimal folding on statement STMT.  Only operations like
    *&x created by constant propagation are handled.  The statement cannot
    be replaced with a new one.  Return true if the statement was
@@ -2906,51 +2957,9 @@ fold_stmt (gimple_stmt_iterator *gsi)
 bool
 fold_stmt_inplace (gimple stmt)
 {
-  gimple_stmt_iterator si;
-  bool changed = false;
-
-  /* Fold the main computation performed by the statement.  */
-  switch (gimple_code (stmt))
-    {
-    case GIMPLE_ASSIGN:
-      {
-       unsigned old_num_ops;
-       tree new_rhs;
-       old_num_ops = gimple_num_ops (stmt);
-       si = gsi_for_stmt (stmt);
-       new_rhs = fold_gimple_assign (&si);
-       if (new_rhs != NULL_TREE
-           && get_gimple_rhs_num_ops (TREE_CODE (new_rhs)) < old_num_ops)
-         {
-           gimple_assign_set_rhs_from_tree (&si, new_rhs);
-           changed = true;
-         }
-       gcc_assert (gsi_stmt (si) == stmt);
-       break;
-      }
-    case GIMPLE_COND:
-      changed |= fold_gimple_cond (stmt);
-      break;
-
-    default:
-      break;
-    }
-
-  /* Fold *& on the lhs.  */
-  if (gimple_has_lhs (stmt))
-    {
-      tree lhs = gimple_get_lhs (stmt);
-      if (lhs && REFERENCE_CLASS_P (lhs))
-       {
-         tree new_lhs = maybe_fold_reference (lhs, true);
-         if (new_lhs)
-           {
-             gimple_set_lhs (stmt, new_lhs);
-             changed = true;
-           }
-       }
-    }
-
+  gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+  bool changed = fold_stmt_1 (&gsi, true);
+  gcc_assert (gsi_stmt (gsi) == stmt);
   return changed;
 }