re PR rtl-optimization/19210 (not using do-loop for some loops)
gcc: 2005-07-21 Paolo Bonzini <bonzini@gnu.org> Zdenek Dvorak <dvorakz@suse.cz> PR tree-optimization/19210 * common.opt (Wunsafe-loop-optimizations, funsafe-loop-optimizations): New. * Makefile.in (tree-ssa-loop-niter.o): Depend intl.o. * loop-iv.c (get_simple_loop_desc): If -funsafe-loop-optimizations, rely on unproven assumptions. * predict.c (predict_loops): Adjust call to number_of_iterations_exit. * tree-flow.h (number_of_iterations_exit): Add final parameter. * tree-scalar-evolution.c (number_of_iterations_in_loop): Adjust call to number_of_iterations_exit. * tree-ssa-loop-ivcanon.c (empty_loop_p): Likewise. * tree-ssa-loop-ivopts.c (niter_for_exit): Likewise. * tree-ssa-loop-niter.c (find_loop_niter, estimate_numbers_of_iterations_loop): Likewise. (number_of_iterations_exit): Honor the new options. * doc/invoke.texi (Wunsafe-loop-optimizations, funsafe-loop-optimizations): Document them. gcc/testsuite: 2005-07-21 Paolo Bonzini <bonzini@gnu.org> * gcc.dg/tree-ssa/pr19210-1.c: New. * gcc.dg/tree-ssa/pr19210-2.c: New. Co-Authored-By: Zdenek Dvorak <dvorakz@suse.cz> From-SVN: r102225
This commit is contained in:
parent
cb83c2ec41
commit
f9cc1a70d5
@ -1,3 +1,24 @@
|
||||
2005-07-21 Paolo Bonzini <bonzini@gnu.org>
|
||||
Zdenek Dvorak <dvorakz@suse.cz>
|
||||
|
||||
PR tree-optimization/19210
|
||||
* common.opt (Wunsafe-loop-optimizations, funsafe-loop-optimizations):
|
||||
New.
|
||||
* Makefile.in (tree-ssa-loop-niter.o): Depend intl.o.
|
||||
* loop-iv.c (get_simple_loop_desc): If -funsafe-loop-optimizations,
|
||||
rely on unproven assumptions.
|
||||
* predict.c (predict_loops): Adjust call to number_of_iterations_exit.
|
||||
* tree-flow.h (number_of_iterations_exit): Add final parameter.
|
||||
* tree-scalar-evolution.c (number_of_iterations_in_loop): Adjust call
|
||||
to number_of_iterations_exit.
|
||||
* tree-ssa-loop-ivcanon.c (empty_loop_p): Likewise.
|
||||
* tree-ssa-loop-ivopts.c (niter_for_exit): Likewise.
|
||||
* tree-ssa-loop-niter.c (find_loop_niter,
|
||||
estimate_numbers_of_iterations_loop): Likewise.
|
||||
(number_of_iterations_exit): Honor the new options.
|
||||
* doc/invoke.texi (Wunsafe-loop-optimizations,
|
||||
funsafe-loop-optimizations): Document them.
|
||||
|
||||
2005-07-21 Richard Sandiford <richard@codesourcery.com>
|
||||
|
||||
PR rtl-optimization/22167
|
||||
|
@ -1869,7 +1869,7 @@ tree-ssa-loop-niter.o : tree-ssa-loop-niter.c $(TREE_FLOW_H) $(CONFIG_H) \
|
||||
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
|
||||
tree-inline.h output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
|
||||
$(FLAGS_H) tree-pass.h $(SCEV_H) $(TREE_DATA_REF_H) $(BASIC_BLOCK_H) \
|
||||
$(GGC_H) hard-reg-set.h tree-chrec.h
|
||||
$(GGC_H) hard-reg-set.h tree-chrec.h intl.h
|
||||
tree-ssa-loop-ivcanon.o : tree-ssa-loop-ivcanon.c $(TREE_FLOW_H) $(CONFIG_H) \
|
||||
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
|
||||
tree-inline.h output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
|
||||
@ -2288,7 +2288,7 @@ cfgloopanal.o : cfgloopanal.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
|
||||
$(OBSTACK_H) output.h
|
||||
loop-iv.o : loop-iv.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(BASIC_BLOCK_H) \
|
||||
hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h $(TM_H) $(OBSTACK_H) \
|
||||
output.h
|
||||
output.h intl.h
|
||||
loop-invariant.o : loop-invariant.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
|
||||
$(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h \
|
||||
$(TM_H) function.h $(FLAGS_H) $(DF_H) $(OBSTACK_H) output.h
|
||||
|
@ -93,6 +93,10 @@ Wlarger-than-
|
||||
Common RejectNegative Joined UInteger
|
||||
-Wlarger-than-<number> Warn if an object is larger than <number> bytes
|
||||
|
||||
Wunsafe-loop-optimizations
|
||||
Common Var(warn_unsafe_loop_optimizations)
|
||||
Warn if the loop cannot be optimized due to nontrivial assumptions.
|
||||
|
||||
Wmissing-noreturn
|
||||
Common Var(warn_missing_noreturn)
|
||||
Warn about functions which might be candidates for __attribute__((noreturn))
|
||||
@ -402,6 +406,10 @@ fforce-mem
|
||||
Common Report Var(flag_force_mem)
|
||||
Copy memory operands into registers before use
|
||||
|
||||
fforward-propagate
|
||||
Common Report Var(flag_forward_propagate)
|
||||
Perform a forward propagation pass on RTL
|
||||
|
||||
; Nonzero means don't put addresses of constant functions in registers.
|
||||
; Used for compiling the Unix kernel, where strange substitutions are
|
||||
; done on the assembly output.
|
||||
@ -963,6 +971,13 @@ funroll-all-loops
|
||||
Common Report Var(flag_unroll_all_loops)
|
||||
Perform loop unrolling for all loops
|
||||
|
||||
; Nonzero means that loop optimizer may assume that the induction variables
|
||||
; that control loops do not overflow and that the loops with nontrivial
|
||||
; exit condition are not infinite
|
||||
funsafe-loop-optimizations
|
||||
Common Report Var(flag_unsafe_loop_optimizations)
|
||||
Allow loop optimizations to assume that the loops behave in normal way
|
||||
|
||||
; Nonzero means that unsafe floating-point math optimizations are allowed
|
||||
; for the sake of speed. IEEE compliance is not guaranteed, and operations
|
||||
; are allowed to assume that their arguments and results are "normal"
|
||||
|
@ -230,7 +230,7 @@ Objective-C and Objective-C++ Dialects}.
|
||||
-Wimport -Wno-import -Winit-self -Winline @gol
|
||||
-Wno-int-to-pointer-cast @gol
|
||||
-Wno-invalid-offsetof -Winvalid-pch @gol
|
||||
-Wlarger-than-@var{len} -Wlong-long @gol
|
||||
-Wlarger-than-@var{len} -Wunsafe-loop-optimizations -Wlong-long @gol
|
||||
-Wmain -Wmissing-braces -Wmissing-field-initializers @gol
|
||||
-Wmissing-format-attribute -Wmissing-include-dirs @gol
|
||||
-Wmissing-noreturn @gol
|
||||
@ -311,7 +311,7 @@ Objective-C and Objective-C++ Dialects}.
|
||||
-fno-default-inline -fno-defer-pop -floop-optimize2 -fmove-loop-invariants @gol
|
||||
-fno-function-cse -fno-guess-branch-probability @gol
|
||||
-fno-inline -fno-math-errno -fno-peephole -fno-peephole2 @gol
|
||||
-funsafe-math-optimizations -ffinite-math-only @gol
|
||||
-funsafe-math-optimizations -funsafe-loop-optimizations -ffinite-math-only @gol
|
||||
-fno-trapping-math -fno-zero-initialized-in-bss @gol
|
||||
-fomit-frame-pointer -foptimize-register-move @gol
|
||||
-foptimize-sibling-calls -fprefetch-loop-arrays @gol
|
||||
@ -2988,6 +2988,13 @@ global variable or whenever a built-in function is shadowed.
|
||||
@opindex Wlarger-than
|
||||
Warn whenever an object of larger than @var{len} bytes is defined.
|
||||
|
||||
@item -Wunsafe-loop-optimizations
|
||||
@opindex Wunsafe-loop-optimizations
|
||||
Warn if the loop cannot be optimized because the compiler could not
|
||||
assume anything on the bounds of the loop indices. With
|
||||
@option{-funsafe-loop-optimizations} warn if the compiler made
|
||||
such assumptions.
|
||||
|
||||
@item -Wpointer-arith
|
||||
@opindex Wpointer-arith
|
||||
Warn about anything that depends on the ``size of'' a function type or
|
||||
@ -4728,6 +4735,15 @@ Perform loop optimizations using the new loop optimizer. The optimizations
|
||||
(loop unrolling, peeling and unswitching, loop invariant motion) are enabled
|
||||
by separate flags.
|
||||
|
||||
@item -funsafe-loop-optimizations
|
||||
@opindex funsafe-loop-optimizations
|
||||
If given, the loop optimizer will assume that loop indices do not
|
||||
overflow, and that the loops with nontrivial exit condition are not
|
||||
infinite. This enables a wider range of loop optimizations even if
|
||||
the loop optimizer itself cannot prove that these assumptions are valid.
|
||||
Using @option{-Wunsafe-loop-optimizations}, the compiler will warn you
|
||||
if it finds this kind of loop.
|
||||
|
||||
@item -fcrossjumping
|
||||
@opindex crossjumping
|
||||
Perform cross-jumping transformation. This transformation unifies equivalent code and save code size. The
|
||||
|
@ -57,7 +57,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
#include "basic-block.h"
|
||||
#include "cfgloop.h"
|
||||
#include "expr.h"
|
||||
#include "intl.h"
|
||||
#include "output.h"
|
||||
#include "toplev.h"
|
||||
|
||||
/* The insn information. */
|
||||
|
||||
@ -2692,6 +2694,41 @@ get_simple_loop_desc (struct loop *loop)
|
||||
find_simple_exit (loop, desc);
|
||||
loop->aux = desc;
|
||||
|
||||
if (desc->simple_p && (desc->assumptions || desc->infinite))
|
||||
{
|
||||
const char *wording;
|
||||
|
||||
/* Assume that no overflow happens and that the loop is finite.
|
||||
We already warned at the tree level if we ran optimizations there. */
|
||||
if (!flag_tree_loop_optimize && warn_unsafe_loop_optimizations)
|
||||
{
|
||||
if (desc->infinite)
|
||||
{
|
||||
wording =
|
||||
flag_unsafe_loop_optimizations
|
||||
? N_("assuming that the loop is not infinite")
|
||||
: N_("cannot optimize possibly infinite loops");
|
||||
warning (OPT_Wunsafe_loop_optimizations, "%s",
|
||||
gettext (wording));
|
||||
}
|
||||
if (desc->assumptions)
|
||||
{
|
||||
wording =
|
||||
flag_unsafe_loop_optimizations
|
||||
? N_("assuming that the loop counter does not overflow")
|
||||
: N_("cannot optimize loop, the loop counter may overflow");
|
||||
warning (OPT_Wunsafe_loop_optimizations, "%s",
|
||||
gettext (wording));
|
||||
}
|
||||
}
|
||||
|
||||
if (flag_unsafe_loop_optimizations)
|
||||
{
|
||||
desc->assumptions = NULL_RTX;
|
||||
desc->infinite = NULL_RTX;
|
||||
}
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
|
@ -643,7 +643,7 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
|
||||
{
|
||||
tree niter = NULL;
|
||||
|
||||
if (number_of_iterations_exit (loop, exits[j], &niter_desc))
|
||||
if (number_of_iterations_exit (loop, exits[j], &niter_desc, false))
|
||||
niter = niter_desc.niter;
|
||||
if (!niter || TREE_CODE (niter_desc.niter) != INTEGER_CST)
|
||||
niter = loop_niter_by_eval (loop, exits[j]);
|
||||
|
@ -1,3 +1,8 @@
|
||||
2005-07-21 Paolo Bonzini <bonzini@gnu.org>
|
||||
|
||||
* gcc.dg/tree-ssa/pr19210-1.c: New.
|
||||
* gcc.dg/tree-ssa/pr19210-2.c: New.
|
||||
|
||||
2005-07-21 Richard Sandiford <richard@codesourcery.com>
|
||||
|
||||
PR rtl-optimization/22167
|
||||
|
20
gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c
Normal file
20
gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c
Normal file
@ -0,0 +1,20 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -Wunsafe-loop-optimizations" } */
|
||||
extern void g(void);
|
||||
|
||||
void
|
||||
f (unsigned n)
|
||||
{
|
||||
unsigned k;
|
||||
for(k = 0;k <= n;k++) /* { dg-warning "cannot optimize.*infinite loops" } */
|
||||
g();
|
||||
|
||||
for(k = 0;k <= n;k += 4) /* { dg-warning "cannot optimize.*overflow" } */
|
||||
g();
|
||||
|
||||
for(k = 5;k <= n;k += 5) /* { dg-warning "cannot optimize.*overflow" } */
|
||||
g();
|
||||
|
||||
for(k = 15;k >= n;k--) /* { dg-warning "cannot optimize.*infinite" } */
|
||||
g();
|
||||
}
|
21
gcc/testsuite/gcc.dg/tree-ssa/pr19210-2.c
Normal file
21
gcc/testsuite/gcc.dg/tree-ssa/pr19210-2.c
Normal file
@ -0,0 +1,21 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -funsafe-loop-optimizations -Wunsafe-loop-optimizations" } */
|
||||
extern void g(void);
|
||||
|
||||
void
|
||||
f (unsigned n)
|
||||
{
|
||||
unsigned k;
|
||||
for(k = 0;k <= n;k++) /* { dg-warning "assuming.*not infinite" } */
|
||||
g();
|
||||
|
||||
for(k = 5;k <= n;k += 4) /* { dg-warning "assuming.*not overflow" } */
|
||||
g();
|
||||
|
||||
for(k = 5;k <= n;k += 5) /* { dg-warning "assuming.*not overflow" } */
|
||||
g();
|
||||
|
||||
for(k = 15;k >= n;k--) /* { dg-warning "assuming.*not infinite" } */
|
||||
g();
|
||||
|
||||
}
|
@ -722,7 +722,7 @@ void remove_empty_loops (struct loops *);
|
||||
void tree_ssa_iv_optimize (struct loops *);
|
||||
|
||||
bool number_of_iterations_exit (struct loop *, edge,
|
||||
struct tree_niter_desc *niter);
|
||||
struct tree_niter_desc *niter, bool);
|
||||
tree find_loop_niter (struct loop *, edge *);
|
||||
tree loop_niter_by_eval (struct loop *, edge);
|
||||
tree find_loop_niter_by_eval (struct loop *, edge *);
|
||||
|
@ -2235,7 +2235,7 @@ number_of_iterations_in_loop (struct loop *loop)
|
||||
if (!exit)
|
||||
goto end;
|
||||
|
||||
if (!number_of_iterations_exit (loop, exit, &niter_desc))
|
||||
if (!number_of_iterations_exit (loop, exit, &niter_desc, false))
|
||||
goto end;
|
||||
|
||||
type = TREE_TYPE (niter_desc.niter);
|
||||
|
@ -393,7 +393,7 @@ empty_loop_p (struct loop *loop)
|
||||
return false;
|
||||
|
||||
/* The loop must be finite. */
|
||||
if (!number_of_iterations_exit (loop, exit, &niter))
|
||||
if (!number_of_iterations_exit (loop, exit, &niter, false))
|
||||
return false;
|
||||
|
||||
/* Values of all loop exit phi nodes must be invariants. */
|
||||
|
@ -712,7 +712,8 @@ niter_for_exit (struct ivopts_data *data, edge exit)
|
||||
nfe_desc = xmalloc (sizeof (struct nfe_cache_elt));
|
||||
nfe_desc->exit = exit;
|
||||
nfe_desc->valid_p = number_of_iterations_exit (data->current_loop,
|
||||
exit, &nfe_desc->niter);
|
||||
exit, &nfe_desc->niter,
|
||||
true);
|
||||
*slot = nfe_desc;
|
||||
}
|
||||
else
|
||||
|
@ -29,6 +29,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
#include "basic-block.h"
|
||||
#include "output.h"
|
||||
#include "diagnostic.h"
|
||||
#include "intl.h"
|
||||
#include "tree-flow.h"
|
||||
#include "tree-dump.h"
|
||||
#include "cfgloop.h"
|
||||
@ -39,6 +40,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
#include "tree-data-ref.h"
|
||||
#include "params.h"
|
||||
#include "flags.h"
|
||||
#include "toplev.h"
|
||||
#include "tree-inline.h"
|
||||
|
||||
#define SWAP(X, Y) do { void *tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
|
||||
@ -906,11 +908,14 @@ simplify_using_outer_evolutions (struct loop *loop, tree expr)
|
||||
EXIT (an exit edge of the LOOP) in NITER. Returns true if some
|
||||
useful information could be derived (and fields of NITER has
|
||||
meaning described in comments at struct tree_niter_desc
|
||||
declaration), false otherwise. */
|
||||
declaration), false otherwise. If WARN is true and
|
||||
-Wunsafe-loop-optimizations was given, warn if the optimizer is going to use
|
||||
potentially unsafe assumptions. */
|
||||
|
||||
bool
|
||||
number_of_iterations_exit (struct loop *loop, edge exit,
|
||||
struct tree_niter_desc *niter)
|
||||
struct tree_niter_desc *niter,
|
||||
bool warn)
|
||||
{
|
||||
tree stmt, cond, type;
|
||||
tree op0, base0, step0;
|
||||
@ -990,7 +995,45 @@ number_of_iterations_exit (struct loop *loop, edge exit,
|
||||
= simplify_using_initial_conditions (loop,
|
||||
niter->may_be_zero,
|
||||
&niter->additional_info);
|
||||
return integer_onep (niter->assumptions);
|
||||
|
||||
if (integer_onep (niter->assumptions))
|
||||
return true;
|
||||
|
||||
/* With -funsafe-loop-optimizations we assume that nothing bad can happen.
|
||||
But if we can prove that there is overflow or some other source of weird
|
||||
behavior, ignore the loop even with -funsafe-loop-optimizations. */
|
||||
if (integer_zerop (niter->assumptions))
|
||||
return false;
|
||||
|
||||
if (flag_unsafe_loop_optimizations)
|
||||
niter->assumptions = boolean_true_node;
|
||||
|
||||
if (warn)
|
||||
{
|
||||
const char *wording;
|
||||
location_t loc = EXPR_LOCATION (stmt);
|
||||
|
||||
/* We can provide a more specific warning if one of the operator is
|
||||
constant and the other advances by +1 or -1. */
|
||||
if (step1 ? !step0 && (integer_onep (step1) || integer_all_onesp (step1))
|
||||
: step0 && (integer_onep (step0) || integer_all_onesp (step0)))
|
||||
wording =
|
||||
flag_unsafe_loop_optimizations
|
||||
? N_("assuming that the loop is not infinite")
|
||||
: N_("cannot optimize possibly infinite loops");
|
||||
else
|
||||
wording =
|
||||
flag_unsafe_loop_optimizations
|
||||
? N_("assuming that the loop counter does not overflow")
|
||||
: N_("cannot optimize loop, the loop counter may overflow");
|
||||
|
||||
if (LOCATION_LINE (loc) > 0)
|
||||
warning (OPT_Wunsafe_loop_optimizations, "%H%s", &loc, gettext (wording));
|
||||
else
|
||||
warning (OPT_Wunsafe_loop_optimizations, "%s", gettext (wording));
|
||||
}
|
||||
|
||||
return flag_unsafe_loop_optimizations;
|
||||
}
|
||||
|
||||
/* Try to determine the number of iterations of LOOP. If we succeed,
|
||||
@ -1014,7 +1057,7 @@ find_loop_niter (struct loop *loop, edge *exit)
|
||||
if (!just_once_each_iteration_p (loop, ex->src))
|
||||
continue;
|
||||
|
||||
if (!number_of_iterations_exit (loop, ex, &desc))
|
||||
if (!number_of_iterations_exit (loop, ex, &desc, false))
|
||||
continue;
|
||||
|
||||
if (nonzero_p (desc.may_be_zero))
|
||||
@ -1360,7 +1403,7 @@ estimate_numbers_of_iterations_loop (struct loop *loop)
|
||||
exits = get_loop_exit_edges (loop, &n_exits);
|
||||
for (i = 0; i < n_exits; i++)
|
||||
{
|
||||
if (!number_of_iterations_exit (loop, exits[i], &niter_desc))
|
||||
if (!number_of_iterations_exit (loop, exits[i], &niter_desc, false))
|
||||
continue;
|
||||
|
||||
niter = niter_desc.niter;
|
||||
|
Loading…
Reference in New Issue
Block a user