diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-03-16 10:50:42 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-03-16 10:50:42 +0000 |
commit | 35af01889aa8a9281e2c7addfedfaae568822c75 (patch) | |
tree | 597667654769fc455fccebf8f723c1871062cb36 /gcc/cselib.c | |
parent | e88bd90b6f84aaeb665413f9700792b7156d17a1 (diff) | |
download | gcc-35af01889aa8a9281e2c7addfedfaae568822c75.tar.gz |
PR debug/43051
PR debug/43092
* cselib.c (cselib_preserve_constants,
cfa_base_preserved_val): New static variables.
(preserve_only_constants): New function.
(cselib_reset_table): If cfa_base_preserved_val is non-NULL, don't
clear its REG_VALUES. If cselib_preserve_constants, don't
empty the whole hash table, but preserve there VALUEs with constants,
cfa_base_preserved_val and cfa_base_preserved_val plus constant.
(cselib_preserve_cfa_base_value): New function.
(cselib_invalidate_regno): Don't invalidate cfa_base_preserved_val.
(cselib_init): Change argument to int bitfield. Set
cselib_preserve_constants to whether CSELIB_PRESERVE_CONSTANTS
is in it.
(cselib_finish): Clear cselib_preserve_constants and
cfa_base_preserved_val.
* cselib.h (enum cselib_record_what): New enum.
(cselib_init): Change argument to int.
(cselib_preserve_cfa_base_value): New prototype.
* postreload.c (reload_cse_regs_1): Adjust cselib_init caller.
* dse.c (dse_step1): Likewise.
* cfgcleanup.c (thread_jump): Likewise.
* sched-deps.c (sched_analyze): Likewise.
* gcse.c (local_cprop_pass): Likewise.
* simplify-rtx.c (simplify_replace_fn_rtx): Add argument to callback.
If FN is non-NULL, call the callback always and whenever it returns
non-NULL just return that. Only do rtx_equal_p if FN is NULL.
* rtl.h (simplify_replace_fn_rtx): Add argument to callback.
* combine.c (propagate_for_debug_subst): Add old_rtx argument,
compare from with old_rtx and if it isn't rtx_equal_p, return NULL.
* Makefile.in (var-tracking.o): Depend on $(RECOG_H).
* var-tracking.c: Include recog.h.
(bb_stack_adjust_offset): Remove.
(vt_stack_adjustments): Don't call it, instead just gather the
adjustments using insn_stack_adjust_offset_pre_post on each bb insn.
(adjust_stack_reference): Remove.
(compute_cfa_pointer): New function.
(hard_frame_pointer_adjustment, cfa_base_rtx): New static variables.
(struct adjust_mem_data): New type.
(adjust_mems, adjust_mem_uses, adjust_mem_stores, adjust_insn): New
functions.
(get_address_mode): New function.
(replace_expr_with_values): Use it.
(use_type): Don't do cselib_lookup for VAR_LOC_UNKNOWN_P.
Use get_address_mode. For cfa_base_rtx return MO_CLOBBER.
(adjust_sets): Remove.
(add_uses): Don't add extra MO_VAL_USE for cfa_base_rtx plus constant.
Use get_address_mode.
(get_adjusted_src): Remove.
(add_stores): Don't call it. Never reuse expr SET. Don't add extra
MO_VAL_USE for cfa_base_rtx plus constant. Use get_address_mode.
(add_with_sets): Don't call adjust_sets.
(fp_setter, vt_init_cfa_base): New functions.
(vt_initialize): Change return type to bool. Move most of pool etc.
initialization to the beginning of the function from end. Pass
CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS to cselib_init.
If !frame_pointer_needed, call vt_stack_adjustment before mos
vector is filled, call vt_init_cfa_base if argp/framep has been
eliminated to sp. If frame_pointer_needed and argp/framep has
been eliminated to hard frame pointer, set
hard_frame_pointer_adjustment and call vt_init_cfa_base after
encountering fp setter in the prologue. For MO_ADJUST, call
log_op_type before pusing the op into mos vector, not afterwards.
Call adjust_insn before cselib_process_insn/add_with_sets,
call cancel_changes (0) afterwards.
(variable_tracking_main_1): Adjust for vt_initialize calling
vt_stack_adjustments and returning whether it succeeded or not.
* gcc.dg/guality/pr43051-1.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@157476 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cselib.c')
-rw-r--r-- | gcc/cselib.c | 90 |
1 files changed, 81 insertions, 9 deletions
diff --git a/gcc/cselib.c b/gcc/cselib.c index f63ea3f5f1c..9073b9928be 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see #include "target.h" static bool cselib_record_memory; +static bool cselib_preserve_constants; static int entry_and_rtx_equal_p (const void *, const void *); static hashval_t get_value_hash (const void *); static struct elt_list *new_elt_list (struct elt_list *, cselib_val *); @@ -135,6 +136,11 @@ static int values_became_useless; presence in the list by checking the next pointer. */ static cselib_val dummy_val; +/* If non-NULL, value of the eliminated arg_pointer_rtx or frame_pointer_rtx + that is constant through the whole function and should never be + eliminated. */ +static cselib_val *cfa_base_preserved_val; + /* Used to list all values that contain memory reference. May or may not contain the useless values - the list is compacted each time memory is invalidated. */ @@ -229,6 +235,35 @@ cselib_clear_table (void) cselib_reset_table (1); } +/* Remove from hash table all VALUEs except constants. */ + +static int +preserve_only_constants (void **x, void *info ATTRIBUTE_UNUSED) +{ + cselib_val *v = (cselib_val *)*x; + + if (v->locs != NULL + && v->locs->next == NULL) + { + if (CONSTANT_P (v->locs->loc) + && (GET_CODE (v->locs->loc) != CONST + || !references_value_p (v->locs->loc, 0))) + return 1; + if (cfa_base_preserved_val) + { + if (v == cfa_base_preserved_val) + return 1; + if (GET_CODE (v->locs->loc) == PLUS + && CONST_INT_P (XEXP (v->locs->loc, 1)) + && XEXP (v->locs->loc, 0) == cfa_base_preserved_val->val_rtx) + return 1; + } + } + + htab_clear_slot (cselib_hash_table, x); + return 1; +} + /* Remove all entries from the hash table, arranging for the next value to be numbered NUM. */ @@ -237,15 +272,37 @@ cselib_reset_table (unsigned int num) { unsigned int i; - for (i = 0; i < n_used_regs; i++) - REG_VALUES (used_regs[i]) = 0; - max_value_regs = 0; - n_used_regs = 0; + if (cfa_base_preserved_val) + { + unsigned int regno = REGNO (cfa_base_preserved_val->locs->loc); + unsigned int new_used_regs = 0; + for (i = 0; i < n_used_regs; i++) + if (used_regs[i] == regno) + { + new_used_regs = 1; + continue; + } + else + REG_VALUES (used_regs[i]) = 0; + gcc_assert (new_used_regs == 1); + n_used_regs = new_used_regs; + used_regs[0] = regno; + max_value_regs + = hard_regno_nregs[regno][GET_MODE (cfa_base_preserved_val->locs->loc)]; + } + else + { + for (i = 0; i < n_used_regs; i++) + REG_VALUES (used_regs[i]) = 0; + n_used_regs = 0; + } - /* ??? Preserve constants? */ - htab_empty (cselib_hash_table); + if (cselib_preserve_constants) + htab_traverse (cselib_hash_table, preserve_only_constants, NULL); + else + htab_empty (cselib_hash_table); n_useless_values = 0; @@ -434,6 +491,18 @@ cselib_preserved_value_p (cselib_val *v) return PRESERVED_VALUE_P (v->val_rtx); } +/* Arrange for a REG value to be assumed constant through the whole function, + never invalidated and preserved across cselib_reset_table calls. */ + +void +cselib_preserve_cfa_base_value (cselib_val *v) +{ + if (cselib_preserve_constants + && v->locs + && REG_P (v->locs->loc)) + cfa_base_preserved_val = v; +} + /* Clean all non-constant expressions in the hash table, but retain their values. */ @@ -1600,7 +1669,7 @@ cselib_invalidate_regno (unsigned int regno, enum machine_mode mode) if (i < FIRST_PSEUDO_REGISTER && v != NULL) this_last = end_hard_regno (GET_MODE (v->val_rtx), i) - 1; - if (this_last < regno || v == NULL) + if (this_last < regno || v == NULL || v == cfa_base_preserved_val) { l = &(*l)->next; continue; @@ -2018,7 +2087,7 @@ cselib_process_insn (rtx insn) init_alias_analysis. */ void -cselib_init (bool record_memory) +cselib_init (int record_what) { elt_list_pool = create_alloc_pool ("elt_list", sizeof (struct elt_list), 10); @@ -2027,7 +2096,8 @@ cselib_init (bool record_memory) cselib_val_pool = create_alloc_pool ("cselib_val_list", sizeof (cselib_val), 10); value_pool = create_alloc_pool ("value", RTX_CODE_SIZE (VALUE), 100); - cselib_record_memory = record_memory; + cselib_record_memory = record_what & CSELIB_RECORD_MEMORY; + cselib_preserve_constants = record_what & CSELIB_PRESERVE_CONSTANTS; /* (mem:BLK (scratch)) is a special mechanism to conflict with everything, see canon_true_dependence. This is only created once. */ @@ -2061,6 +2131,8 @@ void cselib_finish (void) { cselib_discard_hook = NULL; + cselib_preserve_constants = false; + cfa_base_preserved_val = NULL; free_alloc_pool (elt_list_pool); free_alloc_pool (elt_loc_list_pool); free_alloc_pool (cselib_val_pool); |