tm.texi (TARGET_IRA_COVER_CLASSES): Modify description.
2008-01-29 Vladimir Makarov <vmakarov@redhat.com> * doc/tm.texi (TARGET_IRA_COVER_CLASSES): Modify description. * doc/passes.texi: Remove entries about regclass, local-alloc, and global. Modify entries about regmove and IRA. * ra-conflict.c: Remove the file. * reload.c (push_reload, find_dummy_reload): Remove flag_ira. * tree-pass.h (pass_local_alloc, pass_global_alloc): Remove. (pass_regclass_init): Rename to pass_reginfo_init. * cfgloopanal.c (estimate_reg_pressure_cost): Remove flag_ira. * toplev.h (flag_ira): Remove. * caller-save.c (setup_save_areas): Remove flag_ira. * ira-color.c (ira_reuse_stack_slot, ira_mark_new_stack_slot): Ditto. * global.c: Remove the file. * opts.c: (decode_options): Remove flag_ira. * hard-reg-set.h (losing_caller_save_reg_set): Remove. * regmove.c: Modify file description. (find_use_as_address, try_auto_increment): Define them only if AUTO_INC_DEC is defined. (replacement_quality, replace_in_call_usage, fixup_match_1, stable_and_no_regs_but_for_p): Remove. (reg_set_in_bb): Make it static. (regmove_optimize): Remove flag_ira and code which worked for !flag_ira. * local-alloc.c: Remove the file. * common.opt (fira): Remove. * ira.c: Include except.h. (eliminable_regset): Move from global.c. (mark_elimination): Ditto. Remove flag_ira. (reg_renumber, struct equivalence, reg_equiv, equiv_mem, equiv_mem_modified, validate_equiv_mem_from_store, validate_equiv_mem, equiv_init_varies_p, equiv_init_movable_p, contains_replace_regs, memref_referenced_p, memref_used_between_p, no_equiv, recorded_label_ref): Move from local-alloc.c. (update_equiv_regs): Ditto. Make it static. (print_insn_chain, print_insn_chains): Move it from global.c. pseudo_for_reload_consideration_p): Ditto. Remove flag_ira. (build_insn_chain): Ditto. Make it static. (ra_init_live_subregs): Move from ra-conflict.c. Make it static. Rename to init_live_subregs. (gate_ira): Remove flag_ira. * regclass.c: Rename reginfo.c. Change file description. (FORBIDDEN_INC_DEC_CLASSES): Remove. (reg_class_superclasses, forbidden_inc_dec_class, in_inc_dec): Remove. (init_reg_sets_1): Remove code for evaluation of reg_class_superclasses and losing_caller_save_reg_set. (init_regs): Remove init_reg_autoinc. (struct costs, costs, init_cost, ok_for_index_p_nonstrict, ok_for_base_p_nonstrict): Remove. (regclass_init): Rename to reginfo_init. Don't initialize init_cost. (pass_regclass_init): Rename to pass_reginfo_init. Modify corresponding entries. (dump_regclass, record_operand_costs, scan_one_insn, init_reg_autoinc, regclass, record_reg_classes, copy_cost, record_address_regs, auto_inc_dec_reg_p): Remove. (gt-regclass.h): Rename to gt-reginfo.h. * rtl.h (dump_global_regs, retry_global_alloc, build_insn_chain, dump_local_alloc, update_equiv_regs): Remove. * Makefile.in (RA_H): Remove. (OBJS-common): Remove global.o, local-alloc.o, and ra-conflict.o. Rename regclass.o to reginfo.o. (regclass.o): Rename to reginfo.o. Rename gt-regclass.h to gt-reginfo.h. (global.o, local-alloc.o, ra-conflict.o): Remove entries. (GTFILES): Rename regclass.c to reginfo.c. * passes.c (init_optimization_passes): Remove pass_local_alloc and pass_global_alloc. Rename pass_regclass_init to pass_reginfo_init. * reload1.c (compute_use_by_pseudos, reload, count_pseudo, count_spilled_pseudo, find_reg, alter_reg, delete_output_reload): Remove flag_ira. (finish_spills): Ditto. Remove code for !flga_ira. From-SVN: r143757
This commit is contained in:
parent
00b251a037
commit
2af2dbdc68
21 changed files with 1536 additions and 7912 deletions
|
@ -1,3 +1,99 @@
|
|||
2008-01-29 Vladimir Makarov <vmakarov@redhat.com>
|
||||
|
||||
* doc/tm.texi (TARGET_IRA_COVER_CLASSES): Modify description.
|
||||
* doc/passes.texi: Remove entries about regclass, local-alloc, and
|
||||
global. Modify entries about regmove and IRA.
|
||||
|
||||
* ra-conflict.c: Remove the file.
|
||||
|
||||
* reload.c (push_reload, find_dummy_reload): Remove flag_ira.
|
||||
|
||||
* tree-pass.h (pass_local_alloc, pass_global_alloc): Remove.
|
||||
(pass_regclass_init): Rename to pass_reginfo_init.
|
||||
|
||||
* cfgloopanal.c (estimate_reg_pressure_cost): Remove flag_ira.
|
||||
|
||||
* toplev.h (flag_ira): Remove.
|
||||
|
||||
* caller-save.c (setup_save_areas): Remove flag_ira.
|
||||
|
||||
* ira-color.c (ira_reuse_stack_slot, ira_mark_new_stack_slot):
|
||||
Ditto.
|
||||
|
||||
* global.c: Remove the file.
|
||||
|
||||
* opts.c: (decode_options): Remove flag_ira.
|
||||
|
||||
* hard-reg-set.h (losing_caller_save_reg_set): Remove.
|
||||
|
||||
* regmove.c: Modify file description.
|
||||
(find_use_as_address, try_auto_increment): Define them only if
|
||||
AUTO_INC_DEC is defined.
|
||||
(replacement_quality, replace_in_call_usage, fixup_match_1,
|
||||
stable_and_no_regs_but_for_p): Remove.
|
||||
(reg_set_in_bb): Make it static.
|
||||
(regmove_optimize): Remove flag_ira and code which worked for
|
||||
!flag_ira.
|
||||
|
||||
* local-alloc.c: Remove the file.
|
||||
|
||||
* common.opt (fira): Remove.
|
||||
|
||||
* ira.c: Include except.h.
|
||||
(eliminable_regset): Move from global.c.
|
||||
(mark_elimination): Ditto. Remove flag_ira.
|
||||
(reg_renumber, struct equivalence, reg_equiv, equiv_mem,
|
||||
equiv_mem_modified, validate_equiv_mem_from_store,
|
||||
validate_equiv_mem, equiv_init_varies_p, equiv_init_movable_p,
|
||||
contains_replace_regs, memref_referenced_p, memref_used_between_p,
|
||||
no_equiv, recorded_label_ref): Move from local-alloc.c.
|
||||
(update_equiv_regs): Ditto. Make it static.
|
||||
(print_insn_chain, print_insn_chains): Move it from global.c.
|
||||
pseudo_for_reload_consideration_p): Ditto. Remove flag_ira.
|
||||
(build_insn_chain): Ditto. Make it static.
|
||||
(ra_init_live_subregs): Move from ra-conflict.c. Make it static.
|
||||
Rename to init_live_subregs.
|
||||
(gate_ira): Remove flag_ira.
|
||||
|
||||
* regclass.c: Rename reginfo.c. Change file description.
|
||||
(FORBIDDEN_INC_DEC_CLASSES): Remove.
|
||||
(reg_class_superclasses, forbidden_inc_dec_class, in_inc_dec):
|
||||
Remove.
|
||||
(init_reg_sets_1): Remove code for evaluation of
|
||||
reg_class_superclasses and losing_caller_save_reg_set.
|
||||
(init_regs): Remove init_reg_autoinc.
|
||||
(struct costs, costs, init_cost, ok_for_index_p_nonstrict,
|
||||
ok_for_base_p_nonstrict): Remove.
|
||||
(regclass_init): Rename to reginfo_init. Don't initialize
|
||||
init_cost.
|
||||
(pass_regclass_init): Rename to pass_reginfo_init. Modify
|
||||
corresponding entries.
|
||||
(dump_regclass, record_operand_costs, scan_one_insn,
|
||||
init_reg_autoinc, regclass, record_reg_classes, copy_cost,
|
||||
record_address_regs, auto_inc_dec_reg_p): Remove.
|
||||
(gt-regclass.h): Rename to gt-reginfo.h.
|
||||
|
||||
* rtl.h (dump_global_regs, retry_global_alloc,
|
||||
build_insn_chain, dump_local_alloc, update_equiv_regs):
|
||||
Remove.
|
||||
|
||||
* Makefile.in (RA_H): Remove.
|
||||
(OBJS-common): Remove global.o, local-alloc.o, and ra-conflict.o.
|
||||
Rename regclass.o to reginfo.o.
|
||||
(regclass.o): Rename to reginfo.o. Rename gt-regclass.h to
|
||||
gt-reginfo.h.
|
||||
(global.o, local-alloc.o, ra-conflict.o): Remove entries.
|
||||
(GTFILES): Rename regclass.c to reginfo.c.
|
||||
|
||||
* passes.c (init_optimization_passes): Remove pass_local_alloc and
|
||||
pass_global_alloc. Rename pass_regclass_init to
|
||||
pass_reginfo_init.
|
||||
|
||||
* reload1.c (compute_use_by_pseudos, reload, count_pseudo,
|
||||
count_spilled_pseudo, find_reg, alter_reg, delete_output_reload):
|
||||
Remove flag_ira.
|
||||
(finish_spills): Ditto. Remove code for !flga_ira.
|
||||
|
||||
2009-01-29 Kenneth Zadeck <zadeck@naturalbridge.com>
|
||||
|
||||
PR middle-end/35854
|
||||
|
|
|
@ -824,7 +824,6 @@ FUNCTION_H = function.h $(TREE_H) $(HASHTAB_H) varray.h
|
|||
EXPR_H = expr.h insn-config.h $(FUNCTION_H) $(RTL_H) $(FLAGS_H) $(TREE_H) $(MACHMODE_H) $(EMIT_RTL_H)
|
||||
OPTABS_H = optabs.h insn-codes.h
|
||||
REGS_H = regs.h varray.h $(MACHMODE_H) $(OBSTACK_H) $(BASIC_BLOCK_H) $(FUNCTION_H)
|
||||
RA_H = ra.h $(REGS_H)
|
||||
RESOURCE_H = resource.h hard-reg-set.h
|
||||
SCHED_INT_H = sched-int.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H) $(DF_H) vecprim.h
|
||||
SEL_SCHED_IR_H = sel-sched-ir.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H) \
|
||||
|
@ -1115,7 +1114,6 @@ OBJS-common = \
|
|||
gimple-low.o \
|
||||
gimple-pretty-print.o \
|
||||
gimplify.o \
|
||||
global.o \
|
||||
graph.o \
|
||||
graphds.o \
|
||||
graphite.o \
|
||||
|
@ -1140,7 +1138,6 @@ OBJS-common = \
|
|||
langhooks.o \
|
||||
lcm.o \
|
||||
lists.o \
|
||||
local-alloc.o \
|
||||
loop-doloop.o \
|
||||
loop-init.o \
|
||||
loop-invariant.o \
|
||||
|
@ -1167,11 +1164,10 @@ OBJS-common = \
|
|||
print-rtl.o \
|
||||
print-tree.o \
|
||||
profile.o \
|
||||
ra-conflict.o \
|
||||
real.o \
|
||||
recog.o \
|
||||
reg-stack.o \
|
||||
regclass.o \
|
||||
reginfo.o \
|
||||
regmove.o \
|
||||
regrename.o \
|
||||
regstat.o \
|
||||
|
@ -2842,25 +2838,13 @@ combine.o : combine.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
|||
rtlhooks-def.h $(BASIC_BLOCK_H) $(RECOG_H) $(REAL_H) hard-reg-set.h \
|
||||
$(TOPLEV_H) $(TM_P_H) $(TREE_H) $(TARGET_H) output.h $(PARAMS_H) $(OPTABS_H) \
|
||||
insn-codes.h $(TIMEVAR_H) tree-pass.h $(DF_H) vecprim.h $(CGRAPH_H)
|
||||
regclass.o : regclass.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
reginfo.o : reginfo.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) addresses.h $(REGS_H) insn-config.h \
|
||||
$(RECOG_H) reload.h $(REAL_H) $(TOPLEV_H) $(FUNCTION_H) output.h $(GGC_H) \
|
||||
$(TM_P_H) $(EXPR_H) $(TIMEVAR_H) gt-regclass.h $(HASHTAB_H) \
|
||||
$(TM_P_H) $(EXPR_H) $(TIMEVAR_H) gt-reginfo.h $(HASHTAB_H) \
|
||||
$(TARGET_H) tree-pass.h $(DF_H) ira.h
|
||||
local-alloc.o : local-alloc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(RTL_H) $(FLAGS_H) $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
|
||||
output.h $(FUNCTION_H) $(INSN_ATTR_H) $(TOPLEV_H) except.h reload.h $(TM_P_H) \
|
||||
$(GGC_H) $(INTEGRATE_H) $(TIMEVAR_H) tree-pass.h $(DF_H) $(DBGCNT_H)
|
||||
bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(FLAGS_H) $(GGC_H) gt-bitmap.h $(BITMAP_H) $(OBSTACK_H) $(HASHTAB_H)
|
||||
global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(FLAGS_H) reload.h $(FUNCTION_H) $(RECOG_H) $(REGS_H) hard-reg-set.h \
|
||||
insn-config.h output.h $(TOPLEV_H) $(TM_P_H) $(MACHMODE_H) tree-pass.h \
|
||||
$(TIMEVAR_H) vecprim.h $(DF_H) $(DBGCNT_H) $(RA_H) ira.h
|
||||
ra-conflict.o : ra-conflict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(FLAGS_H) reload.h $(FUNCTION_H) $(RECOG_H) $(REGS_H) hard-reg-set.h \
|
||||
insn-config.h output.h $(TOPLEV_H) $(TM_P_H) $(MACHMODE_H) tree-pass.h \
|
||||
$(TIMEVAR_H) vecprim.h $(DF_H) $(RA_H) sbitmap.h sparseset.h
|
||||
varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) \
|
||||
$(HASHTAB_H) $(BCONFIG_H) $(VARRAY_H) $(TOPLEV_H)
|
||||
vec.o : vec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h vec.h $(GGC_H) \
|
||||
|
@ -3303,7 +3287,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
|
|||
$(srcdir)/expr.h \
|
||||
$(srcdir)/function.c $(srcdir)/except.h \
|
||||
$(srcdir)/gcse.c $(srcdir)/integrate.c $(srcdir)/lists.c $(srcdir)/optabs.c \
|
||||
$(srcdir)/profile.c $(srcdir)/regclass.c $(srcdir)/mcf.c \
|
||||
$(srcdir)/profile.c $(srcdir)/reginfo.c $(srcdir)/mcf.c \
|
||||
$(srcdir)/reg-stack.c $(srcdir)/cfglayout.c $(srcdir)/cfglayout.h \
|
||||
$(srcdir)/sdbout.c $(srcdir)/stor-layout.c \
|
||||
$(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \
|
||||
|
|
|
@ -448,7 +448,7 @@ setup_save_areas (void)
|
|||
SET_HARD_REG_BIT (hard_regs_used, r);
|
||||
}
|
||||
|
||||
if (flag_ira && optimize && flag_ira_share_save_slots)
|
||||
if (optimize && flag_ira_share_save_slots)
|
||||
{
|
||||
rtx insn, slot;
|
||||
struct insn_chain *chain, *next;
|
||||
|
|
|
@ -396,8 +396,8 @@ estimate_reg_pressure_cost (unsigned n_new, unsigned n_old, bool speed)
|
|||
one. */
|
||||
cost = target_spill_cost [speed] * n_new;
|
||||
|
||||
if (optimize && flag_ira && (flag_ira_region == IRA_REGION_ALL
|
||||
|| flag_ira_region == IRA_REGION_MIXED)
|
||||
if (optimize && (flag_ira_region == IRA_REGION_ALL
|
||||
|| flag_ira_region == IRA_REGION_MIXED)
|
||||
&& number_of_loops () <= (unsigned) IRA_MAX_LOOPS_NUM)
|
||||
/* IRA regional allocation deals with high register pressure
|
||||
better. So decrease the cost (to do more accurate the cost
|
||||
|
|
|
@ -679,10 +679,6 @@ Common Report Var(flag_ipa_struct_reorg)
|
|||
Perform structure layout optimizations based
|
||||
on profiling information.
|
||||
|
||||
fira
|
||||
Common Report Var(flag_ira) Init(0)
|
||||
Use integrated register allocator.
|
||||
|
||||
fira-algorithm=
|
||||
Common Joined RejectNegative
|
||||
-fira-algorithm=[CB|priority] Set the used IRA algorithm
|
||||
|
|
|
@ -826,24 +826,12 @@ them on the stack. This is done in several subpasses:
|
|||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Register class preferencing. The RTL code is scanned to find out
|
||||
which register class is best for each pseudo register. The source
|
||||
file is @file{regclass.c}.
|
||||
Register move optimizations. This pass makes some simple RTL code
|
||||
transformations which improve the subsequent register allocation. The
|
||||
source file is @file{regmove.c}.
|
||||
|
||||
@item
|
||||
Local register allocation. This pass allocates hard registers to
|
||||
pseudo registers that are used only within one basic block. Because
|
||||
the basic block is linear, it can use fast and powerful techniques to
|
||||
do a decent job. The source is located in @file{local-alloc.c}.
|
||||
|
||||
@item
|
||||
Global register allocation. This pass allocates hard registers for
|
||||
the remaining pseudo registers (those whose life spans are not
|
||||
contained in one basic block). The pass is located in @file{global.c}.
|
||||
|
||||
@item
|
||||
The optional integrated register allocator (@acronym{IRA}). It can be
|
||||
used instead of the local and global allocator. It is called
|
||||
The integrated register allocator (@acronym{IRA}). It is called
|
||||
integrated because coalescing, register live range splitting, and hard
|
||||
register preferencing are done on-the-fly during coloring. It also
|
||||
has better integration with the reload pass. Pseudo-registers spilled
|
||||
|
|
1849
gcc/global.c
1849
gcc/global.c
File diff suppressed because it is too large
Load diff
|
@ -601,9 +601,6 @@ extern char call_really_used_regs[];
|
|||
|
||||
extern HARD_REG_SET call_used_reg_set;
|
||||
|
||||
/* Registers that we don't want to caller save. */
|
||||
extern HARD_REG_SET losing_caller_save_reg_set;
|
||||
|
||||
/* Indexed by hard register number, contains 1 for registers that are
|
||||
fixed use -- i.e. in fixed_regs -- or a function value return register
|
||||
or TARGET_STRUCT_VALUE_RTX or STATIC_CHAIN_REGNUM. These are the
|
||||
|
|
|
@ -2962,7 +2962,7 @@ ira_reuse_stack_slot (int regno, unsigned int inherent_size,
|
|||
bitmap_iterator bi;
|
||||
struct ira_spilled_reg_stack_slot *slot = NULL;
|
||||
|
||||
ira_assert (flag_ira && inherent_size == PSEUDO_REGNO_BYTES (regno)
|
||||
ira_assert (inherent_size == PSEUDO_REGNO_BYTES (regno)
|
||||
&& inherent_size <= total_size
|
||||
&& ALLOCNO_HARD_REGNO (allocno) < 0);
|
||||
if (! flag_ira_share_spill_slots)
|
||||
|
@ -3074,7 +3074,7 @@ ira_mark_new_stack_slot (rtx x, int regno, unsigned int total_size)
|
|||
int slot_num;
|
||||
ira_allocno_t allocno;
|
||||
|
||||
ira_assert (flag_ira && PSEUDO_REGNO_BYTES (regno) <= total_size);
|
||||
ira_assert (PSEUDO_REGNO_BYTES (regno) <= total_size);
|
||||
allocno = ira_regno_allocno_map[regno];
|
||||
slot_num = -ALLOCNO_HARD_REGNO (allocno) - 2;
|
||||
if (slot_num == -1)
|
||||
|
|
2545
gcc/local-alloc.c
2545
gcc/local-alloc.c
File diff suppressed because it is too large
Load diff
|
@ -870,7 +870,6 @@ decode_options (unsigned int argc, const char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
flag_ira = 1;
|
||||
/* Use priority coloring if cover classes is not defined for the
|
||||
target. */
|
||||
if (targetm.ira_cover_classes == NULL)
|
||||
|
@ -1098,7 +1097,7 @@ decode_options (unsigned int argc, const char **argv)
|
|||
if (!flag_sel_sched_pipelining)
|
||||
flag_sel_sched_pipelining_outer_loops = 0;
|
||||
|
||||
if (flag_ira && !targetm.ira_cover_classes
|
||||
if (!targetm.ira_cover_classes
|
||||
&& flag_ira_algorithm == IRA_ALGORITHM_CB)
|
||||
{
|
||||
inform (input_location,
|
||||
|
|
|
@ -749,7 +749,7 @@ init_optimization_passes (void)
|
|||
NEXT_PASS (pass_cse2);
|
||||
NEXT_PASS (pass_rtl_dse1);
|
||||
NEXT_PASS (pass_rtl_fwprop_addr);
|
||||
NEXT_PASS (pass_regclass_init);
|
||||
NEXT_PASS (pass_reginfo_init);
|
||||
NEXT_PASS (pass_inc_dec);
|
||||
NEXT_PASS (pass_initialize_regs);
|
||||
NEXT_PASS (pass_outof_cfg_layout_mode);
|
||||
|
@ -768,8 +768,6 @@ init_optimization_passes (void)
|
|||
NEXT_PASS (pass_sms);
|
||||
NEXT_PASS (pass_sched);
|
||||
NEXT_PASS (pass_subregs_of_mode_init);
|
||||
NEXT_PASS (pass_local_alloc);
|
||||
NEXT_PASS (pass_global_alloc);
|
||||
NEXT_PASS (pass_ira);
|
||||
NEXT_PASS (pass_subregs_of_mode_finish);
|
||||
NEXT_PASS (pass_postreload);
|
||||
|
|
1241
gcc/ra-conflict.c
1241
gcc/ra-conflict.c
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
876
gcc/regmove.c
876
gcc/regmove.c
|
@ -20,10 +20,8 @@ along with GCC; see the file COPYING3. If not see
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
|
||||
/* This module looks for cases where matching constraints would force
|
||||
an instruction to need a reload, and this reload would be a register
|
||||
to register move. It then attempts to change the registers used by the
|
||||
instruction to avoid the move instruction. */
|
||||
/* This module makes some simple RTL code transformations which
|
||||
improve the subsequent register allocation. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
|
@ -64,13 +62,8 @@ static rtx discover_flags_reg (void);
|
|||
static void mark_flags_life_zones (rtx);
|
||||
static void flags_set_1 (rtx, const_rtx, void *);
|
||||
|
||||
static int try_auto_increment (rtx, rtx, rtx, rtx, HOST_WIDE_INT, int);
|
||||
static int find_matches (rtx, struct match *);
|
||||
static void replace_in_call_usage (rtx *, unsigned int, rtx, rtx);
|
||||
static int fixup_match_1 (rtx, rtx, rtx, rtx, rtx, int, int, int);
|
||||
static int stable_and_no_regs_but_for_p (rtx, rtx, rtx);
|
||||
static int regclass_compatible_p (int, int);
|
||||
static int replacement_quality (rtx);
|
||||
static int fixup_match_2 (rtx, rtx, rtx, rtx);
|
||||
|
||||
/* Return nonzero if registers with CLASS1 and CLASS2 can be merged without
|
||||
|
@ -85,132 +78,6 @@ regclass_compatible_p (int class0, int class1)
|
|||
&& ! CLASS_LIKELY_SPILLED_P (class1)));
|
||||
}
|
||||
|
||||
/* Find the place in the rtx X where REG is used as a memory address.
|
||||
Return the MEM rtx that so uses it.
|
||||
If PLUSCONST is nonzero, search instead for a memory address equivalent to
|
||||
(plus REG (const_int PLUSCONST)).
|
||||
|
||||
If such an address does not appear, return 0.
|
||||
If REG appears more than once, or is used other than in such an address,
|
||||
return (rtx) 1. */
|
||||
|
||||
static rtx
|
||||
find_use_as_address (rtx x, rtx reg, HOST_WIDE_INT plusconst)
|
||||
{
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
const char * const fmt = GET_RTX_FORMAT (code);
|
||||
int i;
|
||||
rtx value = 0;
|
||||
rtx tem;
|
||||
|
||||
if (code == MEM && XEXP (x, 0) == reg && plusconst == 0)
|
||||
return x;
|
||||
|
||||
if (code == MEM && GET_CODE (XEXP (x, 0)) == PLUS
|
||||
&& XEXP (XEXP (x, 0), 0) == reg
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
|
||||
&& INTVAL (XEXP (XEXP (x, 0), 1)) == plusconst)
|
||||
return x;
|
||||
|
||||
if (code == SIGN_EXTRACT || code == ZERO_EXTRACT)
|
||||
{
|
||||
/* If REG occurs inside a MEM used in a bit-field reference,
|
||||
that is unacceptable. */
|
||||
if (find_use_as_address (XEXP (x, 0), reg, 0) != 0)
|
||||
return (rtx) (size_t) 1;
|
||||
}
|
||||
|
||||
if (x == reg)
|
||||
return (rtx) (size_t) 1;
|
||||
|
||||
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
||||
{
|
||||
if (fmt[i] == 'e')
|
||||
{
|
||||
tem = find_use_as_address (XEXP (x, i), reg, plusconst);
|
||||
if (value == 0)
|
||||
value = tem;
|
||||
else if (tem != 0)
|
||||
return (rtx) (size_t) 1;
|
||||
}
|
||||
else if (fmt[i] == 'E')
|
||||
{
|
||||
int j;
|
||||
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
||||
{
|
||||
tem = find_use_as_address (XVECEXP (x, i, j), reg, plusconst);
|
||||
if (value == 0)
|
||||
value = tem;
|
||||
else if (tem != 0)
|
||||
return (rtx) (size_t) 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/* INC_INSN is an instruction that adds INCREMENT to REG.
|
||||
Try to fold INC_INSN as a post/pre in/decrement into INSN.
|
||||
Iff INC_INSN_SET is nonzero, inc_insn has a destination different from src.
|
||||
Return nonzero for success. */
|
||||
static int
|
||||
try_auto_increment (rtx insn, rtx inc_insn, rtx inc_insn_set, rtx reg,
|
||||
HOST_WIDE_INT increment, int pre)
|
||||
{
|
||||
enum rtx_code inc_code;
|
||||
|
||||
rtx pset = single_set (insn);
|
||||
if (pset)
|
||||
{
|
||||
/* Can't use the size of SET_SRC, we might have something like
|
||||
(sign_extend:SI (mem:QI ... */
|
||||
rtx use = find_use_as_address (pset, reg, 0);
|
||||
if (use != 0 && use != (rtx) (size_t) 1)
|
||||
{
|
||||
int size = GET_MODE_SIZE (GET_MODE (use));
|
||||
if (0
|
||||
|| (HAVE_POST_INCREMENT
|
||||
&& pre == 0 && (inc_code = POST_INC, increment == size))
|
||||
|| (HAVE_PRE_INCREMENT
|
||||
&& pre == 1 && (inc_code = PRE_INC, increment == size))
|
||||
|| (HAVE_POST_DECREMENT
|
||||
&& pre == 0 && (inc_code = POST_DEC, increment == -size))
|
||||
|| (HAVE_PRE_DECREMENT
|
||||
&& pre == 1 && (inc_code = PRE_DEC, increment == -size))
|
||||
)
|
||||
{
|
||||
if (inc_insn_set)
|
||||
validate_change
|
||||
(inc_insn,
|
||||
&SET_SRC (inc_insn_set),
|
||||
XEXP (SET_SRC (inc_insn_set), 0), 1);
|
||||
validate_change (insn, &XEXP (use, 0),
|
||||
gen_rtx_fmt_e (inc_code, Pmode, reg), 1);
|
||||
if (apply_change_group ())
|
||||
{
|
||||
/* If there is a REG_DEAD note on this insn, we must
|
||||
change this not to REG_UNUSED meaning that the register
|
||||
is set, but the value is dead. Failure to do so will
|
||||
result in sched1 dying -- when it recomputes lifetime
|
||||
information, the number of REG_DEAD notes will have
|
||||
changed. */
|
||||
rtx note = find_reg_note (insn, REG_DEAD, reg);
|
||||
if (note)
|
||||
PUT_MODE (note, REG_UNUSED);
|
||||
|
||||
add_reg_note (insn, REG_INC, reg);
|
||||
|
||||
if (! inc_insn_set)
|
||||
delete_insn (inc_insn);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Determine if the pattern generated by add_optab has a clobber,
|
||||
such as might be issued for a flags hard register. To make the
|
||||
|
@ -376,43 +243,140 @@ flags_set_1 (rtx x, const_rtx pat, void *data ATTRIBUTE_UNUSED)
|
|||
&& reg_overlap_mentioned_p (x, flags_set_1_rtx))
|
||||
flags_set_1_set = 1;
|
||||
}
|
||||
|
||||
#ifdef AUTO_INC_DEC
|
||||
|
||||
/* Find the place in the rtx X where REG is used as a memory address.
|
||||
Return the MEM rtx that so uses it.
|
||||
If PLUSCONST is nonzero, search instead for a memory address equivalent to
|
||||
(plus REG (const_int PLUSCONST)).
|
||||
|
||||
If such an address does not appear, return 0.
|
||||
If REG appears more than once, or is used other than in such an address,
|
||||
return (rtx) 1. */
|
||||
|
||||
static rtx
|
||||
find_use_as_address (rtx x, rtx reg, HOST_WIDE_INT plusconst)
|
||||
{
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
const char * const fmt = GET_RTX_FORMAT (code);
|
||||
int i;
|
||||
rtx value = 0;
|
||||
rtx tem;
|
||||
|
||||
if (code == MEM && XEXP (x, 0) == reg && plusconst == 0)
|
||||
return x;
|
||||
|
||||
if (code == MEM && GET_CODE (XEXP (x, 0)) == PLUS
|
||||
&& XEXP (XEXP (x, 0), 0) == reg
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
|
||||
&& INTVAL (XEXP (XEXP (x, 0), 1)) == plusconst)
|
||||
return x;
|
||||
|
||||
if (code == SIGN_EXTRACT || code == ZERO_EXTRACT)
|
||||
{
|
||||
/* If REG occurs inside a MEM used in a bit-field reference,
|
||||
that is unacceptable. */
|
||||
if (find_use_as_address (XEXP (x, 0), reg, 0) != 0)
|
||||
return (rtx) (size_t) 1;
|
||||
}
|
||||
|
||||
if (x == reg)
|
||||
return (rtx) (size_t) 1;
|
||||
|
||||
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
||||
{
|
||||
if (fmt[i] == 'e')
|
||||
{
|
||||
tem = find_use_as_address (XEXP (x, i), reg, plusconst);
|
||||
if (value == 0)
|
||||
value = tem;
|
||||
else if (tem != 0)
|
||||
return (rtx) (size_t) 1;
|
||||
}
|
||||
else if (fmt[i] == 'E')
|
||||
{
|
||||
int j;
|
||||
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
||||
{
|
||||
tem = find_use_as_address (XVECEXP (x, i, j), reg, plusconst);
|
||||
if (value == 0)
|
||||
value = tem;
|
||||
else if (tem != 0)
|
||||
return (rtx) (size_t) 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/* INC_INSN is an instruction that adds INCREMENT to REG.
|
||||
Try to fold INC_INSN as a post/pre in/decrement into INSN.
|
||||
Iff INC_INSN_SET is nonzero, inc_insn has a destination different from src.
|
||||
Return nonzero for success. */
|
||||
static int
|
||||
try_auto_increment (rtx insn, rtx inc_insn, rtx inc_insn_set, rtx reg,
|
||||
HOST_WIDE_INT increment, int pre)
|
||||
{
|
||||
enum rtx_code inc_code;
|
||||
|
||||
rtx pset = single_set (insn);
|
||||
if (pset)
|
||||
{
|
||||
/* Can't use the size of SET_SRC, we might have something like
|
||||
(sign_extend:SI (mem:QI ... */
|
||||
rtx use = find_use_as_address (pset, reg, 0);
|
||||
if (use != 0 && use != (rtx) (size_t) 1)
|
||||
{
|
||||
int size = GET_MODE_SIZE (GET_MODE (use));
|
||||
if (0
|
||||
|| (HAVE_POST_INCREMENT
|
||||
&& pre == 0 && (inc_code = POST_INC, increment == size))
|
||||
|| (HAVE_PRE_INCREMENT
|
||||
&& pre == 1 && (inc_code = PRE_INC, increment == size))
|
||||
|| (HAVE_POST_DECREMENT
|
||||
&& pre == 0 && (inc_code = POST_DEC, increment == -size))
|
||||
|| (HAVE_PRE_DECREMENT
|
||||
&& pre == 1 && (inc_code = PRE_DEC, increment == -size))
|
||||
)
|
||||
{
|
||||
if (inc_insn_set)
|
||||
validate_change
|
||||
(inc_insn,
|
||||
&SET_SRC (inc_insn_set),
|
||||
XEXP (SET_SRC (inc_insn_set), 0), 1);
|
||||
validate_change (insn, &XEXP (use, 0),
|
||||
gen_rtx_fmt_e (inc_code, Pmode, reg), 1);
|
||||
if (apply_change_group ())
|
||||
{
|
||||
/* If there is a REG_DEAD note on this insn, we must
|
||||
change this not to REG_UNUSED meaning that the register
|
||||
is set, but the value is dead. Failure to do so will
|
||||
result in sched1 dying -- when it recomputes lifetime
|
||||
information, the number of REG_DEAD notes will have
|
||||
changed. */
|
||||
rtx note = find_reg_note (insn, REG_DEAD, reg);
|
||||
if (note)
|
||||
PUT_MODE (note, REG_UNUSED);
|
||||
|
||||
add_reg_note (insn, REG_INC, reg);
|
||||
|
||||
if (! inc_insn_set)
|
||||
delete_insn (inc_insn);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int *regno_src_regno;
|
||||
|
||||
/* Indicate how good a choice REG (which appears as a source) is to replace
|
||||
a destination register with. The higher the returned value, the better
|
||||
the choice. The main objective is to avoid using a register that is
|
||||
a candidate for tying to a hard register, since the output might in
|
||||
turn be a candidate to be tied to a different hard register. */
|
||||
static int
|
||||
replacement_quality (rtx reg)
|
||||
{
|
||||
int src_regno;
|
||||
|
||||
/* Bad if this isn't a register at all. */
|
||||
if (!REG_P (reg))
|
||||
return 0;
|
||||
|
||||
/* If this register is not meant to get a hard register,
|
||||
it is a poor choice. */
|
||||
if (REG_LIVE_LENGTH (REGNO (reg)) < 0)
|
||||
return 0;
|
||||
|
||||
src_regno = regno_src_regno[REGNO (reg)];
|
||||
|
||||
/* If it was not copied from another register, it is fine. */
|
||||
if (src_regno < 0)
|
||||
return 3;
|
||||
|
||||
/* Copied from a hard register? */
|
||||
if (src_regno < FIRST_PSEUDO_REGISTER)
|
||||
return 1;
|
||||
|
||||
/* Copied from a pseudo register - not as bad as from a hard register,
|
||||
yet still cumbersome, since the register live length will be lengthened
|
||||
when the registers get tied. */
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Return 1 if INSN might end a basic block. */
|
||||
|
||||
|
@ -898,7 +862,7 @@ copy_src_to_dest (rtx insn, rtx src, rtx dest)
|
|||
/* reg_set_in_bb[REGNO] points to basic block iff the register is set
|
||||
only once in the given block and has REG_EQUAL note. */
|
||||
|
||||
basic_block *reg_set_in_bb;
|
||||
static basic_block *reg_set_in_bb;
|
||||
|
||||
/* Size of reg_set_in_bb array. */
|
||||
static unsigned int max_reg_computed;
|
||||
|
@ -1126,7 +1090,7 @@ regmove_optimize (rtx f, int nregs)
|
|||
for (pass = 0; pass <= 2; pass++)
|
||||
{
|
||||
/* We need fewer optimizations for IRA. */
|
||||
if ((! flag_regmove || flag_ira) && pass >= flag_expensive_optimizations)
|
||||
if (! flag_regmove && pass >= flag_expensive_optimizations)
|
||||
goto done;
|
||||
|
||||
if (dump_file)
|
||||
|
@ -1137,7 +1101,6 @@ regmove_optimize (rtx f, int nregs)
|
|||
insn = pass ? PREV_INSN (insn) : NEXT_INSN (insn))
|
||||
{
|
||||
rtx set;
|
||||
int op_no, match_no;
|
||||
|
||||
set = single_set (insn);
|
||||
if (! set)
|
||||
|
@ -1174,103 +1137,6 @@ regmove_optimize (rtx f, int nregs)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* All optimizations important for IRA have been done. */
|
||||
if (! flag_regmove || flag_ira)
|
||||
continue;
|
||||
|
||||
if (! find_matches (insn, &match))
|
||||
continue;
|
||||
|
||||
/* Now scan through the operands looking for a source operand
|
||||
which is supposed to match the destination operand.
|
||||
Then scan forward for an instruction which uses the dest
|
||||
operand.
|
||||
If it dies there, then replace the dest in both operands with
|
||||
the source operand. */
|
||||
|
||||
for (op_no = 0; op_no < recog_data.n_operands; op_no++)
|
||||
{
|
||||
rtx src, dst, src_subreg;
|
||||
enum reg_class src_class, dst_class;
|
||||
|
||||
match_no = match.with[op_no];
|
||||
|
||||
/* Nothing to do if the two operands aren't supposed to match. */
|
||||
if (match_no < 0)
|
||||
continue;
|
||||
|
||||
src = recog_data.operand[op_no];
|
||||
dst = recog_data.operand[match_no];
|
||||
|
||||
if (!REG_P (src))
|
||||
continue;
|
||||
|
||||
src_subreg = src;
|
||||
if (GET_CODE (dst) == SUBREG
|
||||
&& GET_MODE_SIZE (GET_MODE (dst))
|
||||
>= GET_MODE_SIZE (GET_MODE (SUBREG_REG (dst))))
|
||||
{
|
||||
dst = SUBREG_REG (dst);
|
||||
src_subreg = lowpart_subreg (GET_MODE (dst),
|
||||
src, GET_MODE (src));
|
||||
if (!src_subreg)
|
||||
continue;
|
||||
}
|
||||
if (!REG_P (dst)
|
||||
|| REGNO (dst) < FIRST_PSEUDO_REGISTER)
|
||||
continue;
|
||||
|
||||
if (REGNO (src) < FIRST_PSEUDO_REGISTER)
|
||||
{
|
||||
if (match.commutative[op_no] < op_no)
|
||||
regno_src_regno[REGNO (dst)] = REGNO (src);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (REG_LIVE_LENGTH (REGNO (src)) < 0)
|
||||
continue;
|
||||
|
||||
/* op_no/src must be a read-only operand, and
|
||||
match_operand/dst must be a write-only operand. */
|
||||
if (match.use[op_no] != READ
|
||||
|| match.use[match_no] != WRITE)
|
||||
continue;
|
||||
|
||||
if (match.early_clobber[match_no]
|
||||
&& count_occurrences (PATTERN (insn), src, 0) > 1)
|
||||
continue;
|
||||
|
||||
/* Make sure match_operand is the destination. */
|
||||
if (recog_data.operand[match_no] != SET_DEST (set))
|
||||
continue;
|
||||
|
||||
/* If the operands already match, then there is nothing to do. */
|
||||
if (operands_match_p (src, dst))
|
||||
continue;
|
||||
|
||||
/* But in the commutative case, we might find a better match. */
|
||||
if (match.commutative[op_no] >= 0)
|
||||
{
|
||||
rtx comm = recog_data.operand[match.commutative[op_no]];
|
||||
if (operands_match_p (comm, dst)
|
||||
&& (replacement_quality (comm)
|
||||
>= replacement_quality (src)))
|
||||
continue;
|
||||
}
|
||||
|
||||
src_class = reg_preferred_class (REGNO (src));
|
||||
dst_class = reg_preferred_class (REGNO (dst));
|
||||
if (! regclass_compatible_p (src_class, dst_class))
|
||||
continue;
|
||||
|
||||
if (GET_MODE (src) != GET_MODE (dst))
|
||||
continue;
|
||||
|
||||
if (fixup_match_1 (insn, set, src, src_subreg, dst, pass,
|
||||
op_no, match_no))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1656,478 +1522,6 @@ find_matches (rtx insn, struct match *matchp)
|
|||
return any_matches;
|
||||
}
|
||||
|
||||
/* Try to replace all occurrences of DST_REG with SRC in LOC, that is
|
||||
assumed to be in INSN. */
|
||||
|
||||
static void
|
||||
replace_in_call_usage (rtx *loc, unsigned int dst_reg, rtx src, rtx insn)
|
||||
{
|
||||
rtx x = *loc;
|
||||
enum rtx_code code;
|
||||
const char *fmt;
|
||||
int i, j;
|
||||
|
||||
if (! x)
|
||||
return;
|
||||
|
||||
code = GET_CODE (x);
|
||||
if (code == REG)
|
||||
{
|
||||
if (REGNO (x) != dst_reg)
|
||||
return;
|
||||
|
||||
validate_change (insn, loc, src, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Process each of our operands recursively. */
|
||||
fmt = GET_RTX_FORMAT (code);
|
||||
for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
|
||||
if (*fmt == 'e')
|
||||
replace_in_call_usage (&XEXP (x, i), dst_reg, src, insn);
|
||||
else if (*fmt == 'E')
|
||||
for (j = 0; j < XVECLEN (x, i); j++)
|
||||
replace_in_call_usage (& XVECEXP (x, i, j), dst_reg, src, insn);
|
||||
}
|
||||
|
||||
/* Try to replace output operand DST in SET, with input operand SRC. SET is
|
||||
the only set in INSN. INSN has just been recognized and constrained.
|
||||
SRC is operand number OPERAND_NUMBER in INSN.
|
||||
DST is operand number MATCH_NUMBER in INSN.
|
||||
If BACKWARD is nonzero, we have been called in a backward pass.
|
||||
Return nonzero for success. */
|
||||
|
||||
static int
|
||||
fixup_match_1 (rtx insn, rtx set, rtx src, rtx src_subreg, rtx dst,
|
||||
int backward, int operand_number, int match_number)
|
||||
{
|
||||
rtx p;
|
||||
rtx post_inc = 0, post_inc_set = 0, search_end = 0;
|
||||
int success = 0;
|
||||
int num_calls = 0, freq_calls = 0, s_num_calls = 0, s_freq_calls = 0;
|
||||
enum rtx_code code = NOTE;
|
||||
HOST_WIDE_INT insn_const = 0, newconst = 0;
|
||||
rtx overlap = 0; /* need to move insn ? */
|
||||
rtx src_note = find_reg_note (insn, REG_DEAD, src), dst_note = NULL_RTX;
|
||||
int length, s_length;
|
||||
|
||||
if (! src_note)
|
||||
{
|
||||
/* Look for (set (regX) (op regA constX))
|
||||
(set (regY) (op regA constY))
|
||||
and change that to
|
||||
(set (regA) (op regA constX)).
|
||||
(set (regY) (op regA constY-constX)).
|
||||
This works for add and shift operations, if
|
||||
regA is dead after or set by the second insn. */
|
||||
|
||||
code = GET_CODE (SET_SRC (set));
|
||||
if ((code == PLUS || code == LSHIFTRT
|
||||
|| code == ASHIFT || code == ASHIFTRT)
|
||||
&& XEXP (SET_SRC (set), 0) == src
|
||||
&& GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
|
||||
insn_const = INTVAL (XEXP (SET_SRC (set), 1));
|
||||
else if (! stable_and_no_regs_but_for_p (SET_SRC (set), src, dst))
|
||||
return 0;
|
||||
else
|
||||
/* We might find a src_note while scanning. */
|
||||
code = NOTE;
|
||||
}
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
"Could fix operand %d of insn %d matching operand %d.\n",
|
||||
operand_number, INSN_UID (insn), match_number);
|
||||
|
||||
/* If SRC is equivalent to a constant set in a different basic block,
|
||||
then do not use it for this optimization. We want the equivalence
|
||||
so that if we have to reload this register, we can reload the
|
||||
constant, rather than extending the lifespan of the register. */
|
||||
if (reg_is_remote_constant_p (src, insn))
|
||||
return 0;
|
||||
|
||||
/* Scan forward to find the next instruction that
|
||||
uses the output operand. If the operand dies here,
|
||||
then replace it in both instructions with
|
||||
operand_number. */
|
||||
|
||||
for (length = s_length = 0, p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
|
||||
{
|
||||
if (CALL_P (p))
|
||||
replace_in_call_usage (& CALL_INSN_FUNCTION_USAGE (p),
|
||||
REGNO (dst), src, p);
|
||||
|
||||
/* ??? We can't scan past the end of a basic block without updating
|
||||
the register lifetime info (REG_DEAD/basic_block_live_at_start). */
|
||||
if (perhaps_ends_bb_p (p))
|
||||
break;
|
||||
else if (! INSN_P (p))
|
||||
continue;
|
||||
|
||||
length++;
|
||||
if (src_note)
|
||||
s_length++;
|
||||
|
||||
if (reg_set_p (src, p) || reg_set_p (dst, p)
|
||||
|| (GET_CODE (PATTERN (p)) == USE
|
||||
&& reg_overlap_mentioned_p (src, XEXP (PATTERN (p), 0))))
|
||||
break;
|
||||
|
||||
/* See if all of DST dies in P. This test is
|
||||
slightly more conservative than it needs to be. */
|
||||
if ((dst_note = find_regno_note (p, REG_DEAD, REGNO (dst)))
|
||||
&& (GET_MODE (XEXP (dst_note, 0)) == GET_MODE (dst)))
|
||||
{
|
||||
/* If we would be moving INSN, check that we won't move it
|
||||
into the shadow of a live a live flags register. */
|
||||
/* ??? We only try to move it in front of P, although
|
||||
we could move it anywhere between OVERLAP and P. */
|
||||
if (overlap && GET_MODE (PREV_INSN (p)) != VOIDmode)
|
||||
break;
|
||||
|
||||
if (! src_note)
|
||||
{
|
||||
rtx q;
|
||||
rtx set2 = NULL_RTX;
|
||||
|
||||
/* If an optimization is done, the value of SRC while P
|
||||
is executed will be changed. Check that this is OK. */
|
||||
if (reg_overlap_mentioned_p (src, PATTERN (p)))
|
||||
break;
|
||||
for (q = p; q; q = NEXT_INSN (q))
|
||||
{
|
||||
/* ??? We can't scan past the end of a basic block without
|
||||
updating the register lifetime info
|
||||
(REG_DEAD/basic_block_live_at_start). */
|
||||
if (perhaps_ends_bb_p (q))
|
||||
{
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
else if (! INSN_P (q))
|
||||
continue;
|
||||
else if (reg_overlap_mentioned_p (src, PATTERN (q))
|
||||
|| reg_set_p (src, q))
|
||||
break;
|
||||
}
|
||||
if (q)
|
||||
set2 = single_set (q);
|
||||
if (! q || ! set2 || GET_CODE (SET_SRC (set2)) != code
|
||||
|| XEXP (SET_SRC (set2), 0) != src
|
||||
|| GET_CODE (XEXP (SET_SRC (set2), 1)) != CONST_INT
|
||||
|| (SET_DEST (set2) != src
|
||||
&& ! find_reg_note (q, REG_DEAD, src)))
|
||||
{
|
||||
/* If this is a PLUS, we can still save a register by doing
|
||||
src += insn_const;
|
||||
P;
|
||||
src -= insn_const; .
|
||||
This also gives opportunities for subsequent
|
||||
optimizations in the backward pass, so do it there. */
|
||||
if (code == PLUS && backward
|
||||
/* Don't do this if we can likely tie DST to SET_DEST
|
||||
of P later; we can't do this tying here if we got a
|
||||
hard register. */
|
||||
&& ! (dst_note && ! REG_N_CALLS_CROSSED (REGNO (dst))
|
||||
&& single_set (p)
|
||||
&& REG_P (SET_DEST (single_set (p)))
|
||||
&& (REGNO (SET_DEST (single_set (p)))
|
||||
< FIRST_PSEUDO_REGISTER))
|
||||
/* We may only emit an insn directly after P if we
|
||||
are not in the shadow of a live flags register. */
|
||||
&& GET_MODE (p) == VOIDmode)
|
||||
{
|
||||
search_end = q;
|
||||
q = insn;
|
||||
set2 = set;
|
||||
newconst = -insn_const;
|
||||
code = MINUS;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
newconst = INTVAL (XEXP (SET_SRC (set2), 1)) - insn_const;
|
||||
/* Reject out of range shifts. */
|
||||
if (code != PLUS
|
||||
&& (newconst < 0
|
||||
|| ((unsigned HOST_WIDE_INT) newconst
|
||||
>= (GET_MODE_BITSIZE (GET_MODE
|
||||
(SET_SRC (set2)))))))
|
||||
break;
|
||||
if (code == PLUS)
|
||||
{
|
||||
post_inc = q;
|
||||
if (SET_DEST (set2) != src)
|
||||
post_inc_set = set2;
|
||||
}
|
||||
}
|
||||
/* We use 1 as last argument to validate_change so that all
|
||||
changes are accepted or rejected together by apply_change_group
|
||||
when it is called by validate_replace_rtx . */
|
||||
validate_change (q, &XEXP (SET_SRC (set2), 1),
|
||||
GEN_INT (newconst), 1);
|
||||
}
|
||||
validate_change (insn, recog_data.operand_loc[match_number], src, 1);
|
||||
if (validate_replace_rtx (dst, src_subreg, p))
|
||||
success = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (reg_overlap_mentioned_p (dst, PATTERN (p)))
|
||||
break;
|
||||
if (! src_note && reg_overlap_mentioned_p (src, PATTERN (p)))
|
||||
{
|
||||
/* INSN was already checked to be movable wrt. the registers that it
|
||||
sets / uses when we found no REG_DEAD note for src on it, but it
|
||||
still might clobber the flags register. We'll have to check that
|
||||
we won't insert it into the shadow of a live flags register when
|
||||
we finally know where we are to move it. */
|
||||
overlap = p;
|
||||
src_note = find_reg_note (p, REG_DEAD, src);
|
||||
}
|
||||
|
||||
/* If we have passed a call instruction, and the pseudo-reg SRC is not
|
||||
already live across a call, then don't perform the optimization. */
|
||||
if (CALL_P (p))
|
||||
{
|
||||
if (REG_N_CALLS_CROSSED (REGNO (src)) == 0)
|
||||
break;
|
||||
|
||||
num_calls++;
|
||||
freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (p));
|
||||
|
||||
if (src_note)
|
||||
{
|
||||
s_num_calls++;
|
||||
s_freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! success)
|
||||
return 0;
|
||||
|
||||
/* Remove the death note for DST from P. */
|
||||
remove_note (p, dst_note);
|
||||
if (code == MINUS)
|
||||
{
|
||||
post_inc = emit_insn_after (copy_rtx (PATTERN (insn)), p);
|
||||
if ((HAVE_PRE_INCREMENT || HAVE_PRE_DECREMENT)
|
||||
&& search_end
|
||||
&& try_auto_increment (search_end, post_inc, 0, src, newconst, 1))
|
||||
post_inc = 0;
|
||||
validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (insn_const), 0);
|
||||
INC_REG_N_SETS (REGNO (src), 1);
|
||||
REG_LIVE_LENGTH (REGNO (src))++;
|
||||
}
|
||||
if (overlap)
|
||||
{
|
||||
/* The lifetime of src and dest overlap,
|
||||
but we can change this by moving insn. */
|
||||
rtx pat = PATTERN (insn);
|
||||
if (src_note)
|
||||
remove_note (overlap, src_note);
|
||||
if ((HAVE_POST_INCREMENT || HAVE_POST_DECREMENT)
|
||||
&& code == PLUS
|
||||
&& try_auto_increment (overlap, insn, 0, src, insn_const, 0))
|
||||
insn = overlap;
|
||||
else
|
||||
{
|
||||
rtx notes = REG_NOTES (insn);
|
||||
|
||||
p = emit_insn_after_setloc (pat, PREV_INSN (p), INSN_LOCATOR (insn));
|
||||
delete_insn (insn);
|
||||
REG_NOTES (p) = notes;
|
||||
df_notes_rescan (p);
|
||||
}
|
||||
}
|
||||
/* Sometimes we'd generate src = const; src += n;
|
||||
if so, replace the instruction that set src
|
||||
in the first place. */
|
||||
|
||||
if (! overlap && (code == PLUS || code == MINUS))
|
||||
{
|
||||
rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
|
||||
rtx q, set2 = NULL_RTX;
|
||||
int num_calls2 = 0, s_length2 = 0, freq_calls2 = 0;
|
||||
|
||||
if (note && CONSTANT_P (XEXP (note, 0)))
|
||||
{
|
||||
for (q = PREV_INSN (insn); q; q = PREV_INSN (q))
|
||||
{
|
||||
/* ??? We can't scan past the end of a basic block without
|
||||
updating the register lifetime info
|
||||
(REG_DEAD/basic_block_live_at_start). */
|
||||
if (perhaps_ends_bb_p (q))
|
||||
{
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
else if (! INSN_P (q))
|
||||
continue;
|
||||
|
||||
s_length2++;
|
||||
if (reg_set_p (src, q))
|
||||
{
|
||||
set2 = single_set (q);
|
||||
break;
|
||||
}
|
||||
if (reg_overlap_mentioned_p (src, PATTERN (q)))
|
||||
{
|
||||
q = 0;
|
||||
break;
|
||||
}
|
||||
if (CALL_P (p))
|
||||
{
|
||||
num_calls2++;
|
||||
freq_calls2 += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (p));
|
||||
}
|
||||
}
|
||||
if (q && set2 && SET_DEST (set2) == src && CONSTANT_P (SET_SRC (set2))
|
||||
&& validate_change (insn, &SET_SRC (set), XEXP (note, 0), 0))
|
||||
{
|
||||
delete_insn (q);
|
||||
INC_REG_N_SETS (REGNO (src), -1);
|
||||
REG_N_CALLS_CROSSED (REGNO (src)) -= num_calls2;
|
||||
REG_FREQ_CALLS_CROSSED (REGNO (src)) -= freq_calls2;
|
||||
REG_LIVE_LENGTH (REGNO (src)) -= s_length2;
|
||||
insn_const = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((HAVE_PRE_INCREMENT || HAVE_PRE_DECREMENT)
|
||||
&& (code == PLUS || code == MINUS) && insn_const
|
||||
&& try_auto_increment (p, insn, 0, src, insn_const, 1))
|
||||
insn = p;
|
||||
else if ((HAVE_POST_INCREMENT || HAVE_POST_DECREMENT)
|
||||
&& post_inc
|
||||
&& try_auto_increment (p, post_inc, post_inc_set, src, newconst, 0))
|
||||
post_inc = 0;
|
||||
/* If post_inc still prevails, try to find an
|
||||
insn where it can be used as a pre-in/decrement.
|
||||
If code is MINUS, this was already tried. */
|
||||
if (post_inc && code == PLUS
|
||||
/* Check that newconst is likely to be usable
|
||||
in a pre-in/decrement before starting the search. */
|
||||
&& ((HAVE_PRE_INCREMENT && newconst > 0 && newconst <= MOVE_MAX)
|
||||
|| (HAVE_PRE_DECREMENT && newconst < 0 && newconst >= -MOVE_MAX))
|
||||
&& exact_log2 (newconst))
|
||||
{
|
||||
rtx q, inc_dest;
|
||||
|
||||
inc_dest = post_inc_set ? SET_DEST (post_inc_set) : src;
|
||||
for (q = post_inc; (q = NEXT_INSN (q)); )
|
||||
{
|
||||
/* ??? We can't scan past the end of a basic block without updating
|
||||
the register lifetime info
|
||||
(REG_DEAD/basic_block_live_at_start). */
|
||||
if (perhaps_ends_bb_p (q))
|
||||
break;
|
||||
else if (! INSN_P (q))
|
||||
continue;
|
||||
else if (src != inc_dest
|
||||
&& (reg_overlap_mentioned_p (src, PATTERN (q))
|
||||
|| reg_set_p (src, q)))
|
||||
break;
|
||||
else if (reg_set_p (inc_dest, q))
|
||||
break;
|
||||
else if (reg_overlap_mentioned_p (inc_dest, PATTERN (q)))
|
||||
{
|
||||
try_auto_increment (q, post_inc,
|
||||
post_inc_set, inc_dest, newconst, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Move the death note for DST to INSN if it is used
|
||||
there. */
|
||||
if (reg_overlap_mentioned_p (dst, PATTERN (insn)))
|
||||
{
|
||||
XEXP (dst_note, 1) = REG_NOTES (insn);
|
||||
REG_NOTES (insn) = dst_note;
|
||||
}
|
||||
|
||||
if (src_note)
|
||||
{
|
||||
/* Move the death note for SRC from INSN to P. */
|
||||
if (! overlap)
|
||||
remove_note (insn, src_note);
|
||||
XEXP (src_note, 1) = REG_NOTES (p);
|
||||
REG_NOTES (p) = src_note;
|
||||
|
||||
REG_N_CALLS_CROSSED (REGNO (src)) += s_num_calls;
|
||||
REG_FREQ_CALLS_CROSSED (REGNO (src)) += s_freq_calls;
|
||||
}
|
||||
|
||||
INC_REG_N_SETS (REGNO (src), 1);
|
||||
INC_REG_N_SETS (REGNO (dst), -1);
|
||||
|
||||
REG_N_CALLS_CROSSED (REGNO (dst)) -= num_calls;
|
||||
REG_FREQ_CALLS_CROSSED (REGNO (dst)) -= freq_calls;
|
||||
|
||||
REG_LIVE_LENGTH (REGNO (src)) += s_length;
|
||||
if (REG_LIVE_LENGTH (REGNO (dst)) >= 0)
|
||||
{
|
||||
REG_LIVE_LENGTH (REGNO (dst)) -= length;
|
||||
/* REG_LIVE_LENGTH is only an approximation after
|
||||
combine if sched is not run, so make sure that we
|
||||
still have a reasonable value. */
|
||||
if (REG_LIVE_LENGTH (REGNO (dst)) < 2)
|
||||
REG_LIVE_LENGTH (REGNO (dst)) = 2;
|
||||
}
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
"Fixed operand %d of insn %d matching operand %d.\n",
|
||||
operand_number, INSN_UID (insn), match_number);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Return nonzero if X is stable and mentions no registers but for
|
||||
mentioning SRC or mentioning / changing DST . If in doubt, presume
|
||||
it is unstable.
|
||||
The rationale is that we want to check if we can move an insn easily
|
||||
while just paying attention to SRC and DST. */
|
||||
static int
|
||||
stable_and_no_regs_but_for_p (rtx x, rtx src, rtx dst)
|
||||
{
|
||||
RTX_CODE code = GET_CODE (x);
|
||||
switch (GET_RTX_CLASS (code))
|
||||
{
|
||||
case RTX_UNARY:
|
||||
case RTX_BIN_ARITH:
|
||||
case RTX_COMM_ARITH:
|
||||
case RTX_COMPARE:
|
||||
case RTX_COMM_COMPARE:
|
||||
case RTX_TERNARY:
|
||||
case RTX_BITFIELD_OPS:
|
||||
{
|
||||
int i;
|
||||
const char *fmt = GET_RTX_FORMAT (code);
|
||||
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
||||
if (fmt[i] == 'e'
|
||||
&& ! stable_and_no_regs_but_for_p (XEXP (x, i), src, dst))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
case RTX_OBJ:
|
||||
if (code == REG)
|
||||
return x == src || x == dst;
|
||||
/* If this is a MEM, look inside - there might be a register hidden in
|
||||
the address of an unchanging MEM. */
|
||||
if (code == MEM
|
||||
&& ! stable_and_no_regs_but_for_p (XEXP (x, 0), src, dst))
|
||||
return 0;
|
||||
/* Fall through. */
|
||||
default:
|
||||
return ! rtx_unstable_p (x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
|
|
|
@ -1549,9 +1549,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
|
|||
&& reg_mentioned_p (XEXP (note, 0), in)
|
||||
/* Check that a former pseudo is valid; see find_dummy_reload. */
|
||||
&& (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
|
||||
|| (! bitmap_bit_p (flag_ira
|
||||
? DF_LR_OUT (ENTRY_BLOCK_PTR)
|
||||
: DF_LIVE_OUT (ENTRY_BLOCK_PTR),
|
||||
|| (! bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
|
||||
ORIGINAL_REGNO (XEXP (note, 0)))
|
||||
&& hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))] == 1))
|
||||
&& ! refers_to_regno_for_reload_p (regno,
|
||||
|
@ -2029,9 +2027,7 @@ find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
|
|||
can ignore the conflict). We must never introduce writes
|
||||
to such hardregs, as they would clobber the other live
|
||||
pseudo. See PR 20973. */
|
||||
|| (!bitmap_bit_p (flag_ira
|
||||
? DF_LR_OUT (ENTRY_BLOCK_PTR)
|
||||
: DF_LIVE_OUT (ENTRY_BLOCK_PTR),
|
||||
|| (!bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
|
||||
ORIGINAL_REGNO (in))
|
||||
/* Similarly, only do this if we can be sure that the death
|
||||
note is still valid. global can assign some hardreg to
|
||||
|
|
|
@ -557,7 +557,7 @@ compute_use_by_pseudos (HARD_REG_SET *to, regset from)
|
|||
which might still contain registers that have not
|
||||
actually been allocated since they have an
|
||||
equivalence. */
|
||||
gcc_assert ((flag_ira && ira_conflicts_p) || reload_completed);
|
||||
gcc_assert (ira_conflicts_p || reload_completed);
|
||||
}
|
||||
else
|
||||
add_to_hard_reg_set (to, PSEUDO_REGNO_MODE (regno), r);
|
||||
|
@ -901,7 +901,7 @@ reload (rtx first, int global)
|
|||
for (n = 0, i = LAST_VIRTUAL_REGISTER + 1; i < max_regno; i++)
|
||||
temp_pseudo_reg_arr[n++] = i;
|
||||
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
if (ira_conflicts_p)
|
||||
/* Ask IRA to order pseudo-registers for better stack slot
|
||||
sharing. */
|
||||
ira_sort_regnos_for_alter_reg (temp_pseudo_reg_arr, n, reg_max_ref_width);
|
||||
|
@ -1055,7 +1055,7 @@ reload (rtx first, int global)
|
|||
|
||||
calculate_needs_all_insns (global);
|
||||
|
||||
if (! flag_ira || ! ira_conflicts_p)
|
||||
if (! ira_conflicts_p)
|
||||
/* Don't do it for IRA. We need this info because we don't
|
||||
change live_throughout and dead_or_set for chains when IRA
|
||||
is used. */
|
||||
|
@ -1614,7 +1614,7 @@ calculate_needs_all_insns (int global)
|
|||
reg_equiv_memory_loc
|
||||
[REGNO (SET_DEST (set))]))))
|
||||
{
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
if (ira_conflicts_p)
|
||||
/* Inform IRA about the insn deletion. */
|
||||
ira_mark_memory_move_deletion (REGNO (SET_DEST (set)),
|
||||
REGNO (SET_SRC (set)));
|
||||
|
@ -1723,7 +1723,7 @@ count_pseudo (int reg)
|
|||
|| REGNO_REG_SET_P (&spilled_pseudos, reg)
|
||||
/* Ignore spilled pseudo-registers which can be here only if IRA
|
||||
is used. */
|
||||
|| (flag_ira && ira_conflicts_p && r < 0))
|
||||
|| (ira_conflicts_p && r < 0))
|
||||
return;
|
||||
|
||||
SET_REGNO_REG_SET (&pseudos_counted, reg);
|
||||
|
@ -1804,7 +1804,7 @@ count_spilled_pseudo (int spilled, int spilled_nregs, int reg)
|
|||
|
||||
/* Ignore spilled pseudo-registers which can be here only if IRA is
|
||||
used. */
|
||||
if ((flag_ira && ira_conflicts_p && r < 0)
|
||||
if ((ira_conflicts_p && r < 0)
|
||||
|| REGNO_REG_SET_P (&spilled_pseudos, reg)
|
||||
|| spilled + spilled_nregs <= r || r + nregs <= spilled)
|
||||
return;
|
||||
|
@ -1876,7 +1876,7 @@ find_reg (struct insn_chain *chain, int order)
|
|||
if (! ok)
|
||||
continue;
|
||||
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
if (ira_conflicts_p)
|
||||
{
|
||||
/* Ask IRA to find a better pseudo-register for
|
||||
spilling. */
|
||||
|
@ -2158,7 +2158,7 @@ alter_reg (int i, int from_reg, bool dont_share_p)
|
|||
unsigned int min_align = reg_max_ref_width[i] * BITS_PER_UNIT;
|
||||
int adjust = 0;
|
||||
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
if (ira_conflicts_p)
|
||||
{
|
||||
/* Mark the spill for IRA. */
|
||||
SET_REGNO_REG_SET (&spilled_pseudos, i);
|
||||
|
@ -2177,8 +2177,7 @@ alter_reg (int i, int from_reg, bool dont_share_p)
|
|||
enough inherent space and enough total space.
|
||||
Otherwise, we allocate a new slot, making sure that it has no less
|
||||
inherent space, and no less total space, then the previous slot. */
|
||||
else if (from_reg == -1
|
||||
|| (!dont_share_p && flag_ira && ira_conflicts_p))
|
||||
else if (from_reg == -1 || (!dont_share_p && ira_conflicts_p))
|
||||
{
|
||||
rtx stack_slot;
|
||||
|
||||
|
@ -2203,7 +2202,7 @@ alter_reg (int i, int from_reg, bool dont_share_p)
|
|||
adjust);
|
||||
}
|
||||
|
||||
if (! dont_share_p && flag_ira && ira_conflicts_p)
|
||||
if (! dont_share_p && ira_conflicts_p)
|
||||
/* Inform IRA about allocation a new stack slot. */
|
||||
ira_mark_new_stack_slot (stack_slot, i, total_size);
|
||||
}
|
||||
|
@ -3905,7 +3904,7 @@ finish_spills (int global)
|
|||
spill_reg_order[i] = -1;
|
||||
|
||||
EXECUTE_IF_SET_IN_REG_SET (&spilled_pseudos, FIRST_PSEUDO_REGISTER, i, rsi)
|
||||
if (! flag_ira || ! ira_conflicts_p || reg_renumber[i] >= 0)
|
||||
if (! ira_conflicts_p || reg_renumber[i] >= 0)
|
||||
{
|
||||
/* Record the current hard register the pseudo is allocated to
|
||||
in pseudo_previous_regs so we avoid reallocating it to the
|
||||
|
@ -3915,7 +3914,7 @@ finish_spills (int global)
|
|||
SET_HARD_REG_BIT (pseudo_previous_regs[i], reg_renumber[i]);
|
||||
/* Mark it as no longer having a hard register home. */
|
||||
reg_renumber[i] = -1;
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
if (ira_conflicts_p)
|
||||
/* Inform IRA about the change. */
|
||||
ira_mark_allocation_change (i);
|
||||
/* We will need to scan everything again. */
|
||||
|
@ -3923,8 +3922,10 @@ finish_spills (int global)
|
|||
}
|
||||
|
||||
/* Retry global register allocation if possible. */
|
||||
if (global)
|
||||
if (global && ira_conflicts_p)
|
||||
{
|
||||
unsigned int n;
|
||||
|
||||
memset (pseudo_forbidden_regs, 0, max_regno * sizeof (HARD_REG_SET));
|
||||
/* For every insn that needs reloads, set the registers used as spill
|
||||
regs in pseudo_forbidden_regs for every pseudo live across the
|
||||
|
@ -3945,49 +3946,23 @@ finish_spills (int global)
|
|||
}
|
||||
}
|
||||
|
||||
if (! flag_ira || ! ira_conflicts_p)
|
||||
{
|
||||
/* Retry allocating the spilled pseudos. For each reg,
|
||||
merge the various reg sets that indicate which hard regs
|
||||
can't be used, and call retry_global_alloc. We change
|
||||
spill_pseudos here to only contain pseudos that did not
|
||||
get a new hard register. */
|
||||
for (i = FIRST_PSEUDO_REGISTER; i < (unsigned)max_regno; i++)
|
||||
if (reg_old_renumber[i] != reg_renumber[i])
|
||||
{
|
||||
HARD_REG_SET forbidden;
|
||||
|
||||
COPY_HARD_REG_SET (forbidden, bad_spill_regs_global);
|
||||
IOR_HARD_REG_SET (forbidden, pseudo_forbidden_regs[i]);
|
||||
IOR_HARD_REG_SET (forbidden, pseudo_previous_regs[i]);
|
||||
retry_global_alloc (i, forbidden);
|
||||
if (reg_renumber[i] >= 0)
|
||||
CLEAR_REGNO_REG_SET (&spilled_pseudos, i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Retry allocating the pseudos spilled in IRA and the
|
||||
reload. For each reg, merge the various reg sets that
|
||||
indicate which hard regs can't be used, and call
|
||||
ira_reassign_pseudos. */
|
||||
unsigned int n;
|
||||
|
||||
for (n = 0, i = FIRST_PSEUDO_REGISTER; i < (unsigned) max_regno; i++)
|
||||
if (reg_old_renumber[i] != reg_renumber[i])
|
||||
{
|
||||
if (reg_renumber[i] < 0)
|
||||
temp_pseudo_reg_arr[n++] = i;
|
||||
else
|
||||
CLEAR_REGNO_REG_SET (&spilled_pseudos, i);
|
||||
}
|
||||
if (ira_reassign_pseudos (temp_pseudo_reg_arr, n,
|
||||
bad_spill_regs_global,
|
||||
pseudo_forbidden_regs, pseudo_previous_regs,
|
||||
&spilled_pseudos))
|
||||
something_changed = 1;
|
||||
|
||||
}
|
||||
/* Retry allocating the pseudos spilled in IRA and the
|
||||
reload. For each reg, merge the various reg sets that
|
||||
indicate which hard regs can't be used, and call
|
||||
ira_reassign_pseudos. */
|
||||
for (n = 0, i = FIRST_PSEUDO_REGISTER; i < (unsigned) max_regno; i++)
|
||||
if (reg_old_renumber[i] != reg_renumber[i])
|
||||
{
|
||||
if (reg_renumber[i] < 0)
|
||||
temp_pseudo_reg_arr[n++] = i;
|
||||
else
|
||||
CLEAR_REGNO_REG_SET (&spilled_pseudos, i);
|
||||
}
|
||||
if (ira_reassign_pseudos (temp_pseudo_reg_arr, n,
|
||||
bad_spill_regs_global,
|
||||
pseudo_forbidden_regs, pseudo_previous_regs,
|
||||
&spilled_pseudos))
|
||||
something_changed = 1;
|
||||
}
|
||||
/* Fix up the register information in the insn chain.
|
||||
This involves deleting those of the spilled pseudos which did not get
|
||||
|
@ -3997,7 +3972,7 @@ finish_spills (int global)
|
|||
HARD_REG_SET used_by_pseudos;
|
||||
HARD_REG_SET used_by_pseudos2;
|
||||
|
||||
if (! flag_ira || ! ira_conflicts_p)
|
||||
if (! ira_conflicts_p)
|
||||
{
|
||||
/* Don't do it for IRA because IRA and the reload still can
|
||||
assign hard registers to the spilled pseudos on next
|
||||
|
@ -7000,7 +6975,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
|
|||
&& REG_N_SETS (REGNO (old)) == 1)
|
||||
{
|
||||
reg_renumber[REGNO (old)] = REGNO (reloadreg);
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
if (ira_conflicts_p)
|
||||
/* Inform IRA about the change. */
|
||||
ira_mark_allocation_change (REGNO (old));
|
||||
alter_reg (REGNO (old), -1, false);
|
||||
|
@ -8541,7 +8516,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
|
|||
|
||||
/* For the debugging info, say the pseudo lives in this reload reg. */
|
||||
reg_renumber[REGNO (reg)] = REGNO (new_reload_reg);
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
if (ira_conflicts_p)
|
||||
/* Inform IRA about the change. */
|
||||
ira_mark_allocation_change (REGNO (reg));
|
||||
alter_reg (REGNO (reg), -1, false);
|
||||
|
|
12
gcc/rtl.h
12
gcc/rtl.h
|
@ -2212,17 +2212,11 @@ extern void expand_dec (rtx, rtx);
|
|||
extern bool can_copy_p (enum machine_mode);
|
||||
extern rtx fis_get_condition (rtx);
|
||||
|
||||
/* In global.c */
|
||||
/* In ira.c */
|
||||
#ifdef HARD_CONST
|
||||
extern HARD_REG_SET eliminable_regset;
|
||||
#endif
|
||||
extern void mark_elimination (int, int);
|
||||
extern void dump_global_regs (FILE *);
|
||||
#ifdef HARD_CONST
|
||||
/* Yes, this ifdef is silly, but HARD_REG_SET is not always defined. */
|
||||
extern void retry_global_alloc (int, HARD_REG_SET);
|
||||
#endif
|
||||
extern void build_insn_chain (void);
|
||||
|
||||
/* In regclass.c */
|
||||
extern int reg_classes_intersect_p (enum reg_class, enum reg_class);
|
||||
|
@ -2247,10 +2241,6 @@ extern bool invalid_mode_change_p (unsigned int, enum reg_class,
|
|||
/* In reorg.c */
|
||||
extern void dbr_schedule (rtx);
|
||||
|
||||
/* In local-alloc.c */
|
||||
extern void dump_local_alloc (FILE *);
|
||||
extern int update_equiv_regs (void);
|
||||
|
||||
/* In reload1.c */
|
||||
extern int function_invariant_p (const_rtx);
|
||||
|
||||
|
|
|
@ -140,7 +140,6 @@ extern int flag_unroll_all_loops;
|
|||
extern int flag_unswitch_loops;
|
||||
extern int flag_cprop_registers;
|
||||
extern int time_report;
|
||||
extern int flag_ira;
|
||||
extern int flag_ira_coalesce;
|
||||
extern int flag_ira_move_spills;
|
||||
extern int flag_ira_share_save_slots;
|
||||
|
|
|
@ -450,7 +450,7 @@ extern struct rtl_opt_pass pass_web;
|
|||
extern struct rtl_opt_pass pass_cse2;
|
||||
extern struct rtl_opt_pass pass_df_initialize_opt;
|
||||
extern struct rtl_opt_pass pass_df_initialize_no_opt;
|
||||
extern struct rtl_opt_pass pass_regclass_init;
|
||||
extern struct rtl_opt_pass pass_reginfo_init;
|
||||
extern struct rtl_opt_pass pass_subregs_of_mode_init;
|
||||
extern struct rtl_opt_pass pass_subregs_of_mode_finish;
|
||||
extern struct rtl_opt_pass pass_inc_dec;
|
||||
|
@ -468,8 +468,6 @@ extern struct rtl_opt_pass pass_mode_switching;
|
|||
extern struct rtl_opt_pass pass_see;
|
||||
extern struct rtl_opt_pass pass_sms;
|
||||
extern struct rtl_opt_pass pass_sched;
|
||||
extern struct rtl_opt_pass pass_local_alloc;
|
||||
extern struct rtl_opt_pass pass_global_alloc;
|
||||
extern struct rtl_opt_pass pass_ira;
|
||||
extern struct rtl_opt_pass pass_postreload;
|
||||
extern struct rtl_opt_pass pass_clean_state;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue