aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>2009-09-24 20:44:55 +0000
committerKaveh Ghazi <ghazi@gcc.gnu.org>2009-09-24 20:44:55 +0000
commite3d5405d071e33540d70c62c6e24a2dfa7cc7d9d (patch)
tree942e85ee11d063e393b8d23171086e6c6108a90e
parent18b802688624127aa26b3d75dd0ce41e06cbeee9 (diff)
downloadgcc-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
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/fold-const.c71
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/torture/builtin-math-7.c6
-rw-r--r--gcc/tree-complex.c8
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