Commit c63f5a42 by Richard Henderson Committed by Richard Henderson

re PR middle-end/19609 (real and imaginary part interchanged when flags_complex_divide_method=1)

        PR middle-end/19609
        * tree-complex.c (expand_complex_div_wide): Use the correct formulae.

From-SVN: r94222
parent 52e6723c
2005-01-25 Richard Henderson <rth@redhat.com>
PR middle-end/19609
* tree-complex.c (expand_complex_div_wide): Use the correct formulae.
2005-01-25 Roger Sayle <roger@eyesopen.com> 2005-01-25 Roger Sayle <roger@eyesopen.com>
* expmed.c (choose_multiplier): Change interface to return the * expmed.c (choose_multiplier): Change interface to return the
......
...@@ -169,7 +169,8 @@ expand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type, ...@@ -169,7 +169,8 @@ expand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type,
tree ar, tree ai, tree br, tree bi, tree ar, tree ai, tree br, tree bi,
enum tree_code code) enum tree_code code)
{ {
tree rr, ri, ratio, div, t1, t2, min, max, cond; tree rr, ri, ratio, div, t1, t2, tr, ti, cond;
basic_block bb_cond, bb_true, bb_false, bb_join;
/* Examine |br| < |bi|, and branch. */ /* Examine |br| < |bi|, and branch. */
t1 = gimplify_build1 (bsi, ABS_EXPR, inner_type, br); t1 = gimplify_build1 (bsi, ABS_EXPR, inner_type, br);
...@@ -177,30 +178,15 @@ expand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type, ...@@ -177,30 +178,15 @@ expand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type,
cond = fold (build (LT_EXPR, boolean_type_node, t1, t2)); cond = fold (build (LT_EXPR, boolean_type_node, t1, t2));
STRIP_NOPS (cond); STRIP_NOPS (cond);
if (TREE_CONSTANT (cond)) bb_cond = bb_true = bb_false = bb_join = NULL;
rr = ri = tr = ti = NULL;
if (!TREE_CONSTANT (cond))
{ {
if (integer_zerop (cond))
min = bi, max = br;
else
min = br, max = bi;
}
else
{
basic_block bb_cond, bb_true, bb_false, bb_join;
tree l1, l2, l3;
edge e; edge e;
l1 = create_artificial_label (); cond = build (COND_EXPR, void_type_node, cond, NULL, NULL);
t1 = build (GOTO_EXPR, void_type_node, l1);
l2 = create_artificial_label ();
t2 = build (GOTO_EXPR, void_type_node, l2);
cond = build (COND_EXPR, void_type_node, cond, t1, t2);
bsi_insert_before (bsi, cond, BSI_SAME_STMT); bsi_insert_before (bsi, cond, BSI_SAME_STMT);
min = make_rename_temp (inner_type, NULL);
max = make_rename_temp (inner_type, NULL);
l3 = create_artificial_label ();
/* Split the original block, and create the TRUE and FALSE blocks. */ /* Split the original block, and create the TRUE and FALSE blocks. */
e = split_block (bsi->bb, cond); e = split_block (bsi->bb, cond);
bb_cond = e->src; bb_cond = e->src;
...@@ -208,6 +194,11 @@ expand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type, ...@@ -208,6 +194,11 @@ expand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type,
bb_true = create_empty_bb (bb_cond); bb_true = create_empty_bb (bb_cond);
bb_false = create_empty_bb (bb_true); bb_false = create_empty_bb (bb_true);
t1 = build (GOTO_EXPR, void_type_node, tree_block_label (bb_true));
t2 = build (GOTO_EXPR, void_type_node, tree_block_label (bb_false));
COND_EXPR_THEN (cond) = t1;
COND_EXPR_ELSE (cond) = t2;
/* Wire the blocks together. */ /* Wire the blocks together. */
e->flags = EDGE_TRUE_VALUE; e->flags = EDGE_TRUE_VALUE;
redirect_edge_succ (e, bb_true); redirect_edge_succ (e, bb_true);
...@@ -223,46 +214,92 @@ expand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type, ...@@ -223,46 +214,92 @@ expand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type,
set_immediate_dominator (CDI_DOMINATORS, bb_false, bb_cond); set_immediate_dominator (CDI_DOMINATORS, bb_false, bb_cond);
} }
/* Compute min and max for TRUE block. */ rr = make_rename_temp (inner_type, NULL);
*bsi = bsi_start (bb_true); ri = make_rename_temp (inner_type, NULL);
t1 = build (LABEL_EXPR, void_type_node, l1);
bsi_insert_after (bsi, t1, BSI_NEW_STMT);
t1 = build (MODIFY_EXPR, inner_type, min, br);
bsi_insert_after (bsi, t1, BSI_NEW_STMT);
t1 = build (MODIFY_EXPR, inner_type, max, bi);
bsi_insert_after (bsi, t1, BSI_NEW_STMT);
/* Compute min and max for FALSE block. */
*bsi = bsi_start (bb_false);
t1 = build (LABEL_EXPR, void_type_node, l2);
bsi_insert_after (bsi, t1, BSI_NEW_STMT);
t1 = build (MODIFY_EXPR, inner_type, min, bi);
bsi_insert_after (bsi, t1, BSI_NEW_STMT);
t1 = build (MODIFY_EXPR, inner_type, max, br);
bsi_insert_after (bsi, t1, BSI_NEW_STMT);
/* Insert the join label into the tail of the original block. */
*bsi = bsi_start (bb_join);
t1 = build (LABEL_EXPR, void_type_node, l3);
bsi_insert_before (bsi, t1, BSI_SAME_STMT);
} }
/* Now we have MIN(|br|, |bi|) and MAX(|br|, |bi|). We now use the /* In the TRUE branch, we compute
ratio min/max to scale both the dividend and divisor. */ ratio = br/bi;
ratio = gimplify_build2 (bsi, code, inner_type, min, max); div = (br * ratio) + bi;
tr = (ar * ratio) + ai;
/* Calculate the divisor: min*ratio + max. */ ti = (ai * ratio) - ar;
t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, min, ratio); tr = tr / div;
div = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, max); ti = ti / div; */
if (bb_true || integer_nonzerop (cond))
/* Result is now ((ar + ai*ratio)/div) + i((ai - ar*ratio)/div). */ {
t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, ratio); if (bb_true)
t2 = gimplify_build2 (bsi, PLUS_EXPR, inner_type, ar, t1); {
rr = gimplify_build2 (bsi, code, inner_type, t2, div); *bsi = bsi_last (bb_true);
bsi_insert_after (bsi, build_empty_stmt (), BSI_NEW_STMT);
t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, ratio); }
t2 = gimplify_build2 (bsi, MINUS_EXPR, inner_type, ai, t1);
ri = gimplify_build2 (bsi, code, inner_type, t2, div); ratio = gimplify_build2 (bsi, code, inner_type, br, bi);
t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, br, ratio);
div = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, bi);
t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, ratio);
tr = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, ai);
t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, ratio);
ti = gimplify_build2 (bsi, MINUS_EXPR, inner_type, t1, ar);
tr = gimplify_build2 (bsi, code, inner_type, tr, div);
ti = gimplify_build2 (bsi, code, inner_type, ti, div);
if (bb_true)
{
t1 = build (MODIFY_EXPR, inner_type, rr, tr);
bsi_insert_before (bsi, t1, BSI_SAME_STMT);
t1 = build (MODIFY_EXPR, inner_type, ri, ti);
bsi_insert_before (bsi, t1, BSI_SAME_STMT);
bsi_remove (bsi);
}
}
/* 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; */
if (bb_false || integer_zerop (cond))
{
if (bb_false)
{
*bsi = bsi_last (bb_false);
bsi_insert_after (bsi, build_empty_stmt (), BSI_NEW_STMT);
}
ratio = gimplify_build2 (bsi, code, inner_type, bi, br);
t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, bi, ratio);
div = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, br);
t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, ratio);
tr = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, ar);
t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, ratio);
ti = gimplify_build2 (bsi, MINUS_EXPR, inner_type, ai, t1);
tr = gimplify_build2 (bsi, code, inner_type, tr, div);
ti = gimplify_build2 (bsi, code, inner_type, ti, div);
if (bb_false)
{
t1 = build (MODIFY_EXPR, inner_type, rr, tr);
bsi_insert_before (bsi, t1, BSI_SAME_STMT);
t1 = build (MODIFY_EXPR, inner_type, ri, ti);
bsi_insert_before (bsi, t1, BSI_SAME_STMT);
bsi_remove (bsi);
}
}
if (bb_join)
*bsi = bsi_start (bb_join);
else
rr = tr, ri = ti;
update_complex_assignment (bsi, rr, ri); update_complex_assignment (bsi, rr, ri);
} }
......
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