OSDN Git Service

2012-01-30 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-complex.c
index 939bd6f..0547fcf 100644 (file)
@@ -1,18 +1,19 @@
 /* Lower complex number operations to scalar operations.
-   Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
-   
+
 GCC is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
 Free Software Foundation; either version 3, or (at your option) any
 later version.
-   
+
 GCC is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
-   
+
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
@@ -22,28 +23,29 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
-#include "real.h"
 #include "flags.h"
 #include "tree-flow.h"
 #include "gimple.h"
 #include "tree-iterator.h"
 #include "tree-pass.h"
 #include "tree-ssa-propagate.h"
-#include "diagnostic.h"
 
 
 /* For each complex ssa name, a lattice value.  We're interested in finding
    out whether a complex number is degenerate in some way, having only real
    or only complex parts.  */
 
-typedef enum
+enum
 {
   UNINITIALIZED = 0,
   ONLY_REAL = 1,
   ONLY_IMAG = 2,
   VARYING = 3
-} complex_lattice_t;
+};
+
+/* The type complex_lattice_t holds combinations of the above
+   constants.  */
+typedef int complex_lattice_t;
 
 #define PAIR(a, b)  ((a) << 2 | (b))
 
@@ -61,7 +63,7 @@ static VEC(tree, heap) *complex_ssa_name_components;
 
 /* Lookup UID in the complex_variable_components hashtable and return the
    associated tree.  */
-static tree 
+static tree
 cvc_lookup (unsigned int uid)
 {
   struct int_tree_map *h, in;
@@ -69,12 +71,12 @@ cvc_lookup (unsigned int uid)
   h = (struct int_tree_map *) htab_find_with_hash (complex_variable_components, &in, uid);
   return h ? h->to : NULL;
 }
+
 /* Insert the pair UID, TO into the complex_variable_components hashtable.  */
 
-static void 
+static void
 cvc_insert (unsigned int uid, tree to)
