re PR middle-end/26899 (Fold does not fold (i0 > i1 + 1) || (i1 < i0 - 1))

2006-10-28  Richard Guenther  <rguenther@suse.de>

	PR middle-end/26899
	* fold-const.c (maybe_canonicalize_comparison_1): Helper
	for maybe_canonicalize_comparison.
	(maybe_canonicalize_comparison): New function for canonicalizing
	comparison trees.
	(fold_comparison): Call it to canonicalize comparisons with
	constants involved.

	* gcc.dg/tree-ssa/pr26899.c: New testcase.

From-SVN: r118106
This commit is contained in:
Richard Guenther 2006-10-28 18:03:21 +00:00 committed by Richard Biener
parent 4d81bf8435
commit e73dbcaefc
4 changed files with 149 additions and 0 deletions

View File

@ -1,3 +1,13 @@
2006-10-28 Richard Guenther <rguenther@suse.de>
PR middle-end/26899
* fold-const.c (maybe_canonicalize_comparison_1): Helper
for maybe_canonicalize_comparison.
(maybe_canonicalize_comparison): New function for canonicalizing
comparison trees.
(fold_comparison): Call it to canonicalize comparisons with
constants involved.
2006-10-28 Richard Guenther <rguenther@suse.de>
PR target/28806

View File

@ -7749,6 +7749,126 @@ fold_minmax (enum tree_code code, tree type, tree op0, tree op1)
return NULL_TREE;
}
/* Helper that tries to canonicalize the comparison ARG0 CODE ARG1
by changing CODE to reduce the magnitude of constants involved in
ARG0 of the comparison.
Returns a canonicalized comparison tree if a simplification was
possible, otherwise returns NULL_TREE. */
static tree
maybe_canonicalize_comparison_1 (enum tree_code code, tree type,
tree arg0, tree arg1)
{
enum tree_code code0 = TREE_CODE (arg0);
tree t, cst0 = NULL_TREE;
int sgn0;
bool swap = false;
/* Match A +- CST code arg1 and CST code arg1. */
if (!(((code0 == MINUS_EXPR
|| code0 == PLUS_EXPR)
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
|| code0 == INTEGER_CST))
return NULL_TREE;
/* Identify the constant in arg0 and its sign. */
if (code0 == INTEGER_CST)
cst0 = arg0;
else
cst0 = TREE_OPERAND (arg0, 1);
sgn0 = tree_int_cst_sgn (cst0);
/* Overflowed constants and zero will cause problems. */
if (integer_zerop (cst0)
|| TREE_OVERFLOW (cst0))
return NULL_TREE;
/* See if we can reduce the mangitude of the constant in
arg0 by changing the comparison code. */
if (code0 == INTEGER_CST)
{
/* CST <= arg1 -> CST-1 < arg1. */
if (code == LE_EXPR && sgn0 == 1)
code = LT_EXPR;
/* -CST < arg1 -> -CST-1 <= arg1. */
else if (code == LT_EXPR && sgn0 == -1)
code = LE_EXPR;
/* CST > arg1 -> CST-1 >= arg1. */
else if (code == GT_EXPR && sgn0 == 1)
code = GE_EXPR;
/* -CST >= arg1 -> -CST-1 > arg1. */
else if (code == GE_EXPR && sgn0 == -1)
code = GT_EXPR;
else
return NULL_TREE;
/* arg1 code' CST' might be more canonical. */
swap = true;
}
else
{
/* A - CST < arg1 -> A - CST-1 <= arg1. */
if (code == LT_EXPR
&& code0 == ((sgn0 == -1) ? PLUS_EXPR : MINUS_EXPR))
code = LE_EXPR;
/* A + CST > arg1 -> A + CST-1 >= arg1. */
else if (code == GT_EXPR
&& code0 == ((sgn0 == -1) ? MINUS_EXPR : PLUS_EXPR))
code = GE_EXPR;
/* A + CST <= arg1 -> A + CST-1 < arg1. */
else if (code == LE_EXPR
&& code0 == ((sgn0 == -1) ? MINUS_EXPR : PLUS_EXPR))
code = LT_EXPR;
/* A - CST >= arg1 -> A - CST-1 > arg1. */
else if (code == GE_EXPR
&& code0 == ((sgn0 == -1) ? PLUS_EXPR : MINUS_EXPR))
code = GT_EXPR;
else
return NULL_TREE;
}
/* Now build the constant reduced in magnitude. */
t = int_const_binop (sgn0 == -1 ? PLUS_EXPR : MINUS_EXPR,
cst0, build_int_cst (TREE_TYPE (cst0), 1), 0);
if (code0 != INTEGER_CST)
t = fold_build2 (code0, TREE_TYPE (arg0), TREE_OPERAND (arg0, 0), t);
/* If swapping might yield to a more canonical form, do so. */
if (swap)
return fold_build2 (swap_tree_comparison (code), type, arg1, t);
else
return fold_build2 (code, type, t, arg1);
}
/* Canonicalize the comparison ARG0 CODE ARG1 with type TYPE with undefined
overflow further. Try to decrease the magnitude of constants involved
by changing LE_EXPR and GE_EXPR to LT_EXPR and GT_EXPR or vice versa
and put sole constants at the second argument position.
Returns the canonicalized tree if changed, otherwise NULL_TREE. */
static tree
maybe_canonicalize_comparison (enum tree_code code, tree type,
tree arg0, tree arg1)
{
tree t;
/* In principle pointers also have undefined overflow behavior,
but that causes problems elsewhere. */
if ((flag_wrapv || flag_trapv)
|| (TYPE_UNSIGNED (TREE_TYPE (arg0))
&& !POINTER_TYPE_P (TREE_TYPE (arg0))))
return NULL_TREE;
/* Try canonicalization by simplifying arg0. */
t = maybe_canonicalize_comparison_1 (code, type, arg0, arg1);
if (t)
return t;
/* Try canonicalization by simplifying arg1 using the swapped
comparsion. */
code = swap_tree_comparison (code);
return maybe_canonicalize_comparison_1 (code, type, arg1, arg0);
}
/* Subroutine of fold_binary. This routine performs all of the
transformations that are common to the equality/inequality
operators (EQ_EXPR and NE_EXPR) and the ordering operators
@ -7877,6 +7997,10 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
variable2);
}
tem = maybe_canonicalize_comparison (code, type, arg0, arg1);
if (tem)
return tem;
if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
{
tree targ0 = strip_float_extensions (arg0);

View File

@ -1,3 +1,8 @@
2006-10-28 Richard Guenther <rguenther@suse.de>
PR middle-end/26899
* gcc.dg/tree-ssa/pr26899.c: New testcase.
2006-10-28 Richard Guenther <rguenther@suse.de>
PR target/28806

View File

@ -0,0 +1,10 @@
/* { dg-options "-fdump-tree-gimple" } */
int foo (int i, int j)
{
return (i < j + 1) || (j > i - 1);
}
/* { dg-final { scan-tree-dump "j >= i" "gimple" } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */