X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Ftree-ssa-pre.c;h=60ae35cef73164e8969d96efc6a48fa6cf721647;hp=b00307aff2b2cd2fa304385be942857d34d94230;hb=d6152abcbb4afe750c58974625f5218f93604105;hpb=6ef9bbe066d3b9482e5b186e3e4839ffed453207 diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index b00307aff2b..60ae35cef73 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -484,10 +484,12 @@ static tree pretemp; static tree storetemp; static tree prephitemp; -/* Set of blocks with statements that have had its EH information - cleaned up. */ +/* Set of blocks with statements that have had their EH properties changed. */ static bitmap need_eh_cleanup; +/* Set of blocks with statements that have had their AB properties changed. */ +static bitmap need_ab_cleanup; + /* The phi_translate_table caches phi translations for a given expression and predecessor. */ @@ -578,8 +580,7 @@ phi_trans_add (pre_expr e, pre_expr v, basic_block pred) slot = htab_find_slot_with_hash (phi_translate_table, new_pair, new_pair->hashcode, INSERT); - if (*slot) - free (*slot); + free (*slot); *slot = (void *) new_pair; } @@ -893,9 +894,7 @@ bitmap_value_insert_into_set (bitmap_set_t set, pre_expr expr) { unsigned int val = get_expr_value_id (expr); -#ifdef ENABLE_CHECKING - gcc_assert (expr->id == get_or_alloc_expression_id (expr)); -#endif + gcc_checking_assert (expr->id == get_or_alloc_expression_id (expr)); /* Constant values are always considered to be part of the set. */ if (value_id_constant_p (val)) @@ -1151,14 +1150,6 @@ fully_constant_expression (pre_expr e) vn_nary_op_t nary = PRE_EXPR_NARY (e); switch (TREE_CODE_CLASS (nary->opcode)) { - case tcc_expression: - if (nary->opcode == TRUTH_NOT_EXPR) - goto do_unary; - if (nary->opcode != TRUTH_AND_EXPR - && nary->opcode != TRUTH_OR_EXPR - && nary->opcode != TRUTH_XOR_EXPR) - return e; - /* Fallthrough. */ case tcc_binary: case tcc_comparison: { @@ -1200,7 +1191,6 @@ fully_constant_expression (pre_expr e) return e; /* Fallthrough. */ case tcc_unary: -do_unary: { /* We have to go from trees to pre exprs to value ids to constants. */ @@ -1409,7 +1399,7 @@ get_representative_for (const pre_expr e) if (!pretemp || exprtype != TREE_TYPE (pretemp)) { pretemp = create_tmp_reg (exprtype, "pretmp"); - get_var_ann (pretemp); + add_referenced_var (pretemp); } name = make_ssa_name (pretemp, gimple_build_nop ()); @@ -1453,20 +1443,18 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2, unsigned int i; bool changed = false; vn_nary_op_t nary = PRE_EXPR_NARY (expr); - struct vn_nary_op_s newnary; - /* The NARY structure is only guaranteed to have been - allocated to the nary->length operands. */ - memcpy (&newnary, nary, (sizeof (struct vn_nary_op_s) - - sizeof (tree) * (4 - nary->length))); + vn_nary_op_t newnary = XALLOCAVAR (struct vn_nary_op_s, + sizeof_vn_nary_op (nary->length)); + memcpy (newnary, nary, sizeof_vn_nary_op (nary->length)); - for (i = 0; i < newnary.length; i++) + for (i = 0; i < newnary->length; i++) { - if (TREE_CODE (newnary.op[i]) != SSA_NAME) + if (TREE_CODE (newnary->op[i]) != SSA_NAME) continue; else { pre_expr leader, result; - unsigned int op_val_id = VN_INFO (newnary.op[i])->value_id; + unsigned int op_val_id = VN_INFO (newnary->op[i])->value_id; leader = find_leader_in_sets (op_val_id, set1, set2); result = phi_translate (leader, set1, set2, pred, phiblock); if (result && result != leader) @@ -1474,12 +1462,12 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2, tree name = get_representative_for (result); if (!name) return NULL; - newnary.op[i] = name; + newnary->op[i] = name; } else if (!result) return NULL; - changed |= newnary.op[i] != nary->op[i]; + changed |= newnary->op[i] != nary->op[i]; } } if (changed) @@ -1487,13 +1475,10 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2, pre_expr constant; unsigned int new_val_id; - tree result = vn_nary_op_lookup_pieces (newnary.length, - newnary.opcode, - newnary.type, - newnary.op[0], - newnary.op[1], - newnary.op[2], - newnary.op[3], + tree result = vn_nary_op_lookup_pieces (newnary->length, + newnary->opcode, + newnary->type, + &newnary->op[0], &nary); if (result && is_gimple_min_invariant (result)) return get_or_alloc_expr_for_constant (result); @@ -1517,13 +1502,10 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2, VEC_safe_grow_cleared (bitmap_set_t, heap, value_expressions, get_max_value_id() + 1); - nary = vn_nary_op_insert_pieces (newnary.length, - newnary.opcode, - newnary.type, - newnary.op[0], - newnary.op[1], - newnary.op[2], - newnary.op[3], + nary = vn_nary_op_insert_pieces (newnary->length, + newnary->opcode, + newnary->type, + &newnary->op[0], result, new_val_id); PRE_EXPR_NARY (expr) = nary; constant = fully_constant_expression (expr); @@ -1681,7 +1663,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2, tree result = vn_reference_lookup_pieces (newvuse, ref->set, ref->type, newoperands, - &newref, true); + &newref, VN_WALK); if (result) VEC_free (vn_reference_op_s, heap, newoperands); @@ -1691,6 +1673,12 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2, result = fold_build1 (VIEW_CONVERT_EXPR, ref->type, result); converted = true; } + else if (!result && newref + && !useless_type_conversion_p (ref->type, newref->type)) + { + VEC_free (vn_reference_op_s, heap, newoperands); + return NULL; + } if (result && is_gimple_min_invariant (result)) { @@ -1712,9 +1700,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2, nresult = vn_nary_op_lookup_pieces (1, TREE_CODE (result), TREE_TYPE (result), - TREE_OPERAND (result, 0), - NULL_TREE, NULL_TREE, - NULL_TREE, + &TREE_OPERAND (result, 0), &nary); if (nresult && is_gimple_min_invariant (nresult)) return get_or_alloc_expr_for_constant (nresult); @@ -1738,9 +1724,8 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2, get_max_value_id() + 1); nary = vn_nary_op_insert_pieces (1, TREE_CODE (result), TREE_TYPE (result), - TREE_OPERAND (result, 0), - NULL_TREE, NULL_TREE, - NULL_TREE, NULL_TREE, + &TREE_OPERAND (result, 0), + NULL_TREE, new_val_id); PRE_EXPR_NARY (expr) = nary; constant = fully_constant_expression (expr); @@ -1886,7 +1871,7 @@ phi_translate_set (bitmap_set_t dest, bitmap_set_t set, basic_block pred, } exprs = sorted_array_from_bitmap_set (set); - for (i = 0; VEC_iterate (pre_expr, exprs, i, expr); i++) + FOR_EACH_VEC_ELT (pre_expr, exprs, i, expr) { pre_expr translated; translated = phi_translate (expr, set, NULL, pred, phiblock); @@ -2150,7 +2135,7 @@ valid_in_sets (bitmap_set_t set1, bitmap_set_t set2, pre_expr expr, vn_reference_op_t vro; unsigned int i; - for (i = 0; VEC_iterate (vn_reference_op_s, ref->operands, i, vro); i++) + FOR_EACH_VEC_ELT (vn_reference_op_s, ref->operands, i, vro) { if (!vro_valid_in_sets (set1, set2, vro)) return false; @@ -2184,7 +2169,7 @@ dependent_clean (bitmap_set_t set1, bitmap_set_t set2, basic_block block) pre_expr expr; int i; - for (i = 0; VEC_iterate (pre_expr, exprs, i, expr); i++) + FOR_EACH_VEC_ELT (pre_expr, exprs, i, expr) { if (!valid_in_sets (set1, set2, expr, block)) bitmap_remove_from_set (set1, expr); @@ -2203,7 +2188,7 @@ clean (bitmap_set_t set, basic_block block) pre_expr expr; int i; - for (i = 0; VEC_iterate (pre_expr, exprs, i, expr); i++) + FOR_EACH_VEC_ELT (pre_expr, exprs, i, expr) { if (!valid_in_sets (set, NULL, expr, block)) bitmap_remove_from_set (set, expr); @@ -2337,7 +2322,7 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge) else bitmap_set_copy (ANTIC_OUT, ANTIC_IN (first)); - for (i = 0; VEC_iterate (basic_block, worklist, i, bprime); i++) + FOR_EACH_VEC_ELT (basic_block, worklist, i, bprime) { if (!gimple_seq_empty_p (phi_nodes (bprime))) { @@ -2480,7 +2465,7 @@ compute_partial_antic_aux (basic_block block, } if (VEC_length (basic_block, worklist) > 0) { - for (i = 0; VEC_iterate (basic_block, worklist, i, bprime); i++) + FOR_EACH_VEC_ELT (basic_block, worklist, i, bprime) { unsigned int i; bitmap_iterator bi; @@ -2594,6 +2579,10 @@ compute_antic (void) { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "Starting iteration %d\n", num_iterations); + /* ??? We need to clear our PHI translation cache here as the + ANTIC sets shrink and we restrict valid translations to + those having operands with leaders in ANTIC. Same below + for PA ANTIC computation. */ num_iterations++; changed = false; for (i = n_basic_blocks - NUM_FIXED_BLOCKS - 1; i >= 0; i--) @@ -2606,10 +2595,8 @@ compute_antic (void) block->index)); } } -#ifdef ENABLE_CHECKING /* Theoretically possible, but *highly* unlikely. */ - gcc_assert (num_iterations < 500); -#endif + gcc_checking_assert (num_iterations < 500); } statistics_histogram_event (cfun, "compute_antic iterations", @@ -2638,10 +2625,8 @@ compute_antic (void) block->index)); } } -#ifdef ENABLE_CHECKING /* Theoretically possible, but *highly* unlikely. */ - gcc_assert (num_iterations < 500); -#endif + gcc_checking_assert (num_iterations < 500); } statistics_histogram_event (cfun, "compute_partial_antic iterations", num_iterations); @@ -2651,11 +2636,13 @@ compute_antic (void) } /* Return true if we can value number the call in STMT. This is true - if we have a pure or constant call. */ + if we have a pure or constant call to a real function. */ static bool can_value_number_call (gimple stmt) { + if (gimple_call_internal_p (stmt)) + return false; if (gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST)) return true; return false; @@ -2764,7 +2751,7 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, gcc_assert (base); offset = int_const_binop (PLUS_EXPR, offset, build_int_cst (TREE_TYPE (offset), - off), 0); + off)); baseop = build_fold_addr_expr (base); } return fold_build2 (MEM_REF, currop->type, baseop, offset); @@ -2772,8 +2759,10 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, break; case TARGET_MEM_REF: { - pre_expr op0expr; - tree genop0 = NULL_TREE; + pre_expr op0expr, op1expr; + tree genop0 = NULL_TREE, genop1 = NULL_TREE; + vn_reference_op_t nextop = VEC_index (vn_reference_op_s, ref->operands, + ++*operand); tree baseop = create_component_ref_by_pieces_1 (block, ref, operand, stmts, domstmt); if (!baseop) @@ -2786,14 +2775,16 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, if (!genop0) return NULL_TREE; } - if (DECL_P (baseop)) - return build5 (TARGET_MEM_REF, currop->type, - baseop, NULL_TREE, - genop0, currop->op1, currop->op2); - else - return build5 (TARGET_MEM_REF, currop->type, - NULL_TREE, baseop, - genop0, currop->op1, currop->op2); + if (nextop->op0) + { + op1expr = get_or_alloc_expr_for (nextop->op0); + genop1 = find_or_generate_expression (block, op1expr, + stmts, domstmt); + if (!genop1) + return NULL_TREE; + } + return build5 (TARGET_MEM_REF, currop->type, + baseop, currop->op2, genop0, currop->op1, genop1); } break; case ADDR_EXPR: @@ -2818,26 +2809,6 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, return folded; } break; - case MISALIGNED_INDIRECT_REF: - { - tree folded; - tree genop1 = create_component_ref_by_pieces_1 (block, ref, - operand, - stmts, domstmt); - if (!genop1) - return NULL_TREE; - genop1 = fold_convert (build_pointer_type (currop->type), - genop1); - - if (currop->opcode == MISALIGNED_INDIRECT_REF) - folded = fold_build2 (currop->opcode, currop->type, - genop1, currop->op1); - else - folded = fold_build1 (currop->opcode, currop->type, - genop1); - return folded; - } - break; case BIT_FIELD_REF: { tree folded; @@ -2884,8 +2855,11 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref, return NULL_TREE; if (genop2) { - /* Drop zero minimum index. */ - if (tree_int_cst_equal (genop2, integer_zero_node)) + tree domain_type = TYPE_DOMAIN (TREE_TYPE (genop0)); + /* Drop zero minimum index if redundant. */ + if (integer_zerop (genop2) + && (!domain_type + || integer_zerop (TYPE_MIN_VALUE (domain_type)))) genop2 = NULL_TREE; else { @@ -3102,50 +3076,53 @@ create_expression_by_pieces (basic_block block, pre_expr expr, case NARY: { vn_nary_op_t nary = PRE_EXPR_NARY (expr); - switch (nary->length) + tree genop[4]; + unsigned i; + for (i = 0; i < nary->length; ++i) { - case 2: - { - pre_expr op1 = get_or_alloc_expr_for (nary->op[0]); - pre_expr op2 = get_or_alloc_expr_for (nary->op[1]); - tree genop1 = find_or_generate_expression (block, op1, - stmts, domstmt); - tree genop2 = find_or_generate_expression (block, op2, - stmts, domstmt); - if (!genop1 || !genop2) - return NULL_TREE; - /* Ensure op2 is a sizetype for POINTER_PLUS_EXPR. It - may be a constant with the wrong type. */ - if (nary->opcode == POINTER_PLUS_EXPR) - { - genop1 = fold_convert (nary->type, genop1); - genop2 = fold_convert (sizetype, genop2); - } - else - { - genop1 = fold_convert (TREE_TYPE (nary->op[0]), genop1); - genop2 = fold_convert (TREE_TYPE (nary->op[1]), genop2); - } - - folded = fold_build2 (nary->opcode, nary->type, - genop1, genop2); - } - break; - case 1: - { - pre_expr op1 = get_or_alloc_expr_for (nary->op[0]); - tree genop1 = find_or_generate_expression (block, op1, - stmts, domstmt); - if (!genop1) - return NULL_TREE; - genop1 = fold_convert (TREE_TYPE (nary->op[0]), genop1); - - folded = fold_build1 (nary->opcode, nary->type, - genop1); - } - break; - default: - return NULL_TREE; + pre_expr op = get_or_alloc_expr_for (nary->op[i]); + genop[i] = find_or_generate_expression (block, op, + stmts, domstmt); + if (!genop[i]) + return NULL_TREE; + /* Ensure genop[] is properly typed for POINTER_PLUS_EXPR. It + may have conversions stripped. */ + if (nary->opcode == POINTER_PLUS_EXPR) + { + if (i == 0) + genop[i] = fold_convert (nary->type, genop[i]); + else if (i == 1) + genop[i] = convert_to_ptrofftype (genop[i]); + } + else + genop[i] = fold_convert (TREE_TYPE (nary->op[i]), genop[i]); + } + if (nary->opcode == CONSTRUCTOR) + { + VEC(constructor_elt,gc) *elts = NULL; + for (i = 0; i < nary->length; ++i) + CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, genop[i]); + folded = build_constructor (nary->type, elts); + } + else + { + switch (nary->length) + { + case 1: + folded = fold_build1 (nary->opcode, nary->type, + genop[0]); + break; + case 2: + folded = fold_build2 (nary->opcode, nary->type, + genop[0], genop[1]); + break; + case 3: + folded = fold_build3 (nary->opcode, nary->type, + genop[0], genop[1], genop[3]); + break; + default: + gcc_unreachable (); + } } } break; @@ -3193,10 +3170,7 @@ create_expression_by_pieces (basic_block block, pre_expr expr, /* Build and insert the assignment of the end result to the temporary that we will return. */ if (!pretemp || exprtype != TREE_TYPE (pretemp)) - { - pretemp = create_tmp_reg (exprtype, "pretmp"); - get_var_ann (pretemp); - } + pretemp = create_tmp_reg (exprtype, "pretmp"); temp = pretemp; add_referenced_var (temp); @@ -3212,6 +3186,11 @@ create_expression_by_pieces (basic_block block, pre_expr expr, /* All the symbols in NEWEXPR should be put into SSA form. */ mark_symbols_for_renaming (newstmt); + /* Fold the last statement. */ + gsi = gsi_last (*stmts); + if (fold_stmt_inplace (&gsi)) + update_stmt (gsi_stmt (gsi)); + /* Add a value number to the temporary. The value may already exist in either NEW_SETS, or AVAIL_OUT, because we are creating the expression by pieces, and this particular piece of @@ -3259,7 +3238,7 @@ inhibit_phi_insertion (basic_block bb, pre_expr expr) memory reference is a simple induction variable. In other cases the vectorizer won't do anything anyway (either it's loop invariant or a complicated expression). */ - for (i = 0; VEC_iterate (vn_reference_op_s, ops, i, op); ++i) + FOR_EACH_VEC_ELT (vn_reference_op_s, ops, i, op) { switch (op->opcode) { @@ -3456,10 +3435,7 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum, /* Now build a phi for the new variable. */ if (!prephitemp || TREE_TYPE (prephitemp) != type) - { - prephitemp = create_tmp_var (type, "prephitmp"); - get_var_ann (prephitemp); - } + prephitemp = create_tmp_var (type, "prephitmp"); temp = prephitemp; add_referenced_var (temp); @@ -3546,7 +3522,7 @@ do_regular_insertion (basic_block block, basic_block dom) pre_expr expr; int i; - for (i = 0; VEC_iterate (pre_expr, exprs, i, expr); i++) + FOR_EACH_VEC_ELT (pre_expr, exprs, i, expr) { if (expr->kind != NAME) { @@ -3627,11 +3603,23 @@ do_regular_insertion (basic_block block, basic_block dom) already existing along every predecessor, and it's defined by some predecessor, it is partially redundant. */ - if (!cant_insert && !all_same && by_some && do_insertion - && dbg_cnt (treepre_insert)) + if (!cant_insert && !all_same && by_some) { - if (insert_into_preds_of_block (block, get_expression_id (expr), - avail)) + if (!do_insertion) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Skipping partial redundancy for " + "expression "); + print_pre_expr (dump_file, expr); + fprintf (dump_file, " (%04d), no redundancy on to be " + "optimized for speed edge\n", val); + } + } + else if (dbg_cnt (treepre_insert) + && insert_into_preds_of_block (block, + get_expression_id (expr), + avail)) new_stuff = true; } /* If all edges produce the same value and that value is @@ -3692,7 +3680,7 @@ do_partial_partial_insertion (basic_block block, basic_block dom) pre_expr expr; int i; - for (i = 0; VEC_iterate (pre_expr, exprs, i, expr); i++) + FOR_EACH_VEC_ELT (pre_expr, exprs, i, expr) { if (expr->kind != NAME) { @@ -4019,7 +4007,7 @@ compute_avail (void) copy_reference_ops_from_call (stmt, &ops); vn_reference_lookup_pieces (gimple_vuse (stmt), 0, gimple_expr_type (stmt), - ops, &ref, false); + ops, &ref, VN_NOWALK); VEC_free (vn_reference_op_s, heap, ops); if (!ref) continue; @@ -4062,9 +4050,8 @@ compute_avail (void) vn_nary_op_lookup_pieces (gimple_num_ops (stmt) - 1, gimple_assign_rhs_code (stmt), gimple_expr_type (stmt), - gimple_assign_rhs1 (stmt), - gimple_assign_rhs2 (stmt), - NULL_TREE, NULL_TREE, &nary); + gimple_assign_rhs1_ptr (stmt), + &nary); if (!nary) continue; @@ -4089,7 +4076,7 @@ compute_avail (void) vn_reference_lookup (gimple_assign_rhs1 (stmt), gimple_vuse (stmt), - true, &ref); + VN_WALK, &ref); if (!ref) continue; @@ -4180,6 +4167,7 @@ static unsigned int eliminate (void) { VEC (gimple, heap) *to_remove = NULL; + VEC (gimple, heap) *to_update = NULL; basic_block b; unsigned int todo = 0; gimple_stmt_iterator gsi; @@ -4269,6 +4257,10 @@ eliminate (void) || TREE_CODE (rhs) != SSA_NAME || may_propagate_copy (rhs, sprime))) { + bool can_make_abnormal_goto + = is_gimple_call (stmt) + && stmt_can_make_abnormal_goto (stmt); + gcc_assert (sprime != rhs); if (dump_file && (dump_flags & TDF_DETAILS)) @@ -4297,14 +4289,24 @@ eliminate (void) stmt = gsi_stmt (gsi); update_stmt (stmt); - /* If we removed EH side effects from the statement, clean + /* If we removed EH side-effects from the statement, clean its EH information. */ if (maybe_clean_or_replace_eh_stmt (stmt, stmt)) { bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index); if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, " Removed EH side effects.\n"); + fprintf (dump_file, " Removed EH side-effects.\n"); + } + + /* Likewise for AB side-effects. */ + if (can_make_abnormal_goto + && !stmt_can_make_abnormal_goto (stmt)) + { + bitmap_set_bit (need_ab_cleanup, + gimple_bb (stmt)->index); + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " Removed AB side-effects.\n"); } } } @@ -4319,7 +4321,7 @@ eliminate (void) tree rhs = gimple_assign_rhs1 (stmt); tree val; val = vn_reference_lookup (gimple_assign_lhs (stmt), - gimple_vuse (stmt), true, NULL); + gimple_vuse (stmt), VN_WALK, NULL); if (TREE_CODE (rhs) == SSA_NAME) rhs = VN_INFO (rhs)->valnum; if (val @@ -4361,13 +4363,27 @@ eliminate (void) } /* Visit indirect calls and turn them into direct calls if possible. */ - if (gimple_code (stmt) == GIMPLE_CALL - && TREE_CODE (gimple_call_fn (stmt)) == SSA_NAME) + if (is_gimple_call (stmt)) { - tree fn = VN_INFO (gimple_call_fn (stmt))->valnum; - if (TREE_CODE (fn) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL) + tree orig_fn = gimple_call_fn (stmt); + tree fn; + if (!orig_fn) + continue; + if (TREE_CODE (orig_fn) == SSA_NAME) + fn = VN_INFO (orig_fn)->valnum; + else if (TREE_CODE (orig_fn) == OBJ_TYPE_REF + && TREE_CODE (OBJ_TYPE_REF_EXPR (orig_fn)) == SSA_NAME) + fn = VN_INFO (OBJ_TYPE_REF_EXPR (orig_fn))->valnum; + else + continue; + if (gimple_call_addr_fndecl (fn) != NULL_TREE + && useless_type_conversion_p (TREE_TYPE (orig_fn), + TREE_TYPE (fn))) { + bool can_make_abnormal_goto + = stmt_can_make_abnormal_goto (stmt); + bool was_noreturn = gimple_call_noreturn_p (stmt); + if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Replacing call target with "); @@ -4377,13 +4393,31 @@ eliminate (void) } gimple_call_set_fn (stmt, fn); - update_stmt (stmt); + VEC_safe_push (gimple, heap, to_update, stmt); + + /* When changing a call into a noreturn call, cfg cleanup + is needed to fix up the noreturn call. */ + if (!was_noreturn && gimple_call_noreturn_p (stmt)) + todo |= TODO_cleanup_cfg; + + /* If we removed EH side-effects from the statement, clean + its EH information. */ if (maybe_clean_or_replace_eh_stmt (stmt, stmt)) { bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index); if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, " Removed EH side effects.\n"); + fprintf (dump_file, " Removed EH side-effects.\n"); + } + + /* Likewise for AB side-effects. */ + if (can_make_abnormal_goto + && !stmt_can_make_abnormal_goto (stmt)) + { + bitmap_set_bit (need_ab_cleanup, + gimple_bb (stmt)->index); + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " Removed AB side-effects.\n"); } /* Changing an indirect call to a direct call may @@ -4473,7 +4507,7 @@ eliminate (void) /* We cannot remove stmts during BB walk, especially not release SSA names there as this confuses the VN machinery. The stmts ending up in to_remove are either stores or simple copies. */ - for (i = 0; VEC_iterate (gimple, to_remove, i, stmt); ++i) + FOR_EACH_VEC_ELT (gimple, to_remove, i, stmt) { tree lhs = gimple_assign_lhs (stmt); tree rhs = gimple_assign_rhs1 (stmt); @@ -4498,9 +4532,12 @@ eliminate (void) if (TREE_CODE (lhs) != SSA_NAME || has_zero_uses (lhs)) { + basic_block bb = gimple_bb (stmt); gsi = gsi_for_stmt (stmt); unlink_stmt_vdef (stmt); gsi_remove (&gsi, true); + if (gimple_purge_dead_eh_edges (bb)) + todo |= TODO_cleanup_cfg; if (TREE_CODE (lhs) == SSA_NAME) bitmap_clear_bit (inserted_exprs, SSA_NAME_VERSION (lhs)); release_defs (stmt); @@ -4508,6 +4545,13 @@ eliminate (void) } VEC_free (gimple, heap, to_remove); + /* We cannot update call statements with virtual operands during + SSA walk. This might remove them which in turn makes our + VN lattice invalid. */ + FOR_EACH_VEC_ELT (gimple, to_update, i, stmt) + update_stmt (stmt); + VEC_free (gimple, heap, to_update); + return todo; } @@ -4759,6 +4803,7 @@ init_pre (bool do_fre) } need_eh_cleanup = BITMAP_ALLOC (NULL); + need_ab_cleanup = BITMAP_ALLOC (NULL); } @@ -4790,6 +4835,14 @@ fini_pre (bool do_fre) BITMAP_FREE (need_eh_cleanup); + if (!bitmap_empty_p (need_ab_cleanup)) + { + gimple_purge_all_dead_abnormal_call_edges (need_ab_cleanup); + cleanup_tree_cfg (); + } + + BITMAP_FREE (need_ab_cleanup); + if (!do_fre) loop_optimizer_finalize (); } @@ -4809,7 +4862,7 @@ execute_pre (bool do_fre) if (!do_fre) loop_optimizer_init (LOOPS_NORMAL); - if (!run_scc_vn ()) + if (!run_scc_vn (do_fre ? VN_WALKREWRITE : VN_WALK)) { if (!do_fre) loop_optimizer_finalize (); @@ -4863,13 +4916,26 @@ execute_pre (bool do_fre) statistics_counter_event (cfun, "Constified", pre_stats.constified); clear_expression_ids (); - free_scc_vn (); if (!do_fre) - remove_dead_inserted_code (); + { + remove_dead_inserted_code (); + todo |= TODO_verify_flow; + } scev_finalize (); fini_pre (do_fre); + if (!do_fre) + /* TODO: tail_merge_optimize may merge all predecessors of a block, in which + case we can merge the block with the remaining predecessor of the block. + It should either: + - call merge_blocks after each tail merge iteration + - call merge_blocks after all tail merge iterations + - mark TODO_cleanup_cfg when necessary + - share the cfg cleanup with fini_pre. */ + todo |= tail_merge_optimize (todo); + free_scc_vn (); + return todo; } @@ -4903,7 +4969,7 @@ struct gimple_opt_pass pass_pre = 0, /* properties_provided */ 0, /* properties_destroyed */ TODO_rebuild_alias, /* todo_flags_start */ - TODO_update_ssa_only_virtuals | TODO_dump_func | TODO_ggc_collect + TODO_update_ssa_only_virtuals | TODO_ggc_collect | TODO_verify_ssa /* todo_flags_finish */ } }; @@ -4938,6 +5004,6 @@ struct gimple_opt_pass pass_fre = 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_dump_func | TODO_ggc_collect | TODO_verify_ssa /* todo_flags_finish */ + TODO_ggc_collect | TODO_verify_ssa /* todo_flags_finish */ } };