-{ 
+{
   struct int_tree_map *h;
   void **loc;
 
@@ -94,7 +96,10 @@ some_nonzerop (tree t)
 {
   int zerop = false;
 
-  if (TREE_CODE (t) == REAL_CST)
+  /* Operations with real or imaginary part of a complex number zero
+     cannot be treated the same as operations with a real or imaginary
+     operand if we care about the signs of zeros in the result.  */
+  if (TREE_CODE (t) == REAL_CST && !flag_signed_zeros)
     zerop = REAL_VALUES_IDENTICAL (TREE_REAL_CST (t), dconst0);
   else if (TREE_CODE (t) == FIXED_CST)
     zerop = fixed_zerop (t);
@@ -169,7 +174,7 @@ init_parameter_lattice_values (void)
 {
   tree parm, ssa_name;
 
-  for (parm = DECL_ARGUMENTS (cfun->decl); parm ; parm = TREE_CHAIN (parm))
+  for (parm = DECL_ARGUMENTS (cfun->decl); parm ; parm = DECL_CHAIN (parm))
     if (is_complex_reg (parm)
        && var_ann (parm) != NULL
        && (ssa_name = gimple_default_def (cfun, parm)) != NULL_TREE)
@@ -207,7 +212,7 @@ init_dont_simulate_again (void)
          stmt = gsi_stmt (gsi);
          op0 = op1 = NULL_TREE;
 
-         /* Most control-altering statements must be initially 
+         /* Most control-altering statements must be initially
             simulated, else we won't cover the entire cfg.  */
          sim_again_p = stmt_ends_bb_p (stmt);
 
@@ -426,11 +431,9 @@ create_one_component_var (tree type, tree orig, const char *prefix,
   if (DECL_NAME (orig) && !DECL_IGNORED_P (orig))
     {
       const char *name = IDENTIFIER_POINTER (DECL_NAME (orig));
-      tree inner_type;
 
       DECL_NAME (r) = get_identifier (ACONCAT ((name, suffix, NULL)));
 
-      inner_type = TREE_TYPE (TREE_TYPE (orig));
       SET_DECL_DEBUG_EXPR (r, build1 (code, type, orig));
       DECL_DEBUG_EXPR_IS_FROM (r) = 1;
       DECL_IGNORED_P (r) = 0;
@@ -563,7 +566,7 @@ set_component_ssa_name (tree ssa_name, bool imag_p, tree value)
      a new ssa name.  */
   else
     comp = get_component_ssa_name (ssa_name, imag_p);
-  
+
   /* Do all the work to assign VALUE to COMP.  */
   list = NULL;
   value = force_gimple_operand (value, &list, false, NULL);
@@ -593,9 +596,10 @@ extract_component (gimple_stmt_iterator *gsi, tree t, bool imagpart_p,
     case VAR_DECL:
     case RESULT_DECL:
     case PARM_DECL:
-    case INDIRECT_REF:
     case COMPONENT_REF:
     case ARRAY_REF:
+    case VIEW_CONVERT_EXPR:
+    case MEM_REF:
       {
        tree inner_type = TREE_TYPE (TREE_TYPE (t));
 
@@ -658,12 +662,16 @@ static void
 update_complex_assignment (gimple_stmt_iterator *gsi, tree r, tree i)
 {
   gimple_stmt_iterator orig_si = *gsi;
+  gimple stmt;
 
   if (gimple_in_ssa_p (cfun))
     update_complex_components (gsi, gsi_stmt (*gsi), r, i);
 
   gimple_assign_set_rhs_with_ops (&orig_si, COMPLEX_EXPR, r, i);
-  update_stmt (gsi_stmt (orig_si));
+  stmt = gsi_stmt (orig_si);
+  update_stmt (stmt);
+  if (maybe_clean_eh_stmt (stmt))
+    gimple_purge_dead_eh_edges (gimple_bb (stmt));
 }
 
 
@@ -676,7 +684,7 @@ update_parameter_components (void)
   edge entry_edge = single_succ_edge (ENTRY_BLOCK_PTR);
   tree parm;
 
-  for (parm = DECL_ARGUMENTS (cfun->decl); parm ; parm = TREE_CHAIN (parm))
+  for (parm = DECL_ARGUMENTS (cfun->decl); parm ; parm = DECL_CHAIN (parm))
     {
       tree type = TREE_TYPE (parm);
       tree ssa_name, r, i;
@@ -745,23 +753,6 @@ update_phi_components (basic_block bb)
     }
 }
 
-/* Mark each virtual op in STMT for ssa update.  */
-
-static void
-update_all_vops (gimple stmt)
-{
-  ssa_op_iter iter;
-  tree sym;
-
-  FOR_EACH_SSA_TREE_OPERAND (sym, stmt, iter, SSA_OP_ALL_VIRTUALS)
-    {
-      if (TREE_CODE (sym) == SSA_NAME)
-       sym = SSA_NAME_VAR (sym);
-      mark_sym_for_renaming (sym);
-    }
-}
-
-
 /* Expand a complex move to scalars.  */
 
 static void
@@ -791,17 +782,14 @@ expand_complex_move (gimple_stmt_iterator *gsi, tree type)
     {
       if (is_ctrl_altering_stmt (stmt))
        {
-         edge_iterator ei;
          edge e;
 
          /* The value is not assigned on the exception edges, so we need not
             concern ourselves there.  We do need to update on the fallthru
             edge.  Find it.  */
-         FOR_EACH_EDGE (e, ei, gsi_bb (*gsi)->succs)
-           if (e->flags & EDGE_FALLTHRU)
-             goto found_fallthru;
-         gcc_unreachable ();
-       found_fallthru:
+         e = find_fallthru_edge (gsi_bb (*gsi)->succs);
+         if (!e)
+           gcc_unreachable ();
 
          r = build1 (REALPART_EXPR, inner_type, lhs);
          i = build1 (IMAGPART_EXPR, inner_type, lhs);
@@ -817,7 +805,6 @@ expand_complex_move (gimple_stmt_iterator *gsi, tree type)
        }
       else
        {
-         update_all_vops (stmt);
          if (gimple_assign_rhs_code (stmt) != COMPLEX_EXPR)
            {
              r = extract_component (gsi, rhs, 0, true);
@@ -860,7 +847,6 @@ expand_complex_move (gimple_stmt_iterator *gsi, tree type)
          gimple_return_set_retval (stmt, lhs);
        }
 
-      update_all_vops (stmt);
       update_stmt (stmt);
     }
 }
@@ -953,27 +939,32 @@ expand_complex_libcall (gimple_stmt_iterator *gsi, tree ar, tree ai,
   enum machine_mode mode;
   enum built_in_function bcode;
   tree fn, type, lhs;
-  gimple stmt;
+  gimple old_stmt, stmt;
 
-  stmt = gsi_stmt (*gsi);
-  lhs = gimple_assign_lhs (stmt);
+  old_stmt = gsi_stmt (*gsi);
+  lhs = gimple_assign_lhs (old_stmt);
   type = TREE_TYPE (lhs);
 
   mode = TYPE_MODE (type);
   gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
 
   if (code == MULT_EXPR)
-    bcode = BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT;
+    bcode = ((enum built_in_function)
+            (BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT));
   else if (code == RDIV_EXPR)
-    bcode = BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT;
+    bcode = ((enum built_in_function)
+            (BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT));
   else
     gcc_unreachable ();
-  fn = built_in_decls[bcode];
+  fn = builtin_decl_explicit (bcode);
 
   stmt = gimple_build_call (fn, 4, ar, ai, br, bi);
   gimple_call_set_lhs (stmt, lhs);
   update_stmt (stmt);
-  gsi_replace (gsi, stmt, true);
+  gsi_replace (gsi, stmt, false);
+
+  if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
+    gimple_purge_dead_eh_edges (gsi_bb (*gsi));
 
   if (gimple_in_ssa_p (cfun))
     {
@@ -1070,7 +1061,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
 */
@@ -1099,7 +1092,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
@@ -1114,12 +1109,13 @@ expand_complex_div_wide (gimple_stmt_iterator *gsi, tree inner_type,
   /* Examine |br| < |bi|, and branch.  */
   t1 = gimplify_build1 (gsi, ABS_EXPR, inner_type, br);
   t2 = gimplify_build1 (gsi, ABS_EXPR, inner_type, bi);
-  compare = fold_build2 (LT_EXPR, boolean_type_node, t1, t2);
+  compare = fold_build2_loc (gimple_location (gsi_stmt (*gsi)),
+                            LT_EXPR, boolean_type_node, t1, t2);
   STRIP_NOPS (compare);
 
   bb_cond = bb_true = bb_false = bb_join = NULL;
   rr = ri = tr = ti = NULL;
-  if (!TREE_CONSTANT (compare))
+  if (TREE_CODE (compare) != INTEGER_CST)
     {
       edge e;
       gimple stmt;
@@ -1135,7 +1131,8 @@ expand_complex_div_wide (gimple_stmt_iterator *gsi, tree inner_type,
 
       gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
 
-      cond = fold_build2 (EQ_EXPR, boolean_type_node, tmp, boolean_true_node);
+      cond = fold_build2_loc (gimple_location (stmt),
+                         EQ_EXPR, boolean_type_node, tmp, boolean_true_node);
       stmt = gimple_build_cond_from_tree (cond, NULL_TREE, NULL_TREE);
       gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
 
@@ -1543,7 +1540,7 @@ expand_complex_operations_1 (gimple_stmt_iterator *gsi)
     case RDIV_EXPR:
       expand_complex_division (gsi, inner_type, ar, ai, br, bi, code, al, bl);
       break;
-      
+
     case NEGATE_EXPR:
       expand_complex_negation (gsi, inner_type, ar, ai);
       break;
@@ -1611,7 +1608,7 @@ tree_lower_complex (void)
   return 0;
 }
 
-struct gimple_opt_pass pass_lower_complex = 
+struct gimple_opt_pass pass_lower_complex =
 {
  {
   GIMPLE_PASS,
@@ -1621,63 +1618,43 @@ struct gimple_opt_pass pass_lower_complex =
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
+  TV_NONE,                             /* tv_id */
   PROP_ssa,                            /* properties_required */
-  0,                                   /* properties_provided */
+  PROP_gimple_lcx,                     /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func
-    | TODO_ggc_collect
+    TODO_ggc_collect
     | TODO_update_ssa
     | TODO_verify_stmts                        /* todo_flags_finish */
  }
 };
 
 \f
-/* Entry point for complex operation lowering without optimization.  */
-
-static unsigned int
-tree_lower_complex_O0 (void)
-{
-  int old_last_basic_block = last_basic_block;
-  gimple_stmt_iterator gsi;
-  basic_block bb;
-
-  FOR_EACH_BB (bb)
-    {
-      if (bb->index >= old_last_basic_block)
-       continue;
-
-      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-       expand_complex_operations_1 (&gsi);
-    }
-  return 0;
-}
-
 static bool
 gate_no_optimization (void)
 {
   /* With errors, normal optimization passes are not run.  If we don't
      lower complex operations at all, rtl expansion will abort.  */
-  return optimize == 0 || sorrycount || errorcount;
+  return !(cfun->curr_properties & PROP_gimple_lcx);
 }
 
-struct gimple_opt_pass pass_lower_complex_O0 = 
+struct gimple_opt_pass pass_lower_complex_O0 =
 {
  {
   GIMPLE_PASS,
   "cplxlower0",                                /* name */
   gate_no_optimization,                        /* gate */
-  tree_lower_complex_O0,               /* execute */
+  tree_lower_complex,                  /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
+  TV_NONE,                             /* tv_id */
   PROP_cfg,                            /* properties_required */
-  0,                                   /* properties_provided */
+  PROP_gimple_lcx,                     /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_ggc_collect
-    | TODO_verify_stmts,               /* todo_flags_finish */
+  TODO_ggc_collect
+    | TODO_update_ssa
+    | TODO_verify_stmts                        /* todo_flags_finish */
  }
 };