diff options
Diffstat (limited to 'gcc/tree-ssa-loop-im.c')
-rw-r--r-- | gcc/tree-ssa-loop-im.c | 44 |
1 files changed, 44 insertions, 0 deletions
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; } |