Mercurial > hg > CbC > CbC_gcc
diff gcc/ddg.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
line wrap: on
line diff
--- a/gcc/ddg.c Sun Aug 21 07:07:55 2011 +0900 +++ b/gcc/ddg.c Fri Oct 27 22:46:09 2017 +0900 @@ -1,6 +1,5 @@ /* DDG - Data Dependence Graph implementation. - Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 2004-2017 Free Software Foundation, Inc. Contributed by Ayal Zaks and Mustafa Hagog <zaks,mustafa@il.ibm.com> This file is part of GCC. @@ -23,26 +22,13 @@ #include "config.h" #include "system.h" #include "coretypes.h" -#include "tm.h" -#include "diagnostic-core.h" +#include "backend.h" #include "rtl.h" -#include "tm_p.h" -#include "hard-reg-set.h" -#include "regs.h" -#include "function.h" -#include "flags.h" -#include "insn-config.h" +#include "df.h" #include "insn-attr.h" -#include "except.h" -#include "recog.h" #include "sched-int.h" -#include "target.h" -#include "cfglayout.h" -#include "cfgloop.h" -#include "sbitmap.h" -#include "expr.h" -#include "bitmap.h" #include "ddg.h" +#include "rtl-iter.h" #ifdef INSN_SCHEDULING @@ -65,27 +51,24 @@ static bool mem_ref_p; /* Auxiliary function for mem_read_insn_p. */ -static int -mark_mem_use (rtx *x, void *data ATTRIBUTE_UNUSED) +static void +mark_mem_use (rtx *x, void *) { - if (MEM_P (*x)) - mem_ref_p = true; - return 0; -} - -/* Auxiliary function for mem_read_insn_p. */ -static void -mark_mem_use_1 (rtx *x, void *data) -{ - for_each_rtx (x, mark_mem_use, data); + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, *x, NONCONST) + if (MEM_P (*iter)) + { + mem_ref_p = true; + break; + } } /* Returns nonzero if INSN reads from memory. */ static bool -mem_read_insn_p (rtx insn) +mem_read_insn_p (rtx_insn *insn) { mem_ref_p = false; - note_uses (&PATTERN (insn), mark_mem_use_1, NULL); + note_uses (&PATTERN (insn), mark_mem_use, NULL); return mem_ref_p; } @@ -98,7 +81,7 @@ /* Returns nonzero if INSN writes to memory. */ static bool -mem_write_insn_p (rtx insn) +mem_write_insn_p (rtx_insn *insn) { mem_ref_p = false; note_stores (PATTERN (insn), mark_mem_store, NULL); @@ -140,11 +123,50 @@ /* Returns nonzero if INSN reads to or writes from memory. */ static bool -mem_access_insn_p (rtx insn) +mem_access_insn_p (rtx_insn *insn) { return rtx_mem_access_p (PATTERN (insn)); } +/* Return true if DEF_INSN contains address being auto-inc or auto-dec + which is used in USE_INSN. Otherwise return false. The result is + being used to decide whether to remove the edge between def_insn and + use_insn when -fmodulo-sched-allow-regmoves is set. This function + doesn't need to consider the specific address register; no reg_moves + will be allowed for any life range defined by def_insn and used + by use_insn, if use_insn uses an address register auto-inc'ed by + def_insn. */ +bool +autoinc_var_is_used_p (rtx_insn *def_insn, rtx_insn *use_insn) +{ + rtx note; + + for (note = REG_NOTES (def_insn); note; note = XEXP (note, 1)) + if (REG_NOTE_KIND (note) == REG_INC + && reg_referenced_p (XEXP (note, 0), PATTERN (use_insn))) + return true; + + return false; +} + +/* Return true if one of the definitions in INSN has MODE_CC. Otherwise + return false. */ +static bool +def_has_ccmode_p (rtx_insn *insn) +{ + df_ref def; + + FOR_EACH_INSN_DEF (def, insn) + { + machine_mode mode = GET_MODE (DF_REF_REG (def)); + + if (GET_MODE_CLASS (mode) == MODE_CC) + return true; + } + + return false; +} + /* Computes the dependence parameters (latency, distance etc.), creates a ddg_edge and adds it to the given DDG. */ static void @@ -173,10 +195,16 @@ compensate for that by generating reg-moves based on the life-range analysis. The anti-deps that will be deleted are the ones which have true-deps edges in the opposite direction (in other words - the kernel has only one def of the relevant register). TODO: - support the removal of all anti-deps edges, i.e. including those + the kernel has only one def of the relevant register). + If the address that is being auto-inc or auto-dec in DEST_NODE + is used in SRC_NODE then do not remove the edge to make sure + reg-moves will not be created for this address. + TODO: support the removal of all anti-deps edges, i.e. including those whose register has multiple defs in the loop. */ - if (flag_modulo_sched_allow_regmoves && (t == ANTI_DEP && dt == REG_DEP)) + if (flag_modulo_sched_allow_regmoves + && (t == ANTI_DEP && dt == REG_DEP) + && !def_has_ccmode_p (dest_node->insn) + && !autoinc_var_is_used_p (dest_node->insn, src_node->insn)) { rtx set; @@ -250,27 +278,24 @@ int regno = DF_REF_REGNO (last_def); struct df_link *r_use; int has_use_in_bb_p = false; - rtx def_insn = DF_REF_INSN (last_def); + rtx_insn *def_insn = DF_REF_INSN (last_def); ddg_node_ptr last_def_node = get_node_of_insn (g, def_insn); ddg_node_ptr use_node; -#ifdef ENABLE_CHECKING - struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb); -#endif df_ref first_def = df_bb_regno_first_def_find (g->bb, regno); gcc_assert (last_def_node); gcc_assert (first_def); -#ifdef ENABLE_CHECKING - if (DF_REF_ID (last_def) != DF_REF_ID (first_def)) - gcc_assert (!bitmap_bit_p (&bb_info->gen, - DF_REF_ID (first_def))); -#endif + if (flag_checking && DF_REF_ID (last_def) != DF_REF_ID (first_def)) + { + struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (g->bb); + gcc_assert (!bitmap_bit_p (&bb_info->gen, DF_REF_ID (first_def))); + } /* Create inter-loop true dependences and anti dependences. */ for (r_use = DF_REF_CHAIN (last_def); r_use != NULL; r_use = r_use->next) { - rtx use_insn = DF_REF_INSN (r_use->ref); + rtx_insn *use_insn = DF_REF_INSN (r_use->ref); if (BLOCK_FOR_INSN (use_insn) != g->bb) continue; @@ -301,8 +326,16 @@ gcc_assert (first_def_node); + /* Always create the edge if the use node is a branch in + order to prevent the creation of reg-moves. + If the address that is being auto-inc or auto-dec in LAST_DEF + is used in USE_INSN then do not remove the edge to make sure + reg-moves will not be created for that address. */ if (DF_REF_ID (last_def) != DF_REF_ID (first_def) - || !flag_modulo_sched_allow_regmoves) + || !flag_modulo_sched_allow_regmoves + || JUMP_P (use_node->insn) + || autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn) + || def_has_ccmode_p (DF_REF_INSN (last_def))) create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP, REG_DEP, 1); @@ -348,41 +381,52 @@ } -static int -walk_mems_2 (rtx *x, rtx mem) +/* Return true if two specified instructions have mem expr with conflict + alias sets. */ +static bool +insns_may_alias_p (rtx_insn *insn1, rtx_insn *insn2) { - if (MEM_P (*x)) + subrtx_iterator::array_type array1; + subrtx_iterator::array_type array2; + FOR_EACH_SUBRTX (iter1, array1, PATTERN (insn1), NONCONST) { - if (may_alias_p (*x, mem)) - return 1; - - return -1; + const_rtx x1 = *iter1; + if (MEM_P (x1)) + FOR_EACH_SUBRTX (iter2, array2, PATTERN (insn2), NONCONST) + { + const_rtx x2 = *iter2; + if (MEM_P (x2) && may_alias_p (x2, x1)) + return true; + } } - return 0; + return false; } -static int -walk_mems_1 (rtx *x, rtx *pat) +/* Given two nodes, analyze their RTL insns and add intra-loop mem deps + to ddg G. */ +static void +add_intra_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to) { - if (MEM_P (*x)) - { - /* Visit all MEMs in *PAT and check indepedence. */ - if (for_each_rtx (pat, (rtx_function) walk_mems_2, *x)) - /* Indicate that dependence was determined and stop traversal. */ - return 1; + + if ((from->cuid == to->cuid) + || !insns_may_alias_p (from->insn, to->insn)) + /* Do not create edge if memory references have disjoint alias sets + or 'to' and 'from' are the same instruction. */ + return; - return -1; + if (mem_write_insn_p (from->insn)) + { + if (mem_read_insn_p (to->insn)) + create_ddg_dep_no_link (g, from, to, + DEBUG_INSN_P (to->insn) + ? ANTI_DEP : TRUE_DEP, MEM_DEP, 0); + else + create_ddg_dep_no_link (g, from, to, + DEBUG_INSN_P (to->insn) + ? ANTI_DEP : OUTPUT_DEP, MEM_DEP, 0); } - return 0; -} - -/* Return 1 if two specified instructions have mem expr with conflict alias sets*/ -static int -insns_may_alias_p (rtx insn1, rtx insn2) -{ - /* For each pair of MEMs in INSN1 and INSN2 check their independence. */ - return for_each_rtx (&PATTERN (insn1), (rtx_function) walk_mems_1, - &PATTERN (insn2)); + else if (!mem_read_insn_p (to->insn)) + create_ddg_dep_no_link (g, from, to, ANTI_DEP, MEM_DEP, 0); } /* Given two nodes, analyze their RTL insns and add inter-loop mem deps @@ -429,7 +473,7 @@ int i; /* Hold the dependency analysis state during dependency calculations. */ struct deps_desc tmp_deps; - rtx head, tail; + rtx_insn *head, *tail; /* Build the dependence information, using the sched_analyze function. */ init_deps_global (); @@ -452,7 +496,15 @@ FOR_EACH_DEP (dest_node->insn, SD_LIST_BACK, sd_it, dep) { - ddg_node_ptr src_node = get_node_of_insn (g, DEP_PRO (dep)); + rtx_insn *src_insn = DEP_PRO (dep); + ddg_node_ptr src_node; + + /* Don't add dependencies on debug insns to non-debug insns + to avoid codegen differences between -g and -g0. */ + if (DEBUG_INSN_P (src_insn) && !DEBUG_INSN_P (dest_node->insn)) + continue; + + src_node = get_node_of_insn (g, src_insn); if (!src_node) continue; @@ -472,10 +524,22 @@ if (DEBUG_INSN_P (j_node->insn)) continue; if (mem_access_insn_p (j_node->insn)) - /* Don't bother calculating inter-loop dep if an intra-loop dep - already exists. */ - if (! TEST_BIT (dest_node->successors, j)) + { + /* Don't bother calculating inter-loop dep if an intra-loop dep + already exists. */ + if (! bitmap_bit_p (dest_node->successors, j)) add_inter_loop_mem_dep (g, dest_node, j_node); + /* If -fmodulo-sched-allow-regmoves + is set certain anti-dep edges are not created. + It might be that these anti-dep edges are on the + path from one memory instruction to another such that + removing these edges could cause a violation of the + memory dependencies. Thus we add intra edges between + every two memory instructions in this case. */ + if (flag_modulo_sched_allow_regmoves + && !bitmap_bit_p (dest_node->predecessors, j)) + add_intra_loop_mem_dep (g, j_node, dest_node); + } } } } @@ -496,7 +560,7 @@ create_ddg (basic_block bb, int closing_branch_deps) { ddg_ptr g; - rtx insn, first_note; + rtx_insn *insn, *first_note; int i; int num_nodes = 0; @@ -536,7 +600,7 @@ g->nodes = (ddg_node_ptr) xcalloc (num_nodes, sizeof (struct ddg_node)); g->closing_branch = NULL; i = 0; - first_note = NULL_RTX; + first_note = NULL; for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); insn = NEXT_INSN (insn)) { @@ -561,12 +625,12 @@ g->nodes[i].cuid = i; g->nodes[i].successors = sbitmap_alloc (num_nodes); - sbitmap_zero (g->nodes[i].successors); + bitmap_clear (g->nodes[i].successors); g->nodes[i].predecessors = sbitmap_alloc (num_nodes); - sbitmap_zero (g->nodes[i].predecessors); + bitmap_clear (g->nodes[i].predecessors); g->nodes[i].first_note = (first_note ? first_note : insn); g->nodes[i++].insn = insn; - first_note = NULL_RTX; + first_note = NULL; } /* We must have found a branch in DDG. */ @@ -654,7 +718,7 @@ } /* Print the given DDG in VCG format. */ -void +DEBUG_FUNCTION void vcg_print_ddg (FILE *file, ddg_ptr g) { int src_cuid; @@ -702,7 +766,7 @@ for (i = 0; i < sccs->num_sccs; i++) { fprintf (file, "SCC number: %d\n", i); - EXECUTE_IF_SET_IN_SBITMAP (sccs->sccs[i]->nodes, 0, u, sbi) + EXECUTE_IF_SET_IN_BITMAP (sccs->sccs[i]->nodes, 0, u, sbi) { fprintf (file, "insn num %d\n", u); print_rtl_single (file, g->nodes[u].insn); @@ -739,8 +803,8 @@ /* Should have allocated the sbitmaps. */ gcc_assert (src->successors && dest->predecessors); - SET_BIT (src->successors, dest->cuid); - SET_BIT (dest->predecessors, src->cuid); + bitmap_set_bit (src->successors, dest->cuid); + bitmap_set_bit (dest->predecessors, src->cuid); e->next_in = dest->in; dest->in = e; e->next_out = src->out; @@ -791,16 +855,16 @@ scc->backarcs = NULL; scc->num_backarcs = 0; scc->nodes = sbitmap_alloc (g->num_nodes); - sbitmap_copy (scc->nodes, nodes); + bitmap_copy (scc->nodes, nodes); /* Mark the backarcs that belong to this SCC. */ - EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi) + EXECUTE_IF_SET_IN_BITMAP (nodes, 0, u, sbi) { ddg_edge_ptr e; ddg_node_ptr n = &g->nodes[u]; for (e = n->out; e; e = e->next_out) - if (TEST_BIT (nodes, e->dest->cuid)) + if (bitmap_bit_p (nodes, e->dest->cuid)) { e->aux.count = IN_SCC; if (e->distance > 0) @@ -859,7 +923,7 @@ /* Given the instruction INSN return the node that represents it. */ ddg_node_ptr -get_node_of_insn (ddg_ptr g, rtx insn) +get_node_of_insn (ddg_ptr g, rtx_insn *insn) { int i; @@ -878,14 +942,14 @@ unsigned int i = 0; sbitmap_iterator sbi; - EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi) + EXECUTE_IF_SET_IN_BITMAP (ops, 0, i, sbi) { const sbitmap node_succ = NODE_SUCCESSORS (&g->nodes[i]); - sbitmap_a_or_b (succ, succ, node_succ); + bitmap_ior (succ, succ, node_succ); }; /* We want those that are not in ops. */ - sbitmap_difference (succ, succ, ops); + bitmap_and_compl (succ, succ, ops); } /* Given a set OPS of nodes in the DDG, find the set of their predecessors @@ -897,14 +961,14 @@ unsigned int i = 0; sbitmap_iterator sbi; - EXECUTE_IF_SET_IN_SBITMAP (ops, 0, i, sbi) + EXECUTE_IF_SET_IN_BITMAP (ops, 0, i, sbi) { const sbitmap node_preds = NODE_PREDECESSORS (&g->nodes[i]); - sbitmap_a_or_b (preds, preds, node_preds); + bitmap_ior (preds, preds, node_preds); }; /* We want those that are not in ops. */ - sbitmap_difference (preds, preds, ops); + bitmap_and_compl (preds, preds, ops); } @@ -927,27 +991,24 @@ (int (*) (const void *, const void *)) compare_sccs); } -#ifdef ENABLE_CHECKING /* Check that every node in SCCS belongs to exactly one strongly connected component and that no element of SCCS is empty. */ static void check_sccs (ddg_all_sccs_ptr sccs, int num_nodes) { int i = 0; - sbitmap tmp = sbitmap_alloc (num_nodes); + auto_sbitmap tmp (num_nodes); - sbitmap_zero (tmp); + bitmap_clear (tmp); for (i = 0; i < sccs->num_sccs; i++) { - gcc_assert (!sbitmap_empty_p (sccs->sccs[i]->nodes)); + gcc_assert (!bitmap_empty_p (sccs->sccs[i]->nodes)); /* Verify that every node in sccs is in exactly one strongly connected component. */ - gcc_assert (!sbitmap_any_common_bits (tmp, sccs->sccs[i]->nodes)); - sbitmap_a_or_b (tmp, tmp, sccs->sccs[i]->nodes); + gcc_assert (!bitmap_intersect_p (tmp, sccs->sccs[i]->nodes)); + bitmap_ior (tmp, tmp, sccs->sccs[i]->nodes); } - sbitmap_free (tmp); } -#endif /* Perform the Strongly Connected Components decomposing algorithm on the DDG and return DDG_ALL_SCCS structure that contains them. */ @@ -956,9 +1017,9 @@ { int i; int num_nodes = g->num_nodes; - sbitmap from = sbitmap_alloc (num_nodes); - sbitmap to = sbitmap_alloc (num_nodes); - sbitmap scc_nodes = sbitmap_alloc (num_nodes); + auto_sbitmap from (num_nodes); + auto_sbitmap to (num_nodes); + auto_sbitmap scc_nodes (num_nodes); ddg_all_sccs_ptr sccs = (ddg_all_sccs_ptr) xmalloc (sizeof (struct ddg_all_sccs)); @@ -977,11 +1038,11 @@ if (backarc->aux.count == IN_SCC) continue; - sbitmap_zero (scc_nodes); - sbitmap_zero (from); - sbitmap_zero (to); - SET_BIT (from, dest->cuid); - SET_BIT (to, src->cuid); + bitmap_clear (scc_nodes); + bitmap_clear (from); + bitmap_clear (to); + bitmap_set_bit (from, dest->cuid); + bitmap_set_bit (to, src->cuid); if (find_nodes_on_paths (scc_nodes, g, from, to)) { @@ -990,12 +1051,10 @@ } } order_sccs (sccs); - sbitmap_free (from); - sbitmap_free (to); - sbitmap_free (scc_nodes); -#ifdef ENABLE_CHECKING - check_sccs (sccs, num_nodes); -#endif + + if (flag_checking) + check_sccs (sccs, num_nodes); + return sccs; } @@ -1011,6 +1070,7 @@ for (i = 0; i < all_sccs->num_sccs; i++) free_scc (all_sccs->sccs[i]); + free (all_sccs->sccs); free (all_sccs); } @@ -1021,27 +1081,26 @@ int find_nodes_on_paths (sbitmap result, ddg_ptr g, sbitmap from, sbitmap to) { - int answer; int change; unsigned int u = 0; int num_nodes = g->num_nodes; sbitmap_iterator sbi; - sbitmap workset = sbitmap_alloc (num_nodes); - sbitmap reachable_from = sbitmap_alloc (num_nodes); - sbitmap reach_to = sbitmap_alloc (num_nodes); - sbitmap tmp = sbitmap_alloc (num_nodes); + auto_sbitmap workset (num_nodes); + auto_sbitmap reachable_from (num_nodes); + auto_sbitmap reach_to (num_nodes); + auto_sbitmap tmp (num_nodes); - sbitmap_copy (reachable_from, from); - sbitmap_copy (tmp, from); + bitmap_copy (reachable_from, from); + bitmap_copy (tmp, from); change = 1; while (change) { change = 0; - sbitmap_copy (workset, tmp); - sbitmap_zero (tmp); - EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi) + bitmap_copy (workset, tmp); + bitmap_clear (tmp); + EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi) { ddg_edge_ptr e; ddg_node_ptr u_node = &g->nodes[u]; @@ -1051,26 +1110,26 @@ ddg_node_ptr v_node = e->dest; int v = v_node->cuid; - if (!TEST_BIT (reachable_from, v)) + if (!bitmap_bit_p (reachable_from, v)) { - SET_BIT (reachable_from, v); - SET_BIT (tmp, v); + bitmap_set_bit (reachable_from, v); + bitmap_set_bit (tmp, v); change = 1; } } } } - sbitmap_copy (reach_to, to); - sbitmap_copy (tmp, to); + bitmap_copy (reach_to, to); + bitmap_copy (tmp, to); change = 1; while (change) { change = 0; - sbitmap_copy (workset, tmp); - sbitmap_zero (tmp); - EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi) + bitmap_copy (workset, tmp); + bitmap_clear (tmp); + EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi) { ddg_edge_ptr e; ddg_node_ptr u_node = &g->nodes[u]; @@ -1080,22 +1139,17 @@ ddg_node_ptr v_node = e->src; int v = v_node->cuid; - if (!TEST_BIT (reach_to, v)) + if (!bitmap_bit_p (reach_to, v)) { - SET_BIT (reach_to, v); - SET_BIT (tmp, v); + bitmap_set_bit (reach_to, v); + bitmap_set_bit (tmp, v); change = 1; } } } } - answer = sbitmap_a_and_b_cg (result, reachable_from, reach_to); - sbitmap_free (workset); - sbitmap_free (reachable_from); - sbitmap_free (reach_to); - sbitmap_free (tmp); - return answer; + return bitmap_and (result, reachable_from, reach_to); } @@ -1114,12 +1168,12 @@ ddg_node_ptr v_node = e->dest; int v = v_node->cuid; - if (TEST_BIT (nodes, v) + if (bitmap_bit_p (nodes, v) && (e->distance == 0) && (v_node->aux.count < u_node->aux.count + e->latency)) { v_node->aux.count = u_node->aux.count + e->latency; - SET_BIT (tmp, v); + bitmap_set_bit (tmp, v); result = 1; } } @@ -1135,10 +1189,9 @@ int i; unsigned int u = 0; int change = 1; - int result; int num_nodes = g->num_nodes; - sbitmap workset = sbitmap_alloc (num_nodes); - sbitmap tmp = sbitmap_alloc (num_nodes); + auto_sbitmap workset (num_nodes); + auto_sbitmap tmp (num_nodes); /* Data will hold the distance of the longest path found so far from @@ -1147,27 +1200,24 @@ g->nodes[i].aux.count = -1; g->nodes[src].aux.count = 0; - sbitmap_zero (tmp); - SET_BIT (tmp, src); + bitmap_clear (tmp); + bitmap_set_bit (tmp, src); while (change) { sbitmap_iterator sbi; change = 0; - sbitmap_copy (workset, tmp); - sbitmap_zero (tmp); - EXECUTE_IF_SET_IN_SBITMAP (workset, 0, u, sbi) + bitmap_copy (workset, tmp); + bitmap_clear (tmp); + EXECUTE_IF_SET_IN_BITMAP (workset, 0, u, sbi) { ddg_node_ptr u_node = &g->nodes[u]; change |= update_dist_to_successors (u_node, nodes, tmp); } } - result = g->nodes[dest].aux.count; - sbitmap_free (workset); - sbitmap_free (tmp); - return result; + return g->nodes[dest].aux.count; } #endif /* INSN_SCHEDULING */