re PR middle-end/28151 (ICE with complex math)

PR middle-end/28151
	* fold-const.c (const_binop): Be prepared for self returning zero.
	Simplify code handling complex values.

From-SVN: r114992
This commit is contained in:
Eric Botcazou 2006-06-25 17:16:25 +00:00 committed by Eric Botcazou
parent 036d1f6aac
commit 858214db14
4 changed files with 54 additions and 48 deletions

View File

@ -1,3 +1,9 @@
2006-06-25 Eric Botcazou <ebotcazou@adacore.com>
PR middle-end/28151
* fold-const.c (const_binop): Be prepared for self returning zero.
Simplify code handling complex values.
2006-06-24 Olivier Hainque <hainque@adacore.com>
* gimplify.c (gimplify_scalar_mode_aggregate_compare): New function.

View File

@ -1544,13 +1544,18 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
/* Combine two constants ARG1 and ARG2 under operation CODE to produce a new
constant. We assume ARG1 and ARG2 have the same data type, or at least
are the same kind of constant and the same machine mode.
are the same kind of constant and the same machine mode. Return zero if
combining the constants is not allowed in the current operating mode.
If NOTRUNC is nonzero, do not truncate the result to fit the data type. */
static tree
const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
{
/* Sanity check for the recursive cases. */
if (!arg1 || !arg2)
return NULL_TREE;
STRIP_NOPS (arg1);
STRIP_NOPS (arg2);
@ -1613,7 +1618,6 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
/* Don't constant fold this floating point operation if
the result has overflowed and flag_trapping_math. */
if (flag_trapping_math
&& MODE_HAS_INFINITIES (mode)
&& REAL_VALUE_ISINF (result)
@ -1625,7 +1629,6 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
result may dependent upon the run-time rounding mode and
flag_rounding_math is set, or if GCC's software emulation
is unable to accurately represent the result. */
if ((flag_rounding_math
|| (REAL_MODE_FORMAT_COMPOSITE_P (mode)
&& !flag_unsafe_math_optimizations))
@ -1649,78 +1652,61 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
tree i1 = TREE_IMAGPART (arg1);
tree r2 = TREE_REALPART (arg2);
tree i2 = TREE_IMAGPART (arg2);
tree t;
tree real, imag;
switch (code)
{
case PLUS_EXPR:
t = build_complex (type,
const_binop (PLUS_EXPR, r1, r2, notrunc),
const_binop (PLUS_EXPR, i1, i2, notrunc));
break;
case MINUS_EXPR:
t = build_complex (type,
const_binop (MINUS_EXPR, r1, r2, notrunc),
const_binop (MINUS_EXPR, i1, i2, notrunc));
real = const_binop (code, r1, r2, notrunc);
imag = const_binop (code, i1, i2, notrunc);
break;
case MULT_EXPR:
t = build_complex (type,
const_binop (MINUS_EXPR,
const_binop (MULT_EXPR,
r1, r2, notrunc),
const_binop (MULT_EXPR,
i1, i2, notrunc),
notrunc),
const_binop (PLUS_EXPR,
const_binop (MULT_EXPR,
r1, i2, notrunc),
const_binop (MULT_EXPR,
i1, r2, notrunc),
notrunc));
real = const_binop (MINUS_EXPR,
const_binop (MULT_EXPR, r1, r2, notrunc),
const_binop (MULT_EXPR, i1, i2, notrunc),
notrunc);
imag = const_binop (PLUS_EXPR,
const_binop (MULT_EXPR, r1, i2, notrunc),
const_binop (MULT_EXPR, i1, r2, notrunc),
notrunc);
break;
case RDIV_EXPR:
{
tree t1, t2, real, imag;
tree magsquared
= const_binop (PLUS_EXPR,
const_binop (MULT_EXPR, r2, r2, notrunc),
const_binop (MULT_EXPR, i2, i2, notrunc),
notrunc);
t1 = const_binop (PLUS_EXPR,
const_binop (MULT_EXPR, r1, r2, notrunc),
const_binop (MULT_EXPR, i1, i2, notrunc),
notrunc);
t2 = const_binop (MINUS_EXPR,
const_binop (MULT_EXPR, i1, r2, notrunc),
const_binop (MULT_EXPR, r1, i2, notrunc),
notrunc);
tree t1
= const_binop (PLUS_EXPR,
const_binop (MULT_EXPR, r1, r2, notrunc),
const_binop (MULT_EXPR, i1, i2, notrunc),
notrunc);
tree t2
= const_binop (MINUS_EXPR,
const_binop (MULT_EXPR, i1, r2, notrunc),
const_binop (MULT_EXPR, r1, i2, notrunc),
notrunc);
if (INTEGRAL_TYPE_P (TREE_TYPE (r1)))
{
real = const_binop (TRUNC_DIV_EXPR, t1, magsquared, notrunc);
imag = const_binop (TRUNC_DIV_EXPR, t2, magsquared, notrunc);
}
else
{
real = const_binop (RDIV_EXPR, t1, magsquared, notrunc);
imag = const_binop (RDIV_EXPR, t2, magsquared, notrunc);
if (!real || !imag)
return NULL_TREE;
}
code = TRUNC_DIV_EXPR;
t = build_complex (type, real, imag);
real = const_binop (code, t1, magsquared, notrunc);
imag = const_binop (code, t2, magsquared, notrunc);
}
break;
default:
return NULL_TREE;
}
return t;
if (real && imag)
return build_complex (type, real, imag);
}
return NULL_TREE;
}

View File

@ -1,3 +1,7 @@
2006-06-25 Eric Botcazou <ebotcazou@adacore.com>
* gcc.c-torture/compile/20060625-1.c: New test.
2006-06-25 Paul Thomas <pault@gcc.gnu.org>
PR fortran/20867

View File

@ -0,0 +1,10 @@
/* PR middle-end/28151 */
/* Testcase by Steven Bosscher <stevenb.gcc@gmail.com> */
_Complex float b;
void foo (void)
{
_Complex float a = __FLT_MAX__;
b = __FLT_MAX__ + a;
}