re PR tree-optimization/23361 (Can't eliminate empty loops with power of two step and variable bounds)
2007-02-09 Zdenek Dvorak <dvorakz@suse.cz> Richard Guenther <rguenther@suse.de> PR middle-end/23361 * fold-const.c (fold_comparison): Handle obfuscated comparisons against INT_MIN/INT_MAX. * tree-ssa-loop-ivcanon.c (remove_empty_loop): Print to dump file if a loop is removed. * gcc.dg/fold-compare-3.c: New testcase. * gcc.dg/tree-ssa/loop-24.c: Likewise. Co-Authored-By: Richard Guenther <rguenther@suse.de> From-SVN: r121742
This commit is contained in:
parent
917fbceb1b
commit
b44e7f07c5
@ -1,3 +1,12 @@
|
||||
2007-02-09 Zdenek Dvorak <dvorakz@suse.cz>
|
||||
Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/23361
|
||||
* fold-const.c (fold_comparison): Handle obfuscated comparisons
|
||||
against INT_MIN/INT_MAX.
|
||||
* tree-ssa-loop-ivcanon.c (remove_empty_loop): Print to dump
|
||||
file if a loop is removed.
|
||||
|
||||
2007-02-09 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* calls.c (store_one_arg): Pass correct alignment to
|
||||
|
@ -8043,6 +8043,40 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
|
||||
|
||||
lhs = fold_build2 (lhs_add ? PLUS_EXPR : MINUS_EXPR,
|
||||
TREE_TYPE (arg1), const2, const1);
|
||||
|
||||
/* If the constant operation overflowed this can be
|
||||
simplified as a comparison against INT_MAX/INT_MIN. */
|
||||
if (TREE_CODE (lhs) == INTEGER_CST
|
||||
&& TREE_OVERFLOW (lhs))
|
||||
{
|
||||
int const1_sgn = tree_int_cst_sgn (const1);
|
||||
enum tree_code code2 = code;
|
||||
|
||||
/* Get the sign of the constant on the lhs if the
|
||||
operation were VARIABLE + CONST1. */
|
||||
if (TREE_CODE (arg0) == MINUS_EXPR)
|
||||
const1_sgn = -const1_sgn;
|
||||
|
||||
/* The sign of the constant determines if we overflowed
|
||||
INT_MAX (const1_sgn == -1) or INT_MIN (const1_sgn == 1).
|
||||
Canonicalize to the INT_MIN overflow by swapping the comparison
|
||||
if necessary. */
|
||||
if (const1_sgn == -1)
|
||||
code2 = swap_tree_comparison (code);
|
||||
|
||||
/* We now can look at the canonicalized case
|
||||
VARIABLE + 1 CODE2 INT_MIN
|
||||
and decide on the result. */
|
||||
if (code2 == LT_EXPR
|
||||
|| code2 == LE_EXPR
|
||||
|| code2 == EQ_EXPR)
|
||||
return omit_one_operand (type, boolean_false_node, variable);
|
||||
else if (code2 == NE_EXPR
|
||||
|| code2 == GE_EXPR
|
||||
|| code2 == GT_EXPR)
|
||||
return omit_one_operand (type, boolean_true_node, variable);
|
||||
}
|
||||
|
||||
if (TREE_CODE (lhs) == TREE_CODE (arg1)
|
||||
&& (TREE_CODE (lhs) != INTEGER_CST
|
||||
|| !TREE_OVERFLOW (lhs)))
|
||||
|
@ -1,3 +1,10 @@
|
||||
2007-02-09 Zdenek Dvorak <dvorakz@suse.cz>
|
||||
Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/23361
|
||||
* gcc.dg/fold-compare-3.c: New testcase.
|
||||
* gcc.dg/tree-ssa/loop-24.c: Likewise.
|
||||
|
||||
2007-02-09 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
* gcc.dg/pr26570.c: Clean up coverage files.
|
||||
|
159
gcc/testsuite/gcc.dg/fold-compare-3.c
Normal file
159
gcc/testsuite/gcc.dg/fold-compare-3.c
Normal file
@ -0,0 +1,159 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-cleanup_cfg1" } */
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
void this_comparison_is_false (void);
|
||||
void this_comparison_is_true (void);
|
||||
void this_comparison_is_not_decidable (void);
|
||||
|
||||
void bla1eq (int var)
|
||||
{
|
||||
if (var + 10 == INT_MIN + 9)
|
||||
this_comparison_is_false ();
|
||||
}
|
||||
|
||||
void bla2eq (int var)
|
||||
{
|
||||
if (var + 10 == INT_MIN + 10)
|
||||
this_comparison_is_not_decidable ();
|
||||
}
|
||||
|
||||
void bla3eq (int var)
|
||||
{
|
||||
if (var - 10 == INT_MAX - 9)
|
||||
this_comparison_is_false ();
|
||||
}
|
||||
|
||||
void bla4eq (int var)
|
||||
{
|
||||
if (var - 10 == INT_MAX - 10)
|
||||
this_comparison_is_not_decidable ();
|
||||
}
|
||||
|
||||
void bla1ne (int var)
|
||||
{
|
||||
if (var + 10 != INT_MIN + 9)
|
||||
this_comparison_is_true ();
|
||||
}
|
||||
|
||||
void bla2ne (int var)
|
||||
{
|
||||
if (var + 10 != INT_MIN + 10)
|
||||
this_comparison_is_not_decidable ();
|
||||
}
|
||||
|
||||
void bla3ne (int var)
|
||||
{
|
||||
if (var - 10 != INT_MAX - 9)
|
||||
this_comparison_is_true ();
|
||||
}
|
||||
|
||||
void bla4ne (int var)
|
||||
{
|
||||
if (var - 10 != INT_MAX - 10)
|
||||
this_comparison_is_not_decidable ();
|
||||
}
|
||||
|
||||
void bla1lt (int var)
|
||||
{
|
||||
if (var + 10 < INT_MIN + 10)
|
||||
this_comparison_is_false ();
|
||||
}
|
||||
|
||||
void bla2lt (int var)
|
||||
{
|
||||
if (var + 10 < INT_MIN + 11)
|
||||
this_comparison_is_not_decidable ();
|
||||
}
|
||||
|
||||
void bla3lt (int var)
|
||||
{
|
||||
if (var - 10 < INT_MAX - 9)
|
||||
this_comparison_is_true ();
|
||||
}
|
||||
|
||||
void bla4lt (int var)
|
||||
{
|
||||
if (var - 10 < INT_MAX - 10)
|
||||
this_comparison_is_not_decidable ();
|
||||
}
|
||||
|
||||
void bla1le (int var)
|
||||
{
|
||||
if (var + 10 <= INT_MIN + 9)
|
||||
this_comparison_is_false ();
|
||||
}
|
||||
|
||||
void bla2le (int var)
|
||||
{
|
||||
if (var + 10 <= INT_MIN + 10)
|
||||
this_comparison_is_not_decidable ();
|
||||
}
|
||||
|
||||
void bla3le (int var)
|
||||
{
|
||||
if (var - 10 <= INT_MAX - 10)
|
||||
this_comparison_is_true ();
|
||||
}
|
||||
|
||||
void bla4le (int var)
|
||||
{
|
||||
if (var - 10 <= INT_MAX - 11)
|
||||
this_comparison_is_not_decidable ();
|
||||
}
|
||||
|
||||
void bla1gt (int var)
|
||||
{
|
||||
if (var + 10 > INT_MIN + 9)
|
||||
this_comparison_is_true ();
|
||||
}
|
||||
|
||||
void bla2gt (int var)
|
||||
{
|
||||
if (var + 10 > INT_MIN + 10)
|
||||
this_comparison_is_not_decidable ();
|
||||
}
|
||||
|
||||
void bla3gt (int var)
|
||||
{
|
||||
if (var - 10 > INT_MAX - 10)
|
||||
this_comparison_is_false ();
|
||||
}
|
||||
|
||||
void bla4gt (int var)
|
||||
{
|
||||
if (var - 10 > INT_MAX - 11)
|
||||
this_comparison_is_not_decidable ();
|
||||
}
|
||||
|
||||
void bla1ge (int var)
|
||||
{
|
||||
if (var + 10 >= INT_MIN + 10)
|
||||
this_comparison_is_true ();
|
||||
}
|
||||
|
||||
void bla2ge (int var)
|
||||
{
|
||||
if (var + 10 >= INT_MIN + 11)
|
||||
this_comparison_is_not_decidable ();
|
||||
}
|
||||
|
||||
void bla3ge (int var)
|
||||
{
|
||||
if (var - 11 >= INT_MAX - 10)
|
||||
this_comparison_is_false ();
|
||||
}
|
||||
|
||||
void bla4ge (int var)
|
||||
{
|
||||
if (var - 10 >= INT_MAX - 10)
|
||||
this_comparison_is_not_decidable ();
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "this_comparison_is_false" 0 "cleanup_cfg1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "this_comparison_is_true" 6 "cleanup_cfg1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "this_comparison_is_not_decidable" 12 "cleanup_cfg1" } } */
|
||||
/* { dg-final { scan-tree-dump-times "if " 12 "cleanup_cfg1" } } */
|
||||
|
||||
/* { dg-final { cleanup-tree-dump "cleanup_cfg1" } } */
|
17
gcc/testsuite/gcc.dg/tree-ssa/loop-24.c
Normal file
17
gcc/testsuite/gcc.dg/tree-ssa/loop-24.c
Normal file
@ -0,0 +1,17 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O -fstrict-overflow -fdump-tree-empty" } */
|
||||
|
||||
void foo(int a, int b)
|
||||
{ for(;a!=b;a+=4); }
|
||||
|
||||
void foo2(int a, int b)
|
||||
{ for(;a<b;a+=4); }
|
||||
|
||||
void foo3(int*a, int* b)
|
||||
{ for(;a<b;a++); }
|
||||
|
||||
void foo4(int*a, int*b)
|
||||
{ for(;a!=b;a++); }
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Removing empty loop" 4 "empty" } } */
|
||||
/* { dg-final { cleanup-tree-dump "empty" } } */
|
@ -480,6 +480,9 @@ remove_empty_loop (struct loop *loop)
|
||||
unsigned n_before, freq_in, freq_h;
|
||||
gcov_type exit_count = exit->count;
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Removing empty loop %d\n", loop->num);
|
||||
|
||||
non_exit = EDGE_SUCC (exit->src, 0);
|
||||
if (non_exit == exit)
|
||||
non_exit = EDGE_SUCC (exit->src, 1);
|
||||
|
Loading…
Reference in New Issue
Block a user