X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=gcc%2Ftree-complex.c;h=b11da01a58b45c00f0e3037f9188af03634170db;hb=99dee82307f1e163e150c9c810452979994047ce;hp=5148ca587bb06f05824cb6b6e7c411365264540e;hpb=5624e564d2239a74daa140e726b7b229d6e9a115;p=thirdparty%2Fgcc.git diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c index 5148ca587bb0..b11da01a58b4 100644 --- a/gcc/tree-complex.c +++ b/gcc/tree-complex.c @@ -1,5 +1,5 @@ /* Lower complex number operations to scalar operations. - Copyright (C) 2004-2015 Free Software Foundation, Inc. + Copyright (C) 2004-2021 Free Software Foundation, Inc. This file is part of GCC. @@ -20,44 +20,26 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" -#include "tm.h" +#include "backend.h" +#include "rtl.h" #include "tree.h" +#include "gimple.h" +#include "cfghooks.h" +#include "tree-pass.h" +#include "ssa.h" +#include "fold-const.h" #include "stor-layout.h" -#include "flags.h" -#include "predict.h" -#include "vec.h" -#include "hashtab.h" -#include "hash-set.h" -#include "machmode.h" -#include "hard-reg-set.h" -#include "input.h" -#include "function.h" -#include "dominance.h" -#include "cfg.h" -#include "basic-block.h" -#include "tree-ssa-alias.h" -#include "internal-fn.h" #include "tree-eh.h" -#include "gimple-expr.h" -#include "is-a.h" -#include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" #include "gimplify-me.h" -#include "gimple-ssa.h" #include "tree-cfg.h" -#include "tree-phinodes.h" -#include "ssa-iterators.h" -#include "stringpool.h" -#include "tree-ssanames.h" -#include "expr.h" #include "tree-dfa.h" #include "tree-ssa.h" -#include "tree-iterator.h" -#include "tree-pass.h" #include "tree-ssa-propagate.h" #include "tree-hasher.h" #include "cfgloop.h" +#include "cfganal.h" /* For each complex ssa name, a lattice value. We're interested in finding @@ -78,6 +60,11 @@ typedef int complex_lattice_t; #define PAIR(a, b) ((a) << 2 | (b)) +class complex_propagate : public ssa_propagation_engine +{ + enum ssa_prop_result visit_stmt (gimple *, edge *, tree *) FINAL OVERRIDE; + enum ssa_prop_result visit_phi (gphi *) FINAL OVERRIDE; +}; static vec complex_lattice_values; @@ -88,6 +75,14 @@ static int_tree_htab_type *complex_variable_components; /* For each complex SSA_NAME, a pair of ssa names for the components. */ static vec complex_ssa_name_components; +/* Vector of PHI triplets (original complex PHI and corresponding real and + imag PHIs if real and/or imag PHIs contain temporarily + non-SSA_NAME/non-invariant args that need to be replaced by SSA_NAMEs. */ +static vec phis_to_revisit; + +/* BBs that need EH cleanup. */ +static bitmap need_eh_cleanup; + /* Lookup UID in the complex_variable_components hashtable and return the associated tree. */ static tree @@ -124,7 +119,7 @@ some_nonzerop (tree t) 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); + zerop = real_identical (&TREE_REAL_CST (t), &dconst0); else if (TREE_CODE (t) == FIXED_CST) zerop = fixed_zerop (t); else if (TREE_CODE (t) == INTEGER_CST) @@ -226,7 +221,7 @@ init_dont_simulate_again (void) for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { - gimple stmt; + gimple *stmt; tree op0, op1; bool sim_again_p; @@ -313,9 +308,9 @@ init_dont_simulate_again (void) /* Evaluate statement STMT against the complex lattice defined above. */ -static enum ssa_prop_result -complex_visit_stmt (gimple stmt, edge *taken_edge_p ATTRIBUTE_UNUSED, - tree *result_p) +enum ssa_prop_result +complex_propagate::visit_stmt (gimple *stmt, edge *taken_edge_p ATTRIBUTE_UNUSED, + tree *result_p) { complex_lattice_t new_l, old_l, op1_l, op2_l; unsigned int ver; @@ -323,7 +318,7 @@ complex_visit_stmt (gimple stmt, edge *taken_edge_p ATTRIBUTE_UNUSED, lhs = gimple_get_lhs (stmt); /* Skip anything but GIMPLE_ASSIGN and GIMPLE_CALL with a lhs. */ - if (!lhs) + if (!lhs || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) return SSA_PROP_VARYING; /* These conditions should be satisfied due to the initial filter @@ -408,8 +403,8 @@ complex_visit_stmt (gimple stmt, edge *taken_edge_p ATTRIBUTE_UNUSED, /* Evaluate a PHI node against the complex lattice defined above. */ -static enum ssa_prop_result -complex_visit_phi (gphi *phi) +enum ssa_prop_result +complex_propagate::visit_phi (gphi *phi) { complex_lattice_t new_l, old_l; unsigned int ver; @@ -422,6 +417,9 @@ complex_visit_phi (gphi *phi) set up in init_dont_simulate_again. */ gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE); + if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) + return SSA_PROP_VARYING; + /* We've set up the lattice values such that IOR neatly models PHI meet. */ new_l = UNINITIALIZED; for (i = gimple_phi_num_args (phi) - 1; i >= 0; --i) @@ -451,8 +449,8 @@ 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)); - - DECL_NAME (r) = get_identifier (ACONCAT ((name, suffix, NULL))); + name = ACONCAT ((name, suffix, NULL)); + DECL_NAME (r) = get_identifier (name); SET_DECL_DEBUG_EXPR (r, build1 (code, type, orig)); DECL_HAS_DEBUG_EXPR_P (r) = 1; @@ -542,7 +540,7 @@ set_component_ssa_name (tree ssa_name, bool imag_p, tree value) complex_lattice_t lattice = find_lattice_value (ssa_name); size_t ssa_name_index; tree comp; - gimple last; + gimple *last; gimple_seq list; /* We know the value must be zero, else there's a bug in our lattice @@ -574,7 +572,8 @@ set_component_ssa_name (tree ssa_name, bool imag_p, tree value) { /* Replace an anonymous base value with the variable from cvc_lookup. This should result in better debug info. */ - if (SSA_NAME_VAR (ssa_name) + if (!SSA_NAME_IS_DEFAULT_DEF (value) + && SSA_NAME_VAR (ssa_name) && (!SSA_NAME_VAR (value) || DECL_IGNORED_P (SSA_NAME_VAR (value))) && !DECL_IGNORED_P (SSA_NAME_VAR (ssa_name))) { @@ -607,7 +606,7 @@ set_component_ssa_name (tree ssa_name, bool imag_p, tree value) static tree extract_component (gimple_stmt_iterator *gsi, tree t, bool imagpart_p, - bool gimple_p) + bool gimple_p, bool phiarg_p = false) { switch (TREE_CODE (t)) { @@ -617,6 +616,21 @@ extract_component (gimple_stmt_iterator *gsi, tree t, bool imagpart_p, case COMPLEX_EXPR: gcc_unreachable (); + case BIT_FIELD_REF: + { + tree inner_type = TREE_TYPE (TREE_TYPE (t)); + t = unshare_expr (t); + TREE_TYPE (t) = inner_type; + TREE_OPERAND (t, 1) = TYPE_SIZE (inner_type); + if (imagpart_p) + TREE_OPERAND (t, 2) = size_binop (PLUS_EXPR, TREE_OPERAND (t, 2), + TYPE_SIZE (inner_type)); + if (gimple_p) + t = force_gimple_operand_gsi (gsi, t, true, NULL, true, + GSI_SAME_STMT); + return t; + } + case VAR_DECL: case RESULT_DECL: case PARM_DECL: @@ -638,7 +652,10 @@ extract_component (gimple_stmt_iterator *gsi, tree t, bool imagpart_p, } case SSA_NAME: - return get_component_ssa_name (t, imagpart_p); + t = get_component_ssa_name (t, imagpart_p); + if (TREE_CODE (t) == SSA_NAME && SSA_NAME_DEF_STMT (t) == NULL) + gcc_assert (phiarg_p); + return t; default: gcc_unreachable (); @@ -648,7 +665,7 @@ extract_component (gimple_stmt_iterator *gsi, tree t, bool imagpart_p, /* Update the complex components of the ssa name on the lhs of STMT. */ static void -update_complex_components (gimple_stmt_iterator *gsi, gimple stmt, tree r, +update_complex_components (gimple_stmt_iterator *gsi, gimple *stmt, tree r, tree i) { tree lhs; @@ -685,16 +702,14 @@ update_complex_components_on_edge (edge e, tree lhs, tree r, tree i) static void update_complex_assignment (gimple_stmt_iterator *gsi, tree r, tree i) { - gimple stmt; - + gimple *old_stmt = gsi_stmt (*gsi); gimple_assign_set_rhs_with_ops (gsi, COMPLEX_EXPR, r, i); - stmt = gsi_stmt (*gsi); + gimple *stmt = gsi_stmt (*gsi); update_stmt (stmt); - if (maybe_clean_eh_stmt (stmt)) - gimple_purge_dead_eh_edges (gimple_bb (stmt)); + if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt)) + bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index); - if (gimple_in_ssa_p (cfun)) - update_complex_components (gsi, gsi_stmt (*gsi), r, i); + update_complex_components (gsi, gsi_stmt (*gsi), r, i); } @@ -740,31 +755,48 @@ update_phi_components (basic_block bb) if (is_complex_reg (gimple_phi_result (phi))) { - tree lr, li; - gimple pr = NULL, pi = NULL; - unsigned int i, n; - - lr = get_component_ssa_name (gimple_phi_result (phi), false); - if (TREE_CODE (lr) == SSA_NAME) - pr = create_phi_node (lr, bb); + gphi *p[2] = { NULL, NULL }; + unsigned int i, j, n; + bool revisit_phi = false; - li = get_component_ssa_name (gimple_phi_result (phi), true); - if (TREE_CODE (li) == SSA_NAME) - pi = create_phi_node (li, bb); + for (j = 0; j < 2; j++) + { + tree l = get_component_ssa_name (gimple_phi_result (phi), j > 0); + if (TREE_CODE (l) == SSA_NAME) + p[j] = create_phi_node (l, bb); + } for (i = 0, n = gimple_phi_num_args (phi); i < n; ++i) { tree comp, arg = gimple_phi_arg_def (phi, i); - if (pr) - { - comp = extract_component (NULL, arg, false, false); - SET_PHI_ARG_DEF (pr, i, comp); - } - if (pi) - { - comp = extract_component (NULL, arg, true, false); - SET_PHI_ARG_DEF (pi, i, comp); - } + for (j = 0; j < 2; j++) + if (p[j]) + { + comp = extract_component (NULL, arg, j > 0, false, true); + if (TREE_CODE (comp) == SSA_NAME + && SSA_NAME_DEF_STMT (comp) == NULL) + { + /* For the benefit of any gimple simplification during + this pass that might walk SSA_NAME def stmts, + don't add SSA_NAMEs without definitions into the + PHI arguments, but put a decl in there instead + temporarily, and revisit this PHI later on. */ + if (SSA_NAME_VAR (comp)) + comp = SSA_NAME_VAR (comp); + else + comp = create_tmp_reg (TREE_TYPE (comp), + get_name (comp)); + revisit_phi = true; + } + SET_PHI_ARG_DEF (p[j], i, comp); + } + } + + if (revisit_phi) + { + phis_to_revisit.safe_push (phi); + phis_to_revisit.safe_push (p[0]); + phis_to_revisit.safe_push (p[1]); } } } @@ -777,7 +809,7 @@ expand_complex_move (gimple_stmt_iterator *gsi, tree type) { tree inner_type = TREE_TYPE (type); tree r, i, lhs, rhs; - gimple stmt = gsi_stmt (*gsi); + gimple *stmt = gsi_stmt (*gsi); if (is_gimple_assign (stmt)) { @@ -838,7 +870,7 @@ expand_complex_move (gimple_stmt_iterator *gsi, tree type) else if (rhs && TREE_CODE (rhs) == SSA_NAME && !TREE_SIDE_EFFECTS (lhs)) { tree x; - gimple t; + gimple *t; location_t loc; loc = gimple_location (stmt); @@ -951,22 +983,22 @@ expand_complex_addition (gimple_stmt_iterator *gsi, tree inner_type, } /* Expand a complex multiplication or division to a libcall to the c99 - compliant routines. */ + compliant routines. TYPE is the complex type of the operation. + If INPLACE_P replace the statement at GSI with + the libcall and return NULL_TREE. Else insert the call, assign its + result to an output variable and return that variable. If INPLACE_P + is true then the statement being replaced should be an assignment + statement. */ -static void -expand_complex_libcall (gimple_stmt_iterator *gsi, tree ar, tree ai, - tree br, tree bi, enum tree_code code) +static tree +expand_complex_libcall (gimple_stmt_iterator *gsi, tree type, tree ar, tree ai, + tree br, tree bi, enum tree_code code, bool inplace_p) { machine_mode mode; enum built_in_function bcode; - tree fn, type, lhs; - gimple old_stmt; + tree fn, lhs; gcall *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); @@ -979,23 +1011,74 @@ expand_complex_libcall (gimple_stmt_iterator *gsi, tree ar, tree ai, else gcc_unreachable (); 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, 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)) + if (inplace_p) { + gimple *old_stmt = gsi_stmt (*gsi); + gimple_call_set_nothrow (stmt, !stmt_could_throw_p (cfun, old_stmt)); + lhs = gimple_assign_lhs (old_stmt); + gimple_call_set_lhs (stmt, lhs); + gsi_replace (gsi, stmt, true); + type = TREE_TYPE (type); - update_complex_components (gsi, stmt, - build1 (REALPART_EXPR, type, lhs), - build1 (IMAGPART_EXPR, type, lhs)); + if (stmt_can_throw_internal (cfun, stmt)) + { + edge_iterator ei; + edge e; + FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->succs) + if (!(e->flags & EDGE_EH)) + break; + basic_block bb = split_edge (e); + gimple_stmt_iterator gsi2 = gsi_start_bb (bb); + update_complex_components (&gsi2, stmt, + build1 (REALPART_EXPR, type, lhs), + build1 (IMAGPART_EXPR, type, lhs)); + return NULL_TREE; + } + else + update_complex_components (gsi, stmt, + build1 (REALPART_EXPR, type, lhs), + build1 (IMAGPART_EXPR, type, lhs)); SSA_NAME_DEF_STMT (lhs) = stmt; + return NULL_TREE; } + + gimple_call_set_nothrow (stmt, true); + lhs = make_ssa_name (type); + gimple_call_set_lhs (stmt, lhs); + gsi_insert_before (gsi, stmt, GSI_SAME_STMT); + + return lhs; +} + +/* Perform a complex multiplication on two complex constants A, B represented + by AR, AI, BR, BI of type TYPE. + The operation we want is: a * b = (ar*br - ai*bi) + i(ar*bi + br*ai). + Insert the GIMPLE statements into GSI. Store the real and imaginary + components of the result into RR and RI. */ + +static void +expand_complex_multiplication_components (gimple_stmt_iterator *gsi, + tree type, tree ar, tree ai, + tree br, tree bi, + tree *rr, tree *ri) +{ + tree t1, t2, t3, t4; + + t1 = gimplify_build2 (gsi, MULT_EXPR, type, ar, br); + t2 = gimplify_build2 (gsi, MULT_EXPR, type, ai, bi); + t3 = gimplify_build2 (gsi, MULT_EXPR, type, ar, bi); + + /* Avoid expanding redundant multiplication for the common + case of squaring a complex number. */ + if (ar == br && ai == bi) + t4 = t3; + else + t4 = gimplify_build2 (gsi, MULT_EXPR, type, ai, br); + + *rr = gimplify_build2 (gsi, MINUS_EXPR, type, t1, t2); + *ri = gimplify_build2 (gsi, PLUS_EXPR, type, t3, t4); } /* Expand complex multiplication to scalars: @@ -1003,11 +1086,12 @@ expand_complex_libcall (gimple_stmt_iterator *gsi, tree ar, tree ai, */ static void -expand_complex_multiplication (gimple_stmt_iterator *gsi, tree inner_type, +expand_complex_multiplication (gimple_stmt_iterator *gsi, tree type, tree ar, tree ai, tree br, tree bi, complex_lattice_t al, complex_lattice_t bl) { tree rr, ri; + tree inner_type = TREE_TYPE (type); if (al < bl) { @@ -1027,7 +1111,7 @@ expand_complex_multiplication (gimple_stmt_iterator *gsi, tree inner_type, case PAIR (ONLY_IMAG, ONLY_REAL): rr = ar; if (TREE_CODE (ai) == REAL_CST - && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ai), dconst1)) + && real_identical (&TREE_REAL_CST (ai), &dconst1)) ri = br; else ri = gimplify_build2 (gsi, MULT_EXPR, inner_type, ai, br); @@ -1053,27 +1137,84 @@ expand_complex_multiplication (gimple_stmt_iterator *gsi, tree inner_type, case PAIR (VARYING, VARYING): if (flag_complex_method == 2 && SCALAR_FLOAT_TYPE_P (inner_type)) { - expand_complex_libcall (gsi, ar, ai, br, bi, MULT_EXPR); - return; - } - else - { - tree t1, t2, t3, t4; - - t1 = gimplify_build2 (gsi, MULT_EXPR, inner_type, ar, br); - t2 = gimplify_build2 (gsi, MULT_EXPR, inner_type, ai, bi); - t3 = gimplify_build2 (gsi, MULT_EXPR, inner_type, ar, bi); + /* If optimizing for size or not at all just do a libcall. + Same if there are exception-handling edges or signaling NaNs. */ + if (optimize == 0 || optimize_bb_for_size_p (gsi_bb (*gsi)) + || stmt_can_throw_internal (cfun, gsi_stmt (*gsi)) + || flag_signaling_nans) + { + expand_complex_libcall (gsi, type, ar, ai, br, bi, + MULT_EXPR, true); + return; + } - /* Avoid expanding redundant multiplication for the common - case of squaring a complex number. */ - if (ar == br && ai == bi) - t4 = t3; - else - t4 = gimplify_build2 (gsi, MULT_EXPR, inner_type, ai, br); + if (!HONOR_NANS (inner_type)) + { + /* If we are not worrying about NaNs expand to + (ar*br - ai*bi) + i(ar*bi + br*ai) directly. */ + expand_complex_multiplication_components (gsi, inner_type, + ar, ai, br, bi, + &rr, &ri); + break; + } - rr = gimplify_build2 (gsi, MINUS_EXPR, inner_type, t1, t2); - ri = gimplify_build2 (gsi, PLUS_EXPR, inner_type, t3, t4); + /* Else, expand x = a * b into + x = (ar*br - ai*bi) + i(ar*bi + br*ai); + if (isunordered (__real__ x, __imag__ x)) + x = __muldc3 (a, b); */ + + tree tmpr, tmpi; + expand_complex_multiplication_components (gsi, inner_type, ar, ai, + br, bi, &tmpr, &tmpi); + + gimple *check + = gimple_build_cond (UNORDERED_EXPR, tmpr, tmpi, + NULL_TREE, NULL_TREE); + + basic_block orig_bb = gsi_bb (*gsi); + /* We want to keep track of the original complex multiplication + statement as we're going to modify it later in + update_complex_assignment. Make sure that insert_cond_bb leaves + that statement in the join block. */ + gsi_prev (gsi); + basic_block cond_bb + = insert_cond_bb (gsi_bb (*gsi), gsi_stmt (*gsi), check, + profile_probability::very_unlikely ()); + + gimple_stmt_iterator cond_bb_gsi = gsi_last_bb (cond_bb); + gsi_insert_after (&cond_bb_gsi, gimple_build_nop (), GSI_NEW_STMT); + + tree libcall_res + = expand_complex_libcall (&cond_bb_gsi, type, ar, ai, br, + bi, MULT_EXPR, false); + tree cond_real = gimplify_build1 (&cond_bb_gsi, REALPART_EXPR, + inner_type, libcall_res); + tree cond_imag = gimplify_build1 (&cond_bb_gsi, IMAGPART_EXPR, + inner_type, libcall_res); + + basic_block join_bb = single_succ_edge (cond_bb)->dest; + *gsi = gsi_start_nondebug_after_labels_bb (join_bb); + + /* We have a conditional block with some assignments in cond_bb. + Wire up the PHIs to wrap up. */ + rr = make_ssa_name (inner_type); + ri = make_ssa_name (inner_type); + edge cond_to_join = single_succ_edge (cond_bb); + edge orig_to_join = find_edge (orig_bb, join_bb); + + gphi *real_phi = create_phi_node (rr, gsi_bb (*gsi)); + add_phi_arg (real_phi, cond_real, cond_to_join, UNKNOWN_LOCATION); + add_phi_arg (real_phi, tmpr, orig_to_join, UNKNOWN_LOCATION); + + gphi *imag_phi = create_phi_node (ri, gsi_bb (*gsi)); + add_phi_arg (imag_phi, cond_imag, cond_to_join, UNKNOWN_LOCATION); + add_phi_arg (imag_phi, tmpi, orig_to_join, UNKNOWN_LOCATION); } + else + /* If we are not worrying about NaNs expand to + (ar*br - ai*bi) + i(ar*bi + br*ai) directly. */ + expand_complex_multiplication_components (gsi, inner_type, ar, ai, + br, bi, &rr, &ri); break; default: @@ -1126,7 +1267,7 @@ expand_complex_div_wide (gimple_stmt_iterator *gsi, tree inner_type, { tree rr, ri, ratio, div, t1, t2, tr, ti, compare; basic_block bb_cond, bb_true, bb_false, bb_join; - gimple stmt; + gimple *stmt; /* Examine |br| < |bi|, and branch. */ t1 = gimplify_build1 (gsi, ABS_EXPR, inner_type, br); @@ -1140,17 +1281,11 @@ expand_complex_div_wide (gimple_stmt_iterator *gsi, tree inner_type, if (TREE_CODE (compare) != INTEGER_CST) { edge e; - gimple stmt; + gimple *stmt; tree cond, tmp; - tmp = create_tmp_var (boolean_type_node); + tmp = make_ssa_name (boolean_type_node); stmt = gimple_build_assign (tmp, compare); - if (gimple_in_ssa_p (cfun)) - { - tmp = make_ssa_name (tmp, stmt); - gimple_assign_set_lhs (stmt, tmp); - } - gsi_insert_before (gsi, stmt, GSI_SAME_STMT); cond = fold_build2_loc (gimple_location (stmt), @@ -1164,13 +1299,19 @@ expand_complex_div_wide (gimple_stmt_iterator *gsi, tree inner_type, bb_join = e->dest; bb_true = create_empty_bb (bb_cond); bb_false = create_empty_bb (bb_true); + bb_true->count = bb_false->count + = bb_cond->count.apply_probability (profile_probability::even ()); /* Wire the blocks together. */ e->flags = EDGE_TRUE_VALUE; + /* TODO: With value profile we could add an historgram to determine real + branch outcome. */ + e->probability = profile_probability::even (); redirect_edge_succ (e, bb_true); - make_edge (bb_cond, bb_false, EDGE_FALSE_VALUE); - make_edge (bb_true, bb_join, EDGE_FALLTHRU); - make_edge (bb_false, bb_join, EDGE_FALLTHRU); + edge e2 = make_edge (bb_cond, bb_false, EDGE_FALSE_VALUE); + e2->probability = profile_probability::even (); + make_single_succ_edge (bb_true, bb_join, EDGE_FALLTHRU); + make_single_succ_edge (bb_false, bb_join, EDGE_FALLTHRU); add_bb_to_loop (bb_true, bb_cond->loop_father); add_bb_to_loop (bb_false, bb_cond->loop_father); @@ -1275,13 +1416,14 @@ expand_complex_div_wide (gimple_stmt_iterator *gsi, tree inner_type, /* Expand complex division to scalars. */ static void -expand_complex_division (gimple_stmt_iterator *gsi, tree inner_type, +expand_complex_division (gimple_stmt_iterator *gsi, tree type, tree ar, tree ai, tree br, tree bi, enum tree_code code, complex_lattice_t al, complex_lattice_t bl) { tree rr, ri; + tree inner_type = TREE_TYPE (type); switch (PAIR (al, bl)) { case PAIR (ONLY_REAL, ONLY_REAL): @@ -1314,6 +1456,7 @@ expand_complex_division (gimple_stmt_iterator *gsi, tree inner_type, rr = gimplify_build2 (gsi, code, inner_type, ai, bi); ri = gimplify_build2 (gsi, code, inner_type, ar, bi); ri = gimplify_build1 (gsi, NEGATE_EXPR, inner_type, ri); + break; case PAIR (ONLY_REAL, VARYING): case PAIR (ONLY_IMAG, VARYING): @@ -1328,7 +1471,7 @@ expand_complex_division (gimple_stmt_iterator *gsi, tree inner_type, case 2: if (SCALAR_FLOAT_TYPE_P (inner_type)) { - expand_complex_libcall (gsi, ar, ai, br, bi, code); + expand_complex_libcall (gsi, type, ar, ai, br, bi, code, true); break; } /* FALLTHRU */ @@ -1388,7 +1531,7 @@ expand_complex_comparison (gimple_stmt_iterator *gsi, tree ar, tree ai, tree br, tree bi, enum tree_code code) { tree cr, ci, cc, type; - gimple stmt; + gimple *stmt; cr = gimplify_build2 (gsi, code, boolean_type_node, ar, br); ci = gimplify_build2 (gsi, code, boolean_type_node, ai, bi); @@ -1428,6 +1571,8 @@ expand_complex_comparison (gimple_stmt_iterator *gsi, tree ar, tree ai, } update_stmt (stmt); + if (maybe_clean_eh_stmt (stmt)) + bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index); } /* Expand inline asm that sets some complex SSA_NAMEs. */ @@ -1466,7 +1611,7 @@ expand_complex_asm (gimple_stmt_iterator *gsi) static void expand_complex_operations_1 (gimple_stmt_iterator *gsi) { - gimple stmt = gsi_stmt (*gsi); + gimple *stmt = gsi_stmt (*gsi); tree type, inner_type, lhs; tree ac, ar, ai, bc, br, bi; complex_lattice_t al, bl; @@ -1548,7 +1693,7 @@ expand_complex_operations_1 (gimple_stmt_iterator *gsi) ac = gimple_assign_rhs1 (stmt); bc = (gimple_num_ops (stmt) > 2) ? gimple_assign_rhs2 (stmt) : NULL; } - /* GIMPLE_CALL can not get here. */ + /* GIMPLE_CALL cannot get here. */ else { ac = gimple_cond_lhs (stmt); @@ -1568,25 +1713,20 @@ expand_complex_operations_1 (gimple_stmt_iterator *gsi) else br = bi = NULL_TREE; - if (gimple_in_ssa_p (cfun)) + al = find_lattice_value (ac); + if (al == UNINITIALIZED) + al = VARYING; + + if (TREE_CODE_CLASS (code) == tcc_unary) + bl = UNINITIALIZED; + else if (ac == bc) + bl = al; + else { - al = find_lattice_value (ac); - if (al == UNINITIALIZED) - al = VARYING; - - if (TREE_CODE_CLASS (code) == tcc_unary) - bl = UNINITIALIZED; - else if (ac == bc) - bl = al; - else - { - bl = find_lattice_value (bc); - if (bl == UNINITIALIZED) - bl = VARYING; - } + bl = find_lattice_value (bc); + if (bl == UNINITIALIZED) + bl = VARYING; } - else - al = bl = VARYING; switch (code) { @@ -1596,7 +1736,7 @@ expand_complex_operations_1 (gimple_stmt_iterator *gsi) break; case MULT_EXPR: - expand_complex_multiplication (gsi, inner_type, ar, ai, br, bi, al, bl); + expand_complex_multiplication (gsi, type, ar, ai, br, bi, al, bl); break; case TRUNC_DIV_EXPR: @@ -1604,7 +1744,7 @@ expand_complex_operations_1 (gimple_stmt_iterator *gsi) case FLOOR_DIV_EXPR: case ROUND_DIV_EXPR: case RDIV_EXPR: - expand_complex_division (gsi, inner_type, ar, ai, br, bi, code, al, bl); + expand_complex_division (gsi, type, ar, ai, br, bi, code, al, bl); break; case NEGATE_EXPR: @@ -1631,45 +1771,77 @@ expand_complex_operations_1 (gimple_stmt_iterator *gsi) static unsigned int tree_lower_complex (void) { - int old_last_basic_block; gimple_stmt_iterator gsi; basic_block bb; + int n_bbs, i; + int *rpo; if (!init_dont_simulate_again ()) return 0; complex_lattice_values.create (num_ssa_names); - complex_lattice_values.safe_grow_cleared (num_ssa_names); + complex_lattice_values.safe_grow_cleared (num_ssa_names, true); init_parameter_lattice_values (); - ssa_propagate (complex_visit_stmt, complex_visit_phi); + class complex_propagate complex_propagate; + complex_propagate.ssa_propagate (); + + need_eh_cleanup = BITMAP_ALLOC (NULL); complex_variable_components = new int_tree_htab_type (10); complex_ssa_name_components.create (2 * num_ssa_names); - complex_ssa_name_components.safe_grow_cleared (2 * num_ssa_names); + complex_ssa_name_components.safe_grow_cleared (2 * num_ssa_names, true); update_parameter_components (); - /* ??? Ideally we'd traverse the blocks in breadth-first order. */ - old_last_basic_block = last_basic_block_for_fn (cfun); - FOR_EACH_BB_FN (bb, cfun) + rpo = XNEWVEC (int, last_basic_block_for_fn (cfun)); + n_bbs = pre_and_rev_post_order_compute (NULL, rpo, false); + for (i = 0; i < n_bbs; i++) { - if (bb->index >= old_last_basic_block) + bb = BASIC_BLOCK_FOR_FN (cfun, rpo[i]); + if (!bb) continue; - update_phi_components (bb); for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) expand_complex_operations_1 (&gsi); } + free (rpo); + + if (!phis_to_revisit.is_empty ()) + { + unsigned int n = phis_to_revisit.length (); + for (unsigned int j = 0; j < n; j += 3) + for (unsigned int k = 0; k < 2; k++) + if (gphi *phi = phis_to_revisit[j + k + 1]) + { + unsigned int m = gimple_phi_num_args (phi); + for (unsigned int l = 0; l < m; ++l) + { + tree op = gimple_phi_arg_def (phi, l); + if (TREE_CODE (op) == SSA_NAME + || is_gimple_min_invariant (op)) + continue; + tree arg = gimple_phi_arg_def (phis_to_revisit[j], l); + op = extract_component (NULL, arg, k > 0, false, false); + SET_PHI_ARG_DEF (phi, l, op); + } + } + phis_to_revisit.release (); + } + gsi_commit_edge_inserts (); + unsigned todo + = gimple_purge_all_dead_eh_edges (need_eh_cleanup) ? TODO_cleanup_cfg : 0; + BITMAP_FREE (need_eh_cleanup); + delete complex_variable_components; complex_variable_components = NULL; complex_ssa_name_components.release (); complex_lattice_values.release (); - return 0; + return todo; } namespace {