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
33 changed files with 1362 additions and 1843 deletions
|
@ -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>
|
||||
|
||||
PR middle-end/57100
|
||||
|
|
|
@ -1328,7 +1328,6 @@ OBJS = \
|
|||
reg-stack.o \
|
||||
regcprop.o \
|
||||
reginfo.o \
|
||||
regmove.o \
|
||||
regrename.o \
|
||||
regstat.o \
|
||||
reload.o \
|
||||
|
|
|
@ -1597,8 +1597,8 @@ Common Joined RejectNegative Var(common_deferred_options) Defer
|
|||
-fopt-info[-<type>=filename] Dump compiler optimization details
|
||||
|
||||
foptimize-register-move
|
||||
Common Report Var(flag_regmove) Optimization
|
||||
Do the full register move optimization pass
|
||||
Common Ignore
|
||||
Does nothing. Preserved for backward compatibility.
|
||||
|
||||
foptimize-sibling-calls
|
||||
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
|
||||
|
||||
fregmove
|
||||
Common Report Var(flag_regmove) Optimization
|
||||
Enables a register move optimization
|
||||
Common Ignore
|
||||
Does nothing. Preserved for backward compatibility.
|
||||
|
||||
frename-registers
|
||||
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-sched-interblock -fno-sched-spec -fno-signed-zeros @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
|
||||
-fprefetch-loop-arrays -fprofile-report @gol
|
||||
-fprofile-correction -fprofile-dir=@var{path} -fprofile-generate @gol
|
||||
-fprofile-generate=@var{path} @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
|
||||
-frerun-cse-after-loop -freschedule-modulo-scheduled-loops @gol
|
||||
-frounding-math -fsched2-use-superblocks -fsched-pressure @gol
|
||||
|
@ -5822,10 +5822,6 @@ Dump after post-reload optimizations.
|
|||
@opindex fdump-rtl-pro_and_epilogue
|
||||
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
|
||||
@itemx -fdump-rtl-sched2
|
||||
@opindex fdump-rtl-sched1
|
||||
|
@ -6738,7 +6734,6 @@ also turns on the following optimization flags:
|
|||
-foptimize-sibling-calls @gol
|
||||
-fpartial-inlining @gol
|
||||
-fpeephole2 @gol
|
||||
-fregmove @gol
|
||||
-freorder-blocks -freorder-functions @gol
|
||||
-frerun-cse-after-loop @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}.
|
||||
|
||||
@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}
|
||||
Use the specified coloring algorithm for the integrated register
|
||||
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
|
||||
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
|
||||
|
||||
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:
|
||||
|
||||
@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
|
||||
The integrated register allocator (@acronym{IRA}). It is called
|
||||
integrated because coalescing, register live range splitting, and hard
|
||||
|
|
224
gcc/ira-build.c
224
gcc/ira-build.c
|
@ -79,6 +79,13 @@ int ira_objects_num;
|
|||
/* Map a conflict id to its conflict record. */
|
||||
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
|
||||
corresponds to the index in the array. Removed copies have NULL
|
||||
element value. */
|
||||
|
@ -515,6 +522,7 @@ ira_create_allocno (int regno, bool cap_p,
|
|||
ALLOCNO_BAD_SPILL_P (a) = false;
|
||||
ALLOCNO_ASSIGNED_P (a) = false;
|
||||
ALLOCNO_MODE (a) = (regno < 0 ? VOIDmode : PSEUDO_REGNO_MODE (regno));
|
||||
ALLOCNO_PREFS (a) = NULL;
|
||||
ALLOCNO_COPIES (a) = NULL;
|
||||
ALLOCNO_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. */
|
||||
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. */
|
||||
void
|
||||
ira_add_allocno_copy_to_list (ira_copy_t cp)
|
||||
static void
|
||||
add_allocno_copy_to_list (ira_copy_t cp)
|
||||
{
|
||||
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
|
||||
first allocno is less than the second one. */
|
||||
void
|
||||
ira_swap_allocno_copy_ends_if_necessary (ira_copy_t cp)
|
||||
static void
|
||||
swap_allocno_copy_ends_if_necessary (ira_copy_t cp)
|
||||
{
|
||||
ira_allocno_t temp;
|
||||
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,
|
||||
loop_tree_node);
|
||||
ira_assert (first != NULL && second != NULL);
|
||||
ira_add_allocno_copy_to_list (cp);
|
||||
ira_swap_allocno_copy_ends_if_necessary (cp);
|
||||
add_allocno_copy_to_list (cp);
|
||||
swap_allocno_copy_ends_if_necessary (cp);
|
||||
return cp;
|
||||
}
|
||||
|
||||
|
@ -2305,6 +2502,7 @@ remove_unnecessary_allocnos (void)
|
|||
map to avoid info propagation of subsequent
|
||||
allocno into this already removed allocno. */
|
||||
a_node->regno_allocno_map[regno] = NULL;
|
||||
ira_remove_allocno_prefs (a);
|
||||
finish_allocno (a);
|
||||
}
|
||||
}
|
||||
|
@ -2388,7 +2586,10 @@ remove_low_level_allocnos (void)
|
|||
#endif
|
||||
}
|
||||
else
|
||||
finish_allocno (a);
|
||||
{
|
||||
ira_remove_allocno_prefs (a);
|
||||
finish_allocno (a);
|
||||
}
|
||||
}
|
||||
if (merged_p)
|
||||
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)
|
||||
fprintf (ira_dump_file, " Remove a%dr%d\n",
|
||||
ALLOCNO_NUM (a), REGNO (allocno_emit_reg (a)));
|
||||
ira_remove_allocno_prefs (a);
|
||||
finish_allocno (a);
|
||||
continue;
|
||||
}
|
||||
|
@ -3131,8 +3333,8 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
|
|||
ira_assert
|
||||
(ALLOCNO_LOOP_TREE_NODE (cp->first) == ira_loop_tree_root
|
||||
&& ALLOCNO_LOOP_TREE_NODE (cp->second) == ira_loop_tree_root);
|
||||
ira_add_allocno_copy_to_list (cp);
|
||||
ira_swap_allocno_copy_ends_if_necessary (cp);
|
||||
add_allocno_copy_to_list (cp);
|
||||
swap_allocno_copy_ends_if_necessary (cp);
|
||||
}
|
||||
rebuild_regno_allocno_maps ();
|
||||
if (ira_max_point != ira_max_point_before_emit)
|
||||
|
@ -3220,6 +3422,7 @@ ira_build (void)
|
|||
df_analyze ();
|
||||
initiate_cost_vectors ();
|
||||
initiate_allocnos ();
|
||||
initiate_prefs ();
|
||||
initiate_copies ();
|
||||
create_loop_tree_nodes ();
|
||||
form_loop_tree ();
|
||||
|
@ -3265,6 +3468,8 @@ ira_build (void)
|
|||
}
|
||||
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
|
||||
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)
|
||||
{
|
||||
int n, nr, nr_big;
|
||||
|
@ -3304,6 +3509,7 @@ void
|
|||
ira_destroy (void)
|
||||
{
|
||||
finish_loop_tree_nodes ();
|
||||
finish_prefs ();
|
||||
finish_copies ();
|
||||
finish_allocnos ();
|
||||
finish_cost_vectors ();
|
||||
|
|
278
gcc/ira-color.c
278
gcc/ira-color.c
|
@ -88,6 +88,17 @@ struct allocno_hard_regs_node
|
|||
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
|
||||
needed only for coloring in the following structure. */
|
||||
struct allocno_color_data
|
||||
|
@ -126,6 +137,11 @@ struct allocno_color_data
|
|||
int hard_regs_subnodes_start;
|
||||
/* The length of the previous array. */
|
||||
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. */
|
||||
|
@ -1113,6 +1129,53 @@ setup_profitable_hard_regs (void)
|
|||
/* This page contains functions used to choose hard registers for
|
||||
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
|
||||
register was already allocated for an allocno. */
|
||||
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. */
|
||||
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. */
|
||||
ira_allocno_t next;
|
||||
};
|
||||
|
@ -1145,11 +1213,11 @@ static struct update_cost_queue_elem *update_cost_queue_tail;
|
|||
Elements are indexed by ALLOCNO_NUM. */
|
||||
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;
|
||||
|
||||
/* Allocate and initialize data necessary for function
|
||||
update_copy_costs. */
|
||||
update_costs_from_copiess. */
|
||||
static void
|
||||
initiate_cost_update (void)
|
||||
{
|
||||
|
@ -1160,13 +1228,15 @@ initiate_cost_update (void)
|
|||
= (struct update_cost_queue_elem *) ira_allocate (size);
|
||||
memset (update_cost_queue_elems, 0, size);
|
||||
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
|
||||
finish_cost_update (void)
|
||||
{
|
||||
ira_free (update_cost_queue_elems);
|
||||
finish_update_cost_records ();
|
||||
}
|
||||
|
||||
/* When we traverse allocnos to update hard register costs, the cost
|
||||
|
@ -1182,10 +1252,10 @@ start_update_cost (void)
|
|||
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. */
|
||||
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;
|
||||
|
||||
|
@ -1194,6 +1264,7 @@ queue_update_cost (ira_allocno_t allocno, int divisor)
|
|||
&& ALLOCNO_CLASS (allocno) != NO_REGS)
|
||||
{
|
||||
elem->check = update_cost_check;
|
||||
elem->from = from;
|
||||
elem->divisor = divisor;
|
||||
elem->next = 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
|
||||
if the queue was empty, otherwise make (*ALLOCNO, *DIVISOR) describe
|
||||
the removed element. */
|
||||
/* Try to remove the first element from update_cost_queue. Return
|
||||
false if the queue was empty, otherwise make (*ALLOCNO, *FROM,
|
||||
*DIVISOR) describe the removed element. */
|
||||
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;
|
||||
|
||||
|
@ -1217,34 +1288,50 @@ get_next_update_cost (ira_allocno_t *allocno, int *divisor)
|
|||
|
||||
*allocno = update_cost_queue;
|
||||
elem = &update_cost_queue_elems[ALLOCNO_NUM (*allocno)];
|
||||
*from = elem->from;
|
||||
*divisor = elem->divisor;
|
||||
update_cost_queue = elem->next;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Update the cost of allocnos to increase chances to remove some
|
||||
copies as the result of subsequent assignment. */
|
||||
static void
|
||||
update_copy_costs (ira_allocno_t allocno, bool decr_p)
|
||||
/* Increase costs of HARD_REGNO by UPDATE_COST for ALLOCNO. Return
|
||||
true if we really modified the cost. */
|
||||
static bool
|
||||
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 reg_class rclass, aclass;
|
||||
ira_allocno_t another_allocno;
|
||||
ira_allocno_t another_allocno, from = NULL;
|
||||
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);
|
||||
|
||||
start_update_cost ();
|
||||
divisor = 1;
|
||||
do
|
||||
{
|
||||
mode = ALLOCNO_MODE (allocno);
|
||||
|
@ -1264,6 +1351,9 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p)
|
|||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
if (another_allocno == from)
|
||||
continue;
|
||||
|
||||
aclass = ALLOCNO_CLASS (another_allocno);
|
||||
if (! TEST_HARD_REG_BIT (reg_class_contents[aclass],
|
||||
hard_regno)
|
||||
|
@ -1280,24 +1370,67 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p)
|
|||
if (update_cost == 0)
|
||||
continue;
|
||||
|
||||
ira_allocate_and_set_or_copy_costs
|
||||
(&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)
|
||||
if (! update_allocno_cost (another_allocno, hard_regno, update_cost))
|
||||
continue;
|
||||
ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno)[i] += update_cost;
|
||||
ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno)[i]
|
||||
+= update_cost;
|
||||
|
||||
queue_update_cost (another_allocno, divisor * COST_HOP_DIVISOR);
|
||||
queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR);
|
||||
if (record_p && ALLOCNO_COLOR_DATA (another_allocno) != NULL)
|
||||
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, &divisor));
|
||||
while (get_next_update_cost (&allocno, &from, &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);
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
@ -1313,10 +1446,10 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
|
|||
int *conflict_costs;
|
||||
bool cont_p;
|
||||
enum reg_class another_aclass;
|
||||
ira_allocno_t allocno, another_allocno;
|
||||
ira_allocno_t allocno, another_allocno, from;
|
||||
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)
|
||||
{
|
||||
if (cp->first == allocno)
|
||||
|
@ -1331,6 +1464,10 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
|
|||
}
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
if (another_allocno == from)
|
||||
continue;
|
||||
|
||||
another_aclass = ALLOCNO_CLASS (another_allocno);
|
||||
if (! ira_reg_classes_intersect_p[aclass][another_aclass]
|
||||
|| 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))
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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--)
|
||||
allocated_hardreg_p[best_hard_regno + i] = true;
|
||||
}
|
||||
restore_costs_from_copies (a);
|
||||
ALLOCNO_HARD_REGNO (a) = best_hard_regno;
|
||||
ALLOCNO_ASSIGNED_P (a) = true;
|
||||
if (best_hard_regno >= 0)
|
||||
update_copy_costs (a, true);
|
||||
update_costs_from_copies (a, true);
|
||||
ira_assert (ALLOCNO_CLASS (a) == aclass);
|
||||
/* We don't need updated costs anymore: */
|
||||
ira_free_allocno_updated_costs (a);
|
||||
|
@ -2164,7 +2303,9 @@ pop_allocnos_from_stack (void)
|
|||
else if (ALLOCNO_ASSIGNED_P (allocno))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -2546,6 +2687,32 @@ color_allocnos (void)
|
|||
ira_allocno_t a;
|
||||
|
||||
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)
|
||||
{
|
||||
n = 0;
|
||||
|
@ -2605,7 +2772,10 @@ color_allocnos (void)
|
|||
{
|
||||
a = ira_allocnos[i];
|
||||
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
|
||||
{
|
||||
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_ASSIGNED_P (subloop_allocno) = true;
|
||||
if (hard_regno >= 0)
|
||||
update_copy_costs (subloop_allocno, true);
|
||||
update_costs_from_copies (subloop_allocno, true);
|
||||
/* We don't need updated costs anymore: */
|
||||
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_ASSIGNED_P (subloop_allocno) = true;
|
||||
if (hard_regno >= 0)
|
||||
update_copy_costs (subloop_allocno, true);
|
||||
update_costs_from_copies (subloop_allocno, true);
|
||||
/* We don't need updated costs anymore: */
|
||||
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_ASSIGNED_P (subloop_allocno) = true;
|
||||
if (hard_regno >= 0)
|
||||
update_copy_costs (subloop_allocno, true);
|
||||
update_costs_from_copies (subloop_allocno, true);
|
||||
/* We don't need updated costs anymore: */
|
||||
ira_free_allocno_updated_costs (subloop_allocno);
|
||||
}
|
||||
|
@ -3813,7 +3983,7 @@ ira_mark_allocation_change (int regno)
|
|||
? ALLOCNO_CLASS_COST (a)
|
||||
: ALLOCNO_HARD_REG_COSTS (a)
|
||||
[ira_class_hard_reg_index[aclass][old_hard_regno]]);
|
||||
update_copy_costs (a, false);
|
||||
update_costs_from_copies (a, false);
|
||||
}
|
||||
ira_overall_cost -= cost;
|
||||
ALLOCNO_HARD_REGNO (a) = hard_regno;
|
||||
|
@ -3828,7 +3998,7 @@ ira_mark_allocation_change (int regno)
|
|||
? ALLOCNO_CLASS_COST (a)
|
||||
: ALLOCNO_HARD_REG_COSTS (a)
|
||||
[ira_class_hard_reg_index[aclass][hard_regno]]);
|
||||
update_copy_costs (a, true);
|
||||
update_costs_from_copies (a, true);
|
||||
}
|
||||
else
|
||||
/* 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 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. */
|
||||
#define REG_SUBREG_P(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;
|
||||
if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_CLASS_COST (a))
|
||||
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);
|
||||
}
|
||||
while (a != NULL);
|
||||
|
@ -498,9 +356,9 @@ static void
|
|||
add_insn_allocno_copies (rtx insn)
|
||||
{
|
||||
rtx set, operand, dup;
|
||||
const char *str;
|
||||
bool commut_p, bound_p[MAX_RECOG_OPERANDS];
|
||||
int i, j, n, freq;
|
||||
bool bound_p[MAX_RECOG_OPERANDS];
|
||||
int i, n, freq;
|
||||
HARD_REG_SET alts;
|
||||
|
||||
freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn));
|
||||
if (freq == 0)
|
||||
|
@ -513,7 +371,7 @@ add_insn_allocno_copies (rtx insn)
|
|||
? SET_SRC (set)
|
||||
: 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);
|
||||
return;
|
||||
}
|
||||
|
@ -521,7 +379,7 @@ add_insn_allocno_copies (rtx insn)
|
|||
there are no dead registers, there will be no such copies. */
|
||||
if (! find_reg_note (insn, REG_DEAD, NULL_RTX))
|
||||
return;
|
||||
extract_insn (insn);
|
||||
ira_setup_alts (insn, alts);
|
||||
for (i = 0; i < recog_data.n_operands; i++)
|
||||
bound_p[i] = false;
|
||||
for (i = 0; i < recog_data.n_operands; i++)
|
||||
|
@ -529,21 +387,18 @@ add_insn_allocno_copies (rtx insn)
|
|||
operand = recog_data.operand[i];
|
||||
if (! REG_SUBREG_P (operand))
|
||||
continue;
|
||||
str = recog_data.constraints[i];
|
||||
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;
|
||||
dup = recog_data.operand[n];
|
||||
if (REG_SUBREG_P (dup)
|
||||
&& find_reg_note (insn, REG_DEAD,
|
||||
REG_P (operand)
|
||||
? operand
|
||||
: SUBREG_REG (operand)) != NULL_RTX)
|
||||
process_regs_for_copy (operand, dup, true, NULL_RTX, freq);
|
||||
}
|
||||
if ((n = ira_get_dup_out_num (i, alts)) >= 0)
|
||||
{
|
||||
bound_p[n] = true;
|
||||
dup = recog_data.operand[n];
|
||||
if (REG_SUBREG_P (dup)
|
||||
&& find_reg_note (insn, REG_DEAD,
|
||||
REG_P (operand)
|
||||
? operand
|
||||
: SUBREG_REG (operand)) != NULL_RTX)
|
||||
process_regs_for_copy (operand, dup, true, NULL_RTX,
|
||||
freq);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < recog_data.n_operands; i++)
|
||||
{
|
||||
|
|
211
gcc/ira-costs.c
211
gcc/ira-costs.c
|
@ -405,7 +405,6 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
|||
{
|
||||
int alt;
|
||||
int i, j, k;
|
||||
rtx set;
|
||||
int insn_allows_mem[MAX_RECOG_OPERANDS];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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];
|
||||
enum machine_mode modes[MAX_RECOG_OPERANDS];
|
||||
rtx ops[MAX_RECOG_OPERANDS];
|
||||
rtx set;
|
||||
int 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);
|
||||
|
||||
ops[i] = recog_data.operand[i];
|
||||
if (GET_CODE (recog_data.operand[i]) == SUBREG)
|
||||
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,
|
||||
recog_data.operand, modes,
|
||||
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 = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
|
||||
{
|
||||
a_num = ALLOCNO_NUM (a);
|
||||
if (regno_aclass[i] == NO_REGS)
|
||||
enum reg_class aclass = regno_aclass[i];
|
||||
int a_num = ALLOCNO_NUM (a);
|
||||
int *total_a_costs = COSTS (total_allocno_costs, a_num)->cost;
|
||||
int *a_costs = COSTS (costs, a_num)->cost;
|
||||
|
||||
if (aclass == NO_REGS)
|
||||
best = NO_REGS;
|
||||
else
|
||||
{
|
||||
int *total_a_costs = COSTS (total_allocno_costs, a_num)->cost;
|
||||
int *a_costs = COSTS (costs, a_num)->cost;
|
||||
|
||||
/* Finding best class which is subset of the common
|
||||
class. */
|
||||
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++)
|
||||
{
|
||||
rclass = cost_classes[k];
|
||||
if (! ira_class_subset_p[rclass][regno_aclass[i]])
|
||||
if (! ira_class_subset_p[rclass][aclass])
|
||||
continue;
|
||||
/* Ignore classes that are too small or invalid
|
||||
for this operand. */
|
||||
|
@ -1792,9 +1812,25 @@ find_costs_and_classes (FILE *dump_file)
|
|||
ALLOCNO_LOOP_TREE_NODE (a)->loop_num);
|
||||
fprintf (dump_file, ") best %s, allocno %s\n",
|
||||
reg_class_names[best],
|
||||
reg_class_names[regno_aclass[i]]);
|
||||
reg_class_names[aclass]);
|
||||
}
|
||||
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
|
||||
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;
|
||||
ira_allocno_t a;
|
||||
enum reg_class rclass, hard_reg_class;
|
||||
enum machine_mode mode;
|
||||
ira_allocno_t a, curr_a;
|
||||
ira_loop_tree_node_t curr_loop_tree_node;
|
||||
enum reg_class rclass;
|
||||
basic_block bb;
|
||||
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)
|
||||
{
|
||||
hard_regno = src_regno;
|
||||
to_p = true;
|
||||
a = ira_curr_regno_allocno_map[dst_regno];
|
||||
to_p = true;
|
||||
}
|
||||
else if (src_regno >= FIRST_PSEUDO_REGISTER
|
||||
&& dst_regno < FIRST_PSEUDO_REGISTER)
|
||||
{
|
||||
hard_regno = dst_regno;
|
||||
to_p = false;
|
||||
a = ira_curr_regno_allocno_map[src_regno];
|
||||
to_p = false;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
@ -1869,20 +1905,31 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node)
|
|||
i = ira_class_hard_reg_index[rclass][hard_regno];
|
||||
if (i < 0)
|
||||
continue;
|
||||
mode = ALLOCNO_MODE (a);
|
||||
hard_reg_class = REGNO_REG_CLASS (hard_regno);
|
||||
ira_init_register_move_cost_if_necessary (mode);
|
||||
cost
|
||||
= (to_p ? ira_register_move_cost[mode][hard_reg_class][rclass]
|
||||
: ira_register_move_cost[mode][rclass][hard_reg_class]) * freq;
|
||||
ira_allocate_and_set_costs (&ALLOCNO_HARD_REG_COSTS (a), rclass,
|
||||
ALLOCNO_CLASS_COST (a));
|
||||
ira_allocate_and_set_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
|
||||
rclass, 0);
|
||||
ALLOCNO_HARD_REG_COSTS (a)[i] -= cost;
|
||||
ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[i] -= cost;
|
||||
ALLOCNO_CLASS_COST (a) = MIN (ALLOCNO_CLASS_COST (a),
|
||||
ALLOCNO_HARD_REG_COSTS (a)[i]);
|
||||
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);
|
||||
hard_reg_class = REGNO_REG_CLASS (hard_regno);
|
||||
ira_init_register_move_cost_if_necessary (mode);
|
||||
cost = (to_p ? ira_register_move_cost[mode][hard_reg_class][rclass]
|
||||
: ira_register_move_cost[mode][rclass][hard_reg_class]) * freq;
|
||||
ira_allocate_and_set_costs (&ALLOCNO_HARD_REG_COSTS (a), rclass,
|
||||
ALLOCNO_CLASS_COST (a));
|
||||
ira_allocate_and_set_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
|
||||
rclass, 0);
|
||||
ALLOCNO_HARD_REG_COSTS (a)[i] -= cost;
|
||||
ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[i] -= cost;
|
||||
ALLOCNO_CLASS_COST (a) = MIN (ALLOCNO_CLASS_COST (a),
|
||||
ALLOCNO_HARD_REG_COSTS (a)[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ extern FILE *ira_dump_file;
|
|||
allocnos. */
|
||||
typedef struct live_range *live_range_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_object *ira_object_t;
|
||||
|
||||
|
@ -346,6 +347,8 @@ struct ira_allocno
|
|||
register class living at the point than number of hard-registers
|
||||
of the class available for the allocation. */
|
||||
int excess_pressure_points_num;
|
||||
/* Allocno hard reg preferences. */
|
||||
ira_pref_t allocno_prefs;
|
||||
/* Copies to other non-conflicting allocnos. The copies can
|
||||
represent move insn or potential move insn usually because of two
|
||||
operand insn constraints. */
|
||||
|
@ -426,6 +429,7 @@ struct ira_allocno
|
|||
#define ALLOCNO_BAD_SPILL_P(A) ((A)->bad_spill_p)
|
||||
#define ALLOCNO_ASSIGNED_P(A) ((A)->assigned_p)
|
||||
#define ALLOCNO_MODE(A) ((A)->mode)
|
||||
#define ALLOCNO_PREFS(A) ((A)->allocno_prefs)
|
||||
#define ALLOCNO_COPIES(A) ((A)->allocno_copies)
|
||||
#define ALLOCNO_HARD_REG_COSTS(A) ((A)->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. */
|
||||
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
|
||||
copies represent move insns or potential move insns usually because
|
||||
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_allocno_classes (void);
|
||||
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 */
|
||||
|
||||
|
@ -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_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 debug (ira_allocno_copy &ref);
|
||||
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_list (live_range_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,
|
||||
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,
|
||||
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));)
|
||||
|
||||
|
||||
/* 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. */
|
||||
typedef struct {
|
||||
/* 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. */
|
||||
static bool
|
||||
ira_bad_reload_regno_1 (int regno, rtx x)
|
||||
|
@ -4655,7 +5176,7 @@ ira (FILE *f)
|
|||
}
|
||||
|
||||
setup_prohibited_mode_move_regs ();
|
||||
|
||||
decrease_live_ranges_number ();
|
||||
df_note_add_problem ();
|
||||
|
||||
/* 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;
|
||||
#endif
|
||||
df_analyze ();
|
||||
|
||||
df_clear_flags (DF_NO_INSN_RESCAN);
|
||||
regstat_init_n_sets_and_refs ();
|
||||
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, OPT_fschedule_insns2, NULL, 1 },
|
||||
#endif
|
||||
{ OPT_LEVELS_2_PLUS, OPT_fregmove, 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_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_if_after_combine);
|
||||
NEXT_PASS (pass_partition_blocks);
|
||||
NEXT_PASS (pass_regmove);
|
||||
NEXT_PASS (pass_outof_cfg_layout_mode);
|
||||
NEXT_PASS (pass_split_all_insns);
|
||||
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>
|
||||
|
||||
* gcc.c-torture/execute/builtins/strncmp-2.c: Enable for SH.
|
||||
|
|
|
@ -8,11 +8,7 @@
|
|||
|
||||
#include "fma_3.h"
|
||||
|
||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd231sd" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub231sd" 4 } } */
|
||||
/* { 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 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[132\]+sd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[132\]+sd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub\[132\]+sd" 8 } } */
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include "fma_5.h"
|
||||
|
||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd132sd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132sd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[132\]+sd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[132\]+sd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[132\]+sd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub\[132\]+sd" 8 } } */
|
||||
|
|
|
@ -8,11 +8,7 @@
|
|||
|
||||
#include "fma_3.h"
|
||||
|
||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd231ss" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub231ss" 4 } } */
|
||||
/* { 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 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[132\]+ss" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[132\]+ss" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[132\]+ss" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub\[132\]+ss" 8 } } */
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include "fma_5.h"
|
||||
|
||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd132ss" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132ss" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[132\]+ss" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[132\]+ss" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[132\]+ss" 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 "vfnmsub132pd" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub231pd" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 28 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd213sd" 28 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 28 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub213sd" 28 } } */
|
||||
/* { 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 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 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 "vfnmadd132pd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 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 "vfnmsub132pd" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub231pd" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 28 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd213sd" 28 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 28 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub213sd" 28 } } */
|
||||
/* { 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 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 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 "vfnmadd132pd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 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 "vfnmadd132pd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 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 "vfnmadd132pd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 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 "vfnmsub132ps" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub231ps" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 60 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd213ss" 60 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 60 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub213ss" 60 } } */
|
||||
/* { 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 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 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 "vfnmadd132ps" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 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 "vfnmsub132ps" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub231ps" 4 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 60 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd213ss" 60 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 60 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub213ss" 60 } } */
|
||||
/* { 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 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 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 "vfnmadd132ps" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 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 "vfnmadd132ps" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 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 "vfnmadd132ps" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */
|
||||
/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 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_COMBINE , "combiner")
|
||||
DEFTIMEVAR (TV_IFCVT , "if-conversion")
|
||||
DEFTIMEVAR (TV_REGMOVE , "regmove")
|
||||
DEFTIMEVAR (TV_MODE_SWITCH , "mode switching")
|
||||
DEFTIMEVAR (TV_SMS , "sms modulo 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_partition_blocks (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_fast_rtl_byte_dce (gcc::context *ctxt);
|
||||
extern rtl_opt_pass *make_pass_lower_subreg2 (gcc::context *ctxt);
|
||||
|
|
Loading…
Add table
Reference in a new issue