X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-complex.c;h=ec2b438ca47c59d29b7a7e97c00b8e95c26412f9;hb=9960d752f0bd2b1e3f0c62d50deae42a1303c8ce;hp=939bd6f1a63c4b49335ee4f2eeefd3bee7477470;hpb=09c1e135de53e8374a9926ec9357698473cd9127;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c index 939bd6f1a63..ec2b438ca47 100644 --- a/gcc/tree-complex.c +++ b/gcc/tree-complex.c @@ -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 . */ @@ -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,19 +939,21 @@ 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]; @@ -973,7 +961,10 @@ expand_complex_libcall (gimple_stmt_iterator *gsi, tree ar, tree ai, 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,9 +1618,9 @@ 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 @@ -1634,50 +1631,32 @@ struct gimple_opt_pass pass_lower_complex = }; -/* 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_dump_func + | TODO_ggc_collect + | TODO_update_ssa + | TODO_verify_stmts /* todo_flags_finish */ } };