OSDN Git Service

PR middle-end/19609
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 25 Jan 2005 18:19:09 +0000 (18:19 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 25 Jan 2005 18:19:09 +0000 (18:19 +0000)
        * tree-complex.c (expand_complex_div_wide): Use the correct formulae.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94222 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/tree-complex.c

index 400456c..2648c68 100644 (file)
@@ -1,3 +1,8 @@
+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>
 
        * expmed.c (choose_multiplier): Change interface to return the
index 6fc6c76..3373326 100644 (file)
@@ -169,7 +169,8 @@ expand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type,
                         tree ar, tree ai, tree br, tree bi,
                         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.  */
   t1 = gimplify_build1 (bsi, ABS_EXPR, inner_type, br);
@@ -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));
   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;
 
-      l1 = create_artificial_label ();
-      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);
+      cond = build (COND_EXPR, void_type_node, cond, NULL, NULL);
       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.  */
       e = split_block (bsi->bb, cond);
       bb_cond = e->src;
@@ -208,6 +194,11 @@ expand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type,
       bb_true = create_empty_bb (bb_cond);
       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.  */
       e->flags = EDGE_TRUE_VALUE;
       redirect_edge_succ (e, bb_true);
@@ -223,46 +214,92 @@ expand_complex_div_wide (block_stmt_iterator *bsi, tree inner_type,
           set_immediate_dominator (CDI_DOMINATORS, bb_false, bb_cond);
         }
 
-      /* Compute min and max for TRUE block.  */
-      *bsi = bsi_start (bb_true);
-      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);
+      rr = make_rename_temp (inner_type, NULL);
+      ri = make_rename_temp (inner_type, NULL);
     }
-  
-  /* Now we have MIN(|br|, |bi|) and MAX(|br|, |bi|).  We now use the
-     ratio min/max to scale both the dividend and divisor.  */
-  ratio = gimplify_build2 (bsi, code, inner_type, min, max);
-
-  /* Calculate the divisor: min*ratio + max.  */
-  t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, min, ratio);
-  div = gimplify_build2 (bsi, PLUS_EXPR, inner_type, t1, max);
-
-  /* Result is now ((ar + ai*ratio)/div) + i((ai - ar*ratio)/div).  */
-  t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, ratio);
-  t2 = gimplify_build2 (bsi, PLUS_EXPR, inner_type, ar, t1);
-  rr = gimplify_build2 (bsi, code, inner_type, t2, div);
-
-  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);
+
+  /* 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;  */
+  if (bb_true || integer_nonzerop (cond))
+    {
+      if (bb_true)
+       {
+         *bsi = bsi_last (bb_true);
+         bsi_insert_after (bsi, build_empty_stmt (), BSI_NEW_STMT);
+       }
+
+      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);
 }