re PR tree-optimization/34099 (optimizer problem)

2007-11-16  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/34099
	* tree-ssa-ccp.c (likely_value): Use a whitelist for operators
	that produce UNDEFINED result if at least one of its operands
	is UNDEFINED.  By default the result is only UNDEFINED if all
	operands are UNDEFINED.

	* g++.dg/torture/pr3499.C: New testcase.
	* gcc.c-torture/execute/pr34099.c: Likewise.

From-SVN: r130222
This commit is contained in:
Richard Guenther 2007-11-16 10:10:05 +00:00 committed by Richard Biener
parent b2c3bcf47b
commit 7f879c9615
5 changed files with 114 additions and 3 deletions

View File

@ -1,3 +1,11 @@
2007-11-16 Richard Guenther <rguenther@suse.de>
PR tree-optimization/34099
* tree-ssa-ccp.c (likely_value): Use a whitelist for operators
that produce UNDEFINED result if at least one of its operands
is UNDEFINED. By default the result is only UNDEFINED if all
operands are UNDEFINED.
2007-11-16 Jakub Jelinek <jakub@redhat.com>
PR driver/30460

View File

@ -1,3 +1,9 @@
2007-11-16 Richard Guenther <rguenther@suse.de>
PR tree-optimization/34099
* g++.dg/torture/pr3499.C: New testcase.
* gcc.c-torture/execute/pr34099.c: Likewise.
2007-11-16 Olivier Hainque <hainque@adacore.com>
* gnat.dg/release_unc_maxalign.adb: New test.

View File

@ -0,0 +1,25 @@
/* { dg-do run } */
#include <complex>
typedef std::complex<double> NumType;
void
multiply(NumType a, NumType b, unsigned ac, NumType &ab)
{
NumType s;
for (unsigned j=0; j<ac; j++)
s = a * b;
ab = s;
}
extern "C" void abort (void);
int main()
{
NumType a(1,2), b(3,-2), c;
multiply(a, b, 1, c);
if (c.real() != 7
|| c.imag() != 4)
abort ();
return 0;
}

View File

@ -0,0 +1,16 @@
int foo (int b, int c)
{
int x;
if (b)
return x & c;
else
return 1;
}
extern void abort (void);
int main()
{
if (foo(1, 0) != 0)
abort ();
return 0;
}

View File

@ -507,7 +507,8 @@ set_lattice_value (tree var, prop_value_t new_val)
If STMT has no operands, then return CONSTANT.
Else if any operands of STMT are undefined, then return UNDEFINED.
Else if undefinedness of operands of STMT cause its value to be
undefined, then return UNDEFINED.
Else if any operands of STMT are constants, then return CONSTANT.
@ -516,7 +517,7 @@ set_lattice_value (tree var, prop_value_t new_val)
static ccp_lattice_t
likely_value (tree stmt)
{
bool has_constant_operand;
bool has_constant_operand, has_undefined_operand, all_undefined_operands;
stmt_ann_t ann;
tree use;
ssa_op_iter iter;
@ -552,17 +553,72 @@ likely_value (tree stmt)
return CONSTANT;
has_constant_operand = false;
has_undefined_operand = false;
all_undefined_operands = true;
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE | SSA_OP_VUSE)
{
prop_value_t *val = get_value (use);
if (val->lattice_val == UNDEFINED)
return UNDEFINED;
has_undefined_operand = true;
else
all_undefined_operands = false;
if (val->lattice_val == CONSTANT)
has_constant_operand = true;
}
/* If the operation combines operands like COMPLEX_EXPR make sure to
not mark the result UNDEFINED if only one part of the result is
undefined. */
if (has_undefined_operand
&& all_undefined_operands)
return UNDEFINED;
else if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
&& has_undefined_operand)
{
switch (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)))
{
/* Unary operators are handled with all_undefined_operands. */
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
case POINTER_PLUS_EXPR:
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case TRUNC_MOD_EXPR:
case CEIL_MOD_EXPR:
case FLOOR_MOD_EXPR:
case ROUND_MOD_EXPR:
case RDIV_EXPR:
case EXACT_DIV_EXPR:
case LSHIFT_EXPR:
case RSHIFT_EXPR:
case LROTATE_EXPR:
case RROTATE_EXPR:
case EQ_EXPR:
case NE_EXPR:
case LT_EXPR:
case GT_EXPR:
/* Not MIN_EXPR, MAX_EXPR. One VARYING operand may be selected.
Not bitwise operators, one VARYING operand may specify the
result completely. Not logical operators for the same reason.
Not LE/GE comparisons or unordered comparisons. Not
COMPLEX_EXPR as one VARYING operand makes the result partly
not UNDEFINED. */
return UNDEFINED;
default:
;
}
}
/* If there was an UNDEFINED operand but the result may be not UNDEFINED
fall back to VARYING even if there were CONSTANT operands. */
if (has_undefined_operand)
return VARYING;
if (has_constant_operand
/* We do not consider virtual operands here -- load from read-only
memory may have only VARYING virtual operands, but still be