mirror of git://gcc.gnu.org/git/gcc.git
regmove.c: Remove.
2013-10-30 Vladimir Makarov <vmakarov@redhat.com> * regmove.c: Remove. * tree-pass.h (make_pass_regmove): Remove. * timevar.def (TV_REGMOVE): Remove. * passes.def (pass_regmove): Remove. * opts.c (default_options_table): Remove entry for regmove. * doc/passes.texi: Remove regmove pass description. * doc/invoke.texi (-foptimize-register-move, -fregmove): Remove options. (-fdump-rtl-regmove): Ditto. * common.opt (foptimize-register-move, fregmove): Ignore. * Makefile.in (OBJS): Remove regmove.o. * regmove.c: Remove. * ira-int.h (struct ira_allocno_pref, ira_pref_t): New structure and type. (struct ira_allocno) New member allocno_prefs. (ALLOCNO_PREFS): New macro. (ira_prefs, ira_prefs_num): New external vars. (ira_setup_alts, ira_get_dup_out_num, ira_debug_pref): New prototypes. (ira_debug_prefs, ira_debug_allocno_prefs, ira_create_pref): Ditto. (ira_add_allocno_pref, ira_remove_pref, ira_remove_allocno_prefs): Ditto. (ira_add_allocno_copy_to_list): Remove prototype. (ira_swap_allocno_copy_ends_if_necessary): Ditto. (ira_pref_iterator): New type. (ira_pref_iter_init, ira_pref_iter_cond): New functions. (FOR_EACH_PREF): New macro. * ira.c (commutative_constraint_p): Move from ira-conflicts.c. (ira_get_dup_out_num): Ditto. Rename from get_dup_num. Modify the code. (ira_setup_alts): New function. (decrease_live_ranges_number): New function. (ira): Call the above function. * ira-build.c (ira_prefs, ira_prefs_num): New global vars. (ira_create_allocno): Initialize allocno prefs. (pref_pool, pref_vec): New static vars. (initiate_prefs, find_allocno_pref, ira_create_pref): New functions. (add_allocno_pref_to_list, ira_add_allocno_pref, print_pref): Ditto. (ira_debug_pref, print_prefs, ira_debug_prefs): Ditto. (print_allocno_prefs, ira_debug_allocno_prefs, finish_pref): Ditto. (ira_remove_pref, ira_remove_allocno_prefs, finish_prefs): Ditto. (ira_add_allocno_copy_to_list): Make static. Rename to add_allocno_copy_to_list. (ira_swap_allocno_copy_ends_if_necessary): Make static. Rename to swap_allocno_copy_ends_if_necessary. (remove_unnecessary_allocnos, remove_low_level_allocnos): Call ira_remove_allocno_prefs. (ira_flattening): Ditto. (ira_build): Call initiate_prefs, print_prefs. (ira_destroy): Call finish_prefs. * ira-color.c (struct update_cost_record): New. (struct allocno_color_data): Add new member update_cost_records. (update_cost_record_pool): New static var. (init_update_cost_records, get_update_cost_record): New functions. (free_update_cost_record_list, finish_update_cost_records): Ditto. (struct update_cost_queue_elem): Add member from. (initiate_cost_update): Call init_update_cost_records. (finish_cost_update): Call finish_update_cost_records. (queue_update_cost, get_next_update_cost): Add new param from. (Update_allocno_cost, update_costs_from_allocno): New functions. (update_costs_from_prefs): Ditto. (update_copy_costs): Rename to update_costs_from_copies. (restore_costs_from_copies): New function. (update_conflict_hard_regno_costs): Don't go back. (assign_hard_reg): Call restore_costs_from_copies. Add printing more debug info. (pop_allocnos): Add priniting more debug info. (color_allocnos): Remove prefs for conflicting hard regs. Call update_costs_from_prefs. * ira-conflicts.c (commutative_constraint_p): Move to ira.c (get_dup_num): Rename, modify, and move to ira.c (process_regs_for_copy): Add prefs. (add_insn_allocno_copies): Put src as first arg of process_regs_for_copy. Remove dead code. Call ira_setup_alts. * ira-costs.c (record_reg_classes): Modify and move code into record_operands_costs. (find_costs_and_classes): Create prefs for the hard reg of small reg class. (process_bb_node_for_hard_reg_moves): Add prefs. 2013-10-30 Vladimir Makarov <vmakarov@redhat.com> * gcc.target/i386/fma_double_3.c: Use pattern for scan-assembler-times instead of just one insn name. * gcc.target/i386/fma_double_5.c: Ditto. * gcc.target/i386/fma_float_3.c: Ditto. * gcc.target/i386/fma_float_5.c: Ditto. * gcc.target/i386/l_fma_double_1.c: Ditto. * gcc.target/i386/l_fma_double_2.c: Ditto. * gcc.target/i386/l_fma_double_3.c: Ditto. * gcc.target/i386/l_fma_double_4.c: Ditto. * gcc.target/i386/l_fma_double_5.c: Ditto. * gcc.target/i386/l_fma_double_6.c: Ditto. * gcc.target/i386/l_fma_float_1.c: Ditto. * gcc.target/i386/l_fma_float_2.c: Ditto. * gcc.target/i386/l_fma_float_3.c: Ditto. * gcc.target/i386/l_fma_float_4.c: Ditto. * gcc.target/i386/l_fma_float_5.c: Ditto. * gcc.target/i386/l_fma_float_6.c: Ditto. From-SVN: r204212
This commit is contained in:
parent
1bef9b2340
commit
3b6d16993b
|
|
@ -1,3 +1,87 @@
|
||||||
|
2013-10-30 Vladimir Makarov <vmakarov@redhat.com>
|
||||||
|
|
||||||
|
* regmove.c: Remove.
|
||||||
|
* tree-pass.h (make_pass_regmove): Remove.
|
||||||
|
* timevar.def (TV_REGMOVE): Remove.
|
||||||
|
* passes.def (pass_regmove): Remove.
|
||||||
|
* opts.c (default_options_table): Remove entry for regmove.
|
||||||
|
* doc/passes.texi: Remove regmove pass description.
|
||||||
|
* doc/invoke.texi (-foptimize-register-move, -fregmove): Remove
|
||||||
|
options.
|
||||||
|
(-fdump-rtl-regmove): Ditto.
|
||||||
|
* common.opt (foptimize-register-move, fregmove): Ignore.
|
||||||
|
* Makefile.in (OBJS): Remove regmove.o.
|
||||||
|
* regmove.c: Remove.
|
||||||
|
* ira-int.h (struct ira_allocno_pref, ira_pref_t): New structure
|
||||||
|
and type.
|
||||||
|
(struct ira_allocno) New member allocno_prefs.
|
||||||
|
(ALLOCNO_PREFS): New macro.
|
||||||
|
(ira_prefs, ira_prefs_num): New external vars.
|
||||||
|
(ira_setup_alts, ira_get_dup_out_num, ira_debug_pref): New
|
||||||
|
prototypes.
|
||||||
|
(ira_debug_prefs, ira_debug_allocno_prefs, ira_create_pref):
|
||||||
|
Ditto.
|
||||||
|
(ira_add_allocno_pref, ira_remove_pref, ira_remove_allocno_prefs):
|
||||||
|
Ditto.
|
||||||
|
(ira_add_allocno_copy_to_list): Remove prototype.
|
||||||
|
(ira_swap_allocno_copy_ends_if_necessary): Ditto.
|
||||||
|
(ira_pref_iterator): New type.
|
||||||
|
(ira_pref_iter_init, ira_pref_iter_cond): New functions.
|
||||||
|
(FOR_EACH_PREF): New macro.
|
||||||
|
* ira.c (commutative_constraint_p): Move from ira-conflicts.c.
|
||||||
|
(ira_get_dup_out_num): Ditto. Rename from get_dup_num. Modify the
|
||||||
|
code.
|
||||||
|
(ira_setup_alts): New function.
|
||||||
|
(decrease_live_ranges_number): New function.
|
||||||
|
(ira): Call the above function.
|
||||||
|
* ira-build.c (ira_prefs, ira_prefs_num): New global vars.
|
||||||
|
(ira_create_allocno): Initialize allocno prefs.
|
||||||
|
(pref_pool, pref_vec): New static vars.
|
||||||
|
(initiate_prefs, find_allocno_pref, ira_create_pref): New
|
||||||
|
functions.
|
||||||
|
(add_allocno_pref_to_list, ira_add_allocno_pref, print_pref): Ditto.
|
||||||
|
(ira_debug_pref, print_prefs, ira_debug_prefs): Ditto.
|
||||||
|
(print_allocno_prefs, ira_debug_allocno_prefs, finish_pref): Ditto.
|
||||||
|
(ira_remove_pref, ira_remove_allocno_prefs, finish_prefs): Ditto.
|
||||||
|
(ira_add_allocno_copy_to_list): Make static. Rename to
|
||||||
|
add_allocno_copy_to_list.
|
||||||
|
(ira_swap_allocno_copy_ends_if_necessary): Make static. Rename to
|
||||||
|
swap_allocno_copy_ends_if_necessary.
|
||||||
|
(remove_unnecessary_allocnos, remove_low_level_allocnos): Call
|
||||||
|
ira_remove_allocno_prefs.
|
||||||
|
(ira_flattening): Ditto.
|
||||||
|
(ira_build): Call initiate_prefs, print_prefs.
|
||||||
|
(ira_destroy): Call finish_prefs.
|
||||||
|
* ira-color.c (struct update_cost_record): New.
|
||||||
|
(struct allocno_color_data): Add new member update_cost_records.
|
||||||
|
(update_cost_record_pool): New static var.
|
||||||
|
(init_update_cost_records, get_update_cost_record): New functions.
|
||||||
|
(free_update_cost_record_list, finish_update_cost_records): Ditto.
|
||||||
|
(struct update_cost_queue_elem): Add member from.
|
||||||
|
(initiate_cost_update): Call init_update_cost_records.
|
||||||
|
(finish_cost_update): Call finish_update_cost_records.
|
||||||
|
(queue_update_cost, get_next_update_cost): Add new param from.
|
||||||
|
(Update_allocno_cost, update_costs_from_allocno): New functions.
|
||||||
|
(update_costs_from_prefs): Ditto.
|
||||||
|
(update_copy_costs): Rename to update_costs_from_copies.
|
||||||
|
(restore_costs_from_copies): New function.
|
||||||
|
(update_conflict_hard_regno_costs): Don't go back.
|
||||||
|
(assign_hard_reg): Call restore_costs_from_copies. Add printing
|
||||||
|
more debug info.
|
||||||
|
(pop_allocnos): Add priniting more debug info.
|
||||||
|
(color_allocnos): Remove prefs for conflicting hard regs.
|
||||||
|
Call update_costs_from_prefs.
|
||||||
|
* ira-conflicts.c (commutative_constraint_p): Move to ira.c
|
||||||
|
(get_dup_num): Rename, modify, and move to ira.c
|
||||||
|
(process_regs_for_copy): Add prefs.
|
||||||
|
(add_insn_allocno_copies): Put src as first arg of
|
||||||
|
process_regs_for_copy. Remove dead code. Call ira_setup_alts.
|
||||||
|
* ira-costs.c (record_reg_classes): Modify and move code into
|
||||||
|
record_operands_costs.
|
||||||
|
(find_costs_and_classes): Create prefs for the hard reg of small
|
||||||
|
reg class.
|
||||||
|
(process_bb_node_for_hard_reg_moves): Add prefs.
|
||||||
|
|
||||||
2013-10-30 Richard Biener <rguenther@suse.de>
|
2013-10-30 Richard Biener <rguenther@suse.de>
|
||||||
|
|
||||||
PR middle-end/57100
|
PR middle-end/57100
|
||||||
|
|
|
||||||
|
|
@ -1328,7 +1328,6 @@ OBJS = \
|
||||||
reg-stack.o \
|
reg-stack.o \
|
||||||
regcprop.o \
|
regcprop.o \
|
||||||
reginfo.o \
|
reginfo.o \
|
||||||
regmove.o \
|
|
||||||
regrename.o \
|
regrename.o \
|
||||||
regstat.o \
|
regstat.o \
|
||||||
reload.o \
|
reload.o \
|
||||||
|
|
|
||||||
|
|
@ -1597,8 +1597,8 @@ Common Joined RejectNegative Var(common_deferred_options) Defer
|
||||||
-fopt-info[-<type>=filename] Dump compiler optimization details
|
-fopt-info[-<type>=filename] Dump compiler optimization details
|
||||||
|
|
||||||
foptimize-register-move
|
foptimize-register-move
|
||||||
Common Report Var(flag_regmove) Optimization
|
Common Ignore
|
||||||
Do the full register move optimization pass
|
Does nothing. Preserved for backward compatibility.
|
||||||
|
|
||||||
foptimize-sibling-calls
|
foptimize-sibling-calls
|
||||||
Common Report Var(flag_optimize_sibling_calls) Optimization
|
Common Report Var(flag_optimize_sibling_calls) Optimization
|
||||||
|
|
@ -1735,8 +1735,8 @@ Common Report Var(flag_pcc_struct_return,0) Optimization
|
||||||
Return small aggregates in registers
|
Return small aggregates in registers
|
||||||
|
|
||||||
fregmove
|
fregmove
|
||||||
Common Report Var(flag_regmove) Optimization
|
Common Ignore
|
||||||
Enables a register move optimization
|
Does nothing. Preserved for backward compatibility.
|
||||||
|
|
||||||
frename-registers
|
frename-registers
|
||||||
Common Report Var(flag_rename_registers) Init(2) Optimization
|
Common Report Var(flag_rename_registers) Init(2) Optimization
|
||||||
|
|
|
||||||
|
|
@ -388,13 +388,13 @@ Objective-C and Objective-C++ Dialects}.
|
||||||
-fno-inline -fno-math-errno -fno-peephole -fno-peephole2 @gol
|
-fno-inline -fno-math-errno -fno-peephole -fno-peephole2 @gol
|
||||||
-fno-sched-interblock -fno-sched-spec -fno-signed-zeros @gol
|
-fno-sched-interblock -fno-sched-spec -fno-signed-zeros @gol
|
||||||
-fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol
|
-fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol
|
||||||
-fomit-frame-pointer -foptimize-register-move -foptimize-sibling-calls @gol
|
-fomit-frame-pointer -foptimize-sibling-calls @gol
|
||||||
-fpartial-inlining -fpeel-loops -fpredictive-commoning @gol
|
-fpartial-inlining -fpeel-loops -fpredictive-commoning @gol
|
||||||
-fprefetch-loop-arrays -fprofile-report @gol
|
-fprefetch-loop-arrays -fprofile-report @gol
|
||||||
-fprofile-correction -fprofile-dir=@var{path} -fprofile-generate @gol
|
-fprofile-correction -fprofile-dir=@var{path} -fprofile-generate @gol
|
||||||
-fprofile-generate=@var{path} @gol
|
-fprofile-generate=@var{path} @gol
|
||||||
-fprofile-use -fprofile-use=@var{path} -fprofile-values @gol
|
-fprofile-use -fprofile-use=@var{path} -fprofile-values @gol
|
||||||
-freciprocal-math -free -fregmove -frename-registers -freorder-blocks @gol
|
-freciprocal-math -free -frename-registers -freorder-blocks @gol
|
||||||
-freorder-blocks-and-partition -freorder-functions @gol
|
-freorder-blocks-and-partition -freorder-functions @gol
|
||||||
-frerun-cse-after-loop -freschedule-modulo-scheduled-loops @gol
|
-frerun-cse-after-loop -freschedule-modulo-scheduled-loops @gol
|
||||||
-frounding-math -fsched2-use-superblocks -fsched-pressure @gol
|
-frounding-math -fsched2-use-superblocks -fsched-pressure @gol
|
||||||
|
|
@ -5822,10 +5822,6 @@ Dump after post-reload optimizations.
|
||||||
@opindex fdump-rtl-pro_and_epilogue
|
@opindex fdump-rtl-pro_and_epilogue
|
||||||
Dump after generating the function prologues and epilogues.
|
Dump after generating the function prologues and epilogues.
|
||||||
|
|
||||||
@item -fdump-rtl-regmove
|
|
||||||
@opindex fdump-rtl-regmove
|
|
||||||
Dump after the register move pass.
|
|
||||||
|
|
||||||
@item -fdump-rtl-sched1
|
@item -fdump-rtl-sched1
|
||||||
@itemx -fdump-rtl-sched2
|
@itemx -fdump-rtl-sched2
|
||||||
@opindex fdump-rtl-sched1
|
@opindex fdump-rtl-sched1
|
||||||
|
|
@ -6738,7 +6734,6 @@ also turns on the following optimization flags:
|
||||||
-foptimize-sibling-calls @gol
|
-foptimize-sibling-calls @gol
|
||||||
-fpartial-inlining @gol
|
-fpartial-inlining @gol
|
||||||
-fpeephole2 @gol
|
-fpeephole2 @gol
|
||||||
-fregmove @gol
|
|
||||||
-freorder-blocks -freorder-functions @gol
|
-freorder-blocks -freorder-functions @gol
|
||||||
-frerun-cse-after-loop @gol
|
-frerun-cse-after-loop @gol
|
||||||
-fsched-interblock -fsched-spec @gol
|
-fsched-interblock -fsched-spec @gol
|
||||||
|
|
@ -7262,20 +7257,6 @@ registers after writing to their lower 32-bit half.
|
||||||
|
|
||||||
Enabled for x86 at levels @option{-O2}, @option{-O3}.
|
Enabled for x86 at levels @option{-O2}, @option{-O3}.
|
||||||
|
|
||||||
@item -foptimize-register-move
|
|
||||||
@itemx -fregmove
|
|
||||||
@opindex foptimize-register-move
|
|
||||||
@opindex fregmove
|
|
||||||
Attempt to reassign register numbers in move instructions and as
|
|
||||||
operands of other simple instructions in order to maximize the amount of
|
|
||||||
register tying. This is especially helpful on machines with two-operand
|
|
||||||
instructions.
|
|
||||||
|
|
||||||
Note @option{-fregmove} and @option{-foptimize-register-move} are the same
|
|
||||||
optimization.
|
|
||||||
|
|
||||||
Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
|
|
||||||
|
|
||||||
@item -fira-algorithm=@var{algorithm}
|
@item -fira-algorithm=@var{algorithm}
|
||||||
Use the specified coloring algorithm for the integrated register
|
Use the specified coloring algorithm for the integrated register
|
||||||
allocator. The @var{algorithm} argument can be @samp{priority}, which
|
allocator. The @var{algorithm} argument can be @samp{priority}, which
|
||||||
|
|
|
||||||
|
|
@ -823,14 +823,6 @@ RTL expressions for the instructions by substitution, simplifies the
|
||||||
result using algebra, and then attempts to match the result against
|
result using algebra, and then attempts to match the result against
|
||||||
the machine description. The code is located in @file{combine.c}.
|
the machine description. The code is located in @file{combine.c}.
|
||||||
|
|
||||||
@item Register movement
|
|
||||||
|
|
||||||
This pass 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. The code is
|
|
||||||
located in @file{regmove.c}.
|
|
||||||
|
|
||||||
@item Mode switching optimization
|
@item Mode switching optimization
|
||||||
|
|
||||||
This pass looks for instructions that require the processor to be in a
|
This pass looks for instructions that require the processor to be in a
|
||||||
|
|
@ -868,11 +860,6 @@ them by an equivalent expression (e.g.@: a constant) or by placing
|
||||||
them on the stack. This is done in several subpasses:
|
them on the stack. This is done in several subpasses:
|
||||||
|
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
|
||||||
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
|
@item
|
||||||
The integrated register allocator (@acronym{IRA}). It is called
|
The integrated register allocator (@acronym{IRA}). It is called
|
||||||
integrated because coalescing, register live range splitting, and hard
|
integrated because coalescing, register live range splitting, and hard
|
||||||
|
|
|
||||||
222
gcc/ira-build.c
222
gcc/ira-build.c
|
|
@ -79,6 +79,13 @@ int ira_objects_num;
|
||||||
/* Map a conflict id to its conflict record. */
|
/* Map a conflict id to its conflict record. */
|
||||||
ira_object_t *ira_object_id_map;
|
ira_object_t *ira_object_id_map;
|
||||||
|
|
||||||
|
/* Array of references to all allocno preferences. The order number
|
||||||
|
of the preference corresponds to the index in the array. */
|
||||||
|
ira_pref_t *ira_prefs;
|
||||||
|
|
||||||
|
/* Size of the previous array. */
|
||||||
|
int ira_prefs_num;
|
||||||
|
|
||||||
/* Array of references to all copies. The order number of the copy
|
/* Array of references to all copies. The order number of the copy
|
||||||
corresponds to the index in the array. Removed copies have NULL
|
corresponds to the index in the array. Removed copies have NULL
|
||||||
element value. */
|
element value. */
|
||||||
|
|
@ -515,6 +522,7 @@ ira_create_allocno (int regno, bool cap_p,
|
||||||
ALLOCNO_BAD_SPILL_P (a) = false;
|
ALLOCNO_BAD_SPILL_P (a) = false;
|
||||||
ALLOCNO_ASSIGNED_P (a) = false;
|
ALLOCNO_ASSIGNED_P (a) = false;
|
||||||
ALLOCNO_MODE (a) = (regno < 0 ? VOIDmode : PSEUDO_REGNO_MODE (regno));
|
ALLOCNO_MODE (a) = (regno < 0 ? VOIDmode : PSEUDO_REGNO_MODE (regno));
|
||||||
|
ALLOCNO_PREFS (a) = NULL;
|
||||||
ALLOCNO_COPIES (a) = NULL;
|
ALLOCNO_COPIES (a) = NULL;
|
||||||
ALLOCNO_HARD_REG_COSTS (a) = NULL;
|
ALLOCNO_HARD_REG_COSTS (a) = NULL;
|
||||||
ALLOCNO_CONFLICT_HARD_REG_COSTS (a) = NULL;
|
ALLOCNO_CONFLICT_HARD_REG_COSTS (a) = NULL;
|
||||||
|
|
@ -1163,6 +1171,195 @@ finish_allocnos (void)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Pools for allocno preferences. */
|
||||||
|
static alloc_pool pref_pool;
|
||||||
|
|
||||||
|
/* Vec containing references to all created preferences. It is a
|
||||||
|
container of array ira_prefs. */
|
||||||
|
static vec<ira_pref_t> pref_vec;
|
||||||
|
|
||||||
|
/* The function initializes data concerning allocno prefs. */
|
||||||
|
static void
|
||||||
|
initiate_prefs (void)
|
||||||
|
{
|
||||||
|
pref_pool
|
||||||
|
= create_alloc_pool ("prefs", sizeof (struct ira_allocno_pref), 100);
|
||||||
|
pref_vec.create (get_max_uid ());
|
||||||
|
ira_prefs = NULL;
|
||||||
|
ira_prefs_num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return pref for A and HARD_REGNO if any. */
|
||||||
|
static ira_pref_t
|
||||||
|
find_allocno_pref (ira_allocno_t a, int hard_regno)
|
||||||
|
{
|
||||||
|
ira_pref_t pref;
|
||||||
|
|
||||||
|
for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = pref->next_pref)
|
||||||
|
if (pref->allocno == a && pref->hard_regno == hard_regno)
|
||||||
|
return pref;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create and return pref with given attributes A, HARD_REGNO, and FREQ. */
|
||||||
|
ira_pref_t
|
||||||
|
ira_create_pref (ira_allocno_t a, int hard_regno, int freq)
|
||||||
|
{
|
||||||
|
ira_pref_t pref;
|
||||||
|
|
||||||
|
pref = (ira_pref_t) pool_alloc (pref_pool);
|
||||||
|
pref->num = ira_prefs_num;
|
||||||
|
pref->allocno = a;
|
||||||
|
pref->hard_regno = hard_regno;
|
||||||
|
pref->freq = freq;
|
||||||
|
pref_vec.safe_push (pref);
|
||||||
|
ira_prefs = pref_vec.address ();
|
||||||
|
ira_prefs_num = pref_vec.length ();
|
||||||
|
return pref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach a pref PREF to the cooresponding allocno. */
|
||||||
|
static void
|
||||||
|
add_allocno_pref_to_list (ira_pref_t pref)
|
||||||
|
{
|
||||||
|
ira_allocno_t a = pref->allocno;
|
||||||
|
|
||||||
|
pref->next_pref = ALLOCNO_PREFS (a);
|
||||||
|
ALLOCNO_PREFS (a) = pref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create (or update frequency if the pref already exists) the pref of
|
||||||
|
allocnos A preferring HARD_REGNO with frequency FREQ. */
|
||||||
|
void
|
||||||
|
ira_add_allocno_pref (ira_allocno_t a, int hard_regno, int freq)
|
||||||
|
{
|
||||||
|
ira_pref_t pref;
|
||||||
|
|
||||||
|
if (freq <= 0)
|
||||||
|
return;
|
||||||
|
if ((pref = find_allocno_pref (a, hard_regno)) != NULL)
|
||||||
|
{
|
||||||
|
pref->freq += freq;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pref = ira_create_pref (a, hard_regno, freq);
|
||||||
|
ira_assert (a != NULL);
|
||||||
|
add_allocno_pref_to_list (pref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print info about PREF into file F. */
|
||||||
|
static void
|
||||||
|
print_pref (FILE *f, ira_pref_t pref)
|
||||||
|
{
|
||||||
|
fprintf (f, " pref%d:a%d(r%d)<-hr%d@%d\n", pref->num,
|
||||||
|
ALLOCNO_NUM (pref->allocno), ALLOCNO_REGNO (pref->allocno),
|
||||||
|
pref->hard_regno, pref->freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print info about PREF into stderr. */
|
||||||
|
void
|
||||||
|
ira_debug_pref (ira_pref_t pref)
|
||||||
|
{
|
||||||
|
print_pref (stderr, pref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print info about all prefs into file F. */
|
||||||
|
static void
|
||||||
|
print_prefs (FILE *f)
|
||||||
|
{
|
||||||
|
ira_pref_t pref;
|
||||||
|
ira_pref_iterator pi;
|
||||||
|
|
||||||
|
FOR_EACH_PREF (pref, pi)
|
||||||
|
print_pref (f, pref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print info about all prefs into stderr. */
|
||||||
|
void
|
||||||
|
ira_debug_prefs (void)
|
||||||
|
{
|
||||||
|
print_prefs (stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print info about prefs involving allocno A into file F. */
|
||||||
|
static void
|
||||||
|
print_allocno_prefs (FILE *f, ira_allocno_t a)
|
||||||
|
{
|
||||||
|
ira_pref_t pref;
|
||||||
|
|
||||||
|
fprintf (f, " a%d(r%d):", ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
|
||||||
|
for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = pref->next_pref)
|
||||||
|
fprintf (f, " pref%d:hr%d@%d", pref->num, pref->hard_regno, pref->freq);
|
||||||
|
fprintf (f, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print info about prefs involving allocno A into stderr. */
|
||||||
|
void
|
||||||
|
ira_debug_allocno_prefs (ira_allocno_t a)
|
||||||
|
{
|
||||||
|
print_allocno_prefs (stderr, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The function frees memory allocated for PREF. */
|
||||||
|
static void
|
||||||
|
finish_pref (ira_pref_t pref)
|
||||||
|
{
|
||||||
|
ira_prefs[pref->num] = NULL;
|
||||||
|
pool_free (pref_pool, pref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove PREF from the list of allocno prefs and free memory for
|
||||||
|
it. */
|
||||||
|
void
|
||||||
|
ira_remove_pref (ira_pref_t pref)
|
||||||
|
{
|
||||||
|
ira_pref_t cpref, prev;
|
||||||
|
|
||||||
|
if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL)
|
||||||
|
fprintf (ira_dump_file, " Removing pref%d:hr%d@%d\n",
|
||||||
|
pref->num, pref->hard_regno, pref->freq);
|
||||||
|
for (prev = NULL, cpref = ALLOCNO_PREFS (pref->allocno);
|
||||||
|
cpref != NULL;
|
||||||
|
prev = cpref, cpref = cpref->next_pref)
|
||||||
|
if (cpref == pref)
|
||||||
|
break;
|
||||||
|
ira_assert (cpref != NULL);
|
||||||
|
if (prev == NULL)
|
||||||
|
ALLOCNO_PREFS (pref->allocno) = pref->next_pref;
|
||||||
|
else
|
||||||
|
prev->next_pref = pref->next_pref;
|
||||||
|
finish_pref (pref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove all prefs of allocno A. */
|
||||||
|
void
|
||||||
|
ira_remove_allocno_prefs (ira_allocno_t a)
|
||||||
|
{
|
||||||
|
ira_pref_t pref, next_pref;
|
||||||
|
|
||||||
|
for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = next_pref)
|
||||||
|
{
|
||||||
|
next_pref = pref->next_pref;
|
||||||
|
finish_pref (pref);
|
||||||
|
}
|
||||||
|
ALLOCNO_PREFS (a) = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free memory allocated for all prefs. */
|
||||||
|
static void
|
||||||
|
finish_prefs (void)
|
||||||
|
{
|
||||||
|
ira_pref_t pref;
|
||||||
|
ira_pref_iterator pi;
|
||||||
|
|
||||||
|
FOR_EACH_PREF (pref, pi)
|
||||||
|
finish_pref (pref);
|
||||||
|
pref_vec.release ();
|
||||||
|
free_alloc_pool (pref_pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Pools for copies. */
|
/* Pools for copies. */
|
||||||
static alloc_pool copy_pool;
|
static alloc_pool copy_pool;
|
||||||
|
|
||||||
|
|
@ -1235,8 +1432,8 @@ ira_create_copy (ira_allocno_t first, ira_allocno_t second, int freq,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attach a copy CP to allocnos involved into the copy. */
|
/* Attach a copy CP to allocnos involved into the copy. */
|
||||||
void
|
static void
|
||||||
ira_add_allocno_copy_to_list (ira_copy_t cp)
|
add_allocno_copy_to_list (ira_copy_t cp)
|
||||||
{
|
{
|
||||||
ira_allocno_t first = cp->first, second = cp->second;
|
ira_allocno_t first = cp->first, second = cp->second;
|
||||||
|
|
||||||
|
|
@ -1264,8 +1461,8 @@ ira_add_allocno_copy_to_list (ira_copy_t cp)
|
||||||
|
|
||||||
/* Make a copy CP a canonical copy where number of the
|
/* Make a copy CP a canonical copy where number of the
|
||||||
first allocno is less than the second one. */
|
first allocno is less than the second one. */
|
||||||
void
|
static void
|
||||||
ira_swap_allocno_copy_ends_if_necessary (ira_copy_t cp)
|
swap_allocno_copy_ends_if_necessary (ira_copy_t cp)
|
||||||
{
|
{
|
||||||
ira_allocno_t temp;
|
ira_allocno_t temp;
|
||||||
ira_copy_t temp_cp;
|
ira_copy_t temp_cp;
|
||||||
|
|
@ -1305,8 +1502,8 @@ ira_add_allocno_copy (ira_allocno_t first, ira_allocno_t second, int freq,
|
||||||
cp = ira_create_copy (first, second, freq, constraint_p, insn,
|
cp = ira_create_copy (first, second, freq, constraint_p, insn,
|
||||||
loop_tree_node);
|
loop_tree_node);
|
||||||
ira_assert (first != NULL && second != NULL);
|
ira_assert (first != NULL && second != NULL);
|
||||||
ira_add_allocno_copy_to_list (cp);
|
add_allocno_copy_to_list (cp);
|
||||||
ira_swap_allocno_copy_ends_if_necessary (cp);
|
swap_allocno_copy_ends_if_necessary (cp);
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2305,6 +2502,7 @@ remove_unnecessary_allocnos (void)
|
||||||
map to avoid info propagation of subsequent
|
map to avoid info propagation of subsequent
|
||||||
allocno into this already removed allocno. */
|
allocno into this already removed allocno. */
|
||||||
a_node->regno_allocno_map[regno] = NULL;
|
a_node->regno_allocno_map[regno] = NULL;
|
||||||
|
ira_remove_allocno_prefs (a);
|
||||||
finish_allocno (a);
|
finish_allocno (a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2388,8 +2586,11 @@ remove_low_level_allocnos (void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
ira_remove_allocno_prefs (a);
|
||||||
finish_allocno (a);
|
finish_allocno (a);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (merged_p)
|
if (merged_p)
|
||||||
ira_rebuild_start_finish_chains ();
|
ira_rebuild_start_finish_chains ();
|
||||||
}
|
}
|
||||||
|
|
@ -3105,6 +3306,7 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
|
||||||
if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
|
if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
|
||||||
fprintf (ira_dump_file, " Remove a%dr%d\n",
|
fprintf (ira_dump_file, " Remove a%dr%d\n",
|
||||||
ALLOCNO_NUM (a), REGNO (allocno_emit_reg (a)));
|
ALLOCNO_NUM (a), REGNO (allocno_emit_reg (a)));
|
||||||
|
ira_remove_allocno_prefs (a);
|
||||||
finish_allocno (a);
|
finish_allocno (a);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -3131,8 +3333,8 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
|
||||||
ira_assert
|
ira_assert
|
||||||
(ALLOCNO_LOOP_TREE_NODE (cp->first) == ira_loop_tree_root
|
(ALLOCNO_LOOP_TREE_NODE (cp->first) == ira_loop_tree_root
|
||||||
&& ALLOCNO_LOOP_TREE_NODE (cp->second) == ira_loop_tree_root);
|
&& ALLOCNO_LOOP_TREE_NODE (cp->second) == ira_loop_tree_root);
|
||||||
ira_add_allocno_copy_to_list (cp);
|
add_allocno_copy_to_list (cp);
|
||||||
ira_swap_allocno_copy_ends_if_necessary (cp);
|
swap_allocno_copy_ends_if_necessary (cp);
|
||||||
}
|
}
|
||||||
rebuild_regno_allocno_maps ();
|
rebuild_regno_allocno_maps ();
|
||||||
if (ira_max_point != ira_max_point_before_emit)
|
if (ira_max_point != ira_max_point_before_emit)
|
||||||
|
|
@ -3220,6 +3422,7 @@ ira_build (void)
|
||||||
df_analyze ();
|
df_analyze ();
|
||||||
initiate_cost_vectors ();
|
initiate_cost_vectors ();
|
||||||
initiate_allocnos ();
|
initiate_allocnos ();
|
||||||
|
initiate_prefs ();
|
||||||
initiate_copies ();
|
initiate_copies ();
|
||||||
create_loop_tree_nodes ();
|
create_loop_tree_nodes ();
|
||||||
form_loop_tree ();
|
form_loop_tree ();
|
||||||
|
|
@ -3265,6 +3468,8 @@ ira_build (void)
|
||||||
}
|
}
|
||||||
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
|
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
|
||||||
print_copies (ira_dump_file);
|
print_copies (ira_dump_file);
|
||||||
|
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
|
||||||
|
print_prefs (ira_dump_file);
|
||||||
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
|
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
|
||||||
{
|
{
|
||||||
int n, nr, nr_big;
|
int n, nr, nr_big;
|
||||||
|
|
@ -3304,6 +3509,7 @@ void
|
||||||
ira_destroy (void)
|
ira_destroy (void)
|
||||||
{
|
{
|
||||||
finish_loop_tree_nodes ();
|
finish_loop_tree_nodes ();
|
||||||
|
finish_prefs ();
|
||||||
finish_copies ();
|
finish_copies ();
|
||||||
finish_allocnos ();
|
finish_allocnos ();
|
||||||
finish_cost_vectors ();
|
finish_cost_vectors ();
|
||||||
|
|
|
||||||
274
gcc/ira-color.c
274
gcc/ira-color.c
|
|
@ -88,6 +88,17 @@ struct allocno_hard_regs_node
|
||||||
allocno_hard_regs_node_t parent, first, prev, next;
|
allocno_hard_regs_node_t parent, first, prev, next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Info about changing hard reg costs of an allocno. */
|
||||||
|
struct update_cost_record
|
||||||
|
{
|
||||||
|
/* Hard regno for which we changed the cost. */
|
||||||
|
int hard_regno;
|
||||||
|
/* Divisor used when we changed the cost of HARD_REGNO. */
|
||||||
|
int divisor;
|
||||||
|
/* Next record for given allocno. */
|
||||||
|
struct update_cost_record *next;
|
||||||
|
};
|
||||||
|
|
||||||
/* To decrease footprint of ira_allocno structure we store all data
|
/* To decrease footprint of ira_allocno structure we store all data
|
||||||
needed only for coloring in the following structure. */
|
needed only for coloring in the following structure. */
|
||||||
struct allocno_color_data
|
struct allocno_color_data
|
||||||
|
|
@ -126,6 +137,11 @@ struct allocno_color_data
|
||||||
int hard_regs_subnodes_start;
|
int hard_regs_subnodes_start;
|
||||||
/* The length of the previous array. */
|
/* The length of the previous array. */
|
||||||
int hard_regs_subnodes_num;
|
int hard_regs_subnodes_num;
|
||||||
|
/* Records about updating allocno hard reg costs from copies. If
|
||||||
|
the allocno did not get expected hard register, these records are
|
||||||
|
used to restore original hard reg costs of allocnos connected to
|
||||||
|
this allocno by copies. */
|
||||||
|
struct update_cost_record *update_cost_records;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* See above. */
|
/* See above. */
|
||||||
|
|
@ -1113,6 +1129,53 @@ setup_profitable_hard_regs (void)
|
||||||
/* This page contains functions used to choose hard registers for
|
/* This page contains functions used to choose hard registers for
|
||||||
allocnos. */
|
allocnos. */
|
||||||
|
|
||||||
|
/* Pool for update cost records. */
|
||||||
|
static alloc_pool update_cost_record_pool;
|
||||||
|
|
||||||
|
/* Initiate update cost records. */
|
||||||
|
static void
|
||||||
|
init_update_cost_records (void)
|
||||||
|
{
|
||||||
|
update_cost_record_pool
|
||||||
|
= create_alloc_pool ("update cost records",
|
||||||
|
sizeof (struct update_cost_record), 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return new update cost record with given params. */
|
||||||
|
static struct update_cost_record *
|
||||||
|
get_update_cost_record (int hard_regno, int divisor,
|
||||||
|
struct update_cost_record *next)
|
||||||
|
{
|
||||||
|
struct update_cost_record *record;
|
||||||
|
|
||||||
|
record = (struct update_cost_record *) pool_alloc (update_cost_record_pool);
|
||||||
|
record->hard_regno = hard_regno;
|
||||||
|
record->divisor = divisor;
|
||||||
|
record->next = next;
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free memory for all records in LIST. */
|
||||||
|
static void
|
||||||
|
free_update_cost_record_list (struct update_cost_record *list)
|
||||||
|
{
|
||||||
|
struct update_cost_record *next;
|
||||||
|
|
||||||
|
while (list != NULL)
|
||||||
|
{
|
||||||
|
next = list->next;
|
||||||
|
pool_free (update_cost_record_pool, list);
|
||||||
|
list = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free memory allocated for all update cost records. */
|
||||||
|
static void
|
||||||
|
finish_update_cost_records (void)
|
||||||
|
{
|
||||||
|
free_alloc_pool (update_cost_record_pool);
|
||||||
|
}
|
||||||
|
|
||||||
/* Array whose element value is TRUE if the corresponding hard
|
/* Array whose element value is TRUE if the corresponding hard
|
||||||
register was already allocated for an allocno. */
|
register was already allocated for an allocno. */
|
||||||
static bool allocated_hardreg_p[FIRST_PSEUDO_REGISTER];
|
static bool allocated_hardreg_p[FIRST_PSEUDO_REGISTER];
|
||||||
|
|
@ -1129,6 +1192,11 @@ struct update_cost_queue_elem
|
||||||
connecting this allocno to the one being allocated. */
|
connecting this allocno to the one being allocated. */
|
||||||
int divisor;
|
int divisor;
|
||||||
|
|
||||||
|
/* Allocno from which we are chaning costs of connected allocnos.
|
||||||
|
It is used not go back in graph of allocnos connected by
|
||||||
|
copies. */
|
||||||
|
ira_allocno_t from;
|
||||||
|
|
||||||
/* The next allocno in the queue, or null if this is the last element. */
|
/* The next allocno in the queue, or null if this is the last element. */
|
||||||
ira_allocno_t next;
|
ira_allocno_t next;
|
||||||
};
|
};
|
||||||
|
|
@ -1145,11 +1213,11 @@ static struct update_cost_queue_elem *update_cost_queue_tail;
|
||||||
Elements are indexed by ALLOCNO_NUM. */
|
Elements are indexed by ALLOCNO_NUM. */
|
||||||
static struct update_cost_queue_elem *update_cost_queue_elems;
|
static struct update_cost_queue_elem *update_cost_queue_elems;
|
||||||
|
|
||||||
/* The current value of update_copy_cost call count. */
|
/* The current value of update_costs_from_copies call count. */
|
||||||
static int update_cost_check;
|
static int update_cost_check;
|
||||||
|
|
||||||
/* Allocate and initialize data necessary for function
|
/* Allocate and initialize data necessary for function
|
||||||
update_copy_costs. */
|
update_costs_from_copiess. */
|
||||||
static void
|
static void
|
||||||
initiate_cost_update (void)
|
initiate_cost_update (void)
|
||||||
{
|
{
|
||||||
|
|
@ -1160,13 +1228,15 @@ initiate_cost_update (void)
|
||||||
= (struct update_cost_queue_elem *) ira_allocate (size);
|
= (struct update_cost_queue_elem *) ira_allocate (size);
|
||||||
memset (update_cost_queue_elems, 0, size);
|
memset (update_cost_queue_elems, 0, size);
|
||||||
update_cost_check = 0;
|
update_cost_check = 0;
|
||||||
|
init_update_cost_records ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deallocate data used by function update_copy_costs. */
|
/* Deallocate data used by function update_costs_from_copies. */
|
||||||
static void
|
static void
|
||||||
finish_cost_update (void)
|
finish_cost_update (void)
|
||||||
{
|
{
|
||||||
ira_free (update_cost_queue_elems);
|
ira_free (update_cost_queue_elems);
|
||||||
|
finish_update_cost_records ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When we traverse allocnos to update hard register costs, the cost
|
/* When we traverse allocnos to update hard register costs, the cost
|
||||||
|
|
@ -1182,10 +1252,10 @@ start_update_cost (void)
|
||||||
update_cost_queue = NULL;
|
update_cost_queue = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add (ALLOCNO, DIVISOR) to the end of update_cost_queue, unless
|
/* Add (ALLOCNO, FROM, DIVISOR) to the end of update_cost_queue, unless
|
||||||
ALLOCNO is already in the queue, or has NO_REGS class. */
|
ALLOCNO is already in the queue, or has NO_REGS class. */
|
||||||
static inline void
|
static inline void
|
||||||
queue_update_cost (ira_allocno_t allocno, int divisor)
|
queue_update_cost (ira_allocno_t allocno, ira_allocno_t from, int divisor)
|
||||||
{
|
{
|
||||||
struct update_cost_queue_elem *elem;
|
struct update_cost_queue_elem *elem;
|
||||||
|
|
||||||
|
|
@ -1194,6 +1264,7 @@ queue_update_cost (ira_allocno_t allocno, int divisor)
|
||||||
&& ALLOCNO_CLASS (allocno) != NO_REGS)
|
&& ALLOCNO_CLASS (allocno) != NO_REGS)
|
||||||
{
|
{
|
||||||
elem->check = update_cost_check;
|
elem->check = update_cost_check;
|
||||||
|
elem->from = from;
|
||||||
elem->divisor = divisor;
|
elem->divisor = divisor;
|
||||||
elem->next = NULL;
|
elem->next = NULL;
|
||||||
if (update_cost_queue == NULL)
|
if (update_cost_queue == NULL)
|
||||||
|
|
@ -1204,11 +1275,11 @@ queue_update_cost (ira_allocno_t allocno, int divisor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to remove the first element from update_cost_queue. Return false
|
/* Try to remove the first element from update_cost_queue. Return
|
||||||
if the queue was empty, otherwise make (*ALLOCNO, *DIVISOR) describe
|
false if the queue was empty, otherwise make (*ALLOCNO, *FROM,
|
||||||
the removed element. */
|
*DIVISOR) describe the removed element. */
|
||||||
static inline bool
|
static inline bool
|
||||||
get_next_update_cost (ira_allocno_t *allocno, int *divisor)
|
get_next_update_cost (ira_allocno_t *allocno, ira_allocno_t *from, int *divisor)
|
||||||
{
|
{
|
||||||
struct update_cost_queue_elem *elem;
|
struct update_cost_queue_elem *elem;
|
||||||
|
|
||||||
|
|
@ -1217,34 +1288,50 @@ get_next_update_cost (ira_allocno_t *allocno, int *divisor)
|
||||||
|
|
||||||
*allocno = update_cost_queue;
|
*allocno = update_cost_queue;
|
||||||
elem = &update_cost_queue_elems[ALLOCNO_NUM (*allocno)];
|
elem = &update_cost_queue_elems[ALLOCNO_NUM (*allocno)];
|
||||||
|
*from = elem->from;
|
||||||
*divisor = elem->divisor;
|
*divisor = elem->divisor;
|
||||||
update_cost_queue = elem->next;
|
update_cost_queue = elem->next;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the cost of allocnos to increase chances to remove some
|
/* Increase costs of HARD_REGNO by UPDATE_COST for ALLOCNO. Return
|
||||||
copies as the result of subsequent assignment. */
|
true if we really modified the cost. */
|
||||||
static void
|
static bool
|
||||||
update_copy_costs (ira_allocno_t allocno, bool decr_p)
|
update_allocno_cost (ira_allocno_t allocno, int hard_regno, int update_cost)
|
||||||
{
|
{
|
||||||
int i, cost, update_cost, hard_regno, divisor;
|
int i;
|
||||||
|
enum reg_class aclass = ALLOCNO_CLASS (allocno);
|
||||||
|
|
||||||
|
i = ira_class_hard_reg_index[aclass][hard_regno];
|
||||||
|
if (i < 0)
|
||||||
|
return false;
|
||||||
|
ira_allocate_and_set_or_copy_costs
|
||||||
|
(&ALLOCNO_UPDATED_HARD_REG_COSTS (allocno), aclass,
|
||||||
|
ALLOCNO_UPDATED_CLASS_COST (allocno),
|
||||||
|
ALLOCNO_HARD_REG_COSTS (allocno));
|
||||||
|
ira_allocate_and_set_or_copy_costs
|
||||||
|
(&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno),
|
||||||
|
aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (allocno));
|
||||||
|
ALLOCNO_UPDATED_HARD_REG_COSTS (allocno)[i] += update_cost;
|
||||||
|
ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno)[i] += update_cost;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update (decrease if DECR_P) HARD_REGNO cost of allocnos connected
|
||||||
|
by copies to ALLOCNO to increase chances to remove some copies as
|
||||||
|
the result of subsequent assignment. Record cost updates if
|
||||||
|
RECORD_P is true. */
|
||||||
|
static void
|
||||||
|
update_costs_from_allocno (ira_allocno_t allocno, int hard_regno,
|
||||||
|
int divisor, bool decr_p, bool record_p)
|
||||||
|
{
|
||||||
|
int cost, update_cost;
|
||||||
enum machine_mode mode;
|
enum machine_mode mode;
|
||||||
enum reg_class rclass, aclass;
|
enum reg_class rclass, aclass;
|
||||||
ira_allocno_t another_allocno;
|
ira_allocno_t another_allocno, from = NULL;
|
||||||
ira_copy_t cp, next_cp;
|
ira_copy_t cp, next_cp;
|
||||||
|
|
||||||
hard_regno = ALLOCNO_HARD_REGNO (allocno);
|
|
||||||
ira_assert (hard_regno >= 0);
|
|
||||||
|
|
||||||
aclass = ALLOCNO_CLASS (allocno);
|
|
||||||
if (aclass == NO_REGS)
|
|
||||||
return;
|
|
||||||
i = ira_class_hard_reg_index[aclass][hard_regno];
|
|
||||||
ira_assert (i >= 0);
|
|
||||||
rclass = REGNO_REG_CLASS (hard_regno);
|
rclass = REGNO_REG_CLASS (hard_regno);
|
||||||
|
|
||||||
start_update_cost ();
|
|
||||||
divisor = 1;
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
mode = ALLOCNO_MODE (allocno);
|
mode = ALLOCNO_MODE (allocno);
|
||||||
|
|
@ -1264,6 +1351,9 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p)
|
||||||
else
|
else
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
|
|
||||||
|
if (another_allocno == from)
|
||||||
|
continue;
|
||||||
|
|
||||||
aclass = ALLOCNO_CLASS (another_allocno);
|
aclass = ALLOCNO_CLASS (another_allocno);
|
||||||
if (! TEST_HARD_REG_BIT (reg_class_contents[aclass],
|
if (! TEST_HARD_REG_BIT (reg_class_contents[aclass],
|
||||||
hard_regno)
|
hard_regno)
|
||||||
|
|
@ -1280,24 +1370,67 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p)
|
||||||
if (update_cost == 0)
|
if (update_cost == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ira_allocate_and_set_or_copy_costs
|
if (! update_allocno_cost (another_allocno, hard_regno, update_cost))
|
||||||
(&ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno), aclass,
|
|
||||||
ALLOCNO_UPDATED_CLASS_COST (another_allocno),
|
|
||||||
ALLOCNO_HARD_REG_COSTS (another_allocno));
|
|
||||||
ira_allocate_and_set_or_copy_costs
|
|
||||||
(&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno),
|
|
||||||
aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno));
|
|
||||||
i = ira_class_hard_reg_index[aclass][hard_regno];
|
|
||||||
if (i < 0)
|
|
||||||
continue;
|
continue;
|
||||||
ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno)[i] += update_cost;
|
queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR);
|
||||||
ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno)[i]
|
if (record_p && ALLOCNO_COLOR_DATA (another_allocno) != NULL)
|
||||||
+= update_cost;
|
ALLOCNO_COLOR_DATA (another_allocno)->update_cost_records
|
||||||
|
= get_update_cost_record (hard_regno, divisor,
|
||||||
|
ALLOCNO_COLOR_DATA (another_allocno)
|
||||||
|
->update_cost_records);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (get_next_update_cost (&allocno, &from, &divisor));
|
||||||
|
}
|
||||||
|
|
||||||
queue_update_cost (another_allocno, divisor * COST_HOP_DIVISOR);
|
/* Decrease preferred ALLOCNO hard register costs and costs of
|
||||||
|
allocnos connected to ALLOCNO through copy. */
|
||||||
|
static void
|
||||||
|
update_costs_from_prefs (ira_allocno_t allocno)
|
||||||
|
{
|
||||||
|
ira_pref_t pref;
|
||||||
|
|
||||||
|
start_update_cost ();
|
||||||
|
for (pref = ALLOCNO_PREFS (allocno); pref != NULL; pref = pref->next_pref)
|
||||||
|
update_costs_from_allocno (allocno, pref->hard_regno,
|
||||||
|
COST_HOP_DIVISOR, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update (decrease if DECR_P) the cost of allocnos connected to
|
||||||
|
ALLOCNO through copies to increase chances to remove some copies as
|
||||||
|
the result of subsequent assignment. ALLOCNO was just assigned to
|
||||||
|
a hard register. */
|
||||||
|
static void
|
||||||
|
update_costs_from_copies (ira_allocno_t allocno, bool decr_p)
|
||||||
|
{
|
||||||
|
int hard_regno;
|
||||||
|
|
||||||
|
hard_regno = ALLOCNO_HARD_REGNO (allocno);
|
||||||
|
ira_assert (hard_regno >= 0 && ALLOCNO_CLASS (allocno) != NO_REGS);
|
||||||
|
start_update_cost ();
|
||||||
|
update_costs_from_allocno (allocno, hard_regno, 1, decr_p, true);
|
||||||
}
|
}
|
||||||
while (get_next_update_cost (&allocno, &divisor));
|
|
||||||
|
/* Restore costs of allocnos connected to ALLOCNO by copies as it was
|
||||||
|
before updating costs of these allocnos from given allocno. This
|
||||||
|
is a wise thing to do as if given allocno did not get an expected
|
||||||
|
hard reg, using smaller cost of the hard reg for allocnos connected
|
||||||
|
by copies to given allocno becomes actually misleading. Free all
|
||||||
|
update cost records for ALLOCNO as we don't need them anymore. */
|
||||||
|
static void
|
||||||
|
restore_costs_from_copies (ira_allocno_t allocno)
|
||||||
|
{
|
||||||
|
struct update_cost_record *records, *curr;
|
||||||
|
|
||||||
|
if (ALLOCNO_COLOR_DATA (allocno) == NULL)
|
||||||
|
return;
|
||||||
|
records = ALLOCNO_COLOR_DATA (allocno)->update_cost_records;
|
||||||
|
start_update_cost ();
|
||||||
|
for (curr = records; curr != NULL; curr = curr->next)
|
||||||
|
update_costs_from_allocno (allocno, curr->hard_regno,
|
||||||
|
curr->divisor, true, false);
|
||||||
|
free_update_cost_record_list (records);
|
||||||
|
ALLOCNO_COLOR_DATA (allocno)->update_cost_records = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function updates COSTS (decrease if DECR_P) for hard_registers
|
/* This function updates COSTS (decrease if DECR_P) for hard_registers
|
||||||
|
|
@ -1313,10 +1446,10 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
|
||||||
int *conflict_costs;
|
int *conflict_costs;
|
||||||
bool cont_p;
|
bool cont_p;
|
||||||
enum reg_class another_aclass;
|
enum reg_class another_aclass;
|
||||||
ira_allocno_t allocno, another_allocno;
|
ira_allocno_t allocno, another_allocno, from;
|
||||||
ira_copy_t cp, next_cp;
|
ira_copy_t cp, next_cp;
|
||||||
|
|
||||||
while (get_next_update_cost (&allocno, &divisor))
|
while (get_next_update_cost (&allocno, &from, &divisor))
|
||||||
for (cp = ALLOCNO_COPIES (allocno); cp != NULL; cp = next_cp)
|
for (cp = ALLOCNO_COPIES (allocno); cp != NULL; cp = next_cp)
|
||||||
{
|
{
|
||||||
if (cp->first == allocno)
|
if (cp->first == allocno)
|
||||||
|
|
@ -1331,6 +1464,10 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
|
|
||||||
|
if (another_allocno == from)
|
||||||
|
continue;
|
||||||
|
|
||||||
another_aclass = ALLOCNO_CLASS (another_allocno);
|
another_aclass = ALLOCNO_CLASS (another_allocno);
|
||||||
if (! ira_reg_classes_intersect_p[aclass][another_aclass]
|
if (! ira_reg_classes_intersect_p[aclass][another_aclass]
|
||||||
|| ALLOCNO_ASSIGNED_P (another_allocno)
|
|| ALLOCNO_ASSIGNED_P (another_allocno)
|
||||||
|
|
@ -1374,7 +1511,7 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
|
||||||
* COST_HOP_DIVISOR
|
* COST_HOP_DIVISOR
|
||||||
* COST_HOP_DIVISOR
|
* COST_HOP_DIVISOR
|
||||||
* COST_HOP_DIVISOR))
|
* COST_HOP_DIVISOR))
|
||||||
queue_update_cost (another_allocno, divisor * COST_HOP_DIVISOR);
|
queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1640,7 +1777,8 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
|
||||||
continue;
|
continue;
|
||||||
full_costs[j] -= conflict_costs[k];
|
full_costs[j] -= conflict_costs[k];
|
||||||
}
|
}
|
||||||
queue_update_cost (conflict_a, COST_HOP_DIVISOR);
|
queue_update_cost (conflict_a, NULL, COST_HOP_DIVISOR);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1654,7 +1792,7 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
|
||||||
if (! retry_p)
|
if (! retry_p)
|
||||||
{
|
{
|
||||||
start_update_cost ();
|
start_update_cost ();
|
||||||
queue_update_cost (a, COST_HOP_DIVISOR);
|
queue_update_cost (a, NULL, COST_HOP_DIVISOR);
|
||||||
update_conflict_hard_regno_costs (full_costs, aclass, false);
|
update_conflict_hard_regno_costs (full_costs, aclass, false);
|
||||||
}
|
}
|
||||||
min_cost = min_full_cost = INT_MAX;
|
min_cost = min_full_cost = INT_MAX;
|
||||||
|
|
@ -1711,10 +1849,11 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
|
||||||
for (i = hard_regno_nregs[best_hard_regno][mode] - 1; i >= 0; i--)
|
for (i = hard_regno_nregs[best_hard_regno][mode] - 1; i >= 0; i--)
|
||||||
allocated_hardreg_p[best_hard_regno + i] = true;
|
allocated_hardreg_p[best_hard_regno + i] = true;
|
||||||
}
|
}
|
||||||
|
restore_costs_from_copies (a);
|
||||||
ALLOCNO_HARD_REGNO (a) = best_hard_regno;
|
ALLOCNO_HARD_REGNO (a) = best_hard_regno;
|
||||||
ALLOCNO_ASSIGNED_P (a) = true;
|
ALLOCNO_ASSIGNED_P (a) = true;
|
||||||
if (best_hard_regno >= 0)
|
if (best_hard_regno >= 0)
|
||||||
update_copy_costs (a, true);
|
update_costs_from_copies (a, true);
|
||||||
ira_assert (ALLOCNO_CLASS (a) == aclass);
|
ira_assert (ALLOCNO_CLASS (a) == aclass);
|
||||||
/* We don't need updated costs anymore: */
|
/* We don't need updated costs anymore: */
|
||||||
ira_free_allocno_updated_costs (a);
|
ira_free_allocno_updated_costs (a);
|
||||||
|
|
@ -2164,7 +2303,9 @@ pop_allocnos_from_stack (void)
|
||||||
else if (ALLOCNO_ASSIGNED_P (allocno))
|
else if (ALLOCNO_ASSIGNED_P (allocno))
|
||||||
{
|
{
|
||||||
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
|
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
|
||||||
fprintf (ira_dump_file, "spill\n");
|
fprintf (ira_dump_file, "spill%s\n",
|
||||||
|
ALLOCNO_COLOR_DATA (allocno)->may_be_spilled_p
|
||||||
|
? "" : "!");
|
||||||
}
|
}
|
||||||
ALLOCNO_COLOR_DATA (allocno)->in_graph_p = true;
|
ALLOCNO_COLOR_DATA (allocno)->in_graph_p = true;
|
||||||
}
|
}
|
||||||
|
|
@ -2546,6 +2687,32 @@ color_allocnos (void)
|
||||||
ira_allocno_t a;
|
ira_allocno_t a;
|
||||||
|
|
||||||
setup_profitable_hard_regs ();
|
setup_profitable_hard_regs ();
|
||||||
|
EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
|
||||||
|
{
|
||||||
|
int l, nr;
|
||||||
|
HARD_REG_SET conflict_hard_regs;
|
||||||
|
allocno_color_data_t data;
|
||||||
|
ira_pref_t pref, next_pref;
|
||||||
|
|
||||||
|
a = ira_allocnos[i];
|
||||||
|
nr = ALLOCNO_NUM_OBJECTS (a);
|
||||||
|
CLEAR_HARD_REG_SET (conflict_hard_regs);
|
||||||
|
for (l = 0; l < nr; l++)
|
||||||
|
{
|
||||||
|
ira_object_t obj = ALLOCNO_OBJECT (a, l);
|
||||||
|
IOR_HARD_REG_SET (conflict_hard_regs,
|
||||||
|
OBJECT_CONFLICT_HARD_REGS (obj));
|
||||||
|
}
|
||||||
|
data = ALLOCNO_COLOR_DATA (a);
|
||||||
|
for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = next_pref)
|
||||||
|
{
|
||||||
|
next_pref = pref->next_pref;
|
||||||
|
if (! ira_hard_reg_in_set_p (pref->hard_regno,
|
||||||
|
ALLOCNO_MODE (a),
|
||||||
|
data->profitable_hard_regs))
|
||||||
|
ira_remove_pref (pref);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY)
|
if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY)
|
||||||
{
|
{
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
@ -2605,7 +2772,10 @@ color_allocnos (void)
|
||||||
{
|
{
|
||||||
a = ira_allocnos[i];
|
a = ira_allocnos[i];
|
||||||
if (ALLOCNO_CLASS (a) != NO_REGS && ! empty_profitable_hard_regs (a))
|
if (ALLOCNO_CLASS (a) != NO_REGS && ! empty_profitable_hard_regs (a))
|
||||||
|
{
|
||||||
ALLOCNO_COLOR_DATA (a)->in_graph_p = true;
|
ALLOCNO_COLOR_DATA (a)->in_graph_p = true;
|
||||||
|
update_costs_from_prefs (a);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ALLOCNO_HARD_REGNO (a) = -1;
|
ALLOCNO_HARD_REGNO (a) = -1;
|
||||||
|
|
@ -2772,7 +2942,7 @@ color_pass (ira_loop_tree_node_t loop_tree_node)
|
||||||
ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
|
ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
|
||||||
ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
|
ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
|
||||||
if (hard_regno >= 0)
|
if (hard_regno >= 0)
|
||||||
update_copy_costs (subloop_allocno, true);
|
update_costs_from_copies (subloop_allocno, true);
|
||||||
/* We don't need updated costs anymore: */
|
/* We don't need updated costs anymore: */
|
||||||
ira_free_allocno_updated_costs (subloop_allocno);
|
ira_free_allocno_updated_costs (subloop_allocno);
|
||||||
}
|
}
|
||||||
|
|
@ -2816,7 +2986,7 @@ color_pass (ira_loop_tree_node_t loop_tree_node)
|
||||||
ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
|
ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
|
||||||
ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
|
ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
|
||||||
if (hard_regno >= 0)
|
if (hard_regno >= 0)
|
||||||
update_copy_costs (subloop_allocno, true);
|
update_costs_from_copies (subloop_allocno, true);
|
||||||
/* We don't need updated costs anymore: */
|
/* We don't need updated costs anymore: */
|
||||||
ira_free_allocno_updated_costs (subloop_allocno);
|
ira_free_allocno_updated_costs (subloop_allocno);
|
||||||
}
|
}
|
||||||
|
|
@ -2832,7 +3002,7 @@ color_pass (ira_loop_tree_node_t loop_tree_node)
|
||||||
ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
|
ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
|
||||||
ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
|
ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
|
||||||
if (hard_regno >= 0)
|
if (hard_regno >= 0)
|
||||||
update_copy_costs (subloop_allocno, true);
|
update_costs_from_copies (subloop_allocno, true);
|
||||||
/* We don't need updated costs anymore: */
|
/* We don't need updated costs anymore: */
|
||||||
ira_free_allocno_updated_costs (subloop_allocno);
|
ira_free_allocno_updated_costs (subloop_allocno);
|
||||||
}
|
}
|
||||||
|
|
@ -3813,7 +3983,7 @@ ira_mark_allocation_change (int regno)
|
||||||
? ALLOCNO_CLASS_COST (a)
|
? ALLOCNO_CLASS_COST (a)
|
||||||
: ALLOCNO_HARD_REG_COSTS (a)
|
: ALLOCNO_HARD_REG_COSTS (a)
|
||||||
[ira_class_hard_reg_index[aclass][old_hard_regno]]);
|
[ira_class_hard_reg_index[aclass][old_hard_regno]]);
|
||||||
update_copy_costs (a, false);
|
update_costs_from_copies (a, false);
|
||||||
}
|
}
|
||||||
ira_overall_cost -= cost;
|
ira_overall_cost -= cost;
|
||||||
ALLOCNO_HARD_REGNO (a) = hard_regno;
|
ALLOCNO_HARD_REGNO (a) = hard_regno;
|
||||||
|
|
@ -3828,7 +3998,7 @@ ira_mark_allocation_change (int regno)
|
||||||
? ALLOCNO_CLASS_COST (a)
|
? ALLOCNO_CLASS_COST (a)
|
||||||
: ALLOCNO_HARD_REG_COSTS (a)
|
: ALLOCNO_HARD_REG_COSTS (a)
|
||||||
[ira_class_hard_reg_index[aclass][hard_regno]]);
|
[ira_class_hard_reg_index[aclass][hard_regno]]);
|
||||||
update_copy_costs (a, true);
|
update_costs_from_copies (a, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* Reload changed class of the allocno. */
|
/* Reload changed class of the allocno. */
|
||||||
|
|
|
||||||
|
|
@ -208,149 +208,6 @@ allocnos_conflict_for_copy_p (ira_allocno_t a1, ira_allocno_t a2)
|
||||||
return OBJECTS_CONFLICT_P (obj1, obj2);
|
return OBJECTS_CONFLICT_P (obj1, obj2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return TRUE if the operand constraint STR is commutative. */
|
|
||||||
static bool
|
|
||||||
commutative_constraint_p (const char *str)
|
|
||||||
{
|
|
||||||
int curr_alt, c;
|
|
||||||
bool ignore_p;
|
|
||||||
|
|
||||||
for (ignore_p = false, curr_alt = 0;;)
|
|
||||||
{
|
|
||||||
c = *str;
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
str += CONSTRAINT_LEN (c, str);
|
|
||||||
if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
|
|
||||||
ignore_p = true;
|
|
||||||
else if (c == ',')
|
|
||||||
{
|
|
||||||
curr_alt++;
|
|
||||||
ignore_p = false;
|
|
||||||
}
|
|
||||||
else if (! ignore_p)
|
|
||||||
{
|
|
||||||
/* Usually `%' is the first constraint character but the
|
|
||||||
documentation does not require this. */
|
|
||||||
if (c == '%')
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the number of the operand which should be the same in any
|
|
||||||
case as operand with number OP_NUM (or negative value if there is
|
|
||||||
no such operand). If USE_COMMUT_OP_P is TRUE, the function makes
|
|
||||||
temporarily commutative operand exchange before this. The function
|
|
||||||
takes only really possible alternatives into consideration. */
|
|
||||||
static int
|
|
||||||
get_dup_num (int op_num, bool use_commut_op_p)
|
|
||||||
{
|
|
||||||
int curr_alt, c, original, dup;
|
|
||||||
bool ignore_p, commut_op_used_p;
|
|
||||||
const char *str;
|
|
||||||
rtx op;
|
|
||||||
|
|
||||||
if (op_num < 0 || recog_data.n_alternatives == 0)
|
|
||||||
return -1;
|
|
||||||
op = recog_data.operand[op_num];
|
|
||||||
commut_op_used_p = true;
|
|
||||||
if (use_commut_op_p)
|
|
||||||
{
|
|
||||||
if (commutative_constraint_p (recog_data.constraints[op_num]))
|
|
||||||
op_num++;
|
|
||||||
else if (op_num > 0 && commutative_constraint_p (recog_data.constraints
|
|
||||||
[op_num - 1]))
|
|
||||||
op_num--;
|
|
||||||
else
|
|
||||||
commut_op_used_p = false;
|
|
||||||
}
|
|
||||||
str = recog_data.constraints[op_num];
|
|
||||||
for (ignore_p = false, original = -1, curr_alt = 0;;)
|
|
||||||
{
|
|
||||||
c = *str;
|
|
||||||
if (c == '\0')
|
|
||||||
break;
|
|
||||||
if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
|
|
||||||
ignore_p = true;
|
|
||||||
else if (c == ',')
|
|
||||||
{
|
|
||||||
curr_alt++;
|
|
||||||
ignore_p = false;
|
|
||||||
}
|
|
||||||
else if (! ignore_p)
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case 'X':
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case 'm':
|
|
||||||
case 'o':
|
|
||||||
/* Accept a register which might be placed in memory. */
|
|
||||||
return -1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'V':
|
|
||||||
case '<':
|
|
||||||
case '>':
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
|
||||||
if (address_operand (op, VOIDmode))
|
|
||||||
return -1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'g':
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case 'r':
|
|
||||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
|
||||||
case 'h': case 'j': case 'k': case 'l':
|
|
||||||
case 'q': case 't': case 'u':
|
|
||||||
case 'v': case 'w': case 'x': case 'y': case 'z':
|
|
||||||
case 'A': case 'B': case 'C': case 'D':
|
|
||||||
case 'Q': case 'R': case 'S': case 'T': case 'U':
|
|
||||||
case 'W': case 'Y': case 'Z':
|
|
||||||
{
|
|
||||||
enum reg_class cl;
|
|
||||||
|
|
||||||
cl = (c == 'r'
|
|
||||||
? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, str));
|
|
||||||
if (cl != NO_REGS)
|
|
||||||
return -1;
|
|
||||||
#ifdef EXTRA_CONSTRAINT_STR
|
|
||||||
else if (EXTRA_CONSTRAINT_STR (op, c, str))
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
|
||||||
if (original != -1 && original != c)
|
|
||||||
return -1;
|
|
||||||
original = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
str += CONSTRAINT_LEN (c, str);
|
|
||||||
}
|
|
||||||
if (original == -1)
|
|
||||||
return -1;
|
|
||||||
dup = original - '0';
|
|
||||||
if (use_commut_op_p)
|
|
||||||
{
|
|
||||||
if (commutative_constraint_p (recog_data.constraints[dup]))
|
|
||||||
dup++;
|
|
||||||
else if (dup > 0
|
|
||||||
&& commutative_constraint_p (recog_data.constraints[dup -1]))
|
|
||||||
dup--;
|
|
||||||
else if (! commut_op_used_p)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return dup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check that X is REG or SUBREG of REG. */
|
/* Check that X is REG or SUBREG of REG. */
|
||||||
#define REG_SUBREG_P(x) \
|
#define REG_SUBREG_P(x) \
|
||||||
(REG_P (x) || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))))
|
(REG_P (x) || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))))
|
||||||
|
|
@ -461,6 +318,7 @@ process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p,
|
||||||
ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= cost;
|
ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= cost;
|
||||||
if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_CLASS_COST (a))
|
if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_CLASS_COST (a))
|
||||||
ALLOCNO_CLASS_COST (a) = ALLOCNO_HARD_REG_COSTS (a)[index];
|
ALLOCNO_CLASS_COST (a) = ALLOCNO_HARD_REG_COSTS (a)[index];
|
||||||
|
ira_add_allocno_pref (a, allocno_preferenced_hard_regno, freq);
|
||||||
a = ira_parent_or_cap_allocno (a);
|
a = ira_parent_or_cap_allocno (a);
|
||||||
}
|
}
|
||||||
while (a != NULL);
|
while (a != NULL);
|
||||||
|
|
@ -498,9 +356,9 @@ static void
|
||||||
add_insn_allocno_copies (rtx insn)
|
add_insn_allocno_copies (rtx insn)
|
||||||
{
|
{
|
||||||
rtx set, operand, dup;
|
rtx set, operand, dup;
|
||||||
const char *str;
|
bool bound_p[MAX_RECOG_OPERANDS];
|
||||||
bool commut_p, bound_p[MAX_RECOG_OPERANDS];
|
int i, n, freq;
|
||||||
int i, j, n, freq;
|
HARD_REG_SET alts;
|
||||||
|
|
||||||
freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn));
|
freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn));
|
||||||
if (freq == 0)
|
if (freq == 0)
|
||||||
|
|
@ -513,7 +371,7 @@ add_insn_allocno_copies (rtx insn)
|
||||||
? SET_SRC (set)
|
? SET_SRC (set)
|
||||||
: SUBREG_REG (SET_SRC (set))) != NULL_RTX)
|
: SUBREG_REG (SET_SRC (set))) != NULL_RTX)
|
||||||
{
|
{
|
||||||
process_regs_for_copy (SET_DEST (set), SET_SRC (set),
|
process_regs_for_copy (SET_SRC (set), SET_DEST (set),
|
||||||
false, insn, freq);
|
false, insn, freq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -521,7 +379,7 @@ add_insn_allocno_copies (rtx insn)
|
||||||
there are no dead registers, there will be no such copies. */
|
there are no dead registers, there will be no such copies. */
|
||||||
if (! find_reg_note (insn, REG_DEAD, NULL_RTX))
|
if (! find_reg_note (insn, REG_DEAD, NULL_RTX))
|
||||||
return;
|
return;
|
||||||
extract_insn (insn);
|
ira_setup_alts (insn, alts);
|
||||||
for (i = 0; i < recog_data.n_operands; i++)
|
for (i = 0; i < recog_data.n_operands; i++)
|
||||||
bound_p[i] = false;
|
bound_p[i] = false;
|
||||||
for (i = 0; i < recog_data.n_operands; i++)
|
for (i = 0; i < recog_data.n_operands; i++)
|
||||||
|
|
@ -529,11 +387,7 @@ add_insn_allocno_copies (rtx insn)
|
||||||
operand = recog_data.operand[i];
|
operand = recog_data.operand[i];
|
||||||
if (! REG_SUBREG_P (operand))
|
if (! REG_SUBREG_P (operand))
|
||||||
continue;
|
continue;
|
||||||
str = recog_data.constraints[i];
|
if ((n = ira_get_dup_out_num (i, alts)) >= 0)
|
||||||
while (*str == ' ' || *str == '\t')
|
|
||||||
str++;
|
|
||||||
for (j = 0, commut_p = false; j < 2; j++, commut_p = true)
|
|
||||||
if ((n = get_dup_num (i, commut_p)) >= 0)
|
|
||||||
{
|
{
|
||||||
bound_p[n] = true;
|
bound_p[n] = true;
|
||||||
dup = recog_data.operand[n];
|
dup = recog_data.operand[n];
|
||||||
|
|
@ -542,7 +396,8 @@ add_insn_allocno_copies (rtx insn)
|
||||||
REG_P (operand)
|
REG_P (operand)
|
||||||
? operand
|
? operand
|
||||||
: SUBREG_REG (operand)) != NULL_RTX)
|
: SUBREG_REG (operand)) != NULL_RTX)
|
||||||
process_regs_for_copy (operand, dup, true, NULL_RTX, freq);
|
process_regs_for_copy (operand, dup, true, NULL_RTX,
|
||||||
|
freq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < recog_data.n_operands; i++)
|
for (i = 0; i < recog_data.n_operands; i++)
|
||||||
|
|
|
||||||
187
gcc/ira-costs.c
187
gcc/ira-costs.c
|
|
@ -405,7 +405,6 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
||||||
{
|
{
|
||||||
int alt;
|
int alt;
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
rtx set;
|
|
||||||
int insn_allows_mem[MAX_RECOG_OPERANDS];
|
int insn_allows_mem[MAX_RECOG_OPERANDS];
|
||||||
|
|
||||||
for (i = 0; i < n_ops; i++)
|
for (i = 0; i < n_ops; i++)
|
||||||
|
|
@ -914,60 +913,6 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
||||||
ALLOCNO_BAD_SPILL_P (a) = true;
|
ALLOCNO_BAD_SPILL_P (a) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this insn is a single set copying operand 1 to operand 0 and
|
|
||||||
one operand is an allocno with the other a hard reg or an allocno
|
|
||||||
that prefers a hard register that is in its own register class
|
|
||||||
then we may want to adjust the cost of that register class to -1.
|
|
||||||
|
|
||||||
Avoid the adjustment if the source does not die to avoid
|
|
||||||
stressing of register allocator by preferrencing two colliding
|
|
||||||
registers into single class.
|
|
||||||
|
|
||||||
Also avoid the adjustment if a copy between hard registers of the
|
|
||||||
class is expensive (ten times the cost of a default copy is
|
|
||||||
considered arbitrarily expensive). This avoids losing when the
|
|
||||||
preferred class is very expensive as the source of a copy
|
|
||||||
instruction. */
|
|
||||||
if ((set = single_set (insn)) != 0
|
|
||||||
&& ops[0] == SET_DEST (set) && ops[1] == SET_SRC (set)
|
|
||||||
&& REG_P (ops[0]) && REG_P (ops[1])
|
|
||||||
&& find_regno_note (insn, REG_DEAD, REGNO (ops[1])))
|
|
||||||
for (i = 0; i <= 1; i++)
|
|
||||||
if (REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER
|
|
||||||
&& REGNO (ops[!i]) < FIRST_PSEUDO_REGISTER)
|
|
||||||
{
|
|
||||||
unsigned int regno = REGNO (ops[i]);
|
|
||||||
unsigned int other_regno = REGNO (ops[!i]);
|
|
||||||
enum machine_mode mode = GET_MODE (ops[!i]);
|
|
||||||
cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
|
|
||||||
enum reg_class *cost_classes = cost_classes_ptr->classes;
|
|
||||||
reg_class_t rclass;
|
|
||||||
int nr;
|
|
||||||
|
|
||||||
for (k = cost_classes_ptr->num - 1; k >= 0; k--)
|
|
||||||
{
|
|
||||||
rclass = cost_classes[k];
|
|
||||||
if (TEST_HARD_REG_BIT (reg_class_contents[rclass], other_regno)
|
|
||||||
&& (reg_class_size[(int) rclass]
|
|
||||||
== ira_reg_class_max_nregs [(int) rclass][(int) mode]))
|
|
||||||
{
|
|
||||||
if (reg_class_size[rclass] == 1)
|
|
||||||
op_costs[i]->cost[k] = -frequency;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (nr = 0;
|
|
||||||
nr < hard_regno_nregs[other_regno][mode];
|
|
||||||
nr++)
|
|
||||||
if (! TEST_HARD_REG_BIT (reg_class_contents[rclass],
|
|
||||||
other_regno + nr))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (nr == hard_regno_nregs[other_regno][mode])
|
|
||||||
op_costs[i]->cost[k] = -frequency;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1204,6 +1149,8 @@ record_operand_costs (rtx insn, enum reg_class *pref)
|
||||||
{
|
{
|
||||||
const char *constraints[MAX_RECOG_OPERANDS];
|
const char *constraints[MAX_RECOG_OPERANDS];
|
||||||
enum machine_mode modes[MAX_RECOG_OPERANDS];
|
enum machine_mode modes[MAX_RECOG_OPERANDS];
|
||||||
|
rtx ops[MAX_RECOG_OPERANDS];
|
||||||
|
rtx set;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < recog_data.n_operands; i++)
|
for (i = 0; i < recog_data.n_operands; i++)
|
||||||
|
|
@ -1221,6 +1168,7 @@ record_operand_costs (rtx insn, enum reg_class *pref)
|
||||||
{
|
{
|
||||||
memcpy (op_costs[i], init_cost, struct_costs_size);
|
memcpy (op_costs[i], init_cost, struct_costs_size);
|
||||||
|
|
||||||
|
ops[i] = recog_data.operand[i];
|
||||||
if (GET_CODE (recog_data.operand[i]) == SUBREG)
|
if (GET_CODE (recog_data.operand[i]) == SUBREG)
|
||||||
recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]);
|
recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]);
|
||||||
|
|
||||||
|
|
@ -1260,6 +1208,77 @@ record_operand_costs (rtx insn, enum reg_class *pref)
|
||||||
record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
|
record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
|
||||||
recog_data.operand, modes,
|
recog_data.operand, modes,
|
||||||
constraints, insn, pref);
|
constraints, insn, pref);
|
||||||
|
|
||||||
|
/* If this insn is a single set copying operand 1 to operand 0 and
|
||||||
|
one operand is an allocno with the other a hard reg or an allocno
|
||||||
|
that prefers a hard register that is in its own register class
|
||||||
|
then we may want to adjust the cost of that register class to -1.
|
||||||
|
|
||||||
|
Avoid the adjustment if the source does not die to avoid
|
||||||
|
stressing of register allocator by preferrencing two colliding
|
||||||
|
registers into single class.
|
||||||
|
|
||||||
|
Also avoid the adjustment if a copy between hard registers of the
|
||||||
|
class is expensive (ten times the cost of a default copy is
|
||||||
|
considered arbitrarily expensive). This avoids losing when the
|
||||||
|
preferred class is very expensive as the source of a copy
|
||||||
|
instruction. */
|
||||||
|
if ((set = single_set (insn)) != NULL_RTX
|
||||||
|
&& ops[0] == SET_DEST (set) && ops[1] == SET_SRC (set))
|
||||||
|
{
|
||||||
|
int regno, other_regno;
|
||||||
|
rtx dest = SET_DEST (set);
|
||||||
|
rtx src = SET_SRC (set);
|
||||||
|
|
||||||
|
dest = SET_DEST (set);
|
||||||
|
src = SET_SRC (set);
|
||||||
|
if (GET_CODE (dest) == SUBREG
|
||||||
|
&& (GET_MODE_SIZE (GET_MODE (dest))
|
||||||
|
== GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))))
|
||||||
|
dest = SUBREG_REG (dest);
|
||||||
|
if (GET_CODE (src) == SUBREG
|
||||||
|
&& (GET_MODE_SIZE (GET_MODE (src))
|
||||||
|
== GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))))
|
||||||
|
src = SUBREG_REG (src);
|
||||||
|
if (REG_P (src) && REG_P (dest)
|
||||||
|
&& find_regno_note (insn, REG_DEAD, REGNO (src))
|
||||||
|
&& (((regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER
|
||||||
|
&& (other_regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER)
|
||||||
|
|| ((regno = REGNO (dest)) >= FIRST_PSEUDO_REGISTER
|
||||||
|
&& (other_regno = REGNO (src)) < FIRST_PSEUDO_REGISTER)))
|
||||||
|
{
|
||||||
|
enum machine_mode mode = GET_MODE (src);
|
||||||
|
cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
|
||||||
|
enum reg_class *cost_classes = cost_classes_ptr->classes;
|
||||||
|
reg_class_t rclass;
|
||||||
|
int k, nr;
|
||||||
|
|
||||||
|
i = regno == (int) REGNO (src) ? 1 : 0;
|
||||||
|
for (k = cost_classes_ptr->num - 1; k >= 0; k--)
|
||||||
|
{
|
||||||
|
rclass = cost_classes[k];
|
||||||
|
if (TEST_HARD_REG_BIT (reg_class_contents[rclass], other_regno)
|
||||||
|
&& (reg_class_size[(int) rclass]
|
||||||
|
== ira_reg_class_max_nregs [(int) rclass][(int) mode]))
|
||||||
|
{
|
||||||
|
if (reg_class_size[rclass] == 1)
|
||||||
|
op_costs[i]->cost[k] = -frequency;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (nr = 0;
|
||||||
|
nr < hard_regno_nregs[other_regno][mode];
|
||||||
|
nr++)
|
||||||
|
if (! TEST_HARD_REG_BIT (reg_class_contents[rclass],
|
||||||
|
other_regno + nr))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (nr == hard_regno_nregs[other_regno][mode])
|
||||||
|
op_costs[i]->cost[k] = -frequency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1741,14 +1760,15 @@ find_costs_and_classes (FILE *dump_file)
|
||||||
a != NULL;
|
a != NULL;
|
||||||
a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
|
a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
|
||||||
{
|
{
|
||||||
a_num = ALLOCNO_NUM (a);
|
enum reg_class aclass = regno_aclass[i];
|
||||||
if (regno_aclass[i] == NO_REGS)
|
int a_num = ALLOCNO_NUM (a);
|
||||||
best = NO_REGS;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int *total_a_costs = COSTS (total_allocno_costs, a_num)->cost;
|
int *total_a_costs = COSTS (total_allocno_costs, a_num)->cost;
|
||||||
int *a_costs = COSTS (costs, a_num)->cost;
|
int *a_costs = COSTS (costs, a_num)->cost;
|
||||||
|
|
||||||
|
if (aclass == NO_REGS)
|
||||||
|
best = NO_REGS;
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Finding best class which is subset of the common
|
/* Finding best class which is subset of the common
|
||||||
class. */
|
class. */
|
||||||
best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
|
best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
|
||||||
|
|
@ -1757,7 +1777,7 @@ find_costs_and_classes (FILE *dump_file)
|
||||||
for (k = 0; k < cost_classes_ptr->num; k++)
|
for (k = 0; k < cost_classes_ptr->num; k++)
|
||||||
{
|
{
|
||||||
rclass = cost_classes[k];
|
rclass = cost_classes[k];
|
||||||
if (! ira_class_subset_p[rclass][regno_aclass[i]])
|
if (! ira_class_subset_p[rclass][aclass])
|
||||||
continue;
|
continue;
|
||||||
/* Ignore classes that are too small or invalid
|
/* Ignore classes that are too small or invalid
|
||||||
for this operand. */
|
for this operand. */
|
||||||
|
|
@ -1792,9 +1812,25 @@ find_costs_and_classes (FILE *dump_file)
|
||||||
ALLOCNO_LOOP_TREE_NODE (a)->loop_num);
|
ALLOCNO_LOOP_TREE_NODE (a)->loop_num);
|
||||||
fprintf (dump_file, ") best %s, allocno %s\n",
|
fprintf (dump_file, ") best %s, allocno %s\n",
|
||||||
reg_class_names[best],
|
reg_class_names[best],
|
||||||
reg_class_names[regno_aclass[i]]);
|
reg_class_names[aclass]);
|
||||||
}
|
}
|
||||||
pref[a_num] = best;
|
pref[a_num] = best;
|
||||||
|
if (pass == flag_expensive_optimizations && best != aclass
|
||||||
|
&& ira_class_hard_regs_num[best] > 0
|
||||||
|
&& (ira_reg_class_max_nregs[best][ALLOCNO_MODE (a)]
|
||||||
|
>= ira_class_hard_regs_num[best]))
|
||||||
|
{
|
||||||
|
int ind = cost_classes_ptr->index[aclass];
|
||||||
|
|
||||||
|
ira_assert (ind >= 0);
|
||||||
|
ira_add_allocno_pref (a, ira_class_hard_regs[best][0],
|
||||||
|
(a_costs[ind] - ALLOCNO_CLASS_COST (a))
|
||||||
|
/ (ira_register_move_cost
|
||||||
|
[ALLOCNO_MODE (a)][best][aclass]));
|
||||||
|
for (k = 0; k < cost_classes_ptr->num; k++)
|
||||||
|
if (ira_class_subset_p[cost_classes[k]][best])
|
||||||
|
a_costs[k] = a_costs[ind];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1820,11 +1856,11 @@ find_costs_and_classes (FILE *dump_file)
|
||||||
static void
|
static void
|
||||||
process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node)
|
process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node)
|
||||||
{
|
{
|
||||||
int i, freq, cost, src_regno, dst_regno, hard_regno;
|
int i, freq, src_regno, dst_regno, hard_regno, a_regno;
|
||||||
bool to_p;
|
bool to_p;
|
||||||
ira_allocno_t a;
|
ira_allocno_t a, curr_a;
|
||||||
enum reg_class rclass, hard_reg_class;
|
ira_loop_tree_node_t curr_loop_tree_node;
|
||||||
enum machine_mode mode;
|
enum reg_class rclass;
|
||||||
basic_block bb;
|
basic_block bb;
|
||||||
rtx insn, set, src, dst;
|
rtx insn, set, src, dst;
|
||||||
|
|
||||||
|
|
@ -1851,15 +1887,15 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node)
|
||||||
&& src_regno < FIRST_PSEUDO_REGISTER)
|
&& src_regno < FIRST_PSEUDO_REGISTER)
|
||||||
{
|
{
|
||||||
hard_regno = src_regno;
|
hard_regno = src_regno;
|
||||||
to_p = true;
|
|
||||||
a = ira_curr_regno_allocno_map[dst_regno];
|
a = ira_curr_regno_allocno_map[dst_regno];
|
||||||
|
to_p = true;
|
||||||
}
|
}
|
||||||
else if (src_regno >= FIRST_PSEUDO_REGISTER
|
else if (src_regno >= FIRST_PSEUDO_REGISTER
|
||||||
&& dst_regno < FIRST_PSEUDO_REGISTER)
|
&& dst_regno < FIRST_PSEUDO_REGISTER)
|
||||||
{
|
{
|
||||||
hard_regno = dst_regno;
|
hard_regno = dst_regno;
|
||||||
to_p = false;
|
|
||||||
a = ira_curr_regno_allocno_map[src_regno];
|
a = ira_curr_regno_allocno_map[src_regno];
|
||||||
|
to_p = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1869,11 +1905,21 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node)
|
||||||
i = ira_class_hard_reg_index[rclass][hard_regno];
|
i = ira_class_hard_reg_index[rclass][hard_regno];
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
continue;
|
continue;
|
||||||
|
a_regno = ALLOCNO_REGNO (a);
|
||||||
|
for (curr_loop_tree_node = ALLOCNO_LOOP_TREE_NODE (a);
|
||||||
|
curr_loop_tree_node != NULL;
|
||||||
|
curr_loop_tree_node = curr_loop_tree_node->parent)
|
||||||
|
if ((curr_a = curr_loop_tree_node->regno_allocno_map[a_regno]) != NULL)
|
||||||
|
ira_add_allocno_pref (curr_a, hard_regno, freq);
|
||||||
|
{
|
||||||
|
int cost;
|
||||||
|
enum reg_class hard_reg_class;
|
||||||
|
enum machine_mode mode;
|
||||||
|
|
||||||
mode = ALLOCNO_MODE (a);
|
mode = ALLOCNO_MODE (a);
|
||||||
hard_reg_class = REGNO_REG_CLASS (hard_regno);
|
hard_reg_class = REGNO_REG_CLASS (hard_regno);
|
||||||
ira_init_register_move_cost_if_necessary (mode);
|
ira_init_register_move_cost_if_necessary (mode);
|
||||||
cost
|
cost = (to_p ? ira_register_move_cost[mode][hard_reg_class][rclass]
|
||||||
= (to_p ? ira_register_move_cost[mode][hard_reg_class][rclass]
|
|
||||||
: ira_register_move_cost[mode][rclass][hard_reg_class]) * freq;
|
: ira_register_move_cost[mode][rclass][hard_reg_class]) * freq;
|
||||||
ira_allocate_and_set_costs (&ALLOCNO_HARD_REG_COSTS (a), rclass,
|
ira_allocate_and_set_costs (&ALLOCNO_HARD_REG_COSTS (a), rclass,
|
||||||
ALLOCNO_CLASS_COST (a));
|
ALLOCNO_CLASS_COST (a));
|
||||||
|
|
@ -1885,6 +1931,7 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node)
|
||||||
ALLOCNO_HARD_REG_COSTS (a)[i]);
|
ALLOCNO_HARD_REG_COSTS (a)[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* After we find hard register and memory costs for allocnos, define
|
/* After we find hard register and memory costs for allocnos, define
|
||||||
its class and modify hard register cost because insns moving
|
its class and modify hard register cost because insns moving
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ extern FILE *ira_dump_file;
|
||||||
allocnos. */
|
allocnos. */
|
||||||
typedef struct live_range *live_range_t;
|
typedef struct live_range *live_range_t;
|
||||||
typedef struct ira_allocno *ira_allocno_t;
|
typedef struct ira_allocno *ira_allocno_t;
|
||||||
|
typedef struct ira_allocno_pref *ira_pref_t;
|
||||||
typedef struct ira_allocno_copy *ira_copy_t;
|
typedef struct ira_allocno_copy *ira_copy_t;
|
||||||
typedef struct ira_object *ira_object_t;
|
typedef struct ira_object *ira_object_t;
|
||||||
|
|
||||||
|
|
@ -346,6 +347,8 @@ struct ira_allocno
|
||||||
register class living at the point than number of hard-registers
|
register class living at the point than number of hard-registers
|
||||||
of the class available for the allocation. */
|
of the class available for the allocation. */
|
||||||
int excess_pressure_points_num;
|
int excess_pressure_points_num;
|
||||||
|
/* Allocno hard reg preferences. */
|
||||||
|
ira_pref_t allocno_prefs;
|
||||||
/* Copies to other non-conflicting allocnos. The copies can
|
/* Copies to other non-conflicting allocnos. The copies can
|
||||||
represent move insn or potential move insn usually because of two
|
represent move insn or potential move insn usually because of two
|
||||||
operand insn constraints. */
|
operand insn constraints. */
|
||||||
|
|
@ -426,6 +429,7 @@ struct ira_allocno
|
||||||
#define ALLOCNO_BAD_SPILL_P(A) ((A)->bad_spill_p)
|
#define ALLOCNO_BAD_SPILL_P(A) ((A)->bad_spill_p)
|
||||||
#define ALLOCNO_ASSIGNED_P(A) ((A)->assigned_p)
|
#define ALLOCNO_ASSIGNED_P(A) ((A)->assigned_p)
|
||||||
#define ALLOCNO_MODE(A) ((A)->mode)
|
#define ALLOCNO_MODE(A) ((A)->mode)
|
||||||
|
#define ALLOCNO_PREFS(A) ((A)->allocno_prefs)
|
||||||
#define ALLOCNO_COPIES(A) ((A)->allocno_copies)
|
#define ALLOCNO_COPIES(A) ((A)->allocno_copies)
|
||||||
#define ALLOCNO_HARD_REG_COSTS(A) ((A)->hard_reg_costs)
|
#define ALLOCNO_HARD_REG_COSTS(A) ((A)->hard_reg_costs)
|
||||||
#define ALLOCNO_UPDATED_HARD_REG_COSTS(A) ((A)->updated_hard_reg_costs)
|
#define ALLOCNO_UPDATED_HARD_REG_COSTS(A) ((A)->updated_hard_reg_costs)
|
||||||
|
|
@ -516,6 +520,33 @@ extern ira_object_t *ira_object_id_map;
|
||||||
/* The size of the previous array. */
|
/* The size of the previous array. */
|
||||||
extern int ira_objects_num;
|
extern int ira_objects_num;
|
||||||
|
|
||||||
|
/* The following structure represents a hard register prefererence of
|
||||||
|
allocno. The preference represent move insns or potential move
|
||||||
|
insns usually because of two operand insn constraints. One move
|
||||||
|
operand is a hard register. */
|
||||||
|
struct ira_allocno_pref
|
||||||
|
{
|
||||||
|
/* The unique order number of the preference node starting with 0. */
|
||||||
|
int num;
|
||||||
|
/* Preferred hard register. */
|
||||||
|
int hard_regno;
|
||||||
|
/* Accumulated execution frequency of insns from which the
|
||||||
|
preference created. */
|
||||||
|
int freq;
|
||||||
|
/* Given allocno. */
|
||||||
|
ira_allocno_t allocno;
|
||||||
|
/* All prefernces with the same allocno are linked by the following
|
||||||
|
member. */
|
||||||
|
ira_pref_t next_pref;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Array of references to all allocno preferences. The order number
|
||||||
|
of the preference corresponds to the index in the array. */
|
||||||
|
extern ira_pref_t *ira_prefs;
|
||||||
|
|
||||||
|
/* Size of the previous array. */
|
||||||
|
extern int ira_prefs_num;
|
||||||
|
|
||||||
/* The following structure represents a copy of two allocnos. The
|
/* The following structure represents a copy of two allocnos. The
|
||||||
copies represent move insns or potential move insns usually because
|
copies represent move insns or potential move insns usually because
|
||||||
of two operand insn constraints. To remove register shuffle, we
|
of two operand insn constraints. To remove register shuffle, we
|
||||||
|
|
@ -925,6 +956,8 @@ extern void ira_print_disposition (FILE *);
|
||||||
extern void ira_debug_disposition (void);
|
extern void ira_debug_disposition (void);
|
||||||
extern void ira_debug_allocno_classes (void);
|
extern void ira_debug_allocno_classes (void);
|
||||||
extern void ira_init_register_move_cost (enum machine_mode);
|
extern void ira_init_register_move_cost (enum machine_mode);
|
||||||
|
extern void ira_setup_alts (rtx insn, HARD_REG_SET &alts);
|
||||||
|
extern int ira_get_dup_out_num (int op_num, HARD_REG_SET &alts);
|
||||||
|
|
||||||
/* ira-build.c */
|
/* ira-build.c */
|
||||||
|
|
||||||
|
|
@ -932,6 +965,10 @@ extern void ira_init_register_move_cost (enum machine_mode);
|
||||||
extern ira_loop_tree_node_t ira_curr_loop_tree_node;
|
extern ira_loop_tree_node_t ira_curr_loop_tree_node;
|
||||||
extern ira_allocno_t *ira_curr_regno_allocno_map;
|
extern ira_allocno_t *ira_curr_regno_allocno_map;
|
||||||
|
|
||||||
|
extern void ira_debug_pref (ira_pref_t);
|
||||||
|
extern void ira_debug_prefs (void);
|
||||||
|
extern void ira_debug_allocno_prefs (ira_allocno_t);
|
||||||
|
|
||||||
extern void ira_debug_copy (ira_copy_t);
|
extern void ira_debug_copy (ira_copy_t);
|
||||||
extern void debug (ira_allocno_copy &ref);
|
extern void debug (ira_allocno_copy &ref);
|
||||||
extern void debug (ira_allocno_copy *ptr);
|
extern void debug (ira_allocno_copy *ptr);
|
||||||
|
|
@ -963,10 +1000,12 @@ extern bool ira_live_ranges_intersect_p (live_range_t, live_range_t);
|
||||||
extern void ira_finish_live_range (live_range_t);
|
extern void ira_finish_live_range (live_range_t);
|
||||||
extern void ira_finish_live_range_list (live_range_t);
|
extern void ira_finish_live_range_list (live_range_t);
|
||||||
extern void ira_free_allocno_updated_costs (ira_allocno_t);
|
extern void ira_free_allocno_updated_costs (ira_allocno_t);
|
||||||
|
extern ira_pref_t ira_create_pref (ira_allocno_t, int, int);
|
||||||
|
extern void ira_add_allocno_pref (ira_allocno_t, int, int);
|
||||||
|
extern void ira_remove_pref (ira_pref_t);
|
||||||
|
extern void ira_remove_allocno_prefs (ira_allocno_t);
|
||||||
extern ira_copy_t ira_create_copy (ira_allocno_t, ira_allocno_t,
|
extern ira_copy_t ira_create_copy (ira_allocno_t, ira_allocno_t,
|
||||||
int, bool, rtx, ira_loop_tree_node_t);
|
int, bool, rtx, ira_loop_tree_node_t);
|
||||||
extern void ira_add_allocno_copy_to_list (ira_copy_t);
|
|
||||||
extern void ira_swap_allocno_copy_ends_if_necessary (ira_copy_t);
|
|
||||||
extern ira_copy_t ira_add_allocno_copy (ira_allocno_t, ira_allocno_t, int,
|
extern ira_copy_t ira_add_allocno_copy (ira_allocno_t, ira_allocno_t, int,
|
||||||
bool, rtx, ira_loop_tree_node_t);
|
bool, rtx, ira_loop_tree_node_t);
|
||||||
|
|
||||||
|
|
@ -1151,6 +1190,44 @@ ira_allocno_object_iter_cond (ira_allocno_object_iterator *i, ira_allocno_t a,
|
||||||
ira_allocno_object_iter_cond (&(ITER), (A), &(O));)
|
ira_allocno_object_iter_cond (&(ITER), (A), &(O));)
|
||||||
|
|
||||||
|
|
||||||
|
/* The iterator for prefs. */
|
||||||
|
typedef struct {
|
||||||
|
/* The number of the current element in IRA_PREFS. */
|
||||||
|
int n;
|
||||||
|
} ira_pref_iterator;
|
||||||
|
|
||||||
|
/* Initialize the iterator I. */
|
||||||
|
static inline void
|
||||||
|
ira_pref_iter_init (ira_pref_iterator *i)
|
||||||
|
{
|
||||||
|
i->n = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return TRUE if we have more prefs to visit, in which case *PREF is
|
||||||
|
set to the pref to be visited. Otherwise, return FALSE. */
|
||||||
|
static inline bool
|
||||||
|
ira_pref_iter_cond (ira_pref_iterator *i, ira_pref_t *pref)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
for (n = i->n; n < ira_prefs_num; n++)
|
||||||
|
if (ira_prefs[n] != NULL)
|
||||||
|
{
|
||||||
|
*pref = ira_prefs[n];
|
||||||
|
i->n = n + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop over all prefs. In each iteration, P is set to the next
|
||||||
|
pref. ITER is an instance of ira_pref_iterator used to iterate
|
||||||
|
the prefs. */
|
||||||
|
#define FOR_EACH_PREF(P, ITER) \
|
||||||
|
for (ira_pref_iter_init (&(ITER)); \
|
||||||
|
ira_pref_iter_cond (&(ITER), &(P));)
|
||||||
|
|
||||||
|
|
||||||
/* The iterator for copies. */
|
/* The iterator for copies. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* The number of the current element in IRA_COPIES. */
|
/* The number of the current element in IRA_COPIES. */
|
||||||
|
|
|
||||||
524
gcc/ira.c
524
gcc/ira.c
|
|
@ -1761,6 +1761,527 @@ setup_prohibited_mode_move_regs (void)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Return TRUE if the operand constraint STR is commutative. */
|
||||||
|
static bool
|
||||||
|
commutative_constraint_p (const char *str)
|
||||||
|
{
|
||||||
|
int curr_alt, c;
|
||||||
|
bool ignore_p;
|
||||||
|
|
||||||
|
for (ignore_p = false, curr_alt = 0;;)
|
||||||
|
{
|
||||||
|
c = *str;
|
||||||
|
if (c == '\0')
|
||||||
|
break;
|
||||||
|
str += CONSTRAINT_LEN (c, str);
|
||||||
|
if (c == '#' || !recog_data.alternative_enabled_p[curr_alt])
|
||||||
|
ignore_p = true;
|
||||||
|
else if (c == ',')
|
||||||
|
{
|
||||||
|
curr_alt++;
|
||||||
|
ignore_p = false;
|
||||||
|
}
|
||||||
|
else if (! ignore_p)
|
||||||
|
{
|
||||||
|
/* Usually `%' is the first constraint character but the
|
||||||
|
documentation does not require this. */
|
||||||
|
if (c == '%')
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup possible alternatives in ALTS for INSN. */
|
||||||
|
void
|
||||||
|
ira_setup_alts (rtx insn, HARD_REG_SET &alts)
|
||||||
|
{
|
||||||
|
/* MAP nalt * nop -> start of constraints for given operand and
|
||||||
|
alternative */
|
||||||
|
static vec<const char *> insn_constraints;
|
||||||
|
int nop, nalt;
|
||||||
|
bool curr_swapped;
|
||||||
|
const char *p;
|
||||||
|
rtx op;
|
||||||
|
int commutative = -1;
|
||||||
|
|
||||||
|
extract_insn (insn);
|
||||||
|
CLEAR_HARD_REG_SET (alts);
|
||||||
|
insn_constraints.release ();
|
||||||
|
insn_constraints.safe_grow_cleared (recog_data.n_operands
|
||||||
|
* recog_data.n_alternatives + 1);
|
||||||
|
/* Check that the hard reg set is enough for holding all
|
||||||
|
alternatives. It is hard to imagine the situation when the
|
||||||
|
assertion is wrong. */
|
||||||
|
ira_assert (recog_data.n_alternatives
|
||||||
|
<= (int) MAX (sizeof (HARD_REG_ELT_TYPE) * CHAR_BIT,
|
||||||
|
FIRST_PSEUDO_REGISTER));
|
||||||
|
for (curr_swapped = false;; curr_swapped = true)
|
||||||
|
{
|
||||||
|
/* Calculate some data common for all alternatives to speed up the
|
||||||
|
function. */
|
||||||
|
for (nop = 0; nop < recog_data.n_operands; nop++)
|
||||||
|
{
|
||||||
|
for (nalt = 0, p = recog_data.constraints[nop];
|
||||||
|
nalt < recog_data.n_alternatives;
|
||||||
|
nalt++)
|
||||||
|
{
|
||||||
|
insn_constraints[nop * recog_data.n_alternatives + nalt] = p;
|
||||||
|
while (*p && *p != ',')
|
||||||
|
p++;
|
||||||
|
if (*p)
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (nalt = 0; nalt < recog_data.n_alternatives; nalt++)
|
||||||
|
{
|
||||||
|
if (! recog_data.alternative_enabled_p[nalt] || TEST_HARD_REG_BIT (alts, nalt))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (nop = 0; nop < recog_data.n_operands; nop++)
|
||||||
|
{
|
||||||
|
int c, len;
|
||||||
|
|
||||||
|
op = recog_data.operand[nop];
|
||||||
|
p = insn_constraints[nop * recog_data.n_alternatives + nalt];
|
||||||
|
if (*p == 0 || *p == ',')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
do
|
||||||
|
switch (c = *p, len = CONSTRAINT_LEN (c, p), c)
|
||||||
|
{
|
||||||
|
case '#':
|
||||||
|
case ',':
|
||||||
|
c = '\0';
|
||||||
|
case '\0':
|
||||||
|
len = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '?': case '!': case '*': case '=': case '+':
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '%':
|
||||||
|
/* We only support one commutative marker, the
|
||||||
|
first one. We already set commutative
|
||||||
|
above. */
|
||||||
|
if (commutative < 0)
|
||||||
|
commutative = nop;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '&':
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
|
goto op_success;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
case 'g':
|
||||||
|
case 'X':
|
||||||
|
case TARGET_MEM_CONSTRAINT:
|
||||||
|
goto op_success;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '<':
|
||||||
|
if (MEM_P (op)
|
||||||
|
&& (GET_CODE (XEXP (op, 0)) == PRE_DEC
|
||||||
|
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
|
||||||
|
goto op_success;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '>':
|
||||||
|
if (MEM_P (op)
|
||||||
|
&& (GET_CODE (XEXP (op, 0)) == PRE_INC
|
||||||
|
|| GET_CODE (XEXP (op, 0)) == POST_INC))
|
||||||
|
goto op_success;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'E':
|
||||||
|
case 'F':
|
||||||
|
if (CONST_DOUBLE_AS_FLOAT_P (op)
|
||||||
|
|| (GET_CODE (op) == CONST_VECTOR
|
||||||
|
&& GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
|
||||||
|
goto op_success;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'G':
|
||||||
|
case 'H':
|
||||||
|
if (CONST_DOUBLE_AS_FLOAT_P (op)
|
||||||
|
&& CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
|
||||||
|
goto op_success;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
if (CONST_SCALAR_INT_P (op))
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
if (CONSTANT_P (op))
|
||||||
|
goto op_success;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
if (CONST_SCALAR_INT_P (op))
|
||||||
|
goto op_success;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
case 'J':
|
||||||
|
case 'K':
|
||||||
|
case 'L':
|
||||||
|
case 'M':
|
||||||
|
case 'N':
|
||||||
|
case 'O':
|
||||||
|
case 'P':
|
||||||
|
if (CONST_INT_P (op)
|
||||||
|
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
|
||||||
|
goto op_success;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'V':
|
||||||
|
if (MEM_P (op) && ! offsettable_memref_p (op))
|
||||||
|
goto op_success;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'o':
|
||||||
|
goto op_success;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
enum reg_class cl;
|
||||||
|
|
||||||
|
cl = (c == 'r' ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p));
|
||||||
|
if (cl != NO_REGS)
|
||||||
|
goto op_success;
|
||||||
|
#ifdef EXTRA_CONSTRAINT_STR
|
||||||
|
else if (EXTRA_CONSTRAINT_STR (op, c, p))
|
||||||
|
goto op_success;
|
||||||
|
else if (EXTRA_MEMORY_CONSTRAINT (c, p))
|
||||||
|
goto op_success;
|
||||||
|
else if (EXTRA_ADDRESS_CONSTRAINT (c, p))
|
||||||
|
goto op_success;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (p += len, c);
|
||||||
|
break;
|
||||||
|
op_success:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
if (nop >= recog_data.n_operands)
|
||||||
|
SET_HARD_REG_BIT (alts, nalt);
|
||||||
|
}
|
||||||
|
if (commutative < 0)
|
||||||
|
break;
|
||||||
|
if (curr_swapped)
|
||||||
|
break;
|
||||||
|
op = recog_data.operand[commutative];
|
||||||
|
recog_data.operand[commutative] = recog_data.operand[commutative + 1];
|
||||||
|
recog_data.operand[commutative + 1] = op;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the number of the output non-early clobber operand which
|
||||||
|
should be the same in any case as operand with number OP_NUM (or
|
||||||
|
negative value if there is no such operand). The function takes
|
||||||
|
only really possible alternatives into consideration. */
|
||||||
|
int
|
||||||
|
ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
|
||||||
|
{
|
||||||
|
int curr_alt, c, original, dup;
|
||||||
|
bool ignore_p, use_commut_op_p;
|
||||||
|
const char *str;
|
||||||
|
#ifdef EXTRA_CONSTRAINT_STR
|
||||||
|
rtx op;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (op_num < 0 || recog_data.n_alternatives == 0)
|
||||||
|
return -1;
|
||||||
|
use_commut_op_p = false;
|
||||||
|
str = recog_data.constraints[op_num];
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
#ifdef EXTRA_CONSTRAINT_STR
|
||||||
|
op = recog_data.operand[op_num];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (ignore_p = false, original = -1, curr_alt = 0;;)
|
||||||
|
{
|
||||||
|
c = *str;
|
||||||
|
if (c == '\0')
|
||||||
|
break;
|
||||||
|
if (c == '#' || !TEST_HARD_REG_BIT (alts, curr_alt))
|
||||||
|
ignore_p = true;
|
||||||
|
else if (c == ',')
|
||||||
|
{
|
||||||
|
curr_alt++;
|
||||||
|
ignore_p = false;
|
||||||
|
}
|
||||||
|
else if (! ignore_p)
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
/* We should find duplications only for input operands. */
|
||||||
|
case '=':
|
||||||
|
case '+':
|
||||||
|
goto fail;
|
||||||
|
case 'X':
|
||||||
|
case 'p':
|
||||||
|
case 'g':
|
||||||
|
goto fail;
|
||||||
|
case 'r':
|
||||||
|
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
||||||
|
case 'h': case 'j': case 'k': case 'l':
|
||||||
|
case 'q': case 't': case 'u':
|
||||||
|
case 'v': case 'w': case 'x': case 'y': case 'z':
|
||||||
|
case 'A': case 'B': case 'C': case 'D':
|
||||||
|
case 'Q': case 'R': case 'S': case 'T': case 'U':
|
||||||
|
case 'W': case 'Y': case 'Z':
|
||||||
|
{
|
||||||
|
enum reg_class cl;
|
||||||
|
|
||||||
|
cl = (c == 'r'
|
||||||
|
? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, str));
|
||||||
|
if (cl != NO_REGS)
|
||||||
|
{
|
||||||
|
if (! targetm.class_likely_spilled_p (cl))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#ifdef EXTRA_CONSTRAINT_STR
|
||||||
|
else if (EXTRA_CONSTRAINT_STR (op, c, str))
|
||||||
|
goto fail;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
|
if (original != -1 && original != c)
|
||||||
|
goto fail;
|
||||||
|
original = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
str += CONSTRAINT_LEN (c, str);
|
||||||
|
}
|
||||||
|
if (original == -1)
|
||||||
|
goto fail;
|
||||||
|
dup = -1;
|
||||||
|
for (ignore_p = false, str = recog_data.constraints[original - '0'];
|
||||||
|
*str != 0;
|
||||||
|
str++)
|
||||||
|
if (ignore_p)
|
||||||
|
{
|
||||||
|
if (*str == ',')
|
||||||
|
ignore_p = false;
|
||||||
|
}
|
||||||
|
else if (*str == '#')
|
||||||
|
ignore_p = true;
|
||||||
|
else if (! ignore_p)
|
||||||
|
{
|
||||||
|
if (*str == '=')
|
||||||
|
dup = original - '0';
|
||||||
|
/* It is better ignore an alternative with early clobber. */
|
||||||
|
else if (*str == '&')
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (dup >= 0)
|
||||||
|
return dup;
|
||||||
|
fail:
|
||||||
|
if (use_commut_op_p)
|
||||||
|
break;
|
||||||
|
use_commut_op_p = true;
|
||||||
|
if (commutative_constraint_p (recog_data.constraints[op_num]))
|
||||||
|
str = recog_data.constraints[op_num + 1];
|
||||||
|
else if (op_num > 0 && commutative_constraint_p (recog_data.constraints
|
||||||
|
[op_num - 1]))
|
||||||
|
str = recog_data.constraints[op_num - 1];
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Search forward to see if the source register of a copy insn dies
|
||||||
|
before either it or the destination register is modified, but don't
|
||||||
|
scan past the end of the basic block. If so, we can replace the
|
||||||
|
source with the destination and let the source die in the copy
|
||||||
|
insn.
|
||||||
|
|
||||||
|
This will reduce the number of registers live in that range and may
|
||||||
|
enable the destination and the source coalescing, thus often saving
|
||||||
|
one register in addition to a register-register copy. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
decrease_live_ranges_number (void)
|
||||||
|
{
|
||||||
|
basic_block bb;
|
||||||
|
rtx insn, set, src, dest, dest_death, p, q, note;
|
||||||
|
int sregno, dregno;
|
||||||
|
|
||||||
|
if (! flag_expensive_optimizations)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ira_dump_file)
|
||||||
|
fprintf (ira_dump_file, "Starting decreasing number of live ranges...\n");
|
||||||
|
|
||||||
|
FOR_EACH_BB (bb)
|
||||||
|
FOR_BB_INSNS (bb, insn)
|
||||||
|
{
|
||||||
|
set = single_set (insn);
|
||||||
|
if (! set)
|
||||||
|
continue;
|
||||||
|
src = SET_SRC (set);
|
||||||
|
dest = SET_DEST (set);
|
||||||
|
if (! REG_P (src) || ! REG_P (dest)
|
||||||
|
|| find_reg_note (insn, REG_DEAD, src))
|
||||||
|
continue;
|
||||||
|
sregno = REGNO (src);
|
||||||
|
dregno = REGNO (dest);
|
||||||
|
|
||||||
|
/* We don't want to mess with hard regs if register classes
|
||||||
|
are small. */
|
||||||
|
if (sregno == dregno
|
||||||
|
|| (targetm.small_register_classes_for_mode_p (GET_MODE (src))
|
||||||
|
&& (sregno < FIRST_PSEUDO_REGISTER
|
||||||
|
|| dregno < FIRST_PSEUDO_REGISTER))
|
||||||
|
/* We don't see all updates to SP if they are in an
|
||||||
|
auto-inc memory reference, so we must disallow this
|
||||||
|
optimization on them. */
|
||||||
|
|| sregno == STACK_POINTER_REGNUM
|
||||||
|
|| dregno == STACK_POINTER_REGNUM)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dest_death = NULL_RTX;
|
||||||
|
|
||||||
|
for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
|
||||||
|
{
|
||||||
|
if (! INSN_P (p))
|
||||||
|
continue;
|
||||||
|
if (BLOCK_FOR_INSN (p) != bb)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (reg_set_p (src, p) || reg_set_p (dest, p)
|
||||||
|
/* If SRC is an asm-declared register, it must not be
|
||||||
|
replaced in any asm. Unfortunately, the REG_EXPR
|
||||||
|
tree for the asm variable may be absent in the SRC
|
||||||
|
rtx, so we can't check the actual register
|
||||||
|
declaration easily (the asm operand will have it,
|
||||||
|
though). To avoid complicating the test for a rare
|
||||||
|
case, we just don't perform register replacement
|
||||||
|
for a hard reg mentioned in an asm. */
|
||||||
|
|| (sregno < FIRST_PSEUDO_REGISTER
|
||||||
|
&& asm_noperands (PATTERN (p)) >= 0
|
||||||
|
&& reg_overlap_mentioned_p (src, PATTERN (p)))
|
||||||
|
/* Don't change hard registers used by a call. */
|
||||||
|
|| (CALL_P (p) && sregno < FIRST_PSEUDO_REGISTER
|
||||||
|
&& find_reg_fusage (p, USE, src))
|
||||||
|
/* Don't change a USE of a register. */
|
||||||
|
|| (GET_CODE (PATTERN (p)) == USE
|
||||||
|
&& reg_overlap_mentioned_p (src, XEXP (PATTERN (p), 0))))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* See if all of SRC dies in P. This test is slightly
|
||||||
|
more conservative than it needs to be. */
|
||||||
|
if ((note = find_regno_note (p, REG_DEAD, sregno))
|
||||||
|
&& GET_MODE (XEXP (note, 0)) == GET_MODE (src))
|
||||||
|
{
|
||||||
|
int failed = 0;
|
||||||
|
|
||||||
|
/* We can do the optimization. Scan forward from INSN
|
||||||
|
again, replacing regs as we go. Set FAILED if a
|
||||||
|
replacement can't be done. In that case, we can't
|
||||||
|
move the death note for SRC. This should be
|
||||||
|
rare. */
|
||||||
|
|
||||||
|
/* Set to stop at next insn. */
|
||||||
|
for (q = next_real_insn (insn);
|
||||||
|
q != next_real_insn (p);
|
||||||
|
q = next_real_insn (q))
|
||||||
|
{
|
||||||
|
if (reg_overlap_mentioned_p (src, PATTERN (q)))
|
||||||
|
{
|
||||||
|
/* If SRC is a hard register, we might miss
|
||||||
|
some overlapping registers with
|
||||||
|
validate_replace_rtx, so we would have to
|
||||||
|
undo it. We can't if DEST is present in
|
||||||
|
the insn, so fail in that combination of
|
||||||
|
cases. */
|
||||||
|
if (sregno < FIRST_PSEUDO_REGISTER
|
||||||
|
&& reg_mentioned_p (dest, PATTERN (q)))
|
||||||
|
failed = 1;
|
||||||
|
|
||||||
|
/* Attempt to replace all uses. */
|
||||||
|
else if (!validate_replace_rtx (src, dest, q))
|
||||||
|
failed = 1;
|
||||||
|
|
||||||
|
/* If this succeeded, but some part of the
|
||||||
|
register is still present, undo the
|
||||||
|
replacement. */
|
||||||
|
else if (sregno < FIRST_PSEUDO_REGISTER
|
||||||
|
&& reg_overlap_mentioned_p (src, PATTERN (q)))
|
||||||
|
{
|
||||||
|
validate_replace_rtx (dest, src, q);
|
||||||
|
failed = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If DEST dies here, remove the death note and
|
||||||
|
save it for later. Make sure ALL of DEST dies
|
||||||
|
here; again, this is overly conservative. */
|
||||||
|
if (! dest_death
|
||||||
|
&& (dest_death = find_regno_note (q, REG_DEAD, dregno)))
|
||||||
|
{
|
||||||
|
if (GET_MODE (XEXP (dest_death, 0)) == GET_MODE (dest))
|
||||||
|
remove_note (q, dest_death);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
failed = 1;
|
||||||
|
dest_death = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! failed)
|
||||||
|
{
|
||||||
|
/* Move death note of SRC from P to INSN. */
|
||||||
|
remove_note (p, note);
|
||||||
|
XEXP (note, 1) = REG_NOTES (insn);
|
||||||
|
REG_NOTES (insn) = note;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DEST is also dead if INSN has a REG_UNUSED note for
|
||||||
|
DEST. */
|
||||||
|
if (! dest_death
|
||||||
|
&& (dest_death
|
||||||
|
= find_regno_note (insn, REG_UNUSED, dregno)))
|
||||||
|
{
|
||||||
|
PUT_REG_NOTE_KIND (dest_death, REG_DEAD);
|
||||||
|
remove_note (insn, dest_death);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put death note of DEST on P if we saw it die. */
|
||||||
|
if (dest_death)
|
||||||
|
{
|
||||||
|
XEXP (dest_death, 1) = REG_NOTES (p);
|
||||||
|
REG_NOTES (p) = dest_death;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If SRC is a hard register which is set or killed in
|
||||||
|
some other way, we can't do this optimization. */
|
||||||
|
else if (sregno < FIRST_PSEUDO_REGISTER && dead_or_set_p (p, src))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Return nonzero if REGNO is a particularly bad choice for reloading X. */
|
/* Return nonzero if REGNO is a particularly bad choice for reloading X. */
|
||||||
static bool
|
static bool
|
||||||
ira_bad_reload_regno_1 (int regno, rtx x)
|
ira_bad_reload_regno_1 (int regno, rtx x)
|
||||||
|
|
@ -4655,7 +5176,7 @@ ira (FILE *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_prohibited_mode_move_regs ();
|
setup_prohibited_mode_move_regs ();
|
||||||
|
decrease_live_ranges_number ();
|
||||||
df_note_add_problem ();
|
df_note_add_problem ();
|
||||||
|
|
||||||
/* DF_LIVE can't be used in the register allocator, too many other
|
/* DF_LIVE can't be used in the register allocator, too many other
|
||||||
|
|
@ -4671,6 +5192,7 @@ ira (FILE *f)
|
||||||
df->changeable_flags |= DF_VERIFY_SCHEDULED;
|
df->changeable_flags |= DF_VERIFY_SCHEDULED;
|
||||||
#endif
|
#endif
|
||||||
df_analyze ();
|
df_analyze ();
|
||||||
|
|
||||||
df_clear_flags (DF_NO_INSN_RESCAN);
|
df_clear_flags (DF_NO_INSN_RESCAN);
|
||||||
regstat_init_n_sets_and_refs ();
|
regstat_init_n_sets_and_refs ();
|
||||||
regstat_compute_ri ();
|
regstat_compute_ri ();
|
||||||
|
|
|
||||||
|
|
@ -473,7 +473,6 @@ static const struct default_options default_options_table[] =
|
||||||
{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_fschedule_insns, NULL, 1 },
|
{ OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_fschedule_insns, NULL, 1 },
|
||||||
{ OPT_LEVELS_2_PLUS, OPT_fschedule_insns2, NULL, 1 },
|
{ OPT_LEVELS_2_PLUS, OPT_fschedule_insns2, NULL, 1 },
|
||||||
#endif
|
#endif
|
||||||
{ OPT_LEVELS_2_PLUS, OPT_fregmove, NULL, 1 },
|
|
||||||
{ OPT_LEVELS_2_PLUS, OPT_fstrict_aliasing, NULL, 1 },
|
{ OPT_LEVELS_2_PLUS, OPT_fstrict_aliasing, NULL, 1 },
|
||||||
{ OPT_LEVELS_2_PLUS, OPT_fstrict_overflow, NULL, 1 },
|
{ OPT_LEVELS_2_PLUS, OPT_fstrict_overflow, NULL, 1 },
|
||||||
{ OPT_LEVELS_2_PLUS, OPT_freorder_blocks, NULL, 1 },
|
{ OPT_LEVELS_2_PLUS, OPT_freorder_blocks, NULL, 1 },
|
||||||
|
|
|
||||||
|
|
@ -350,7 +350,6 @@ along with GCC; see the file COPYING3. If not see
|
||||||
NEXT_PASS (pass_combine);
|
NEXT_PASS (pass_combine);
|
||||||
NEXT_PASS (pass_if_after_combine);
|
NEXT_PASS (pass_if_after_combine);
|
||||||
NEXT_PASS (pass_partition_blocks);
|
NEXT_PASS (pass_partition_blocks);
|
||||||
NEXT_PASS (pass_regmove);
|
|
||||||
NEXT_PASS (pass_outof_cfg_layout_mode);
|
NEXT_PASS (pass_outof_cfg_layout_mode);
|
||||||
NEXT_PASS (pass_split_all_insns);
|
NEXT_PASS (pass_split_all_insns);
|
||||||
NEXT_PASS (pass_lower_subreg2);
|
NEXT_PASS (pass_lower_subreg2);
|
||||||
|
|
|
||||||
1401
gcc/regmove.c
1401
gcc/regmove.c
File diff suppressed because it is too large
Load Diff
|
|
@ -1,3 +1,23 @@
|
||||||
|
2013-10-30 Vladimir Makarov <vmakarov@redhat.com>
|
||||||
|
|
||||||
|
* gcc.target/i386/fma_double_3.c: Use pattern for
|
||||||
|
scan-assembler-times instead of just one insn name.
|
||||||
|
* gcc.target/i386/fma_double_5.c: Ditto.
|
||||||
|
* gcc.target/i386/fma_float_3.c: Ditto.
|
||||||
|
* gcc.target/i386/fma_float_5.c: Ditto.
|
||||||
|
* gcc.target/i386/l_fma_double_1.c: Ditto.
|
||||||
|
* gcc.target/i386/l_fma_double_2.c: Ditto.
|
||||||
|
* gcc.target/i386/l_fma_double_3.c: Ditto.
|
||||||
|
* gcc.target/i386/l_fma_double_4.c: Ditto.
|
||||||
|
* gcc.target/i386/l_fma_double_5.c: Ditto.
|
||||||
|
* gcc.target/i386/l_fma_double_6.c: Ditto.
|
||||||
|
* gcc.target/i386/l_fma_float_1.c: Ditto.
|
||||||
|
* gcc.target/i386/l_fma_float_2.c: Ditto.
|
||||||
|
* gcc.target/i386/l_fma_float_3.c: Ditto.
|
||||||
|
* gcc.target/i386/l_fma_float_4.c: Ditto.
|
||||||
|
* gcc.target/i386/l_fma_float_5.c: Ditto.
|
||||||
|
* gcc.target/i386/l_fma_float_6.c: Ditto.
|
||||||
|
|
||||||
2013-10-30 Christian Bruel <christian.bruel@st.com>
|
2013-10-30 Christian Bruel <christian.bruel@st.com>
|
||||||
|
|
||||||
* gcc.c-torture/execute/builtins/strncmp-2.c: Enable for SH.
|
* gcc.c-torture/execute/builtins/strncmp-2.c: Enable for SH.
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,7 @@
|
||||||
|
|
||||||
#include "fma_3.h"
|
#include "fma_3.h"
|
||||||
|
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 4 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd231sd" 4 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[132\]+sd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[132\]+sd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub231sd" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[132\]+sd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132sd" 4 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd231sd" 4 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132sd" 4 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub231sd" 4 } } */
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#include "fma_5.h"
|
#include "fma_5.h"
|
||||||
|
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[132\]+sd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[132\]+sd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132sd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[132\]+sd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132sd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[132\]+sd" 8 } } */
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,7 @@
|
||||||
|
|
||||||
#include "fma_3.h"
|
#include "fma_3.h"
|
||||||
|
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 4 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[132\]+ss" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd231ss" 4 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[132\]+ss" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[132\]+ss" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub231ss" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[132\]+ss" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132ss" 4 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd231ss" 4 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ss" 4 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub231ss" 4 } } */
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#include "fma_5.h"
|
#include "fma_5.h"
|
||||||
|
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 8 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[132\]+ss" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 8 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[132\]+ss" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132ss" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[132\]+ss" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ss" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[132\]+ss" 8 } } */
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,7 @@ typedef double adouble __attribute__((aligned(sizeof (double))));
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd231pd" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd231pd" 4 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132pd" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub132pd" 4 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub231pd" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub231pd" 4 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 28 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd213sd" 28 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 28 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub213sd" 28 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132sd" 28 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd213sd" 28 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132sd" 28 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub213sd" 28 } } */
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ typedef double adouble __attribute__((aligned(sizeof (double))));
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,7 @@ typedef double adouble __attribute__((aligned(sizeof (double))));
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd231pd" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd231pd" 4 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132pd" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub132pd" 4 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub231pd" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub231pd" 4 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 28 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd213sd" 28 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 28 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub213sd" 28 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132sd" 28 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd213sd" 28 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132sd" 28 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub213sd" 28 } } */
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ typedef double adouble __attribute__((aligned(sizeof (double))));
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ typedef double adouble __attribute__((aligned(sizeof (double))));
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ typedef double adouble __attribute__((aligned(sizeof (double))));
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,7 @@
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd231ps" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd231ps" 4 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ps" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub132ps" 4 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub231ps" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub231ps" 4 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 60 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd213ss" 60 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 60 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub213ss" 60 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132ss" 60 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd213ss" 60 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ss" 60 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub213ss" 60 } } */
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
|
/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,7 @@
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd231ps" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd231ps" 4 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ps" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub132ps" 4 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub231ps" 4 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub231ps" 4 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 60 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd213ss" 60 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 60 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub213ss" 60 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132ss" 60 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd213ss" 60 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ss" 60 } } */
|
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub213ss" 60 } } */
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
|
/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
|
/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
|
/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */
|
||||||
/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */
|
/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,6 @@ DEFTIMEVAR (TV_CSE2 , "CSE 2")
|
||||||
DEFTIMEVAR (TV_BRANCH_PROB , "branch prediction")
|
DEFTIMEVAR (TV_BRANCH_PROB , "branch prediction")
|
||||||
DEFTIMEVAR (TV_COMBINE , "combiner")
|
DEFTIMEVAR (TV_COMBINE , "combiner")
|
||||||
DEFTIMEVAR (TV_IFCVT , "if-conversion")
|
DEFTIMEVAR (TV_IFCVT , "if-conversion")
|
||||||
DEFTIMEVAR (TV_REGMOVE , "regmove")
|
|
||||||
DEFTIMEVAR (TV_MODE_SWITCH , "mode switching")
|
DEFTIMEVAR (TV_MODE_SWITCH , "mode switching")
|
||||||
DEFTIMEVAR (TV_SMS , "sms modulo scheduling")
|
DEFTIMEVAR (TV_SMS , "sms modulo scheduling")
|
||||||
DEFTIMEVAR (TV_SCHED , "scheduling")
|
DEFTIMEVAR (TV_SCHED , "scheduling")
|
||||||
|
|
|
||||||
|
|
@ -524,7 +524,6 @@ extern rtl_opt_pass *make_pass_if_after_combine (gcc::context *ctxt);
|
||||||
extern rtl_opt_pass *make_pass_ree (gcc::context *ctxt);
|
extern rtl_opt_pass *make_pass_ree (gcc::context *ctxt);
|
||||||
extern rtl_opt_pass *make_pass_partition_blocks (gcc::context *ctxt);
|
extern rtl_opt_pass *make_pass_partition_blocks (gcc::context *ctxt);
|
||||||
extern rtl_opt_pass *make_pass_match_asm_constraints (gcc::context *ctxt);
|
extern rtl_opt_pass *make_pass_match_asm_constraints (gcc::context *ctxt);
|
||||||
extern rtl_opt_pass *make_pass_regmove (gcc::context *ctxt);
|
|
||||||
extern rtl_opt_pass *make_pass_split_all_insns (gcc::context *ctxt);
|
extern rtl_opt_pass *make_pass_split_all_insns (gcc::context *ctxt);
|
||||||
extern rtl_opt_pass *make_pass_fast_rtl_byte_dce (gcc::context *ctxt);
|
extern rtl_opt_pass *make_pass_fast_rtl_byte_dce (gcc::context *ctxt);
|
||||||
extern rtl_opt_pass *make_pass_lower_subreg2 (gcc::context *ctxt);
|
extern rtl_opt_pass *make_pass_lower_subreg2 (gcc::context *ctxt);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue