Commit e3d5405d by Kaveh R. Ghazi Committed by Kaveh Ghazi

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
parent 18b80268
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
......
......@@ -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:
......
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.
......
......@@ -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,
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment