Mercurial > hg > CbC > CbC_gcc
diff gcc/tree-outof-ssa.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/gcc/tree-outof-ssa.c Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/tree-outof-ssa.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ /* Convert a program in SSA form into Normal form. - Copyright (C) 2004-2018 Free Software Foundation, Inc. + Copyright (C) 2004-2020 Free Software Foundation, Inc. Contributed by Andrew Macleod <amacleod@redhat.com> This file is part of GCC. @@ -129,8 +129,9 @@ rarely more than 6, and in the bootstrap of gcc, the maximum number of nodes encountered was 12. */ -struct elim_graph +class elim_graph { +public: elim_graph (var_map map); /* Size of the elimination vectors. */ @@ -143,7 +144,7 @@ auto_vec<int> edge_list; /* Source locus on each edge */ - auto_vec<source_location> edge_locus; + auto_vec<location_t> edge_locus; /* Visited vector. */ auto_sbitmap visited; @@ -162,7 +163,7 @@ auto_vec<tree> const_copies; /* Source locations for any constant copies. */ - auto_vec<source_location> copy_locus; + auto_vec<location_t> copy_locus; }; @@ -171,14 +172,43 @@ use its location. Otherwise search instructions in predecessors of E for a location, and use that one. That makes sense because we insert on edges for PHI nodes, and effects of PHIs happen on - the end of the predecessor conceptually. */ + the end of the predecessor conceptually. An exception is made + for EH edges because we don't want to drag the source location + of unrelated statements at the beginning of handlers; they would + be further reused for various EH constructs, which would damage + the coverage information. */ static void set_location_for_edge (edge e) { if (e->goto_locus) + set_curr_insn_location (e->goto_locus); + else if (e->flags & EDGE_EH) { - set_curr_insn_location (e->goto_locus); + basic_block bb = e->dest; + gimple_stmt_iterator gsi; + + do + { + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple *stmt = gsi_stmt (gsi); + if (is_gimple_debug (stmt)) + continue; + if (gimple_has_location (stmt) || gimple_block (stmt)) + { + set_curr_insn_location (gimple_location (stmt)); + return; + } + } + /* Nothing found in this basic block. Make a half-assed attempt + to continue with another block. */ + if (single_succ_p (bb)) + bb = single_succ (bb); + else + bb = e->dest; + } + while (bb != e->dest); } else { @@ -238,7 +268,7 @@ /* Insert a copy instruction from partition SRC to DEST onto edge E. */ static void -insert_partition_copy_on_edge (edge e, int dest, int src, source_location locus) +insert_partition_copy_on_edge (edge e, int dest, int src, location_t locus) { tree var; if (dump_file && (dump_flags & TDF_DETAILS)) @@ -272,7 +302,7 @@ onto edge E. */ static void -insert_value_copy_on_edge (edge e, int dest, tree src, source_location locus) +insert_value_copy_on_edge (edge e, int dest, tree src, location_t locus) { rtx dest_rtx, seq, x; machine_mode dest_mode, src_mode; @@ -333,7 +363,7 @@ static void insert_rtx_to_part_on_edge (edge e, int dest, rtx src, int unsignedsrcp, - source_location locus) + location_t locus) { if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -367,7 +397,7 @@ onto edge E. */ static void -insert_part_to_rtx_on_edge (edge e, rtx dest, int src, source_location locus) +insert_part_to_rtx_on_edge (edge e, rtx dest, int src, location_t locus) { tree var; if (dump_file && (dump_flags & TDF_DETAILS)) @@ -444,7 +474,7 @@ /* Add the edge PRED->SUCC to graph G. */ static inline void -elim_graph_add_edge (elim_graph *g, int pred, int succ, source_location locus) +elim_graph_add_edge (elim_graph *g, int pred, int succ, location_t locus) { g->edge_list.safe_push (pred); g->edge_list.safe_push (succ); @@ -456,7 +486,7 @@ return the successor node. -1 is returned if there is no such edge. */ static inline int -elim_graph_remove_succ_edge (elim_graph *g, int node, source_location *locus) +elim_graph_remove_succ_edge (elim_graph *g, int node, location_t *locus) { int y; unsigned x; @@ -556,7 +586,7 @@ for (gsi = gsi_start_phis (g->e->dest); !gsi_end_p (gsi); gsi_next (&gsi)) { gphi *phi = gsi.phi (); - source_location locus; + location_t locus; p0 = var_to_partition (g->map, gimple_phi_result (phi)); /* Ignore results which are not in partitions. */ @@ -564,7 +594,11 @@ continue; Ti = PHI_ARG_DEF (phi, g->e->dest_idx); - locus = gimple_phi_arg_location_from_edge (phi, g->e); + /* See set_location_for_edge for the rationale. */ + if (g->e->flags & EDGE_EH) + locus = UNKNOWN_LOCATION; + else + locus = gimple_phi_arg_location_from_edge (phi, g->e); /* If this argument is a constant, or a SSA_NAME which is being left in SSA form, just queue a copy to be emitted on this @@ -597,7 +631,7 @@ elim_forward (elim_graph *g, int T) { int S; - source_location locus; + location_t locus; bitmap_set_bit (g->visited, T); FOR_EACH_ELIM_GRAPH_SUCC (g, T, S, locus, @@ -615,7 +649,7 @@ elim_unvisited_predecessor (elim_graph *g, int T) { int P; - source_location locus; + location_t locus; FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus, { @@ -631,7 +665,7 @@ elim_backward (elim_graph *g, int T) { int P; - source_location locus; + location_t locus; bitmap_set_bit (g->visited, T); FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus, @@ -653,6 +687,8 @@ tree type = TREE_TYPE (name); int unsignedp; machine_mode reg_mode = promote_ssa_mode (name, &unsignedp); + if (reg_mode == BLKmode) + return assign_temp (type, 0, 0); rtx x = gen_reg_rtx (reg_mode); if (POINTER_TYPE_P (type)) mark_reg_pointer (x, TYPE_ALIGN (TREE_TYPE (type))); @@ -666,7 +702,7 @@ elim_create (elim_graph *g, int T) { int P, S; - source_location locus; + location_t locus; if (elim_unvisited_predecessor (g, T)) { @@ -741,7 +777,7 @@ { int dest; tree src; - source_location locus; + location_t locus; src = g->const_copies.pop (); dest = g->const_dests.pop (); @@ -809,26 +845,7 @@ gphi *phi = gsi.phi (); result = gimple_phi_result (phi); if (virtual_operand_p (result)) - { - /* There should be no arguments which are not virtual, or the - results will be incorrect. */ - if (flag_checking) - for (size_t i = 0; i < gimple_phi_num_args (phi); i++) - { - tree arg = PHI_ARG_DEF (phi, i); - if (TREE_CODE (arg) == SSA_NAME - && !virtual_operand_p (arg)) - { - fprintf (stderr, "Argument of PHI is not virtual ("); - print_generic_expr (stderr, arg, TDF_SLIM); - fprintf (stderr, "), but the result is :"); - print_gimple_stmt (stderr, phi, 0, TDF_SLIM); - internal_error ("SSA corruption"); - } - } - - remove_phi_node (&gsi, true); - } + remove_phi_node (&gsi, true); else { /* Also remove real PHIs with no uses. */ @@ -1171,15 +1188,19 @@ { tree arg = gimple_phi_arg_def (phi, i); edge e = gimple_phi_arg_edge (phi, i); + /* We are only interested in copies emitted on critical + backedges. */ + if (!(e->flags & EDGE_DFS_BACK) + || !EDGE_CRITICAL_P (e)) + continue; /* If the argument is not an SSA_NAME, then we will need a - constant initialization. If the argument is an SSA_NAME with - a different underlying variable then a copy statement will be - needed. */ - if ((e->flags & EDGE_DFS_BACK) - && (TREE_CODE (arg) != SSA_NAME - || SSA_NAME_VAR (arg) != SSA_NAME_VAR (result) - || trivially_conflicts_p (bb, result, arg))) + constant initialization. If the argument is an SSA_NAME then + a copy statement may be needed. First handle the case + where we cannot insert before the argument definition. */ + if (TREE_CODE (arg) != SSA_NAME + || (gimple_code (SSA_NAME_DEF_STMT (arg)) == GIMPLE_PHI + && trivially_conflicts_p (bb, result, arg))) { tree name; gassign *stmt; @@ -1226,6 +1247,34 @@ gsi_insert_after (&gsi2, stmt, GSI_NEW_STMT); SET_PHI_ARG_DEF (phi, i, name); } + /* Insert a copy before the definition of the backedge value + and adjust all conflicting uses. */ + else if (trivially_conflicts_p (bb, result, arg)) + { + gimple *def = SSA_NAME_DEF_STMT (arg); + if (gimple_nop_p (def) + || gimple_code (def) == GIMPLE_PHI) + continue; + tree name = copy_ssa_name (result); + gimple *stmt = gimple_build_assign (name, result); + imm_use_iterator imm_iter; + gimple *use_stmt; + /* The following matches trivially_conflicts_p. */ + FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, result) + { + if (gimple_bb (use_stmt) != bb + || (gimple_code (use_stmt) != GIMPLE_PHI + && (maybe_renumber_stmts_bb (bb), true) + && gimple_uid (use_stmt) > gimple_uid (def))) + { + use_operand_p use; + FOR_EACH_IMM_USE_ON_STMT (use, imm_iter) + SET_USE (use, name); + } + } + gimple_stmt_iterator gsi = gsi_for_stmt (def); + gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); + } } }