diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2006-06-25 17:16:25 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2006-06-25 17:16:25 +0000 |
commit | 858214db144c6a1f271021102a6315ad1ecd9f51 (patch) | |
tree | d395a0feadd03e36c4eaeb8eebbcadbbf09fdb76 /gcc/fold-const.c | |
parent | 036d1f6aacb3383406872c5410e83b3e91fb6e1b (diff) | |
download | gcc-858214db144c6a1f271021102a6315ad1ecd9f51.zip gcc-858214db144c6a1f271021102a6315ad1ecd9f51.tar.gz gcc-858214db144c6a1f271021102a6315ad1ecd9f51.tar.bz2 |
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
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 82 |
1 files changed, 34 insertions, 48 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index b54658d..5c592c3 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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; } |