diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20050218-1.c | 30 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/loop-7.c | 34 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-im.c | 44 |
5 files changed, 123 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0800575..25fc15a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index eaf57ed..26cfd25 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..104174f --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20050218-1.c @@ -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 index 0000000..e5a4083 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-7.c @@ -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" } } */ diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 65a2a5f..770b71b 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -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; } |