]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/19828 (LIM is pulling out a pure function even though there...
authorZdenek Dvorak <dvorakz@suse.cz>
Sat, 19 Feb 2005 09:26:09 +0000 (10:26 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sat, 19 Feb 2005 09:26:09 +0000 (10:26 +0100)
PR tree-optimization/19828
* tree-ssa-loop-im.c: Add a TODO comment.
(movement_possibility): Return MOVE_PRESERVE_EXECUTION for calls
without side-effects.

* gcc.dg/tree-ssa/loop-7.c: New test.
* gcc.c-torture/execute/20050218-1.c: New test.

Co-Authored-By: Jakub Jelinek <jakub@redhat.com>
From-SVN: r95275

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20050218-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loop-7.c [new file with mode: 0644]
gcc/tree-ssa-loop-im.c

index 08005759c1ea9d5c00d05e6a4829213d0688d626..25fc15a5b1162d5b9121c3375da2635494f8261b 100644 (file)
@@ -1,3 +1,11 @@
+2005-02-19  Zdenek Dvorak  <dvorakz@suse.cz>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/19828
+       * tree-ssa-loop-im.c: Add a TODO comment.
+       (movement_possibility): Return MOVE_PRESERVE_EXECUTION for calls
+       without side-effects.
+
 2005-02-18  James A. Morrison  <phython@gcc.gnu.org>
 
        * tree-ssa-ccp.c (widen_bitfield): Pass type to build_int_cst and don't
index eaf57edcb3c4df528dd749190e46d8c5e3368755..26cfd2587031152e2757fc7730b56cea2ae77343 100644 (file)
@@ -1,3 +1,10 @@
+2005-02-19  Zdenek Dvorak  <dvorakz@suse.cz>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/19828
+       * gcc.dg/tree-ssa/loop-7.c: New test.
+       * gcc.c-torture/execute/20050218-1.c: New test.
+
 2005-02-19  Jakub Jelinek  <jakub@redhat.com>
 
        PR c/20043
diff --git a/gcc/testsuite/gcc.c-torture/execute/20050218-1.c b/gcc/testsuite/gcc.c-torture/execute/20050218-1.c
new file mode 100644 (file)
index 0000000..104174f
--- /dev/null
@@ -0,0 +1,30 @@
+/* PR tree-optimization/19828 */
+typedef __SIZE_TYPE__ size_t;
+extern size_t strlen (const char *s);
+extern int strncmp (const char *s1, const char *s2, size_t n);
+extern void abort (void);
+
+const char *a[16] = { "a", "bc", "de", "fgh" };
+
+int
+foo (char *x, const char *y, size_t n)
+{
+  size_t i, j = 0;
+  for (i = 0; i < n; i++)
+    {
+      if (strncmp (x + j, a[i], strlen (a[i])) != 0)
+        return 2;
+      j += strlen (a[i]);
+      if (y)
+        j += strlen (y);
+    }
+  return 0;
+}
+
+int
+main (void)
+{
+  if (foo ("abcde", (const char *) 0, 3) != 0)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-7.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-7.c
new file mode 100644 (file)
index 0000000..e5a4083
--- /dev/null
@@ -0,0 +1,34 @@
+/* PR tree-optimization/19828 */
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-lim-details" } */
+
+int cst_fun1 (int) __attribute__((__const__));
+int cst_fun2 (int) __attribute__((__const__));
+int pure_fun1 (int) __attribute__((__pure__));
+int pure_fun2 (int) __attribute__((__pure__));
+int foo (void);
+
+int xxx (void)
+{
+  int i, k = foo (), x = 0;
+
+  for (i = 0; i < 100; i++)
+    {
+      x += cst_fun1 (k);
+      x += pure_fun1 (k);
+
+      if (k)
+       {
+         x += cst_fun2 (k);
+         x += pure_fun2 (k);
+       }
+    }
+
+  return x;
+}
+
+/* Calls to cst_fun1 and pure_fun1 may be moved out of the loop.
+   Calls to cst_fun2 and pure_fun2 should not be, since calling
+   with k = 0 may be invalid.  */
+
+/* { dg-final { scan-tree-dump-times "Moving statement" 2 "lim" } } */
index 65a2a5fd48ad39e74d59a4c8acf460af2094c4ae..770b71b12080a01390333eec82942b9330c68bdc 100644 (file)
@@ -38,6 +38,28 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-pass.h"
 #include "flags.h"
 
+/* TODO:  Support for predicated code motion.  I.e.
+
+   while (1)
+     {
+       if (cond)
+        {
+          a = inv;
+          something;
+        }
+     }
+
+   Where COND and INV are is invariants, but evaluating INV may trap or be
+   invalid from some other reason if !COND.  This may be transformed to
+
+   if (cond)
+     a = inv;
+   while (1)
+     {
+       if (cond)
+        something;
+     }  */
+
 /* A type for the list of statements that have to be moved in order to be able
    to hoist an invariant computation.  */
 
@@ -227,6 +249,28 @@ movement_possibility (tree stmt)
       || tree_could_trap_p (rhs))
     return MOVE_PRESERVE_EXECUTION;
 
+  if (get_call_expr_in (stmt))
+    {
+      /* While pure or const call is guaranteed to have no side effects, we
+        cannot move it arbitrarily.  Consider code like
+
+        char *s = something ();
+
+        while (1)
+          {
+            if (s)
+              t = strlen (s);
+            else
+              t = 0;
+          }
+
+        Here the strlen call cannot be moved out of the loop, even though
+        s is invariant.  In addition to possibly creating a call with
+        invalid arguments, moving out a function call that is not executed
+        may cause performance regressions in case the call is costly and
+        not executed at all.  */
+      return MOVE_PRESERVE_EXECUTION;
+    }
   return MOVE_POSSIBLE;
 }