backport: re PR middle-end/30364 (Wrong variable ranges due to constant folding)

2007-03-05  Richard Guenther  <rguenther@suse.de>

	Backport from mainline:
	2007-02-28  Richard Guenther  <rguenther@suse.de>

	PR middle-end/30364
	* fold-const.c (fold_binary): Do not associate expressions
	with more than one variable for integer types that do not wrap.

	* gcc.dg/torture/pr30364-1.c: New testcase.
	* gcc.dg/torture/pr30364-2.c: Likewise.
	* gcc.dg/torture/pr30364-3.c: Likewise.

From-SVN: r122548
This commit is contained in:
Richard Guenther
2007-03-05 13:15:25 +00:00
committed by Richard Biener
parent d21100c100
commit 567ec609c2
6 changed files with 103 additions and 4 deletions

View File

@@ -1,3 +1,12 @@
2007-03-05 Richard Guenther <rguenther@suse.de>
Backport from mainline:
2007-02-28 Richard Guenther <rguenther@suse.de>
PR middle-end/30364
* fold-const.c (fold_binary): Do not associate expressions
with more than one variable for integer types that do not wrap.
2007-03-04 Eric Botcazou <ebotcazou@adacore.com>
PR ada/26797

View File

@@ -8635,6 +8635,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
{
tree var0, con0, lit0, minus_lit0;
tree var1, con1, lit1, minus_lit1;
bool ok = true;
/* Split both trees into variables, constants, and literals. Then
associate each group together, the constants with literals,
@@ -8645,12 +8646,33 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
var1 = split_tree (arg1, code, &con1, &lit1, &minus_lit1,
code == MINUS_EXPR);
/* With undefined overflow we can only associate constants
with one variable. */
if ((POINTER_TYPE_P (type)
|| (INTEGRAL_TYPE_P (type)
&& !(TYPE_UNSIGNED (type) || flag_wrapv)))
&& var0 && var1)
{
tree tmp0 = var0;
tree tmp1 = var1;
if (TREE_CODE (tmp0) == NEGATE_EXPR)
tmp0 = TREE_OPERAND (tmp0, 0);
if (TREE_CODE (tmp1) == NEGATE_EXPR)
tmp1 = TREE_OPERAND (tmp1, 0);
/* The only case we can still associate with two variables
is if they are the same, modulo negation. */
if (!operand_equal_p (tmp0, tmp1, 0))
ok = false;
}
/* Only do something if we found more than two objects. Otherwise,
nothing has changed and we risk infinite recursion. */
if (2 < ((var0 != 0) + (var1 != 0)
+ (con0 != 0) + (con1 != 0)
+ (lit0 != 0) + (lit1 != 0)
+ (minus_lit0 != 0) + (minus_lit1 != 0)))
if (ok
&& (2 < ((var0 != 0) + (var1 != 0)
+ (con0 != 0) + (con1 != 0)
+ (lit0 != 0) + (lit1 != 0)
+ (minus_lit0 != 0) + (minus_lit1 != 0))))
{
/* Recombine MINUS_EXPR operands by using PLUS_EXPR. */
if (code == MINUS_EXPR)

View File

@@ -1,3 +1,13 @@
2007-03-05 Richard Guenther <rguenther@suse.de>
Backport from mainline:
2007-02-28 Richard Guenther <rguenther@suse.de>
PR middle-end/30364
* gcc.dg/torture/pr30364-1.c: New testcase.
* gcc.dg/torture/pr30364-2.c: Likewise.
* gcc.dg/torture/pr30364-3.c: Likewise.
2007-03-05 Tobias Burnus <burnus@net-b.de>
PR fortran/30968

View File

@@ -0,0 +1,19 @@
/* { dg-do run } */
extern void abort (void);
int f(int a, int b)
{
if (a > 0x7FFFFFF0) return 0;
if (b > 0x7FFFFFF0) return 0;
int c = (a - 20) + (b - 20);
return c > 0x7FFFFFF0;
}
int main()
{
if (f (0x7FFFFFF0, 41) != 1)
abort ();
return 0;
}

View File

@@ -0,0 +1,19 @@
/* { dg-do run } */
extern void abort (void);
int f(unsigned int a, unsigned int b)
{
if (a > 0x7FFFFFF0) return 0;
if (b > 0x7FFFFFF0) return 0;
int c = (a - 20) + (b - 20);
return c > 0x7FFFFFF0;
}
int main()
{
if (f (0x7FFFFFF0, 41) != 1)
abort ();
return 0;
}

View File

@@ -0,0 +1,20 @@
/* { dg-do run } */
/* { dg-options "-fwrapv" } */
extern void abort (void);
int f(int a, int b)
{
if (a > 0x7FFFFFF0) return 0;
if (b > 0x7FFFFFF0) return 0;
int c = (a - 20) + (b - 20);
return c > 0x7FFFFFF0;
}
int main()
{
if (f (0x7FFFFFF0, 41) != 1)
abort ();
return 0;
}