Commit fbd28bc3 by Jakub Jelinek Committed by Jakub Jelinek

re PR tree-optimization/53265 (Warn when undefined behavior implies smaller iteration count)

	PR tree-optimization/53265
	* common.opt (Waggressive-loop-optimizations): New option.
	* tree-ssa-loop-niter.c: Include tree-pass.h.
	(do_warn_aggressive_loop_optimizations): New function.
	(record_estimate): Call it.  Don't add !is_exit bounds to loop->bounds
	if number_of_latch_executions returned constant.
	(estimate_numbers_of_iterations_loop): Call number_of_latch_executions
	early.  If number_of_latch_executions returned constant, set
	nb_iterations_upper_bound back to it.
	* cfgloop.h (struct loop): Add warned_aggressive_loop_optimizations
	field.
	* Makefile.in (tree-ssa-loop-niter.o): Depend on $(TREE_PASS_H).
	* doc/invoke.texi (-Wno-aggressive-loop-optimizations): Document.

	* gcc.dg/pr53265.c: New test.
	* gcc.dg/torture/pr49518.c: Add -Wno-aggressive-loop-optimizations
	to dg-options.
	* g++.dg/opt/longbranch2.C (EBCOTLut): Double sizes of a2 and a3
	arrays.
	* gcc.dg/tree-ssa/cunroll-10.c (main): Rename to foo.  Add argument
	n, use it as high bound instead of 4.

	* unwind-dw2.c (execute_cfa_program): Avoid
	-Waggressive-array-optimizations warnings for DW_CFA_GNU_window_save
	on targets with DWARF_FRAME_REGISTERS < 32.

	* testsuite/libmudflap.c/fail37-frag.c: Add optimization barrier.

