diff options
author | Kaveh R. Ghazi <ghazi@caip.rutgers.edu> | 2009-09-24 20:44:55 +0000 |
---|---|---|
committer | Kaveh Ghazi <ghazi@gcc.gnu.org> | 2009-09-24 20:44:55 +0000 |
commit | e3d5405d071e33540d70c62c6e24a2dfa7cc7d9d (patch) | |
tree | 942e85ee11d063e393b8d23171086e6c6108a90e /gcc | |
parent | 18b802688624127aa26b3d75dd0ce41e06cbeee9 (diff) | |
download | gcc-e3d5405d071e33540d70c62c6e24a2dfa7cc7d9d.zip gcc-e3d5405d071e33540d70c62c6e24a2dfa7cc7d9d.tar.gz gcc-e3d5405d071e33540d70c62c6e24a2dfa7cc7d9d.tar.bz2 |
re PR middle-end/41435 (GCC doesn't fold complex int division)
PR middle-end/41435
* fold-const.c (const_binop): Handle complex int division.
* tree-complex.c (expand_complex_div_straight,
expand_complex_div_wide): Update comments.
testsuite:
* gcc.dg/torture/builtin-math-7.c: Test complex int division at
compile-time.
From-SVN: r152145
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/fold-const.c | 71 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/builtin-math-7.c | 6 | ||||
-rw-r--r-- | gcc/tree-complex.c | 8 |
5 files changed, 90 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3a8833d..22ab827 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2009-09-24 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + PR middle-end/41435 + * fold-const.c (const_binop): Handle complex int division. + * tree-complex.c (expand_complex_div_straight, + expand_complex_div_wide): Update comments. + 2009-09-24 DJ Delorie <dj@redhat.com> PR target/41456 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 34e47c1..d754bee 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -1995,9 +1995,22 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) return do_mpc_arg2 (arg1, arg2, type, /* do_nonfinite= */ folding_initializer, mpc_div); + /* Fallthru ... */ #endif + case TRUNC_DIV_EXPR: + case CEIL_DIV_EXPR: + case FLOOR_DIV_EXPR: + case ROUND_DIV_EXPR: + if (flag_complex_method == 0) { + /* Keep this algorithm in sync with + tree-complex.c:expand_complex_div_straight(). + + Expand complex division to scalars, straightforward algorithm. + a / b = ((ar*br + ai*bi)/t) + i((ai*br - ar*bi)/t) + t = br*br + bi*bi + */ tree magsquared = const_binop (PLUS_EXPR, const_binop (MULT_EXPR, r2, r2, notrunc), @@ -2014,12 +2027,64 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc) const_binop (MULT_EXPR, r1, i2, notrunc), notrunc); - if (INTEGRAL_TYPE_P (TREE_TYPE (r1))) - code = TRUNC_DIV_EXPR; - real = const_binop (code, t1, magsquared, notrunc); imag = const_binop (code, t2, magsquared, notrunc); } + else + { + /* Keep this algorithm in sync with + tree-complex.c:expand_complex_div_wide(). + + Expand complex division to scalars, modified algorithm to minimize + overflow with wide input ranges. */ + tree inner_type = TREE_TYPE (type); + tree absr2 = fold_build1 (ABS_EXPR, inner_type, r2); + tree absi2 = fold_build1 (ABS_EXPR, inner_type, i2); + tree compare = fold_build2 (LT_EXPR, boolean_type_node, absr2, absi2); + if (integer_nonzerop (compare)) + { + /* In the TRUE branch, we compute + ratio = br/bi; + div = (br * ratio) + bi; + tr = (ar * ratio) + ai; + ti = (ai * ratio) - ar; + tr = tr / div; + ti = ti / div; */ + tree ratio = fold_build2 (code, inner_type, r2, i2); + tree div = fold_build2 (PLUS_EXPR, inner_type, i2, + fold_build2 (MULT_EXPR, inner_type, + r2, ratio)); + real = fold_build2 (MULT_EXPR, inner_type, r1, ratio); + real = fold_build2 (PLUS_EXPR, inner_type, real, i1); + real = fold_build2 (code, inner_type, real, div); + + imag = fold_build2 (MULT_EXPR, inner_type, i1, ratio); + imag = fold_build2 (MINUS_EXPR, inner_type, imag, r1); + imag = fold_build2 (code, inner_type, imag, div); + } + else + { + /* In the FALSE branch, we compute + ratio = d/c; + divisor = (d * ratio) + c; + tr = (b * ratio) + a; + ti = b - (a * ratio); + tr = tr / div; + ti = ti / div; */ + tree ratio = fold_build2 (code, inner_type, i2, r2); + tree div = fold_build2 (PLUS_EXPR, inner_type, r2, + fold_build2 (MULT_EXPR, inner_type, + i2, ratio)); + + real = fold_build2 (MULT_EXPR, inner_type, i1, ratio); + real = fold_build2 (PLUS_EXPR, inner_type, real, r1); + real = fold_build2 (code, inner_type, real, div); + + imag = fold_build2 (MULT_EXPR, inner_type, r1, ratio); + imag = fold_build2 (MINUS_EXPR, inner_type, i1, imag); + imag = fold_build2 (code, inner_type, imag, div); + } + } break; default: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 51993a1..2511b4e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-09-24 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * gcc.dg/torture/builtin-math-7.c: Test complex int division at + compile-time. + 2009-09-24 Adam Nemet <anemet@caviumnetworks.com> * lib/scanasm.exp (make_pattern_printable): New function. diff --git a/gcc/testsuite/gcc.dg/torture/builtin-math-7.c b/gcc/testsuite/gcc.dg/torture/builtin-math-7.c index 0d6307d..86fd262 100644 --- a/gcc/testsuite/gcc.dg/torture/builtin-math-7.c +++ b/gcc/testsuite/gcc.dg/torture/builtin-math-7.c @@ -62,12 +62,14 @@ int main() TESTIT (double, 3.+4.i, *, 2, 6+8i); TESTIT (double, 3.+4.i, /, 2, 1.5+2i); TESTIT (int, 3+4i, *, 2, 6+8i); - RUNTIME_TESTIT (int, 3+4i, /, 2, 1+2i); + TESTIT (int, 3+4i, /, 2, 1+2i); TESTIT (double, 3.+4.i, *, 2+5i, -14+23i); TESTIT (double, 3.+4.i, /, 5i, .8-.6i); TESTIT (int, 3+4i, *, 2+5i, -14+23i); - RUNTIME_TESTIT (int, 30+40i, /, 5i, 8-6i); + TESTIT (int, 30+40i, /, 5i, 8-6i); + TESTIT (int, 14+6i, /, 7+3i, 2); + TESTIT (int, 8+24i, /, 4+12i, 2); /* Test that we don't overflow. */ TESTIT (double, diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c index f691805..199f1dcf 100644 --- a/gcc/tree-complex.c +++ b/gcc/tree-complex.c @@ -1065,7 +1065,9 @@ expand_complex_multiplication (gimple_stmt_iterator *gsi, tree inner_type, update_complex_assignment (gsi, rr, ri); } -/* Expand complex division to scalars, straightforward algorithm. +/* Keep this algorithm in sync with fold-const.c:const_binop(). + + Expand complex division to scalars, straightforward algorithm. a / b = ((ar*br + ai*bi)/t) + i((ai*br - ar*bi)/t) t = br*br + bi*bi */ @@ -1094,7 +1096,9 @@ expand_complex_div_straight (gimple_stmt_iterator *gsi, tree inner_type, update_complex_assignment (gsi, rr, ri); } -/* Expand complex division to scalars, modified algorithm to minimize +/* Keep this algorithm in sync with fold-const.c:const_binop(). + + Expand complex division to scalars, modified algorithm to minimize overflow with wide input ranges. */ static void |