mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			regmove.c: Remove.
2013-10-30 Vladimir Makarov <vmakarov@redhat.com> * regmove.c: Remove. * tree-pass.h (make_pass_regmove): Remove. * timevar.def (TV_REGMOVE): Remove. * passes.def (pass_regmove): Remove. * opts.c (default_options_table): Remove entry for regmove. * doc/passes.texi: Remove regmove pass description. * doc/invoke.texi (-foptimize-register-move, -fregmove): Remove options. (-fdump-rtl-regmove): Ditto. * common.opt (foptimize-register-move, fregmove): Ignore. * Makefile.in (OBJS): Remove regmove.o. * regmove.c: Remove. * ira-int.h (struct ira_allocno_pref, ira_pref_t): New structure and type. (struct ira_allocno) New member allocno_prefs. (ALLOCNO_PREFS): New macro. (ira_prefs, ira_prefs_num): New external vars. (ira_setup_alts, ira_get_dup_out_num, ira_debug_pref): New prototypes. (ira_debug_prefs, ira_debug_allocno_prefs, ira_create_pref): Ditto. (ira_add_allocno_pref, ira_remove_pref, ira_remove_allocno_prefs): Ditto. (ira_add_allocno_copy_to_list): Remove prototype. (ira_swap_allocno_copy_ends_if_necessary): Ditto. (ira_pref_iterator): New type. (ira_pref_iter_init, ira_pref_iter_cond): New functions. (FOR_EACH_PREF): New macro. * ira.c (commutative_constraint_p): Move from ira-conflicts.c. (ira_get_dup_out_num): Ditto. Rename from get_dup_num. Modify the code. (ira_setup_alts): New function. (decrease_live_ranges_number): New function. (ira): Call the above function. * ira-build.c (ira_prefs, ira_prefs_num): New global vars. (ira_create_allocno): Initialize allocno prefs. (pref_pool, pref_vec): New static vars. (initiate_prefs, find_allocno_pref, ira_create_pref): New functions. (add_allocno_pref_to_list, ira_add_allocno_pref, print_pref): Ditto. (ira_debug_pref, print_prefs, ira_debug_prefs): Ditto. (print_allocno_prefs, ira_debug_allocno_prefs, finish_pref): Ditto. (ira_remove_pref, ira_remove_allocno_prefs, finish_prefs): Ditto. (ira_add_allocno_copy_to_list): Make static. Rename to add_allocno_copy_to_list. (ira_swap_allocno_copy_ends_if_necessary): Make static. Rename to swap_allocno_copy_ends_if_necessary. (remove_unnecessary_allocnos, remove_low_level_allocnos): Call ira_remove_allocno_prefs. (ira_flattening): Ditto. (ira_build): Call initiate_prefs, print_prefs. (ira_destroy): Call finish_prefs. * ira-color.c (struct update_cost_record): New. (struct allocno_color_data): Add new member update_cost_records. (update_cost_record_pool): New static var. (init_update_cost_records, get_update_cost_record): New functions. (free_update_cost_record_list, finish_update_cost_records): Ditto. (struct update_cost_queue_elem): Add member from. (initiate_cost_update): Call init_update_cost_records. (finish_cost_update): Call finish_update_cost_records. (queue_update_cost, get_next_update_cost): Add new param from. (Update_allocno_cost, update_costs_from_allocno): New functions. (update_costs_from_prefs): Ditto. (update_copy_costs): Rename to update_costs_from_copies. (restore_costs_from_copies): New function. (update_conflict_hard_regno_costs): Don't go back. (assign_hard_reg): Call restore_costs_from_copies. Add printing more debug info. (pop_allocnos): Add priniting more debug info. (color_allocnos): Remove prefs for conflicting hard regs. Call update_costs_from_prefs. * ira-conflicts.c (commutative_constraint_p): Move to ira.c (get_dup_num): Rename, modify, and move to ira.c (process_regs_for_copy): Add prefs. (add_insn_allocno_copies): Put src as first arg of process_regs_for_copy. Remove dead code. Call ira_setup_alts. * ira-costs.c (record_reg_classes): Modify and move code into record_operands_costs. (find_costs_and_classes): Create prefs for the hard reg of small reg class. (process_bb_node_for_hard_reg_moves): Add prefs. 2013-10-30 Vladimir Makarov <vmakarov@redhat.com> * gcc.target/i386/fma_double_3.c: Use pattern for scan-assembler-times instead of just one insn name. * gcc.target/i386/fma_double_5.c: Ditto. * gcc.target/i386/fma_float_3.c: Ditto. * gcc.target/i386/fma_float_5.c: Ditto. * gcc.target/i386/l_fma_double_1.c: Ditto. * gcc.target/i386/l_fma_double_2.c: Ditto. * gcc.target/i386/l_fma_double_3.c: Ditto. * gcc.target/i386/l_fma_double_4.c: Ditto. * gcc.target/i386/l_fma_double_5.c: Ditto. * gcc.target/i386/l_fma_double_6.c: Ditto. * gcc.target/i386/l_fma_float_1.c: Ditto. * gcc.target/i386/l_fma_float_2.c: Ditto. * gcc.target/i386/l_fma_float_3.c: Ditto. * gcc.target/i386/l_fma_float_4.c: Ditto. * gcc.target/i386/l_fma_float_5.c: Ditto. * gcc.target/i386/l_fma_float_6.c: Ditto. From-SVN: r204212
This commit is contained in:
		
							parent
							
								
									1bef9b2340
								
							
						
					
					
						commit
						3b6d16993b
					
				|  | @ -1,3 +1,87 @@ | |||
