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:
Vladimir Makarov 2013-10-30 14:27:25 +00:00 committed by Vladimir Makarov
parent 1bef9b2340
commit 3b6d16993b
33 changed files with 1362 additions and 1843 deletions

View File

@ -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

View File

@ -1328,7 +1328,6 @@ OBJS = \
reg-stack.o \
regcprop.o \
reginfo.o \
regmove.o \
regrename.o \
regstat.o \
reload.o \

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 ();

View File

@ -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. */

View File

@ -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++)
{

View File

@ -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]);
}
}
}

View File

@ -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
View File

@ -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 ();

View File

@ -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 },

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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.

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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")

View File

@ -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);