X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-ssa-pre.c;h=557b56a110d320409267bbbbcfecb35945280c73;hb=e6013c28be3801b34d7a1b6f95b42f2544375b28;hp=27e84c22c5c7915b83234b2d5e90cf5896377653;hpb=317e2a6799a4863bca449ada8c3c8109877ef01a;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 27e84c22c5c..557b56a110d 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -1150,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: { @@ -1199,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. */ @@ -1408,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 ()); @@ -1452,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) @@ -1473,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) @@ -1486,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); @@ -1516,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); @@ -1544,7 +1527,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2, tree newvuse = vuse; VEC (vn_reference_op_s, heap) *newoperands = NULL; bool changed = false, same_valid = true; - unsigned int i, j; + unsigned int i, j, n; vn_reference_op_t operand; vn_reference_t newref; @@ -1553,100 +1536,83 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2, { pre_expr opresult; pre_expr leader; - tree oldop0 = operand->op0; - tree oldop1 = operand->op1; - tree oldop2 = operand->op2; - tree op0 = oldop0; - tree op1 = oldop1; - tree op2 = oldop2; + tree op[3]; tree type = operand->type; vn_reference_op_s newop = *operand; - - if (op0 && TREE_CODE (op0) == SSA_NAME) + op[0] = operand->op0; + op[1] = operand->op1; + op[2] = operand->op2; + for (n = 0; n < 3; ++n) { - unsigned int op_val_id = VN_INFO (op0)->value_id; - leader = find_leader_in_sets (op_val_id, set1, set2); - opresult = phi_translate (leader, set1, set2, pred, phiblock); - if (opresult && opresult != leader) + unsigned int op_val_id; + if (!op[n]) + continue; + if (TREE_CODE (op[n]) != SSA_NAME) { - tree name = get_representative_for (opresult); - if (!name) + /* We can't possibly insert these. */ + if (n != 0 + && !is_gimple_min_invariant (op[n])) break; - op0 = name; + continue; } - else if (!opresult) - break; - } - changed |= op0 != oldop0; - - if (op1 && TREE_CODE (op1) == SSA_NAME) - { - unsigned int op_val_id = VN_INFO (op1)->value_id; + op_val_id = VN_INFO (op[n])->value_id; leader = find_leader_in_sets (op_val_id, set1, set2); - opresult = phi_translate (leader, set1, set2, pred, phiblock); - if (opresult && opresult != leader) + if (!leader) + break; + /* Make sure we do not recursively translate ourselves + like for translating a[n_1] with the leader for + n_1 being a[n_1]. */ + if (get_expression_id (leader) != get_expression_id (expr)) { - tree name = get_representative_for (opresult); - if (!name) + opresult = phi_translate (leader, set1, set2, + pred, phiblock); + if (!opresult) break; - op1 = name; + if (opresult != leader) + { + tree name = get_representative_for (opresult); + if (!name) + break; + changed |= name != op[n]; + op[n] = name; + } } - else if (!opresult) - break; } - /* We can't possibly insert these. */ - else if (op1 && !is_gimple_min_invariant (op1)) - break; - changed |= op1 != oldop1; - if (op2 && TREE_CODE (op2) == SSA_NAME) + if (n != 3) { - unsigned int op_val_id = VN_INFO (op2)->value_id; - leader = find_leader_in_sets (op_val_id, set1, set2); - opresult = phi_translate (leader, set1, set2, pred, phiblock); - if (opresult && opresult != leader) - { - tree name = get_representative_for (opresult); - if (!name) - break; - op2 = name; - } - else if (!opresult) - break; + if (newoperands) + VEC_free (vn_reference_op_s, heap, newoperands); + return NULL; } - /* We can't possibly insert these. */ - else if (op2 && !is_gimple_min_invariant (op2)) - break; - changed |= op2 != oldop2; - if (!newoperands) newoperands = VEC_copy (vn_reference_op_s, heap, operands); /* We may have changed from an SSA_NAME to a constant */ - if (newop.opcode == SSA_NAME && TREE_CODE (op0) != SSA_NAME) - newop.opcode = TREE_CODE (op0); + if (newop.opcode == SSA_NAME && TREE_CODE (op[0]) != SSA_NAME) + newop.opcode = TREE_CODE (op[0]); newop.type = type; - newop.op0 = op0; - newop.op1 = op1; - newop.op2 = op2; + newop.op0 = op[0]; + newop.op1 = op[1]; + newop.op2 = op[2]; /* If it transforms a non-constant ARRAY_REF into a constant one, adjust the constant offset. */ if (newop.opcode == ARRAY_REF && newop.off == -1 - && TREE_CODE (op0) == INTEGER_CST - && TREE_CODE (op1) == INTEGER_CST - && TREE_CODE (op2) == INTEGER_CST) + && TREE_CODE (op[0]) == INTEGER_CST + && TREE_CODE (op[1]) == INTEGER_CST + && TREE_CODE (op[2]) == INTEGER_CST) { - double_int off = tree_to_double_int (op0); + double_int off = tree_to_double_int (op[0]); off = double_int_add (off, double_int_neg - (tree_to_double_int (op1))); - off = double_int_mul (off, tree_to_double_int (op2)); + (tree_to_double_int (op[1]))); + off = double_int_mul (off, tree_to_double_int (op[2])); if (double_int_fits_in_shwi_p (off)) newop.off = off.low; } VEC_replace (vn_reference_op_s, newoperands, j, &newop); /* If it transforms from an SSA_NAME to an address, fold with a preceding indirect reference. */ - if (j > 0 && op0 && TREE_CODE (op0) == ADDR_EXPR + if (j > 0 && op[0] && TREE_CODE (op[0]) == ADDR_EXPR && VEC_index (vn_reference_op_s, newoperands, j - 1)->opcode == MEM_REF) vn_reference_fold_indirect (&newoperands, &j); @@ -1717,9 +1683,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); @@ -1743,9 +1707,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); @@ -3096,50 +3059,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; @@ -3187,10 +3153,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); @@ -3206,6 +3169,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 @@ -3450,10 +3418,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); @@ -4068,9 +4033,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; @@ -4935,7 +4899,6 @@ 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 (); @@ -4945,6 +4908,17 @@ execute_pre (bool do_fre) 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; } @@ -4978,7 +4952,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 */ } }; @@ -5013,6 +4987,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 */ } };