From-SVN: r196650
parent df2dfaea
2013-03-14 Jakub Jelinek <jakub@redhat.com> 2013-03-14 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/53265
* common.opt (Waggressive-loop-optimizations): New option.
* tree-ssa-loop-niter.c: Include tree-pass.h.
(do_warn_aggressive_loop_optimizations): New function.
(record_estimate): Call it. Don't add !is_exit bounds to loop->bounds
if number_of_latch_executions returned constant.
(estimate_numbers_of_iterations_loop): Call number_of_latch_executions
early. If number_of_latch_executions returned constant, set
nb_iterations_upper_bound back to it.
* cfgloop.h (struct loop): Add warned_aggressive_loop_optimizations
field.
* Makefile.in (tree-ssa-loop-niter.o): Depend on $(TREE_PASS_H).
* doc/invoke.texi (-Wno-aggressive-loop-optimizations): Document.
* config/aarch64/t-aarch64-linux (MULTARCH_DIRNAME): Remove. * config/aarch64/t-aarch64-linux (MULTARCH_DIRNAME): Remove.
(MULTILIB_OSDIRNAMES): Set. (MULTILIB_OSDIRNAMES): Set.
* genmultilib: If defaultosdirname doesn't start with :: , set * genmultilib: If defaultosdirname doesn't start with :: , set
......
...@@ -2446,7 +2446,7 @@ tree-ssa-loop-niter.o : tree-ssa-loop-niter.c $(TREE_FLOW_H) $(CONFIG_H) \ ...@@ -2446,7 +2446,7 @@ tree-ssa-loop-niter.o : tree-ssa-loop-niter.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \ $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
$(TREE_INLINE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h dumpfile.h \ $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h dumpfile.h \
$(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(TREE_DATA_REF_H) \ $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(TREE_DATA_REF_H) \
$(BASIC_BLOCK_H) $(GGC_H) intl.h $(GIMPLE_PRETTY_PRINT_H) $(BASIC_BLOCK_H) $(GGC_H) intl.h $(GIMPLE_PRETTY_PRINT_H) $(TREE_PASS_H)
tree-ssa-loop-ivcanon.o : tree-ssa-loop-ivcanon.c $(TREE_FLOW_H) $(CONFIG_H) \ tree-ssa-loop-ivcanon.o : tree-ssa-loop-ivcanon.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \ $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
$(TREE_INLINE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h \ $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(TM_H) coretypes.h \
......
...@@ -159,6 +159,10 @@ struct GTY ((chain_next ("%h.next"))) loop { ...@@ -159,6 +159,10 @@ struct GTY ((chain_next ("%h.next"))) loop {
/* True if the loop can be parallel. */ /* True if the loop can be parallel. */
bool can_be_parallel; bool can_be_parallel;
/* True if -Waggressive-loop-optimizations warned about this loop
already. */
bool warned_aggressive_loop_optimizations;
/* An integer estimation of the number of iterations. Estimate_state /* An integer estimation of the number of iterations. Estimate_state
describes what is the state of the estimation. */ describes what is the state of the estimation. */
enum loop_estimation estimate_state; enum loop_estimation estimate_state;
......
...@@ -505,6 +505,10 @@ Waggregate-return ...@@ -505,6 +505,10 @@ Waggregate-return
Common Var(warn_aggregate_return) Warning Common Var(warn_aggregate_return) Warning
Warn about returning structures, unions or arrays Warn about returning structures, unions or arrays
Waggressive-loop-optimizations
Common Var(warn_aggressive_loop_optimizations) Init(1) Warning
Warn if a loop with constant number of iterations triggers undefined behavior
Warray-bounds Warray-bounds
Common Var(warn_array_bounds) Warning Common Var(warn_array_bounds) Warning
Warn if an array is accessed out of bounds Warn if an array is accessed out of bounds
......
...@@ -232,7 +232,8 @@ Objective-C and Objective-C++ Dialects}. ...@@ -232,7 +232,8 @@ Objective-C and Objective-C++ Dialects}.
@xref{Warning Options,,Options to Request or Suppress Warnings}. @xref{Warning Options,,Options to Request or Suppress Warnings}.
@gccoptlist{-fsyntax-only -fmax-errors=@var{n} -Wpedantic @gol @gccoptlist{-fsyntax-only -fmax-errors=@var{n} -Wpedantic @gol
-pedantic-errors @gol -pedantic-errors @gol
-w -Wextra -Wall -Waddress -Waggregate-return -Warray-bounds @gol -w -Wextra -Wall -Waddress -Waggregate-return @gol
-Waggressive-loop-optimizations -Warray-bounds @gol
-Wno-attributes -Wno-builtin-macro-redefined @gol -Wno-attributes -Wno-builtin-macro-redefined @gol
-Wc++-compat -Wc++11-compat -Wcast-align -Wcast-qual @gol -Wc++-compat -Wc++11-compat -Wcast-align -Wcast-qual @gol
-Wchar-subscripts -Wclobbered -Wcomment @gol -Wchar-subscripts -Wclobbered -Wcomment @gol
...@@ -4423,6 +4424,12 @@ Warn if any functions that return structures or unions are defined or ...@@ -4423,6 +4424,12 @@ Warn if any functions that return structures or unions are defined or
called. (In languages where you can return an array, this also elicits called. (In languages where you can return an array, this also elicits
a warning.) a warning.)
@item -Wno-aggressive-loop-optimizations
@opindex Wno-aggressive-loop-optimizations
@opindex Waggressive-loop-optimizations
Warn if in a loop with constant number of iterations the compiler detects
undefined behavior in some statement during one or more of the iterations.
@item -Wno-attributes @item -Wno-attributes
@opindex Wno-attributes @opindex Wno-attributes
@opindex Wattributes @opindex Wattributes
......
2013-03-14 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/53265
* gcc.dg/pr53265.c: New test.
* gcc.dg/torture/pr49518.c: Add -Wno-aggressive-loop-optimizations
to dg-options.
* g++.dg/opt/longbranch2.C (EBCOTLut): Double sizes of a2 and a3
arrays.
* gcc.dg/tree-ssa/cunroll-10.c (main): Rename to foo. Add argument
n, use it as high bound instead of 4.
2013-03-13 Oleg Endo <olegendo@gcc.gnu.org> 2013-03-13 Oleg Endo <olegendo@gcc.gnu.org>
PR target/49880 PR target/49880
......
...@@ -15,8 +15,8 @@ public: ...@@ -15,8 +15,8 @@ public:
class EBCOTLut : public JKeeper { class EBCOTLut : public JKeeper {
unsigned char a1[1<<8]; unsigned char a1[1<<8];
unsigned char a2[1<<8]; unsigned char a2[1<<9];
unsigned char a3[1<<8]; unsigned char a3[1<<9];
long a4[1<<9]; long a4[1<<9];
public: public:
EBCOTLut(void); EBCOTLut(void);
......
/* PR tree-optimization/53265 */
/* { dg-do compile } */
/* { dg-options "-O2 -Wall" } */
void bar (void *);
int baz (int);
void
fn1 (void)
{
unsigned int a[128];
int i;
for (i = 0; i < 128; ++i) /* { dg-message "note: containing loop" } */
a[i] = i * 0x02000001; /* { dg-warning "invokes undefined behavior" } */
bar (a);
}
void
fn2 (void)
{
unsigned long long a[128];
int i;
for (i = 0; i < 128; i++) /* { dg-message "note: containing loop" } */
a[i] = (i + 1LL) * 0x0123456789ABCDEFLL; /* { dg-warning "invokes undefined behavior" } */
bar (a);
}
void
fn3 (void)
{
unsigned char a[16], b[16], c[16];
int i;
bar (b);
for (i = 0; i < (int) (sizeof (a) / sizeof (a[0])); i++) /* { dg-message "note: containing loop" } */
{
c[i + 8] = b[i]; /* { dg-warning "invokes undefined behavior" } */
a[i + 8] = b[i + 8];
}
bar (a);
bar (c);
}
void
fn4 (void)
{
unsigned int *a[32], *o, i;
bar (a);
for (i = 0; i <= sizeof (a) / sizeof (a[0]); i++) /* { dg-message "note: containing loop" "" { xfail *-*-* } } */
{
o = a[i]; /* { dg-warning "invokes undefined behavior" "" { xfail *-*-* } } */
bar (o);
}
}
void
fn5 (void)
{
unsigned short a[23940];
unsigned int b[1140];
int j;
bar (b);
for (j = 0; j < 1140; j++) /* { dg-message "note: containing loop" } */
a[23940 + j - 950] = b[j]; /* { dg-warning "invokes undefined behavior" } */
bar (a);
}
void
fn6 (void)
{
double a[4][3], b[12];
int i;
bar (b);
for (i = 0; i < 12; i++) /* { dg-message "note: containing loop" } */
a[0][i] = b[i] / 10000.0; /* { dg-warning "invokes undefined behavior" } */
bar (a);
}
void
fn7 (void)
{
int a[16], b, c;
bar (a);
for (b = a[c = 0]; c < 16; b = a[++c]) /* { dg-warning "invokes undefined behavior" "" { xfail *-*-* } } */
baz (b);
}
/* { dg-message "note: containing loop" "" { xfail *-*-* } 88 } */
const void *va, *vb, *vc, *vd, *ve;
const void *vf[4];
void
fn8 (void)
{
unsigned long i;
vf[0] = va; vf[1] = vb; vf[2] = vc; vf[3] = vd;
for (i = 0; i < (sizeof (vf) / sizeof (vf[0])); i++)
if (!vf[i])
vf[i] = ve;
}
int wa, wb[53][5], wc[53][5];
void
fn9 (void)
{
int i, j, k;
for (i = 0; i < 53; i++)
for (j = 16 / (((wa & 1) != 0) ? 8 : 4); j > 0; j--)
{
int d = 1;
if (wb[i][j] == 0 || wc[i][1] != 0)
continue;
for (k = 0; k < j; k++)
if (wc[i + k][1])
{
d = 0;
break;
}
if (!d)
continue;
wc[i][j] = baz (0);
}
}
int xa[18];
void
fn10 (void)
{
int i;
for (i = 16; i < 32; i++) /* { dg-message "note: containing loop" } */
xa[i] = 26; /* { dg-warning "invokes undefined behavior" } */
}
__attribute__((noinline)) static void
fn11 (int x)
{
int i = 1;
if (x > 1)
do
baz (i);
while (++i != x); /* { dg-bogus "invokes undefined behavior" } */
}
void
fn12 (void)
{
fn11 (1);
fn11 (1);
fn11 (1);
}
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-Wno-aggressive-loop-optimizations" } */
int a, b; int a, b;
struct S { unsigned int s, t, u; } c, d = { 0, 1, 0 }; struct S { unsigned int s, t, u; } c, d = { 0, 1, 0 };
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
/* { dg-options "-O3 -Warray-bounds -fdump-tree-cunroll-details" } */ /* { dg-options "-O3 -Warray-bounds -fdump-tree-cunroll-details" } */
int a[3]; int a[3];
int b[4]; int b[4];
main() int
foo (int n)
{ {
int i; int i;
for (i=0;i<4;i++) for (i=0;i<n;i++)
if (b[i]==2) if (b[i]==2)
a[i]++; a[i]++;
} }
......
...@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h" #include "flags.h"
#include "diagnostic-core.h" #include "diagnostic-core.h"
#include "tree-inline.h" #include "tree-inline.h"
#include "tree-pass.h"
#define SWAP(X, Y) do { affine_iv *tmp = (X); (X) = (Y); (Y) = tmp; } while (0) #define SWAP(X, Y) do { affine_iv *tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
...@@ -2525,6 +2526,40 @@ record_niter_bound (struct loop *loop, double_int i_bound, bool realistic, ...@@ -2525,6 +2526,40 @@ record_niter_bound (struct loop *loop, double_int i_bound, bool realistic,
loop->nb_iterations_estimate = loop->nb_iterations_upper_bound; loop->nb_iterations_estimate = loop->nb_iterations_upper_bound;
} }
/* Emit a -Waggressive-loop-optimizations warning if needed. */
static void
do_warn_aggressive_loop_optimizations (struct loop *loop,
double_int i_bound, gimple stmt)
{
/* Don't warn if the loop doesn't have known constant bound. */
if (!loop->nb_iterations
|| TREE_CODE (loop->nb_iterations) != INTEGER_CST
|| !warn_aggressive_loop_optimizations
/* To avoid warning multiple times for the same loop,
only start warning when we preserve loops. */
|| (cfun->curr_properties & PROP_loops) == 0
/* Only warn once per loop. */
|| loop->warned_aggressive_loop_optimizations
/* Only warn if undefined behavior gives us lower estimate than the
known constant bound. */
|| i_bound.ucmp (tree_to_double_int (loop->nb_iterations)) >= 0
/* And undefined behavior happens unconditionally. */
|| !dominated_by_p (CDI_DOMINATORS, loop->latch, gimple_bb (stmt)))
return;
edge e = single_exit (loop);
if (e == NULL)
return;
gimple estmt = last_stmt (e->src);
warning_at (gimple_location (stmt), OPT_Waggressive_loop_optimizations,
"iteration %E invokes undefined behavior",
double_int_to_tree (TREE_TYPE (loop->nb_iterations), i_bound));
inform (gimple_location (estmt), "containing loop");
loop->warned_aggressive_loop_optimizations = true;
}
/* Records that AT_STMT is executed at most BOUND + 1 times in LOOP. IS_EXIT /* Records that AT_STMT is executed at most BOUND + 1 times in LOOP. IS_EXIT
is true if the loop is exited immediately after STMT, and this exit is true if the loop is exited immediately after STMT, and this exit
is taken at last when the STMT is executed BOUND + 1 times. is taken at last when the STMT is executed BOUND + 1 times.
...@@ -2560,8 +2595,12 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound, ...@@ -2560,8 +2595,12 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound,
return; return;
/* If we have a guaranteed upper bound, record it in the appropriate /* If we have a guaranteed upper bound, record it in the appropriate
list. */ list, unless this is an !is_exit bound (i.e. undefined behavior in
if (upper) at_stmt) in a loop with known constant number of iterations. */
if (upper
&& (is_exit
|| loop->nb_iterations == NULL_TREE
|| TREE_CODE (loop->nb_iterations) != INTEGER_CST))
{ {
struct nb_iter_bound *elt = ggc_alloc_nb_iter_bound (); struct nb_iter_bound *elt = ggc_alloc_nb_iter_bound ();
...@@ -2591,6 +2630,8 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound, ...@@ -2591,6 +2630,8 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound,
if (i_bound.ult (delta)) if (i_bound.ult (delta))
return; return;
if (upper && !is_exit)
do_warn_aggressive_loop_optimizations (loop, i_bound, at_stmt);
record_niter_bound (loop, i_bound, realistic, upper); record_niter_bound (loop, i_bound, realistic, upper);
} }
...@@ -3311,6 +3352,11 @@ estimate_numbers_of_iterations_loop (struct loop *loop) ...@@ -3311,6 +3352,11 @@ estimate_numbers_of_iterations_loop (struct loop *loop)
/* Force estimate compuation but leave any existing upper bound in place. */ /* Force estimate compuation but leave any existing upper bound in place. */
loop->any_estimate = false; loop->any_estimate = false;
/* Ensure that loop->nb_iterations is computed if possible. If it turns out
to be constant, we avoid undefined behavior implied bounds and instead
diagnose those loops with -Waggressive-loop-optimizations. */
number_of_latch_executions (loop);
exits = get_loop_exit_edges (loop); exits = get_loop_exit_edges (loop);
likely_exit = single_likely_exit (loop); likely_exit = single_likely_exit (loop);
FOR_EACH_VEC_ELT (exits, i, ex) FOR_EACH_VEC_ELT (exits, i, ex)
...@@ -3345,6 +3391,17 @@ estimate_numbers_of_iterations_loop (struct loop *loop) ...@@ -3345,6 +3391,17 @@ estimate_numbers_of_iterations_loop (struct loop *loop)
bound = gcov_type_to_double_int (nit); bound = gcov_type_to_double_int (nit);
record_niter_bound (loop, bound, true, false); record_niter_bound (loop, bound, true, false);
} }
/* If we know the exact number of iterations of this loop, try to
not break code with undefined behavior by not recording smaller
maximum number of iterations. */
if (loop->nb_iterations
&& TREE_CODE (loop->nb_iterations) == INTEGER_CST)
{
loop->any_upper_bound = true;
loop->nb_iterations_upper_bound
= tree_to_double_int (loop->nb_iterations);
}
} }
/* Sets NIT to the estimated number of executions of the latch of the /* Sets NIT to the estimated number of executions of the latch of the
......
2013-03-14 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/53265
* unwind-dw2.c (execute_cfa_program): Avoid
-Waggressive-array-optimizations warnings for DW_CFA_GNU_window_save
on targets with DWARF_FRAME_REGISTERS < 32.
2013-03-13 Oleg Endo <olegendo@gcc.gnu.org> 2013-03-13 Oleg Endo <olegendo@gcc.gnu.org>
PR target/49880 PR target/49880
......
...@@ -1128,6 +1128,7 @@ execute_cfa_program (const unsigned char *insn_ptr, ...@@ -1128,6 +1128,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
case DW_CFA_GNU_window_save: case DW_CFA_GNU_window_save:
/* ??? Hardcoded for SPARC register window configuration. */ /* ??? Hardcoded for SPARC register window configuration. */
if (DWARF_FRAME_REGISTERS >= 32)
for (reg = 16; reg < 32; ++reg) for (reg = 16; reg < 32; ++reg)
{ {
fs->regs.reg[reg].how = REG_SAVED_OFFSET; fs->regs.reg[reg].how = REG_SAVED_OFFSET;
......
2013-03-14 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/53265
* testsuite/libmudflap.c/fail37-frag.c: Add optimization barrier.
2013-02-03 Richard Sandiford <rdsandiford@googlemail.com> 2013-02-03 Richard Sandiford <rdsandiford@googlemail.com>
Update copyright years. Update copyright years.
......
...@@ -13,7 +13,11 @@ main () ...@@ -13,7 +13,11 @@ main ()
{ {
int i; int i;
for (i = 0; i < 5; i++) for (i = 0; i < 5; i++)
{
/* Optimization barrier. Prevent gcc from seeing the undefined behavior. */
__asm ("" : "+r" (i));
x.s[i].f = 0; x.s[i].f = 0;
}
exit (0); exit (0);
} }
/* { dg-output "mudflap violation 1.*" } */ /* { dg-output "mudflap violation 1.*" } */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment