Mercurial > hg > CbC > CbC_gcc
diff gcc/postreload-gcse.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/postreload-gcse.c Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/postreload-gcse.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ /* Post reload partially redundant load elimination - Copyright (C) 2004-2018 Free Software Foundation, Inc. + Copyright (C) 2004-2020 Free Software Foundation, Inc. This file is part of GCC. @@ -35,10 +35,13 @@ #include "cfgrtl.h" #include "profile.h" #include "expr.h" -#include "params.h" #include "tree-pass.h" #include "dbgcnt.h" +#include "intl.h" #include "gcse-common.h" +#include "gcse.h" +#include "regs.h" +#include "function-abi.h" /* The following code implements gcse after reload, the purpose of this pass is to cleanup redundant loads generated by reload and other @@ -364,7 +367,7 @@ int do_not_record_p; hashval_t hash; struct expr *cur_expr, **slot; - struct occr *avail_occr, *last_occr = NULL; + struct occr *avail_occr; hash = hash_expr (x, &do_not_record_p); @@ -405,38 +408,22 @@ cur_expr = *slot; } - /* Search for another occurrence in the same basic block. */ + /* Search for another occurrence in the same basic block. We insert + insns blockwise from start to end, so keep appending to the + start of the list so we have to check only a single element. */ avail_occr = cur_expr->avail_occr; - while (avail_occr - && BLOCK_FOR_INSN (avail_occr->insn) != BLOCK_FOR_INSN (insn)) - { - /* If an occurrence isn't found, save a pointer to the end of - the list. */ - last_occr = avail_occr; - avail_occr = avail_occr->next; - } - - if (avail_occr) - /* Found another instance of the expression in the same basic block. - Prefer this occurrence to the currently recorded one. We want - the last one in the block and the block is scanned from start - to end. */ + if (avail_occr + && BLOCK_FOR_INSN (avail_occr->insn) == BLOCK_FOR_INSN (insn)) avail_occr->insn = insn; else { /* First occurrence of this expression in this basic block. */ avail_occr = (struct occr *) obstack_alloc (&occr_obstack, sizeof (struct occr)); - - /* First occurrence of this expression in any block? */ - if (cur_expr->avail_occr == NULL) - cur_expr->avail_occr = avail_occr; - else - last_occr->next = avail_occr; - avail_occr->insn = insn; - avail_occr->next = NULL; + avail_occr->next = cur_expr->avail_occr; avail_occr->deleted_p = 0; + cur_expr->avail_occr = avail_occr; } } @@ -504,7 +491,7 @@ (long) expr_table->size (), (long) expr_table->elements (), expr_table->collisions ()); - if (expr_table->elements () > 0) + if (!expr_table->is_empty ()) { fprintf (file, "\n\ntable entries:\n"); expr_table->traverse <FILE *, dump_expr_hash_table_entry> (file); @@ -672,7 +659,7 @@ It will set mems_conflict_p to nonzero if there may be a conflict between X and SETTER. */ mems_conflict_p = 0; - note_stores (PATTERN (setter), find_mem_conflicts, x); + note_stores (setter, find_mem_conflicts, x); if (mems_conflict_p) return 1; @@ -774,7 +761,7 @@ rtx note; /* Find all stores and record them. */ - note_stores (PATTERN (insn), record_last_set_info, insn); + note_stores (insn, record_last_set_info, insn); /* Also record autoincremented REGs for this insn as changed. */ for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) @@ -785,25 +772,14 @@ if (CALL_P (insn)) { unsigned int regno; - rtx link, x; hard_reg_set_iterator hrsi; - EXECUTE_IF_SET_IN_HARD_REG_SET (regs_invalidated_by_call, 0, regno, hrsi) + /* We don't track modes of hard registers, so we need to be + conservative and assume that partial kills are full kills. */ + HARD_REG_SET callee_clobbers + = insn_callee_abi (insn).full_and_partial_reg_clobbers (); + EXECUTE_IF_SET_IN_HARD_REG_SET (callee_clobbers, 0, regno, hrsi) record_last_reg_set_info_regno (insn, regno); - for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1)) - { - gcc_assert (GET_CODE (XEXP (link, 0)) != CLOBBER_HIGH); - if (GET_CODE (XEXP (link, 0)) == CLOBBER) - { - x = XEXP (XEXP (link, 0), 0); - if (REG_P (x)) - { - gcc_assert (HARD_REGISTER_P (x)); - record_last_reg_set_info (insn, x); - } - } - } - if (! RTL_CONST_OR_PURE_CALL_P (insn)) record_last_mem_set_info (insn); } @@ -995,7 +971,8 @@ /* If we could not find an occurrence in BB, see if BB has a single predecessor with an occurrence that is transparent through BB. */ - if (single_pred_p (bb) + if (transp + && single_pred_p (bb) && bitmap_bit_p (transp[bb->index], bitmap_index) && (occr = get_bb_avail_insn (single_pred (bb), orig_occr, bitmap_index))) { @@ -1168,10 +1145,21 @@ /* Check if it's worth applying the partial redundancy elimination. */ if (ok_count.to_gcov_type () - < GCSE_AFTER_RELOAD_PARTIAL_FRACTION * not_ok_count.to_gcov_type ()) + < param_gcse_after_reload_partial_fraction * not_ok_count.to_gcov_type ()) goto cleanup; - if (ok_count.to_gcov_type () - < GCSE_AFTER_RELOAD_CRITICAL_FRACTION * critical_count.to_gcov_type ()) + + gcov_type threshold; +#if (GCC_VERSION >= 5000) + if (__builtin_mul_overflow (param_gcse_after_reload_critical_fraction, + critical_count.to_gcov_type (), &threshold)) + threshold = profile_count::max_count; +#else + threshold + = (param_gcse_after_reload_critical_fraction + * critical_count.to_gcov_type ()); +#endif + + if (ok_count.to_gcov_type () < threshold) goto cleanup; /* Generate moves to the loaded register from where @@ -1361,6 +1349,10 @@ static void gcse_after_reload_main (rtx f ATTRIBUTE_UNUSED) { + /* Disable computing transparentness if it is too expensive. */ + bool do_transp + = !gcse_or_cprop_is_too_expensive (_("using simple load CSE after register " + "allocation")); memset (&stats, 0, sizeof (stats)); @@ -1376,21 +1368,27 @@ if (dump_file) dump_hash_table (dump_file); - if (expr_table->elements () > 0) + if (!expr_table->is_empty ()) { /* Knowing which MEMs are transparent through a block can signifiantly increase the number of redundant loads found. So compute transparency information for each memory expression in the hash table. */ df_analyze (); - /* This can not be part of the normal allocation routine because - we have to know the number of elements in the hash table. */ - transp = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), - expr_table->elements ()); - bitmap_vector_ones (transp, last_basic_block_for_fn (cfun)); - expr_table->traverse <FILE *, compute_expr_transp> (dump_file); + if (do_transp) + { + /* This cannot be part of the normal allocation routine because + we have to know the number of elements in the hash table. */ + transp = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), + expr_table->elements ()); + bitmap_vector_ones (transp, last_basic_block_for_fn (cfun)); + expr_table->traverse <FILE *, compute_expr_transp> (dump_file); + } + else + transp = NULL; eliminate_partially_redundant_loads (); delete_redundant_insns (); - sbitmap_vector_free (transp); + if (do_transp) + sbitmap_vector_free (transp); if (dump_file) {