From 43c8a0439187ce4a73c05dbb156cc820c1118bc5 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 7 Nov 2011 00:22:18 +0000 Subject: gcse.c: Adjust outdated comments throughout. * gcse.c: Adjust outdated comments throughout. (struct mem_conflict_info): New structure. (mems_conflict_for_gcse_p): Use it to communicate with caller. (load_killed_in_block_p): Pass it to note_stores. (hash_expr): Remove superfluous line break. (hash_scan_set): Rename PAT parameter into SET. (hash_scan_insn): Reorder cases. (canon_list_insert): Fix long line. (edge_list): Delete. (prune_expressions): Rename E local variable into EXPR. (compute_pre_data): Return struct edge_list * object. (pre_expr_reaches_here_p_work): Fix formatting. (process_insert_insn): Move around comment. (pre_edge_insert): Fix long line. (pre_insert_copies): Likewise. (gcse_emit_move_after): Swap SRC and DEST parameters. (pre_delete): Adjust call to gcse_emit_move_after. (pre_gcse): Take struct edge_list * parameter. Fix long line. (one_pre_gcse_pass): Use flag_gcse_lm condition for all routines. Use a local list of edges. (hoist_code): Fix long line. Adjust call to gcse_emit_move_after. (pre_ldst_expr_hash): Fix long line. (free_ldst_mems): Rename into... (free_ld_motion_mems): ...this. (first_ls_expr): Delete. (next_ls_expr): Likewise. (print_ldst_list): Do not use above two functions. (simple_mem): Adjust interface. (compute_ld_motion_mems): Fix formatting. (update_ld_motion_stores): Reuse local variable. From-SVN: r181054 --- gcc/ChangeLog | 33 ++++++++ gcc/gcse.c | 261 +++++++++++++++++++++++++--------------------------------- 2 files changed, 146 insertions(+), 148 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c40541f..9356d25 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,36 @@ +2011-11-06 Eric Botcazou + + * gcse.c: Adjust outdated comments throughout. + (struct mem_conflict_info): New structure. + (mems_conflict_for_gcse_p): Use it to communicate with caller. + (load_killed_in_block_p): Pass it to note_stores. + (hash_expr): Remove superfluous line break. + (hash_scan_set): Rename PAT parameter into SET. + (hash_scan_insn): Reorder cases. + (canon_list_insert): Fix long line. + (edge_list): Delete. + (prune_expressions): Rename E local variable into EXPR. + (compute_pre_data): Return struct edge_list * object. + (pre_expr_reaches_here_p_work): Fix formatting. + (process_insert_insn): Move around comment. + (pre_edge_insert): Fix long line. + (pre_insert_copies): Likewise. + (gcse_emit_move_after): Swap SRC and DEST parameters. + (pre_delete): Adjust call to gcse_emit_move_after. + (pre_gcse): Take struct edge_list * parameter. Fix long line. + (one_pre_gcse_pass): Use flag_gcse_lm condition for all routines. + Use a local list of edges. + (hoist_code): Fix long line. Adjust call to gcse_emit_move_after. + (pre_ldst_expr_hash): Fix long line. + (free_ldst_mems): Rename into... + (free_ld_motion_mems): ...this. + (first_ls_expr): Delete. + (next_ls_expr): Likewise. + (print_ldst_list): Do not use above two functions. + (simple_mem): Adjust interface. + (compute_ld_motion_mems): Fix formatting. + (update_ld_motion_stores): Reuse local variable. + 2011-11-06 Joseph Myers * c-decl.c (shadow_tag_warned, grokdeclarator): Handle _Alignas diff --git a/gcc/gcse.c b/gcc/gcse.c index 8adbc38..4806753 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -23,10 +23,6 @@ along with GCC; see the file COPYING3. If not see - do rough calc of how many regs are needed in each block, and a rough calc of how many regs are available in each class and use that to throttle back the code in cases where RTX_COST is minimal. - - a store to the same address as a load does not kill the load if the - source of the store is also the destination of the load. Handling this - allows more load motion, particularly out of loops. - */ /* References searched while implementing this. @@ -267,7 +263,7 @@ struct reg_use {rtx reg_rtx; }; struct expr { - /* The expression (SET_SRC for expressions, PATTERN for assignments). */ + /* The expression. */ rtx expr; /* Index in the available expression bitmaps. */ int bitmap_index; @@ -346,14 +342,12 @@ static struct hash_table_d expr_hash_table; /* This is a list of expressions which are MEMs and will be used by load or store motion. - Load motion tracks MEMs which aren't killed by - anything except itself. (i.e., loads and stores to a single location). + Load motion tracks MEMs which aren't killed by anything except itself, + i.e. loads and stores to a single location. We can then allow movement of these MEM refs with a little special allowance. (all stores copy the same value to the reaching reg used for the loads). This means all values used to store into memory must have - no side effects so we can re-issue the setter value. - Store Motion uses this structure as an expression table to track stores - which look interesting, and might be moveable towards the exit block. */ + no side effects so we can re-issue the setter value. */ struct ls_expr { @@ -454,14 +448,14 @@ static int load_killed_in_block_p (const_basic_block, int, const_rtx, int); static void canon_list_insert (rtx, const_rtx, void *); static void alloc_pre_mem (int, int); static void free_pre_mem (void); -static void compute_pre_data (void); +static struct edge_list *compute_pre_data (void); static int pre_expr_reaches_here_p (basic_block, struct expr *, basic_block); static void insert_insn_end_basic_block (struct expr *, basic_block); static void pre_insert_copy_insn (struct expr *, rtx); static void pre_insert_copies (void); static int pre_delete (void); -static int pre_gcse (void); +static int pre_gcse (struct edge_list *); static int one_pre_gcse_pass (void); static void add_label_notes (rtx, rtx); static void alloc_code_hoist_mem (int, int); @@ -478,11 +472,9 @@ static int pre_expr_reaches_here_p_work (basic_block, struct expr *, basic_block, char *); static struct ls_expr * ldst_entry (rtx); static void free_ldst_entry (struct ls_expr *); -static void free_ldst_mems (void); +static void free_ld_motion_mems (void); static void print_ldst_list (FILE *); static struct ls_expr * find_rtx_in_ldst (rtx); -static inline struct ls_expr * first_ls_expr (void); -static inline struct ls_expr * next_ls_expr (struct ls_expr *); static int simple_mem (const_rtx); static void invalidate_any_buried_refs (rtx); static void compute_ld_motion_mems (void); @@ -555,7 +547,6 @@ can_copy_p (enum machine_mode mode) return can_copy[mode] != 0; } - /* Cover function to xmalloc to record bytes allocated. */ @@ -714,7 +705,6 @@ struct reg_avail_info static struct reg_avail_info *reg_avail_info; static basic_block current_bb; - /* See whether X, the source of a set, is something we want to consider for GCSE. */ @@ -935,25 +925,29 @@ oprs_unchanged_p (const_rtx x, const_rtx insn, int avail_p) return 1; } -/* Used for communication between mems_conflict_for_gcse_p and - load_killed_in_block_p. Nonzero if mems_conflict_for_gcse_p finds a - conflict between two memory references. */ -static int gcse_mems_conflict_p; +/* Info passed from load_killed_in_block_p to mems_conflict_for_gcse_p. */ -/* Used for communication between mems_conflict_for_gcse_p and - load_killed_in_block_p. A memory reference for a load instruction, - mems_conflict_for_gcse_p will see if a memory store conflicts with - this memory load. */ -static const_rtx gcse_mem_operand; +struct mem_conflict_info +{ + /* A memory reference for a load instruction, mems_conflict_for_gcse_p will + see if a memory store conflicts with this memory load. */ + const_rtx mem; -/* DEST is the output of an instruction. If it is a memory reference, and - possibly conflicts with the load found in gcse_mem_operand, then set - gcse_mems_conflict_p to a nonzero value. */ + /* True if mems_conflict_for_gcse_p finds a conflict between two memory + references. */ + bool conflict; +}; + +/* DEST is the output of an instruction. If it is a memory reference and + possibly conflicts with the load found in DATA, then communicate this + information back through DATA. */ static void mems_conflict_for_gcse_p (rtx dest, const_rtx setter ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) + void *data) { + struct mem_conflict_info *mci = (struct mem_conflict_info *) data; + while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == STRICT_LOW_PART) @@ -967,17 +961,15 @@ mems_conflict_for_gcse_p (rtx dest, const_rtx setter ATTRIBUTE_UNUSED, /* If we are setting a MEM in our list of specially recognized MEMs, don't mark as killed this time. */ - - if (expr_equiv_p (dest, gcse_mem_operand) && pre_ldst_mems != NULL) + if (pre_ldst_mems != NULL && expr_equiv_p (dest, mci->mem)) { if (!find_rtx_in_ldst (dest)) - gcse_mems_conflict_p = 1; + mci->conflict = true; return; } - if (true_dependence (dest, GET_MODE (dest), gcse_mem_operand, - rtx_addr_varies_p)) - gcse_mems_conflict_p = 1; + if (true_dependence (dest, GET_MODE (dest), mci->mem, rtx_addr_varies_p)) + mci->conflict = true; } /* Return nonzero if the expression in X (a memory reference) is killed @@ -989,7 +981,8 @@ mems_conflict_for_gcse_p (rtx dest, const_rtx setter ATTRIBUTE_UNUSED, AVAIL_P to 0. */ static int -load_killed_in_block_p (const_basic_block bb, int uid_limit, const_rtx x, int avail_p) +load_killed_in_block_p (const_basic_block bb, int uid_limit, const_rtx x, + int avail_p) { VEC (rtx,heap) *list = modify_mem_list[bb->index]; rtx setter; @@ -1001,6 +994,8 @@ load_killed_in_block_p (const_basic_block bb, int uid_limit, const_rtx x, int av FOR_EACH_VEC_ELT_REVERSE (rtx, list, ix, setter) { + struct mem_conflict_info mci; + /* Ignore entries in the list that do not apply. */ if ((avail_p && DF_INSN_LUID (setter) < uid_limit) @@ -1015,14 +1010,11 @@ load_killed_in_block_p (const_basic_block bb, int uid_limit, const_rtx x, int av return 1; /* SETTER must be an INSN of some kind that sets memory. Call - note_stores to examine each hunk of memory that is modified. - - The note_stores interface is pretty limited, so we have to - communicate via global variables. Yuk. */ - gcse_mem_operand = x; - gcse_mems_conflict_p = 0; - note_stores (PATTERN (setter), mems_conflict_for_gcse_p, NULL); - if (gcse_mems_conflict_p) + note_stores to examine each hunk of memory that is modified. */ + mci.mem = x; + mci.conflict = false; + note_stores (PATTERN (setter), mems_conflict_for_gcse_p, &mci); + if (mci.conflict) return 1; } return 0; @@ -1061,8 +1053,7 @@ hash_expr (const_rtx x, enum machine_mode mode, int *do_not_record_p, *do_not_record_p = 0; - hash = hash_rtx (x, mode, do_not_record_p, - NULL, /*have_reg_qty=*/false); + hash = hash_rtx (x, mode, do_not_record_p, NULL, /*have_reg_qty=*/false); return hash % hash_table_size; } @@ -1190,13 +1181,13 @@ insert_expr_in_table (rtx x, enum machine_mode mode, rtx insn, int antic_p, } } -/* Scan pattern PAT of INSN and add an entry to the hash TABLE. */ +/* Scan SET present in INSN and add an entry to the hash TABLE. */ static void -hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table) +hash_scan_set (rtx set, rtx insn, struct hash_table_d *table) { - rtx src = SET_SRC (pat); - rtx dest = SET_DEST (pat); + rtx src = SET_SRC (set); + rtx dest = SET_DEST (set); rtx note; if (GET_CODE (src) == CALL) @@ -1227,7 +1218,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table) && REG_NOTE_KIND (note) == REG_EQUAL && !REG_P (src) && want_to_gcse_p (XEXP (note, 0), NULL)) - src = XEXP (note, 0), pat = gen_rtx_SET (VOIDmode, dest, src); + src = XEXP (note, 0), set = gen_rtx_SET (VOIDmode, dest, src); /* Only record sets of pseudo-regs in the hash table. */ if (regno >= FIRST_PSEUDO_REGISTER @@ -1242,7 +1233,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table) /* Is SET_SRC something we want to gcse? */ && want_to_gcse_p (src, &max_distance) /* Don't CSE a nop. */ - && ! set_noop_p (pat) + && ! set_noop_p (set) /* Don't GCSE if it has attached REG_EQUIV note. At this point this only function parameters should have REG_EQUIV notes and if the argument slot is used somewhere @@ -1286,7 +1277,7 @@ hash_scan_set (rtx pat, rtx insn, struct hash_table_d *table) /* Is SET_DEST something we want to gcse? */ && want_to_gcse_p (dest, &max_distance) /* Don't CSE a nop. */ - && ! set_noop_p (pat) + && ! set_noop_p (set) /* Don't GCSE if it has attached REG_EQUIV note. At this point this only function parameters should have REG_EQUIV notes and if the argument slot is used somewhere @@ -1325,16 +1316,7 @@ hash_scan_call (rtx x ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED, /* Currently nothing to do. */ } -/* Process INSN and add hash table entries as appropriate. - - Only available expressions that set a single pseudo-reg are recorded. - - Single sets in a PARALLEL could be handled, but it's an extra complication - that isn't dealt with right now. The trick is handling the CLOBBERs that - are also in the PARALLEL. Later. - - If SET_P is nonzero, this is for the assignment hash table, - otherwise it is for the expression hash table. */ +/* Process INSN and add hash table entries as appropriate. */ static void hash_scan_insn (rtx insn, struct hash_table_d *table) @@ -1347,6 +1329,13 @@ hash_scan_insn (rtx insn, struct hash_table_d *table) if (GET_CODE (pat) == SET) hash_scan_set (pat, insn, table); + + else if (GET_CODE (pat) == CLOBBER) + hash_scan_clobber (pat, insn, table); + + else if (GET_CODE (pat) == CALL) + hash_scan_call (pat, insn, table); + else if (GET_CODE (pat) == PARALLEL) for (i = 0; i < XVECLEN (pat, 0); i++) { @@ -1359,13 +1348,10 @@ hash_scan_insn (rtx insn, struct hash_table_d *table) else if (GET_CODE (x) == CALL) hash_scan_call (x, insn, table); } - - else if (GET_CODE (pat) == CLOBBER) - hash_scan_clobber (pat, insn, table); - else if (GET_CODE (pat) == CALL) - hash_scan_call (pat, insn, table); } +/* Dump the hash table TABLE to file FILE under the name NAME. */ + static void dump_hash_table (FILE *file, const char *name, struct hash_table_d *table) { @@ -1429,13 +1415,12 @@ record_last_reg_set_info (rtx insn, int regno) } } - /* Record all of the canonicalized MEMs of record_last_mem_set_info's insn. Note we store a pair of elements in the list, so they have to be taken off pairwise. */ static void -canon_list_insert (rtx dest ATTRIBUTE_UNUSED, const_rtx unused1 ATTRIBUTE_UNUSED, +canon_list_insert (rtx dest ATTRIBUTE_UNUSED, const_rtx x ATTRIBUTE_UNUSED, void * v_insn) { rtx dest_addr, insn; @@ -1634,7 +1619,6 @@ free_modify_mem_tables (void) modify_mem_list = 0; canon_modify_mem_list = 0; } - /* For each block, compute whether X is transparent. X is either an expression or an assignment [though we don't care which, for this context @@ -1745,11 +1729,11 @@ compute_transp (const_rtx x, int indx, sbitmap *bmap) compute_transp (XVECEXP (x, i, j), indx, bmap); } } - /* Compute PRE+LCM working variables. */ /* Local properties of expressions. */ + /* Nonzero for expressions that are transparent in the block. */ static sbitmap *transp; @@ -1772,9 +1756,6 @@ static sbitmap *pre_insert_map; /* Nonzero for expressions which should be deleted in a specific block. */ static sbitmap *pre_delete_map; -/* Contains the edge_list returned by pre_edge_lcm. */ -static struct edge_list *edge_list; - /* Allocate vars used for PRE analysis. */ static void @@ -1826,6 +1807,7 @@ static void prune_expressions (bool pre_p) { sbitmap prune_exprs; + struct expr *expr; unsigned int ui; basic_block bb; @@ -1833,17 +1815,16 @@ prune_expressions (bool pre_p) sbitmap_zero (prune_exprs); for (ui = 0; ui < expr_hash_table.size; ui++) { - struct expr *e; - for (e = expr_hash_table.table[ui]; e != NULL; e = e->next_same_hash) + for (expr = expr_hash_table.table[ui]; expr; expr = expr->next_same_hash) { /* Note potentially trapping expressions. */ - if (may_trap_p (e->expr)) + if (may_trap_p (expr->expr)) { - SET_BIT (prune_exprs, e->bitmap_index); + SET_BIT (prune_exprs, expr->bitmap_index); continue; } - if (!pre_p && MEM_P (e->expr)) + if (!pre_p && MEM_P (expr->expr)) /* Note memory references that can be clobbered by a call. We do not split abnormal edges in hoisting, so would a memory reference get hoisted along an abnormal edge, @@ -1851,13 +1832,13 @@ prune_expressions (bool pre_p) constant memory references can be hoisted along abnormal edges. */ { - if (GET_CODE (XEXP (e->expr, 0)) == SYMBOL_REF - && CONSTANT_POOL_ADDRESS_P (XEXP (e->expr, 0))) + if (GET_CODE (XEXP (expr->expr, 0)) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (XEXP (expr->expr, 0))) continue; - if (MEM_READONLY_P (e->expr) - && !MEM_VOLATILE_P (e->expr) - && MEM_NOTRAP_P (e->expr)) + if (MEM_READONLY_P (expr->expr) + && !MEM_VOLATILE_P (expr->expr) + && MEM_NOTRAP_P (expr->expr)) /* Constant memory reference, e.g., a PIC address. */ continue; @@ -1865,7 +1846,7 @@ prune_expressions (bool pre_p) analysis to determine if this mem is actually killed by this call. */ - SET_BIT (prune_exprs, e->bitmap_index); + SET_BIT (prune_exprs, expr->bitmap_index); } } } @@ -1976,9 +1957,10 @@ prune_insertions_deletions (int n_elems) /* Top level routine to do the dataflow analysis needed by PRE. */ -static void +static struct edge_list * compute_pre_data (void) { + struct edge_list *edge_list; basic_block bb; compute_local_properties (transp, comp, antloc, &expr_hash_table); @@ -2004,6 +1986,8 @@ compute_pre_data (void) ae_kill = NULL; prune_insertions_deletions (expr_hash_table.n_elems); + + return edge_list; } /* PRE utilities */ @@ -2022,7 +2006,8 @@ compute_pre_data (void) the closest such expression. */ static int -pre_expr_reaches_here_p_work (basic_block occr_bb, struct expr *expr, basic_block bb, char *visited) +pre_expr_reaches_here_p_work (basic_block occr_bb, struct expr *expr, + basic_block bb, char *visited) { edge pred; edge_iterator ei; @@ -2079,15 +2064,13 @@ pre_expr_reaches_here_p (basic_block occr_bb, struct expr *expr, basic_block bb) return rval; } - -/* Given an expr, generate RTL which we can insert at the end of a BB, - or on an edge. Set the block number of any insns generated to - the value of BB. */ +/* Generate RTL to copy an EXPR to its `reaching_reg' and return it. */ static rtx process_insert_insn (struct expr *expr) { rtx reg = expr->reaching_reg; + /* Copy the expression to make sure we don't have any sharing issues. */ rtx exp = copy_rtx (expr->expr); rtx pat; @@ -2099,8 +2082,7 @@ process_insert_insn (struct expr *expr) emit_move_insn (reg, exp); /* Otherwise, make a new insn to compute this expression and make sure the - insn will be recognized (this also adds any needed CLOBBERs). Copy the - expression to make sure we don't have any sharing issues. */ + insn will be recognized (this also adds any needed CLOBBERs). */ else { rtx insn = emit_insn (gen_rtx_SET (VOIDmode, reg, exp)); @@ -2109,7 +2091,6 @@ process_insert_insn (struct expr *expr) gcc_unreachable (); } - pat = get_insns (); end_sequence (); @@ -2254,7 +2235,9 @@ pre_edge_insert (struct edge_list *edge_list, struct expr **index_map) { SBITMAP_ELT_TYPE insert = pre_insert_map[e]->elms[i]; - for (j = indx; insert && j < (int) expr_hash_table.n_elems; j++, insert >>= 1) + for (j = indx; + insert && j < (int) expr_hash_table.n_elems; + j++, insert >>= 1) if ((insert & 1) != 0 && index_map[j]->reaching_reg != NULL_RTX) { struct expr *expr = index_map[j]; @@ -2430,7 +2413,7 @@ pre_insert_copies (void) Need to do some profiling. */ for (i = 0; i < expr_hash_table.size; i++) - for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash) + for (expr = expr_hash_table.table[i]; expr; expr = expr->next_same_hash) { /* If the basic block isn't reachable, PPOUT will be TRUE. However, we don't want to insert a copy here because the expression may not @@ -2481,8 +2464,9 @@ pre_insert_copies (void) /* Emit move from SRC to DEST noting the equivalence with expression computed in INSN. */ + static rtx -gcse_emit_move_after (rtx src, rtx dest, rtx insn) +gcse_emit_move_after (rtx dest, rtx src, rtx insn) { rtx new_rtx; rtx set = single_set (insn), set2; @@ -2513,7 +2497,7 @@ gcse_emit_move_after (rtx src, rtx dest, rtx insn) the expression into the result of the SET. It is left to later passes (cprop, cse2, flow, combine, regmove) to propagate the copy or eliminate it. - Returns nonzero if a change is made. */ + Return nonzero if a change is made. */ static int pre_delete (void) @@ -2525,15 +2509,11 @@ pre_delete (void) changed = 0; for (i = 0; i < expr_hash_table.size; i++) - for (expr = expr_hash_table.table[i]; - expr != NULL; - expr = expr->next_same_hash) + for (expr = expr_hash_table.table[i]; expr; expr = expr->next_same_hash) { int indx = expr->bitmap_index; - /* We only need to search antic_occr since we require - ANTLOC != 0. */ - + /* We only need to search antic_occr since we require ANTLOC != 0. */ for (occr = expr->antic_occr; occr != NULL; occr = occr->next) { rtx insn = occr->insn; @@ -2551,7 +2531,7 @@ pre_delete (void) if (expr->reaching_reg == NULL) expr->reaching_reg = gen_reg_rtx_and_attrs (SET_DEST (set)); - gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn); + gcse_emit_move_after (SET_DEST (set), expr->reaching_reg, insn); delete_insn (insn); occr->deleted_p = 1; changed = 1; @@ -2593,7 +2573,7 @@ pre_delete (void) redundancies. */ static int -pre_gcse (void) +pre_gcse (struct edge_list *edge_list) { unsigned int i; int did_insert, changed; @@ -2605,7 +2585,7 @@ pre_gcse (void) index_map = XCNEWVEC (struct expr *, expr_hash_table.n_elems); for (i = 0; i < expr_hash_table.size; i++) - for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash) + for (expr = expr_hash_table.table[i]; expr; expr = expr->next_same_hash) index_map[expr->bitmap_index] = expr; /* Delete the redundant insns first so that @@ -2659,20 +2639,23 @@ one_pre_gcse_pass (void) compute_ld_motion_mems (); compute_hash_table (&expr_hash_table); - trim_ld_motion_mems (); + if (flag_gcse_lm) + trim_ld_motion_mems (); if (dump_file) dump_hash_table (dump_file, "Expression", &expr_hash_table); if (expr_hash_table.n_elems > 0) { + struct edge_list *edge_list; alloc_pre_mem (last_basic_block, expr_hash_table.n_elems); - compute_pre_data (); - changed |= pre_gcse (); + edge_list = compute_pre_data (); + changed |= pre_gcse (edge_list); free_edge_list (edge_list); free_pre_mem (); } - free_ldst_mems (); + if (flag_gcse_lm) + free_ld_motion_mems (); remove_fake_exit_edges (); free_hash_table (&expr_hash_table); @@ -2924,6 +2907,7 @@ hoist_expr_reaches_here_p (basic_block expr_bb, int expr_index, basic_block bb, } /* Find occurence in BB. */ + static struct occr * find_occr_in_bb (struct occr *occr, basic_block bb) { @@ -2955,7 +2939,7 @@ hoist_code (void) index_map = XCNEWVEC (struct expr *, expr_hash_table.n_elems); for (i = 0; i < expr_hash_table.size; i++) - for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash) + for (expr = expr_hash_table.table[i]; expr; expr = expr->next_same_hash) index_map[expr->bitmap_index] = expr; /* Calculate sizes of basic blocks and note how far @@ -3145,7 +3129,7 @@ hoist_code (void) expr->reaching_reg = gen_reg_rtx_and_attrs (SET_DEST (set)); - gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), + gcse_emit_move_after (SET_DEST (set), expr->reaching_reg, insn); delete_insn (insn); occr->deleted_p = 1; @@ -3233,9 +3217,9 @@ one_code_hoisting_pass (void) return changed; } -/* Here we provide the things required to do store motion towards - the exit. In order for this to be effective, gcse also needed to - be taught how to move a load when it is kill only by a store to itself. +/* Here we provide the things required to do store motion towards the exit. + In order for this to be effective, gcse also needed to be taught how to + move a load when it is killed only by a store to itself. int i; float a[10]; @@ -3251,7 +3235,7 @@ one_code_hoisting_pass (void) of the loop. The 'Load Motion' referred to and implemented in this file is - an enhancement to gcse which when using edge based lcm, recognizes + an enhancement to gcse which when using edge based LCM, recognizes this situation and allows gcse to move the load out of the loop. Once gcse has hoisted the load, store motion can then push this @@ -3263,7 +3247,8 @@ pre_ldst_expr_hash (const void *p) { int do_not_record_p = 0; const struct ls_expr *const x = (const struct ls_expr *) p; - return hash_rtx (x->pattern, GET_MODE (x->pattern), &do_not_record_p, NULL, false); + return + hash_rtx (x->pattern, GET_MODE (x->pattern), &do_not_record_p, NULL, false); } static int @@ -3326,7 +3311,7 @@ free_ldst_entry (struct ls_expr * ptr) /* Free up all memory associated with the ldst list. */ static void -free_ldst_mems (void) +free_ld_motion_mems (void) { if (pre_ldst_table) htab_delete (pre_ldst_table); @@ -3353,7 +3338,7 @@ print_ldst_list (FILE * file) fprintf (file, "LDST list: \n"); - for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr)) + for (ptr = pre_ldst_mems; ptr != NULL; ptr = ptr->next) { fprintf (file, " Pattern (%3d): ", ptr->index); @@ -3394,35 +3379,16 @@ find_rtx_in_ldst (rtx x) return NULL; return (struct ls_expr *) *slot; } - -/* Return first item in the list. */ - -static inline struct ls_expr * -first_ls_expr (void) -{ - return pre_ldst_mems; -} - -/* Return the next item in the list after the specified one. */ - -static inline struct ls_expr * -next_ls_expr (struct ls_expr * ptr) -{ - return ptr->next; -} /* Load Motion for loads which only kill themselves. */ -/* Return true if x is a simple MEM operation, with no registers or - side effects. These are the types of loads we consider for the - ld_motion list, otherwise we let the usual aliasing take care of it. */ +/* Return true if x, a MEM, is a simple access with no side effects. + These are the types of loads we consider for the ld_motion list, + otherwise we let the usual aliasing take care of it. */ static int simple_mem (const_rtx x) { - if (! MEM_P (x)) - return 0; - if (MEM_VOLATILE_P (x)) return 0; @@ -3499,8 +3465,8 @@ compute_ld_motion_mems (void) rtx insn; pre_ldst_mems = NULL; - pre_ldst_table = htab_create (13, pre_ldst_expr_hash, - pre_ldst_expr_eq, NULL); + pre_ldst_table + = htab_create (13, pre_ldst_expr_hash, pre_ldst_expr_eq, NULL); FOR_EACH_BB (bb) { @@ -3641,7 +3607,7 @@ update_ld_motion_stores (struct expr * expr) if (dump_file) { fprintf (dump_file, "PRE: store updated with reaching reg "); - print_rtl (dump_file, expr->reaching_reg); + print_rtl (dump_file, reg); fprintf (dump_file, ":\n "); print_inline_rtx (dump_file, insn, 8); fprintf (dump_file, "\n"); @@ -3698,7 +3664,6 @@ is_too_expensive (const char *pass) return false; } - /* All the passes implemented in this file. Each pass has its own gate and execute function, and at the end of the file a -- cgit v1.1