| 2013-10-30  Vladimir Makarov  <vmakarov@redhat.com> | ||||
| 
 | ||||
| 	* regmove.c: Remove. | ||||
| 	* tree-pass.h (make_pass_regmove): Remove. | ||||
| 	* timevar.def (TV_REGMOVE): Remove. | ||||
| 	* passes.def (pass_regmove): Remove. | ||||
| 	* opts.c (default_options_table): Remove entry for regmove. | ||||
| 	* doc/passes.texi: Remove regmove pass description. | ||||
| 	* doc/invoke.texi (-foptimize-register-move, -fregmove): Remove | ||||
| 	options. | ||||
| 	(-fdump-rtl-regmove): Ditto. | ||||
| 	* common.opt (foptimize-register-move, fregmove): Ignore. | ||||
| 	* Makefile.in (OBJS): Remove regmove.o. | ||||
| 	* regmove.c: Remove. | ||||
| 	* ira-int.h (struct ira_allocno_pref, ira_pref_t): New structure | ||||
| 	and type. | ||||
| 	(struct ira_allocno) New member allocno_prefs. | ||||
| 	(ALLOCNO_PREFS): New macro. | ||||
| 	(ira_prefs, ira_prefs_num): New external vars. | ||||
| 	(ira_setup_alts, ira_get_dup_out_num, ira_debug_pref): New | ||||
| 	prototypes. | ||||
| 	(ira_debug_prefs, ira_debug_allocno_prefs, ira_create_pref): | ||||
| 	Ditto. | ||||
| 	(ira_add_allocno_pref, ira_remove_pref, ira_remove_allocno_prefs): | ||||
| 	Ditto. | ||||
| 	(ira_add_allocno_copy_to_list): Remove prototype. | ||||
| 	(ira_swap_allocno_copy_ends_if_necessary): Ditto. | ||||
| 	(ira_pref_iterator): New type. | ||||
| 	(ira_pref_iter_init, ira_pref_iter_cond): New functions. | ||||
| 	(FOR_EACH_PREF): New macro. | ||||
| 	* ira.c (commutative_constraint_p): Move from ira-conflicts.c. | ||||
| 	(ira_get_dup_out_num): Ditto. Rename from get_dup_num.  Modify the | ||||
| 	code. | ||||
| 	(ira_setup_alts): New function. | ||||
| 	(decrease_live_ranges_number): New function. | ||||
| 	(ira): Call the above function. | ||||
| 	* ira-build.c (ira_prefs, ira_prefs_num): New global vars. | ||||
| 	(ira_create_allocno): Initialize allocno prefs. | ||||
| 	(pref_pool, pref_vec): New static vars. | ||||
| 	(initiate_prefs, find_allocno_pref, ira_create_pref): New | ||||
| 	functions. | ||||
| 	(add_allocno_pref_to_list, ira_add_allocno_pref, print_pref): Ditto. | ||||
| 	(ira_debug_pref, print_prefs, ira_debug_prefs): Ditto. | ||||
| 	(print_allocno_prefs, ira_debug_allocno_prefs, finish_pref): Ditto. | ||||
| 	(ira_remove_pref, ira_remove_allocno_prefs, finish_prefs): Ditto. | ||||
| 	(ira_add_allocno_copy_to_list): Make static.  Rename to | ||||
| 	add_allocno_copy_to_list. | ||||
| 	(ira_swap_allocno_copy_ends_if_necessary): Make static.  Rename to | ||||
| 	swap_allocno_copy_ends_if_necessary. | ||||
| 	(remove_unnecessary_allocnos, remove_low_level_allocnos): Call | ||||
| 	ira_remove_allocno_prefs. | ||||
| 	(ira_flattening): Ditto. | ||||
| 	(ira_build): Call initiate_prefs, print_prefs. | ||||
| 	(ira_destroy): Call finish_prefs. | ||||
| 	* ira-color.c (struct update_cost_record): New. | ||||
| 	(struct allocno_color_data): Add new member update_cost_records. | ||||
| 	(update_cost_record_pool): New static var. | ||||
| 	(init_update_cost_records, get_update_cost_record): New functions. | ||||
| 	(free_update_cost_record_list, finish_update_cost_records): Ditto. | ||||
| 	(struct update_cost_queue_elem): Add member from. | ||||
| 	(initiate_cost_update): Call init_update_cost_records. | ||||
| 	(finish_cost_update): Call finish_update_cost_records. | ||||
| 	(queue_update_cost, get_next_update_cost): Add new param from. | ||||
| 	(Update_allocno_cost, update_costs_from_allocno): New functions. | ||||
| 	(update_costs_from_prefs): Ditto. | ||||
| 	(update_copy_costs): Rename to update_costs_from_copies. | ||||
| 	(restore_costs_from_copies): New function. | ||||
| 	(update_conflict_hard_regno_costs): Don't go back. | ||||
| 	(assign_hard_reg): Call restore_costs_from_copies.  Add printing | ||||
| 	more debug info. | ||||
| 	(pop_allocnos): Add priniting more debug info. | ||||
| 	(color_allocnos): Remove prefs for conflicting hard regs. | ||||
| 	Call update_costs_from_prefs. | ||||
| 	* ira-conflicts.c (commutative_constraint_p): Move to ira.c | ||||
| 	(get_dup_num): Rename, modify, and move to ira.c | ||||
| 	(process_regs_for_copy): Add prefs. | ||||
| 	(add_insn_allocno_copies): Put src as first arg of | ||||
| 	process_regs_for_copy.  Remove dead code.  Call ira_setup_alts. | ||||
| 	* ira-costs.c (record_reg_classes): Modify and move code into | ||||
| 	record_operands_costs. | ||||
| 	(find_costs_and_classes): Create prefs for the hard reg of small | ||||
| 	reg class. | ||||
| 	(process_bb_node_for_hard_reg_moves): Add prefs. | ||||
| 
 | ||||
| 2013-10-30  Richard Biener  <rguenther@suse.de> | ||||
| 
 | ||||
| 	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…
	
		Reference in New Issue
	
	 Vladimir Makarov
						Vladimir Makarov