diff options
Diffstat (limited to 'toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106869.patch')
-rw-r--r-- | toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106869.patch | 2389 |
1 files changed, 0 insertions, 2389 deletions
diff --git a/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106869.patch b/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106869.patch deleted file mode 100644 index de3d2ff4c..000000000 --- a/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106869.patch +++ /dev/null | |||
@@ -1,2389 +0,0 @@ | |||
1 | 2012-02-08 Ulrich Weigand <ulrich.weigand@linaro.org> | ||
2 | |||
3 | gcc/ | ||
4 | * config/arm/arm.c (arm_option_optimization_table): Enable | ||
5 | -fsched-pressure using -fsched-pressure-algorithm=model by | ||
6 | default when optimizing. | ||
7 | |||
8 | 2012-02-08 Richard Sandiford <richard.sandiford@linaro.org> | ||
9 | |||
10 | gcc/ | ||
11 | * sched-deps.c (fixup_sched_groups): Rename to... | ||
12 | (chain_to_prev_insn): ...this. | ||
13 | (chain_to_prev_insn_p): New function. | ||
14 | (deps_analyze_insn): Use it instead of SCHED_GROUP_P. | ||
15 | |||
16 | 2012-02-08 Richard Sandiford <richard.sandiford@linaro.org> | ||
17 | |||
18 | gcc/ | ||
19 | * sched-int.h (_haifa_insn_data): Move priority_status. | ||
20 | Add model_index. | ||
21 | (INSN_MODEL_INDEX): New macro. | ||
22 | * haifa-sched.c (insn_delay): New function. | ||
23 | (sched_regno_pressure_class): Update commentary. | ||
24 | (mark_regno_birth_or_death): Pass the liveness bitmap and | ||
25 | pressure array as arguments, instead of using curr_reg_live and | ||
26 | curr_reg_pressure. Only update the pressure if the bit in the | ||
27 | liveness set has changed. | ||
28 | (initiate_reg_pressure_info): Always trust the live-in set for | ||
29 | SCHED_PRESSURE_MODEL. | ||
30 | (initiate_bb_reg_pressure_info): Update call to | ||
31 | mark_regno_birth_or_death. | ||
32 | (dep_list_size): Take the list as argument. | ||
33 | (calculate_reg_deaths): New function, extracted from... | ||
34 | (setup_insn_reg_pressure_info): ...here. | ||
35 | (MODEL_BAR): New macro. | ||
36 | (model_pressure_data, model_insn_info, model_pressure_limit) | ||
37 | (model_pressure_group): New structures. | ||
38 | (model_schedule, model_worklist, model_insns, model_num_insns) | ||
39 | (model_curr_point, model_before_pressure, model_next_priority): | ||
40 | New variables. | ||
41 | (MODEL_PRESSURE_DATA, MODEL_MAX_PRESSURE, MODEL_REF_PRESSURE) | ||
42 | (MODEL_INSN_INFO, MODEL_INSN): New macros. | ||
43 | (model_index, model_update_limit_points_in_group): New functions. | ||
44 | (model_update_limit_points, model_last_use_except): Likewise. | ||
45 | (model_start_update_pressure, model_update_pressure): Likewise. | ||
46 | (model_recompute, model_spill_cost, model_excess_group_cost): Likewise. | ||
47 | (model_excess_cost, model_dump_pressure_points): Likewise. | ||
48 | (model_set_excess_costs): Likewise. | ||
49 | (rank_for_schedule): Extend SCHED_PRIORITY_WEIGHTED ordering to | ||
50 | SCHED_PRIORITY_MODEL. Use insn_delay. Use the order in the model | ||
51 | schedule as an alternative tie-breaker. Update the call to | ||
52 | dep_list_size. | ||
53 | (ready_sort): Call model_set_excess_costs. | ||
54 | (update_register_pressure): Update call to mark_regno_birth_or_death. | ||
55 | Rely on that function to check liveness rather than doing it here. | ||
56 | (model_classify_pressure, model_order_p, model_add_to_worklist_at) | ||
57 | (model_remove_from_worklist, model_add_to_worklist, model_promote_insn) | ||
58 | (model_add_to_schedule, model_analyze_insns, model_init_pressure_group) | ||
59 | (model_record_pressure, model_record_pressures): New functions. | ||
60 | (model_record_final_pressures, model_add_successors_to_worklist) | ||
61 | (model_promote_predecessors, model_choose_insn): Likewise. | ||
62 | (model_reset_queue_indices, model_dump_pressure_summary): Likewise. | ||
63 | (model_start_schedule, model_finalize_pressure_group): Likewise. | ||
64 | (model_end_schedule): Likewise. | ||
65 | (schedule_insn): Say when we're scheduling the next instruction | ||
66 | in the model schedule. | ||
67 | (schedule_insn): Handle SCHED_PRESSURE_MODEL. | ||
68 | (queue_to_ready): Do not add instructions that are | ||
69 | MAX_SCHED_READY_INSNS beyond the current point of the model schedule. | ||
70 | Always allow the next instruction in the model schedule to be added. | ||
71 | (debug_ready_list): Print the INSN_REG_PRESSURE_EXCESS_COST_CHANGE | ||
72 | and delay for SCHED_PRESSURE_MODEL too. | ||
73 | (prune_ready_list): Extend SCHED_PRIORITY_WEIGHTED handling to | ||
74 | SCHED_PRIORITY_MODEL, but also take the DFA into account. | ||
75 | (schedule_block): Call model_start_schedule and model_end_schedule. | ||
76 | Extend SCHED_PRIORITY_WEIGHTED stall handling to SCHED_PRIORITY_MODEL. | ||
77 | (sched_init): Extend INSN_REG_PRESSURE_EXCESS_COST_CHANGE handling | ||
78 | to SCHED_PRESSURE_MODEL, but don't allocate saved_reg_live or | ||
79 | region_ref_regs. | ||
80 | (sched_finish): Update accordingly. | ||
81 | (fix_tick_ready): Extend INSN_REG_PRESSURE_EXCESS_COST_CHANGE handling | ||
82 | to SCHED_PRESSURE_MODEL. | ||
83 | (add_jump_dependencies): Update call to dep_list_size. | ||
84 | (haifa_finish_h_i_d): Fix leak of max_reg_pressure. | ||
85 | (haifa_init_insn): Extend INSN_REG_PRESSURE_EXCESS_COST_CHANGE handling | ||
86 | to SCHED_PRESSURE_MODEL. | ||
87 | * sched-deps.c (init_insn_reg_pressure_info): Likewise, but don't | ||
88 | allocate INSN_MAX_REG_PRESSURE for SCHED_PRESSURE_MODEL. | ||
89 | (sched_analyze_insn): Extend INSN_REG_PRESSURE_EXCESS_COST_CHANGE | ||
90 | handling to SCHED_PRESSURE_MODEL. | ||
91 | |||
92 | 2012-02-08 Richard Sandiford <richard.sandiford@linaro.org> | ||
93 | |||
94 | gcc/ | ||
95 | * common.opt (fsched-pressure-algorithm=): New option. | ||
96 | * flag-types.h (sched_pressure_algorithm): New enum. | ||
97 | * sched-int.h (sched_pressure_p): Replace with... | ||
98 | (sched_pressure): ...this new variable. | ||
99 | * haifa-sched.c (sched_pressure_p): Replace with... | ||
100 | (sched_pressure): ...this new variable. | ||
101 | (sched_regno_pressure_class, rank_for_schedule, ready_sort) | ||
102 | (update_reg_and_insn_max_reg_pressure, schedule_insn) | ||
103 | (debug_ready_list, schedule_block, sched_init, sched_finish) | ||
104 | (fix_tick_ready, haifa_init_insn): Update accordingly. | ||
105 | * sched-deps.c (init_insn_reg_pressure_info): Likewise. | ||
106 | * sched-rgn.c (schedule_region): Likewise. | ||
107 | |||
108 | 2012-02-08 Richard Sandiford <richard.sandiford@linaro.org> | ||
109 | |||
110 | gcc/ | ||
111 | Backport from mainline: | ||
112 | |||
113 | 2011-04-01 Bernd Schmidt <bernds@codesourcery.com> | ||
114 | |||
115 | * haifa-sched.c (prune_ready_list): New function, broken out of | ||
116 | schedule_block. | ||
117 | (schedule_block): Use it. | ||
118 | |||
119 | === modified file 'gcc/common.opt' | ||
120 | --- old/gcc/common.opt 2011-04-11 15:26:47 +0000 | ||
121 | +++ new/gcc/common.opt 2012-02-08 23:38:13 +0000 | ||
122 | @@ -1614,6 +1614,19 @@ | ||
123 | Common Report Var(flag_sched_pressure) Init(0) Optimization | ||
124 | Enable register pressure sensitive insn scheduling | ||
125 | |||
126 | +fsched-pressure-algorithm= | ||
127 | +Common Joined RejectNegative Enum(sched_pressure_algorithm) Var(flag_sched_pressure_algorithm) Init(SCHED_PRESSURE_WEIGHTED) | ||
128 | +-fira-algorithm=[CB|priority] Set the used IRA algorithm | ||
129 | + | ||
130 | +Enum | ||
131 | +Name(sched_pressure_algorithm) Type(enum sched_pressure_algorithm) UnknownError(unknown %<fsched-pressure%> algorithm %qs) | ||
132 | + | ||
133 | +EnumValue | ||
134 | +Enum(sched_pressure_algorithm) String(weighted) Value(SCHED_PRESSURE_WEIGHTED) | ||
135 | + | ||
136 | +EnumValue | ||
137 | +Enum(sched_pressure_algorithm) String(model) Value(SCHED_PRESSURE_MODEL) | ||
138 | + | ||
139 | fsched-spec | ||
140 | Common Report Var(flag_schedule_speculative) Init(1) Optimization | ||
141 | Allow speculative motion of non-loads | ||
142 | |||
143 | === modified file 'gcc/config/arm/arm.c' | ||
144 | --- old/gcc/config/arm/arm.c 2012-02-01 14:13:07 +0000 | ||
145 | +++ new/gcc/config/arm/arm.c 2012-02-09 00:47:59 +0000 | ||
146 | @@ -311,6 +311,11 @@ | ||
147 | /* Set default optimization options. */ | ||
148 | static const struct default_options arm_option_optimization_table[] = | ||
149 | { | ||
150 | + /* Enable -fsched-pressure using -fsched-pressure-algorithm=model | ||
151 | + by default when optimizing. */ | ||
152 | + { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 }, | ||
153 | + { OPT_LEVELS_1_PLUS, OPT_fsched_pressure_algorithm_, | ||
154 | + NULL, SCHED_PRESSURE_MODEL }, | ||
155 | /* Enable section anchors by default at -O1 or higher. */ | ||
156 | { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 }, | ||
157 | { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, | ||
158 | |||
159 | === modified file 'gcc/flag-types.h' | ||
160 | --- old/gcc/flag-types.h 2010-11-24 13:28:38 +0000 | ||
161 | +++ new/gcc/flag-types.h 2012-02-08 23:38:13 +0000 | ||
162 | @@ -106,6 +106,14 @@ | ||
163 | }; | ||
164 | #endif | ||
165 | |||
166 | +/* The algorithm used to implement -fsched-pressure. */ | ||
167 | +enum sched_pressure_algorithm | ||
168 | +{ | ||
169 | + SCHED_PRESSURE_NONE, | ||
170 | + SCHED_PRESSURE_WEIGHTED, | ||
171 | + SCHED_PRESSURE_MODEL | ||
172 | +}; | ||
173 | + | ||
174 | /* The algorithm used for the integrated register allocator (IRA). */ | ||
175 | enum ira_algorithm | ||
176 | { | ||
177 | |||
178 | === modified file 'gcc/haifa-sched.c' | ||
179 | --- old/gcc/haifa-sched.c 2011-02-19 20:59:23 +0000 | ||
180 | +++ new/gcc/haifa-sched.c 2012-02-08 23:39:02 +0000 | ||
181 | @@ -348,6 +348,14 @@ | ||
182 | /* Create empty basic block after the specified block. */ | ||
183 | basic_block (* sched_create_empty_bb) (basic_block); | ||
184 | |||
185 | +/* Return the number of cycles until INSN is expected to be ready. | ||
186 | + Return zero if it already is. */ | ||
187 | +static int | ||
188 | +insn_delay (rtx insn) | ||
189 | +{ | ||
190 | + return MAX (INSN_TICK (insn) - clock_var, 0); | ||
191 | +} | ||
192 | + | ||
193 | static int | ||
194 | may_trap_exp (const_rtx x, int is_store) | ||
195 | { | ||
196 | @@ -571,10 +579,10 @@ | ||
197 | |||
198 | /* Do register pressure sensitive insn scheduling if the flag is set | ||
199 | up. */ | ||
200 | -bool sched_pressure_p; | ||
201 | +enum sched_pressure_algorithm sched_pressure; | ||
202 | |||
203 | /* Map regno -> its cover class. The map defined only when | ||
204 | - SCHED_PRESSURE_P is true. */ | ||
205 | + SCHED_PRESSURE != SCHED_PRESSURE_NONE. */ | ||
206 | enum reg_class *sched_regno_cover_class; | ||
207 | |||
208 | /* The current register pressure. Only elements corresponding cover | ||
209 | @@ -602,10 +610,12 @@ | ||
210 | bitmap_clear (region_ref_regs); | ||
211 | } | ||
212 | |||
213 | -/* Update current register pressure related info after birth (if | ||
214 | - BIRTH_P) or death of register REGNO. */ | ||
215 | -static void | ||
216 | -mark_regno_birth_or_death (int regno, bool birth_p) | ||
217 | +/* PRESSURE[CL] describes the pressure on register class CL. Update it | ||
218 | + for the birth (if BIRTH_P) or death (if !BIRTH_P) of register REGNO. | ||
219 | + LIVE tracks the set of live registers; if it is null, assume that | ||
220 | + every birth or death is genuine. */ | ||
221 | +static inline void | ||
222 | +mark_regno_birth_or_death (bitmap live, int *pressure, int regno, bool birth_p) | ||
223 | { | ||
224 | enum reg_class cover_class; | ||
225 | |||
226 | @@ -616,15 +626,17 @@ | ||
227 | { | ||
228 | if (birth_p) | ||
229 | { | ||
230 | - bitmap_set_bit (curr_reg_live, regno); | ||
231 | - curr_reg_pressure[cover_class] | ||
232 | - += ira_reg_class_nregs[cover_class][PSEUDO_REGNO_MODE (regno)]; | ||
233 | + if (!live || bitmap_set_bit (live, regno)) | ||
234 | + pressure[cover_class] | ||
235 | + += (ira_reg_class_nregs | ||
236 | + [cover_class][PSEUDO_REGNO_MODE (regno)]); | ||
237 | } | ||
238 | else | ||
239 | { | ||
240 | - bitmap_clear_bit (curr_reg_live, regno); | ||
241 | - curr_reg_pressure[cover_class] | ||
242 | - -= ira_reg_class_nregs[cover_class][PSEUDO_REGNO_MODE (regno)]; | ||
243 | + if (!live || bitmap_clear_bit (live, regno)) | ||
244 | + pressure[cover_class] | ||
245 | + -= (ira_reg_class_nregs | ||
246 | + [cover_class][PSEUDO_REGNO_MODE (regno)]); | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | @@ -633,13 +645,13 @@ | ||
251 | { | ||
252 | if (birth_p) | ||
253 | { | ||
254 | - bitmap_set_bit (curr_reg_live, regno); | ||
255 | - curr_reg_pressure[cover_class]++; | ||
256 | + if (!live || bitmap_set_bit (live, regno)) | ||
257 | + pressure[cover_class]++; | ||
258 | } | ||
259 | else | ||
260 | { | ||
261 | - bitmap_clear_bit (curr_reg_live, regno); | ||
262 | - curr_reg_pressure[cover_class]--; | ||
263 | + if (!live || bitmap_clear_bit (live, regno)) | ||
264 | + pressure[cover_class]--; | ||
265 | } | ||
266 | } | ||
267 | } | ||
268 | @@ -657,8 +669,10 @@ | ||
269 | curr_reg_pressure[ira_reg_class_cover[i]] = 0; | ||
270 | bitmap_clear (curr_reg_live); | ||
271 | EXECUTE_IF_SET_IN_BITMAP (live, 0, j, bi) | ||
272 | - if (current_nr_blocks == 1 || bitmap_bit_p (region_ref_regs, j)) | ||
273 | - mark_regno_birth_or_death (j, true); | ||
274 | + if (sched_pressure == SCHED_PRESSURE_MODEL | ||
275 | + || current_nr_blocks == 1 | ||
276 | + || bitmap_bit_p (region_ref_regs, j)) | ||
277 | + mark_regno_birth_or_death (curr_reg_live, curr_reg_pressure, j, true); | ||
278 | } | ||
279 | |||
280 | /* Mark registers in X as mentioned in the current region. */ | ||
281 | @@ -712,7 +726,8 @@ | ||
282 | if (regno == INVALID_REGNUM) | ||
283 | break; | ||
284 | if (! bitmap_bit_p (df_get_live_in (bb), regno)) | ||
285 | - mark_regno_birth_or_death (regno, true); | ||
286 | + mark_regno_birth_or_death (curr_reg_live, curr_reg_pressure, | ||
287 | + regno, true); | ||
288 | } | ||
289 | #endif | ||
290 | } | ||
291 | @@ -956,19 +971,19 @@ | ||
292 | return true; | ||
293 | } | ||
294 | |||
295 | -/* Compute the number of nondebug forward deps of an insn. */ | ||
296 | +/* Compute the number of nondebug deps in list LIST for INSN. */ | ||
297 | |||
298 | static int | ||
299 | -dep_list_size (rtx insn) | ||
300 | +dep_list_size (rtx insn, sd_list_types_def list) | ||
301 | { | ||
302 | sd_iterator_def sd_it; | ||
303 | dep_t dep; | ||
304 | int dbgcount = 0, nodbgcount = 0; | ||
305 | |||
306 | if (!MAY_HAVE_DEBUG_INSNS) | ||
307 | - return sd_lists_size (insn, SD_LIST_FORW); | ||
308 | + return sd_lists_size (insn, list); | ||
309 | |||
310 | - FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep) | ||
311 | + FOR_EACH_DEP (insn, list, sd_it, dep) | ||
312 | { | ||
313 | if (DEBUG_INSN_P (DEP_CON (dep))) | ||
314 | dbgcount++; | ||
315 | @@ -976,7 +991,7 @@ | ||
316 | nodbgcount++; | ||
317 | } | ||
318 | |||
319 | - gcc_assert (dbgcount + nodbgcount == sd_lists_size (insn, SD_LIST_FORW)); | ||
320 | + gcc_assert (dbgcount + nodbgcount == sd_lists_size (insn, list)); | ||
321 | |||
322 | return nodbgcount; | ||
323 | } | ||
324 | @@ -995,7 +1010,7 @@ | ||
325 | { | ||
326 | int this_priority = -1; | ||
327 | |||
328 | - if (dep_list_size (insn) == 0) | ||
329 | + if (dep_list_size (insn, SD_LIST_FORW) == 0) | ||
330 | /* ??? We should set INSN_PRIORITY to insn_cost when and insn has | ||
331 | some forward deps but all of them are ignored by | ||
332 | contributes_to_priority hook. At the moment we set priority of | ||
333 | @@ -1091,6 +1106,22 @@ | ||
334 | qsort (READY, N_READY, sizeof (rtx), rank_for_schedule); } \ | ||
335 | while (0) | ||
336 | |||
337 | +/* For each cover class CL, set DEATH[CL] to the number of registers | ||
338 | + in that class that die in INSN. */ | ||
339 | + | ||
340 | +static void | ||
341 | +calculate_reg_deaths (rtx insn, int *death) | ||
342 | +{ | ||
343 | + int i; | ||
344 | + struct reg_use_data *use; | ||
345 | + | ||
346 | + for (i = 0; i < ira_reg_class_cover_size; i++) | ||
347 | + death[ira_reg_class_cover[i]] = 0; | ||
348 | + for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use) | ||
349 | + if (dying_use_p (use)) | ||
350 | + mark_regno_birth_or_death (0, death, use->regno, true); | ||
351 | +} | ||
352 | + | ||
353 | /* Setup info about the current register pressure impact of scheduling | ||
354 | INSN at the current scheduling point. */ | ||
355 | static void | ||
356 | @@ -1102,23 +1133,12 @@ | ||
357 | enum reg_class cl; | ||
358 | struct reg_pressure_data *pressure_info; | ||
359 | int *max_reg_pressure; | ||
360 | - struct reg_use_data *use; | ||
361 | static int death[N_REG_CLASSES]; | ||
362 | |||
363 | gcc_checking_assert (!DEBUG_INSN_P (insn)); | ||
364 | |||
365 | excess_cost_change = 0; | ||
366 | - for (i = 0; i < ira_reg_class_cover_size; i++) | ||
367 | - death[ira_reg_class_cover[i]] = 0; | ||
368 | - for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use) | ||
369 | - if (dying_use_p (use)) | ||
370 | - { | ||
371 | - cl = sched_regno_cover_class[use->regno]; | ||
372 | - if (use->regno < FIRST_PSEUDO_REGISTER) | ||
373 | - death[cl]++; | ||
374 | - else | ||
375 | - death[cl] += ira_reg_class_nregs[cl][PSEUDO_REGNO_MODE (use->regno)]; | ||
376 | - } | ||
377 | + calculate_reg_deaths (insn, death); | ||
378 | pressure_info = INSN_REG_PRESSURE (insn); | ||
379 | max_reg_pressure = INSN_MAX_REG_PRESSURE (insn); | ||
380 | gcc_assert (pressure_info != NULL && max_reg_pressure != NULL); | ||
381 | @@ -1139,7 +1159,765 @@ | ||
382 | } | ||
383 | INSN_REG_PRESSURE_EXCESS_COST_CHANGE (insn) = excess_cost_change; | ||
384 | } | ||
385 | - | ||
386 | + | ||
387 | +/* This is the first page of code related to SCHED_PRESSURE_MODEL. | ||
388 | + It tries to make the scheduler take register pressure into account | ||
389 | + without introducing too many unnecessary stalls. It hooks into the | ||
390 | + main scheduling algorithm at several points: | ||
391 | + | ||
392 | + - Before scheduling starts, model_start_schedule constructs a | ||
393 | + "model schedule" for the current block. This model schedule is | ||
394 | + chosen solely to keep register pressure down. It does not take the | ||
395 | + target's pipeline or the original instruction order into account, | ||
396 | + except as a tie-breaker. It also doesn't work to a particular | ||
397 | + pressure limit. | ||
398 | + | ||
399 | + This model schedule gives us an idea of what pressure can be | ||
400 | + achieved for the block gives us an example of a schedule that | ||
401 | + keeps to that pressure. It also makes the final schedule less | ||
402 | + dependent on the original instruction order. This is important | ||
403 | + because the original order can either be "wide" (many values live | ||
404 | + at once, such as in user-scheduled code) or "narrow" (few values | ||
405 | + live at once, such as after loop unrolling, where several | ||
406 | + iterations are executed sequentially). | ||
407 | + | ||
408 | + We do not apply this model schedule to the rtx stream. We simply | ||
409 | + record it in model_schedule. We also compute the maximum pressure, | ||
410 | + MP, that was seen during this schedule. | ||
411 | + | ||
412 | + - Instructions are added to the ready queue even if they require | ||
413 | + a stall. The length of the stall is instead computed as: | ||
414 | + | ||
415 | + MAX (INSN_TICK (INSN) - clock_var, 0) | ||
416 | + | ||
417 | + (= insn_delay). This allows rank_for_schedule to choose between | ||
418 | + introducing a deliberate stall or increasing pressure. | ||
419 | + | ||
420 | + - Before sorting the ready queue, model_set_excess_costs assigns | ||
421 | + a pressure-based cost to each ready instruction in the queue. | ||
422 | + This is the instruction's INSN_REG_PRESSURE_EXCESS_COST_CHANGE | ||
423 | + (ECC for short) and is effectively measured in cycles. | ||
424 | + | ||
425 | + - rank_for_schedule ranks instructions based on: | ||
426 | + | ||
427 | + ECC (insn) + insn_delay (insn) | ||
428 | + | ||
429 | + then as: | ||
430 | + | ||
431 | + insn_delay (insn) | ||
432 | + | ||
433 | + So, for example, an instruction X1 with an ECC of 1 that can issue | ||
434 | + now will win over an instruction X0 with an ECC of zero that would | ||
435 | + introduce a stall of one cycle. However, an instruction X2 with an | ||
436 | + ECC of 2 that can issue now will lose to X0. | ||
437 | + | ||
438 | + - When an instruction is scheduled, model_recompute updates the model | ||
439 | + schedule with the new pressures (some of which might now exceed the | ||
440 | + original maximum pressure MP). model_update_limit_points then searches | ||
441 | + for the new point of maximum pressure, if not already known. */ | ||
442 | + | ||
443 | +/* Used to separate high-verbosity debug information for SCHED_PRESSURE_MODEL | ||
444 | + from surrounding debug information. */ | ||
445 | +#define MODEL_BAR \ | ||
446 | + ";;\t\t+------------------------------------------------------\n" | ||
447 | + | ||
448 | +/* Information about the pressure on a particular register class at a | ||
449 | + particular point of the model schedule. */ | ||
450 | +struct model_pressure_data { | ||
451 | + /* The pressure at this point of the model schedule, or -1 if the | ||
452 | + point is associated with an instruction that has already been | ||
453 | + scheduled. */ | ||
454 | + int ref_pressure; | ||
455 | + | ||
456 | + /* The maximum pressure during or after this point of the model schedule. */ | ||
457 | + int max_pressure; | ||
458 | +}; | ||
459 | + | ||
460 | +/* Per-instruction information that is used while building the model | ||
461 | + schedule. Here, "schedule" refers to the model schedule rather | ||
462 | + than the main schedule. */ | ||
463 | +struct model_insn_info { | ||
464 | + /* The instruction itself. */ | ||
465 | + rtx insn; | ||
466 | + | ||
467 | + /* If this instruction is in model_worklist, these fields link to the | ||
468 | + previous (higher-priority) and next (lower-priority) instructions | ||
469 | + in the list. */ | ||
470 | + struct model_insn_info *prev; | ||
471 | + struct model_insn_info *next; | ||
472 | + | ||
473 | + /* While constructing the schedule, QUEUE_INDEX describes whether an | ||
474 | + instruction has already been added to the schedule (QUEUE_SCHEDULED), | ||
475 | + is in model_worklist (QUEUE_READY), or neither (QUEUE_NOWHERE). | ||
476 | + old_queue records the value that QUEUE_INDEX had before scheduling | ||
477 | + started, so that we can restore it once the schedule is complete. */ | ||
478 | + int old_queue; | ||
479 | + | ||
480 | + /* The relative importance of an unscheduled instruction. Higher | ||
481 | + values indicate greater importance. */ | ||
482 | + unsigned int model_priority; | ||
483 | + | ||
484 | + /* The length of the longest path of satisfied true dependencies | ||
485 | + that leads to this instruction. */ | ||
486 | + unsigned int depth; | ||
487 | + | ||
488 | + /* The length of the longest path of dependencies of any kind | ||
489 | + that leads from this instruction. */ | ||
490 | + unsigned int alap; | ||
491 | + | ||
492 | + /* The number of predecessor nodes that must still be scheduled. */ | ||
493 | + int unscheduled_preds; | ||
494 | +}; | ||
495 | + | ||
496 | +/* Information about the pressure limit for a particular register class. | ||
497 | + This structure is used when applying a model schedule to the main | ||
498 | + schedule. */ | ||
499 | +struct model_pressure_limit { | ||
500 | + /* The maximum register pressure seen in the original model schedule. */ | ||
501 | + int orig_pressure; | ||
502 | + | ||
503 | + /* The maximum register pressure seen in the current model schedule | ||
504 | + (which excludes instructions that have already been scheduled). */ | ||
505 | + int pressure; | ||
506 | + | ||
507 | + /* The point of the current model schedule at which PRESSURE is first | ||
508 | + reached. It is set to -1 if the value needs to be recomputed. */ | ||
509 | + int point; | ||
510 | +}; | ||
511 | + | ||
512 | +/* Describes a particular way of measuring register pressure. */ | ||
513 | +struct model_pressure_group { | ||
514 | + /* Index CCI describes the maximum pressure on ira_reg_class_cover[CCI]. */ | ||
515 | + struct model_pressure_limit limits[N_REG_CLASSES]; | ||
516 | + | ||
517 | + /* Index (POINT * ira_num_pressure_classes + CCI) describes the pressure | ||
518 | + on register class ira_reg_class_cover[CCI] at point POINT of the | ||
519 | + current model schedule. A POINT of model_num_insns describes the | ||
520 | + pressure at the end of the schedule. */ | ||
521 | + struct model_pressure_data *model; | ||
522 | +}; | ||
523 | + | ||
524 | +/* Index POINT gives the instruction at point POINT of the model schedule. | ||
525 | + This array doesn't change during main scheduling. */ | ||
526 | +static VEC (rtx, heap) *model_schedule; | ||
527 | + | ||
528 | +/* The list of instructions in the model worklist, sorted in order of | ||
529 | + decreasing priority. */ | ||
530 | +static struct model_insn_info *model_worklist; | ||
531 | + | ||
532 | +/* Index I describes the instruction with INSN_LUID I. */ | ||
533 | +static struct model_insn_info *model_insns; | ||
534 | + | ||
535 | +/* The number of instructions in the model schedule. */ | ||
536 | +static int model_num_insns; | ||
537 | + | ||
538 | +/* The index of the first instruction in model_schedule that hasn't yet been | ||
539 | + added to the main schedule, or model_num_insns if all of them have. */ | ||
540 | +static int model_curr_point; | ||
541 | + | ||
542 | +/* Describes the pressure before each instruction in the model schedule. */ | ||
543 | +static struct model_pressure_group model_before_pressure; | ||
544 | + | ||
545 | +/* The first unused model_priority value (as used in model_insn_info). */ | ||
546 | +static unsigned int model_next_priority; | ||
547 | + | ||
548 | + | ||
549 | +/* The model_pressure_data for ira_reg_class_cover[CCI] in GROUP | ||
550 | + at point POINT of the model schedule. */ | ||
551 | +#define MODEL_PRESSURE_DATA(GROUP, POINT, CCI) \ | ||
552 | + (&(GROUP)->model[(POINT) * ira_reg_class_cover_size + (CCI)]) | ||
553 | + | ||
554 | +/* The maximum pressure on ira_reg_class_cover[CCI] in GROUP at or | ||
555 | + after point POINT of the model schedule. */ | ||
556 | +#define MODEL_MAX_PRESSURE(GROUP, POINT, CCI) \ | ||
557 | + (MODEL_PRESSURE_DATA (GROUP, POINT, CCI)->max_pressure) | ||
558 | + | ||
559 | +/* The pressure on ira_reg_class_cover[CCI] in GROUP at point POINT | ||
560 | + of the model schedule. */ | ||
561 | +#define MODEL_REF_PRESSURE(GROUP, POINT, CCI) \ | ||
562 | + (MODEL_PRESSURE_DATA (GROUP, POINT, CCI)->ref_pressure) | ||
563 | + | ||
564 | +/* Information about INSN that is used when creating the model schedule. */ | ||
565 | +#define MODEL_INSN_INFO(INSN) \ | ||
566 | + (&model_insns[INSN_LUID (INSN)]) | ||
567 | + | ||
568 | +/* The instruction at point POINT of the model schedule. */ | ||
569 | +#define MODEL_INSN(POINT) \ | ||
570 | + (VEC_index (rtx, model_schedule, POINT)) | ||
571 | + | ||
572 | + | ||
573 | +/* Return INSN's index in the model schedule, or model_num_insns if it | ||
574 | + doesn't belong to that schedule. */ | ||
575 | + | ||
576 | +static int | ||
577 | +model_index (rtx insn) | ||
578 | +{ | ||
579 | + if (INSN_MODEL_INDEX (insn) == 0) | ||
580 | + return model_num_insns; | ||
581 | + return INSN_MODEL_INDEX (insn) - 1; | ||
582 | +} | ||
583 | + | ||
584 | +/* Make sure that GROUP->limits is up-to-date for the current point | ||
585 | + of the model schedule. */ | ||
586 | + | ||
587 | +static void | ||
588 | +model_update_limit_points_in_group (struct model_pressure_group *group) | ||
589 | +{ | ||
590 | + int cci, max_pressure, point; | ||
591 | + | ||
592 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
593 | + { | ||
594 | + /* We may have passed the final point at which the pressure in | ||
595 | + group->limits[cci].pressure was reached. Update the limit if so. */ | ||
596 | + max_pressure = MODEL_MAX_PRESSURE (group, model_curr_point, cci); | ||
597 | + group->limits[cci].pressure = max_pressure; | ||
598 | + | ||
599 | + /* Find the point at which MAX_PRESSURE is first reached. We need | ||
600 | + to search in three cases: | ||
601 | + | ||
602 | + - We've already moved past the previous pressure point. | ||
603 | + In this case we search forward from model_curr_point. | ||
604 | + | ||
605 | + - We scheduled the previous point of maximum pressure ahead of | ||
606 | + its position in the model schedule, but doing so didn't bring | ||
607 | + the pressure point earlier. In this case we search forward | ||
608 | + from that previous pressure point. | ||
609 | + | ||
610 | + - Scheduling an instruction early caused the maximum pressure | ||
611 | + to decrease. In this case we will have set the pressure | ||
612 | + point to -1, and we search forward from model_curr_point. */ | ||
613 | + point = MAX (group->limits[cci].point, model_curr_point); | ||
614 | + while (point < model_num_insns | ||
615 | + && MODEL_REF_PRESSURE (group, point, cci) < max_pressure) | ||
616 | + point++; | ||
617 | + group->limits[cci].point = point; | ||
618 | + | ||
619 | + gcc_assert (MODEL_REF_PRESSURE (group, point, cci) == max_pressure); | ||
620 | + gcc_assert (MODEL_MAX_PRESSURE (group, point, cci) == max_pressure); | ||
621 | + } | ||
622 | +} | ||
623 | + | ||
624 | +/* Make sure that all register-pressure limits are up-to-date for the | ||
625 | + current position in the model schedule. */ | ||
626 | + | ||
627 | +static void | ||
628 | +model_update_limit_points (void) | ||
629 | +{ | ||
630 | + model_update_limit_points_in_group (&model_before_pressure); | ||
631 | +} | ||
632 | + | ||
633 | +/* Return the model_index of the last unscheduled use in chain USE | ||
634 | + outside of USE's instruction. Return -1 if there are no other uses, | ||
635 | + or model_num_insns if the register is live at the end of the block. */ | ||
636 | + | ||
637 | +static int | ||
638 | +model_last_use_except (struct reg_use_data *use) | ||
639 | +{ | ||
640 | + struct reg_use_data *next; | ||
641 | + int last, index; | ||
642 | + | ||
643 | + last = -1; | ||
644 | + for (next = use->next_regno_use; next != use; next = next->next_regno_use) | ||
645 | + if (NONDEBUG_INSN_P (next->insn) | ||
646 | + && QUEUE_INDEX (next->insn) != QUEUE_SCHEDULED) | ||
647 | + { | ||
648 | + index = model_index (next->insn); | ||
649 | + if (index == model_num_insns) | ||
650 | + return model_num_insns; | ||
651 | + if (last < index) | ||
652 | + last = index; | ||
653 | + } | ||
654 | + return last; | ||
655 | +} | ||
656 | + | ||
657 | +/* An instruction with model_index POINT has just been scheduled, and it | ||
658 | + adds DELTA to the pressure on ira_reg_class_cover[CCI] after POINT - 1. | ||
659 | + Update MODEL_REF_PRESSURE (GROUP, POINT, CCI) and | ||
660 | + MODEL_MAX_PRESSURE (GROUP, POINT, CCI) accordingly. */ | ||
661 | + | ||
662 | +static void | ||
663 | +model_start_update_pressure (struct model_pressure_group *group, | ||
664 | + int point, int cci, int delta) | ||
665 | +{ | ||
666 | + int next_max_pressure; | ||
667 | + | ||
668 | + if (point == model_num_insns) | ||
669 | + { | ||
670 | + /* The instruction wasn't part of the model schedule; it was moved | ||
671 | + from a different block. Update the pressure for the end of | ||
672 | + the model schedule. */ | ||
673 | + MODEL_REF_PRESSURE (group, point, cci) += delta; | ||
674 | + MODEL_MAX_PRESSURE (group, point, cci) += delta; | ||
675 | + } | ||
676 | + else | ||
677 | + { | ||
678 | + /* Record that this instruction has been scheduled. Nothing now | ||
679 | + changes between POINT and POINT + 1, so get the maximum pressure | ||
680 | + from the latter. If the maximum pressure decreases, the new | ||
681 | + pressure point may be before POINT. */ | ||
682 | + MODEL_REF_PRESSURE (group, point, cci) = -1; | ||
683 | + next_max_pressure = MODEL_MAX_PRESSURE (group, point + 1, cci); | ||
684 | + if (MODEL_MAX_PRESSURE (group, point, cci) > next_max_pressure) | ||
685 | + { | ||
686 | + MODEL_MAX_PRESSURE (group, point, cci) = next_max_pressure; | ||
687 | + if (group->limits[cci].point == point) | ||
688 | + group->limits[cci].point = -1; | ||
689 | + } | ||
690 | + } | ||
691 | +} | ||
692 | + | ||
693 | +/* Record that scheduling a later instruction has changed the pressure | ||
694 | + at point POINT of the model schedule by DELTA (which might be 0). | ||
695 | + Update GROUP accordingly. Return nonzero if these changes might | ||
696 | + trigger changes to previous points as well. */ | ||
697 | + | ||
698 | +static int | ||
699 | +model_update_pressure (struct model_pressure_group *group, | ||
700 | + int point, int cci, int delta) | ||
701 | +{ | ||
702 | + int ref_pressure, max_pressure, next_max_pressure; | ||
703 | + | ||
704 | + /* If POINT hasn't yet been scheduled, update its pressure. */ | ||
705 | + ref_pressure = MODEL_REF_PRESSURE (group, point, cci); | ||
706 | + if (ref_pressure >= 0 && delta != 0) | ||
707 | + { | ||
708 | + ref_pressure += delta; | ||
709 | + MODEL_REF_PRESSURE (group, point, cci) = ref_pressure; | ||
710 | + | ||
711 | + /* Check whether the maximum pressure in the overall schedule | ||
712 | + has increased. (This means that the MODEL_MAX_PRESSURE of | ||
713 | + every point <= POINT will need to increae too; see below.) */ | ||
714 | + if (group->limits[cci].pressure < ref_pressure) | ||
715 | + group->limits[cci].pressure = ref_pressure; | ||
716 | + | ||
717 | + /* If we are at maximum pressure, and the maximum pressure | ||
718 | + point was previously unknown or later than POINT, | ||
719 | + bring it forward. */ | ||
720 | + if (group->limits[cci].pressure == ref_pressure | ||
721 | + && !IN_RANGE (group->limits[cci].point, 0, point)) | ||
722 | + group->limits[cci].point = point; | ||
723 | + | ||
724 | + /* If POINT used to be the point of maximum pressure, but isn't | ||
725 | + any longer, we need to recalculate it using a forward walk. */ | ||
726 | + if (group->limits[cci].pressure > ref_pressure | ||
727 | + && group->limits[cci].point == point) | ||
728 | + group->limits[cci].point = -1; | ||
729 | + } | ||
730 | + | ||
731 | + /* Update the maximum pressure at POINT. Changes here might also | ||
732 | + affect the maximum pressure at POINT - 1. */ | ||
733 | + next_max_pressure = MODEL_MAX_PRESSURE (group, point + 1, cci); | ||
734 | + max_pressure = MAX (ref_pressure, next_max_pressure); | ||
735 | + if (MODEL_MAX_PRESSURE (group, point, cci) != max_pressure) | ||
736 | + { | ||
737 | + MODEL_MAX_PRESSURE (group, point, cci) = max_pressure; | ||
738 | + return 1; | ||
739 | + } | ||
740 | + return 0; | ||
741 | +} | ||
742 | + | ||
743 | +/* INSN has just been scheduled. Update the model schedule accordingly. */ | ||
744 | + | ||
745 | +static void | ||
746 | +model_recompute (rtx insn) | ||
747 | +{ | ||
748 | + struct { | ||
749 | + int last_use; | ||
750 | + int regno; | ||
751 | + } uses[FIRST_PSEUDO_REGISTER + MAX_RECOG_OPERANDS]; | ||
752 | + struct reg_use_data *use; | ||
753 | + struct reg_pressure_data *reg_pressure; | ||
754 | + int delta[N_REG_CLASSES]; | ||
755 | + int cci, point, mix, new_last, cl, ref_pressure, queue; | ||
756 | + unsigned int i, num_uses, num_pending_births; | ||
757 | + bool print_p; | ||
758 | + | ||
759 | + /* The destinations of INSN were previously live from POINT onwards, but are | ||
760 | + now live from model_curr_point onwards. Set up DELTA accordingly. */ | ||
761 | + point = model_index (insn); | ||
762 | + reg_pressure = INSN_REG_PRESSURE (insn); | ||
763 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
764 | + { | ||
765 | + cl = ira_reg_class_cover[cci]; | ||
766 | + delta[cl] = reg_pressure[cci].set_increase; | ||
767 | + } | ||
768 | + | ||
769 | + /* Record which registers previously died at POINT, but which now die | ||
770 | + before POINT. Adjust DELTA so that it represents the effect of | ||
771 | + this change after POINT - 1. Set NUM_PENDING_BIRTHS to the number of | ||
772 | + registers that will be born in the range [model_curr_point, POINT). */ | ||
773 | + num_uses = 0; | ||
774 | + num_pending_births = 0; | ||
775 | + for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use) | ||
776 | + { | ||
777 | + new_last = model_last_use_except (use); | ||
778 | + if (new_last < point) | ||
779 | + { | ||
780 | + gcc_assert (num_uses < ARRAY_SIZE (uses)); | ||
781 | + uses[num_uses].last_use = new_last; | ||
782 | + uses[num_uses].regno = use->regno; | ||
783 | + /* This register is no longer live after POINT - 1. */ | ||
784 | + mark_regno_birth_or_death (NULL, delta, use->regno, false); | ||
785 | + num_uses++; | ||
786 | + if (new_last >= 0) | ||
787 | + num_pending_births++; | ||
788 | + } | ||
789 | + } | ||
790 | + | ||
791 | + /* Update the MODEL_REF_PRESSURE and MODEL_MAX_PRESSURE for POINT. | ||
792 | + Also set each group pressure limit for POINT. */ | ||
793 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
794 | + { | ||
795 | + cl = ira_reg_class_cover[cci]; | ||
796 | + model_start_update_pressure (&model_before_pressure, | ||
797 | + point, cci, delta[cl]); | ||
798 | + } | ||
799 | + | ||
800 | + /* Walk the model schedule backwards, starting immediately before POINT. */ | ||
801 | + print_p = false; | ||
802 | + if (point != model_curr_point) | ||
803 | + do | ||
804 | + { | ||
805 | + point--; | ||
806 | + insn = MODEL_INSN (point); | ||
807 | + queue = QUEUE_INDEX (insn); | ||
808 | + | ||
809 | + if (queue != QUEUE_SCHEDULED) | ||
810 | + { | ||
811 | + /* DELTA describes the effect of the move on the register pressure | ||
812 | + after POINT. Make it describe the effect on the pressure | ||
813 | + before POINT. */ | ||
814 | + i = 0; | ||
815 | + while (i < num_uses) | ||
816 | + { | ||
817 | + if (uses[i].last_use == point) | ||
818 | + { | ||
819 | + /* This register is now live again. */ | ||
820 | + mark_regno_birth_or_death (NULL, delta, | ||
821 | + uses[i].regno, true); | ||
822 | + | ||
823 | + /* Remove this use from the array. */ | ||
824 | + uses[i] = uses[num_uses - 1]; | ||
825 | + num_uses--; | ||
826 | + num_pending_births--; | ||
827 | + } | ||
828 | + else | ||
829 | + i++; | ||
830 | + } | ||
831 | + | ||
832 | + if (sched_verbose >= 5) | ||
833 | + { | ||
834 | + char buf[2048]; | ||
835 | + | ||
836 | + if (!print_p) | ||
837 | + { | ||
838 | + fprintf (sched_dump, MODEL_BAR); | ||
839 | + fprintf (sched_dump, ";;\t\t| New pressure for model" | ||
840 | + " schedule\n"); | ||
841 | + fprintf (sched_dump, MODEL_BAR); | ||
842 | + print_p = true; | ||
843 | + } | ||
844 | + | ||
845 | + print_pattern (buf, PATTERN (insn), 0); | ||
846 | + fprintf (sched_dump, ";;\t\t| %3d %4d %-30s ", | ||
847 | + point, INSN_UID (insn), buf); | ||
848 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
849 | + { | ||
850 | + cl = ira_reg_class_cover[cci]; | ||
851 | + ref_pressure = MODEL_REF_PRESSURE (&model_before_pressure, | ||
852 | + point, cci); | ||
853 | + fprintf (sched_dump, " %s:[%d->%d]", | ||
854 | + reg_class_names[ira_reg_class_cover[cci]], | ||
855 | + ref_pressure, ref_pressure + delta[cl]); | ||
856 | + } | ||
857 | + fprintf (sched_dump, "\n"); | ||
858 | + } | ||
859 | + } | ||
860 | + | ||
861 | + /* Adjust the pressure at POINT. Set MIX to nonzero if POINT - 1 | ||
862 | + might have changed as well. */ | ||
863 | + mix = num_pending_births; | ||
864 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
865 | + { | ||
866 | + cl = ira_reg_class_cover[cci]; | ||
867 | + mix |= delta[cl]; | ||
868 | + mix |= model_update_pressure (&model_before_pressure, | ||
869 | + point, cci, delta[cl]); | ||
870 | + } | ||
871 | + } | ||
872 | + while (mix && point > model_curr_point); | ||
873 | + | ||
874 | + if (print_p) | ||
875 | + fprintf (sched_dump, MODEL_BAR); | ||
876 | +} | ||
877 | + | ||
878 | +/* model_spill_cost (CL, P, P') returns the cost of increasing the | ||
879 | + pressure on CL from P to P'. We use this to calculate a "base ECC", | ||
880 | + baseECC (CL, X), for each cover class CL and each instruction X. | ||
881 | + Supposing X changes the pressure on CL from P to P', and that the | ||
882 | + maximum pressure on CL in the current model schedule is MP', then: | ||
883 | + | ||
884 | + * if X occurs before or at the next point of maximum pressure in | ||
885 | + the model schedule and P' > MP', then: | ||
886 | + | ||
887 | + baseECC (CL, X) = model_spill_cost (CL, MP, P') | ||
888 | + | ||
889 | + The idea is that the pressure after scheduling a fixed set of | ||
890 | + instructions -- in this case, the set up to and including the | ||
891 | + next maximum pressure point -- is going to be the same regardless | ||
892 | + of the order; we simply want to keep the intermediate pressure | ||
893 | + under control. Thus X has a cost of zero unless scheduling it | ||
894 | + now would exceed MP'. | ||
895 | + | ||
896 | + If all increases in the set are by the same amount, no zero-cost | ||
897 | + instruction will ever cause the pressure to exceed MP'. However, | ||
898 | + if X is instead moved past an instruction X' with pressure in the | ||
899 | + range (MP' - (P' - P), MP'), the pressure at X' will increase | ||
900 | + beyond MP'. Since baseECC is very much a heuristic anyway, | ||
901 | + it doesn't seem worth the overhead of tracking cases like these. | ||
902 | + | ||
903 | + The cost of exceeding MP' is always based on the original maximum | ||
904 | + pressure MP. This is so that going 2 registers over the original | ||
905 | + limit has the same cost regardless of whether it comes from two | ||
906 | + separate +1 deltas or from a single +2 delta. | ||
907 | + | ||
908 | + * if X occurs after the next point of maximum pressure in the model | ||
909 | + schedule and P' > P, then: | ||
910 | + | ||
911 | + baseECC (CL, X) = model_spill_cost (CL, MP, MP' + (P' - P)) | ||
912 | + | ||
913 | + That is, if we move X forward across a point of maximum pressure, | ||
914 | + and if X increases the pressure by P' - P, then we conservatively | ||
915 | + assume that scheduling X next would increase the maximum pressure | ||
916 | + by P' - P. Again, the cost of doing this is based on the original | ||
917 | + maximum pressure MP, for the same reason as above. | ||
918 | + | ||
919 | + * if P' < P, P > MP, and X occurs at or after the next point of | ||
920 | + maximum pressure, then: | ||
921 | + | ||
922 | + baseECC (CL, X) = -model_spill_cost (CL, MAX (MP, P'), P) | ||
923 | + | ||
924 | + That is, if we have already exceeded the original maximum pressure MP, | ||
925 | + and if X might reduce the maximum pressure again -- or at least push | ||
926 | + it further back, and thus allow more scheduling freedom -- it is given | ||
927 | + a negative cost to reflect the improvement. | ||
928 | + | ||
929 | + * otherwise, | ||
930 | + | ||
931 | + baseECC (CL, X) = 0 | ||
932 | + | ||
933 | + In this case, X is not expected to affect the maximum pressure MP', | ||
934 | + so it has zero cost. | ||
935 | + | ||
936 | + We then create a combined value baseECC (X) that is the sum of | ||
937 | + baseECC (CL, X) for each cover class CL. | ||
938 | + | ||
939 | + baseECC (X) could itself be used as the ECC value described above. | ||
940 | + However, this is often too conservative, in the sense that it | ||
941 | + tends to make high-priority instructions that increase pressure | ||
942 | + wait too long in cases where introducing a spill would be better. | ||
943 | + For this reason the final ECC is a priority-adjusted form of | ||
944 | + baseECC (X). Specifically, we calculate: | ||
945 | + | ||
946 | + P (X) = INSN_PRIORITY (X) - insn_delay (X) - baseECC (X) | ||
947 | + baseP = MAX { P (X) | baseECC (X) <= 0 } | ||
948 | + | ||
949 | + Then: | ||
950 | + | ||
951 | + ECC (X) = MAX (MIN (baseP - P (X), baseECC (X)), 0) | ||
952 | + | ||
953 | + Thus an instruction's effect on pressure is ignored if it has a high | ||
954 | + enough priority relative to the ones that don't increase pressure. | ||
955 | + Negative values of baseECC (X) do not increase the priority of X | ||
956 | + itself, but they do make it harder for other instructions to | ||
957 | + increase the pressure further. | ||
958 | + | ||
959 | + This pressure cost is deliberately timid. The intention has been | ||
960 | + to choose a heuristic that rarely interferes with the normal list | ||
961 | + scheduler in cases where that scheduler would produce good code. | ||
962 | + We simply want to curb some of its worst excesses. */ | ||
963 | + | ||
964 | +/* Return the cost of increasing the pressure in class CL from FROM to TO. | ||
965 | + | ||
966 | + Here we use the very simplistic cost model that every register above | ||
967 | + ira_available_class_regs[CL] has a spill cost of 1. We could use other | ||
968 | + measures instead, such as one based on MEMORY_MOVE_COST. However: | ||
969 | + | ||
970 | + (1) In order for an instruction to be scheduled, the higher cost | ||
971 | + would need to be justified in a single saving of that many stalls. | ||
972 | + This is overly pessimistic, because the benefit of spilling is | ||
973 | + often to avoid a sequence of several short stalls rather than | ||
974 | + a single long one. | ||
975 | + | ||
976 | + (2) The cost is still arbitrary. Because we are not allocating | ||
977 | + registers during scheduling, we have no way of knowing for | ||
978 | + sure how many memory accesses will be required by each spill, | ||
979 | + where the spills will be placed within the block, or even | ||
980 | + which block(s) will contain the spills. | ||
981 | + | ||
982 | + So a higher cost than 1 is often too conservative in practice, | ||
983 | + forcing blocks to contain unnecessary stalls instead of spill code. | ||
984 | + The simple cost below seems to be the best compromise. It reduces | ||
985 | + the interference with the normal list scheduler, which helps make | ||
986 | + it more suitable for a default-on option. */ | ||
987 | + | ||
988 | +static int | ||
989 | +model_spill_cost (int cl, int from, int to) | ||
990 | +{ | ||
991 | + from = MAX (from, ira_available_class_regs[cl]); | ||
992 | + return MAX (to, from) - from; | ||
993 | +} | ||
994 | + | ||
995 | +/* Return baseECC (ira_reg_class_cover[CCI], POINT), given that | ||
996 | + P = curr_reg_pressure[ira_reg_class_cover[CCI]] and that | ||
997 | + P' = P + DELTA. */ | ||
998 | + | ||
999 | +static int | ||
1000 | +model_excess_group_cost (struct model_pressure_group *group, | ||
1001 | + int point, int cci, int delta) | ||
1002 | +{ | ||
1003 | + int pressure, cl; | ||
1004 | + | ||
1005 | + cl = ira_reg_class_cover[cci]; | ||
1006 | + if (delta < 0 && point >= group->limits[cci].point) | ||
1007 | + { | ||
1008 | + pressure = MAX (group->limits[cci].orig_pressure, | ||
1009 | + curr_reg_pressure[cl] + delta); | ||
1010 | + return -model_spill_cost (cl, pressure, curr_reg_pressure[cl]); | ||
1011 | + } | ||
1012 | + | ||
1013 | + if (delta > 0) | ||
1014 | + { | ||
1015 | + if (point > group->limits[cci].point) | ||
1016 | + pressure = group->limits[cci].pressure + delta; | ||
1017 | + else | ||
1018 | + pressure = curr_reg_pressure[cl] + delta; | ||
1019 | + | ||
1020 | + if (pressure > group->limits[cci].pressure) | ||
1021 | + return model_spill_cost (cl, group->limits[cci].orig_pressure, | ||
1022 | + pressure); | ||
1023 | + } | ||
1024 | + | ||
1025 | + return 0; | ||
1026 | +} | ||
1027 | + | ||
1028 | +/* Return baseECC (MODEL_INSN (INSN)). Dump the costs to sched_dump | ||
1029 | + if PRINT_P. */ | ||
1030 | + | ||
1031 | +static int | ||
1032 | +model_excess_cost (rtx insn, bool print_p) | ||
1033 | +{ | ||
1034 | + int point, cci, cl, cost, this_cost, delta; | ||
1035 | + struct reg_pressure_data *insn_reg_pressure; | ||
1036 | + int insn_death[N_REG_CLASSES]; | ||
1037 | + | ||
1038 | + calculate_reg_deaths (insn, insn_death); | ||
1039 | + point = model_index (insn); | ||
1040 | + insn_reg_pressure = INSN_REG_PRESSURE (insn); | ||
1041 | + cost = 0; | ||
1042 | + | ||
1043 | + if (print_p) | ||
1044 | + fprintf (sched_dump, ";;\t\t| %3d %4d | %4d %+3d |", point, | ||
1045 | + INSN_UID (insn), INSN_PRIORITY (insn), insn_delay (insn)); | ||
1046 | + | ||
1047 | + /* Sum up the individual costs for each register class. */ | ||
1048 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
1049 | + { | ||
1050 | + cl = ira_reg_class_cover[cci]; | ||
1051 | + delta = insn_reg_pressure[cci].set_increase - insn_death[cl]; | ||
1052 | + this_cost = model_excess_group_cost (&model_before_pressure, | ||
1053 | + point, cci, delta); | ||
1054 | + cost += this_cost; | ||
1055 | + if (print_p) | ||
1056 | + fprintf (sched_dump, " %s:[%d base cost %d]", | ||
1057 | + reg_class_names[cl], delta, this_cost); | ||
1058 | + } | ||
1059 | + | ||
1060 | + if (print_p) | ||
1061 | + fprintf (sched_dump, "\n"); | ||
1062 | + | ||
1063 | + return cost; | ||
1064 | +} | ||
1065 | + | ||
1066 | +/* Dump the next points of maximum pressure for GROUP. */ | ||
1067 | + | ||
1068 | +static void | ||
1069 | +model_dump_pressure_points (struct model_pressure_group *group) | ||
1070 | +{ | ||
1071 | + int cci, cl; | ||
1072 | + | ||
1073 | + fprintf (sched_dump, ";;\t\t| pressure points"); | ||
1074 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
1075 | + { | ||
1076 | + cl = ira_reg_class_cover[cci]; | ||
1077 | + fprintf (sched_dump, " %s:[%d->%d at ", reg_class_names[cl], | ||
1078 | + curr_reg_pressure[cl], group->limits[cci].pressure); | ||
1079 | + if (group->limits[cci].point < model_num_insns) | ||
1080 | + fprintf (sched_dump, "%d:%d]", group->limits[cci].point, | ||
1081 | + INSN_UID (MODEL_INSN (group->limits[cci].point))); | ||
1082 | + else | ||
1083 | + fprintf (sched_dump, "end]"); | ||
1084 | + } | ||
1085 | + fprintf (sched_dump, "\n"); | ||
1086 | +} | ||
1087 | + | ||
1088 | +/* Set INSN_REG_PRESSURE_EXCESS_COST_CHANGE for INSNS[0...COUNT-1]. */ | ||
1089 | + | ||
1090 | +static void | ||
1091 | +model_set_excess_costs (rtx *insns, int count) | ||
1092 | +{ | ||
1093 | + int i, cost, priority_base, priority; | ||
1094 | + bool print_p; | ||
1095 | + | ||
1096 | + /* Record the baseECC value for each instruction in the model schedule, | ||
1097 | + except that negative costs are converted to zero ones now rather thatn | ||
1098 | + later. Do not assign a cost to debug instructions, since they must | ||
1099 | + not change code-generation decisions. Experiments suggest we also | ||
1100 | + get better results by not assigning a cost to instructions from | ||
1101 | + a different block. | ||
1102 | + | ||
1103 | + Set PRIORITY_BASE to baseP in the block comment above. This is the | ||
1104 | + maximum priority of the "cheap" instructions, which should always | ||
1105 | + include the next model instruction. */ | ||
1106 | + priority_base = 0; | ||
1107 | + print_p = false; | ||
1108 | + for (i = 0; i < count; i++) | ||
1109 | + if (INSN_MODEL_INDEX (insns[i])) | ||
1110 | + { | ||
1111 | + if (sched_verbose >= 6 && !print_p) | ||
1112 | + { | ||
1113 | + fprintf (sched_dump, MODEL_BAR); | ||
1114 | + fprintf (sched_dump, ";;\t\t| Pressure costs for ready queue\n"); | ||
1115 | + model_dump_pressure_points (&model_before_pressure); | ||
1116 | + fprintf (sched_dump, MODEL_BAR); | ||
1117 | + print_p = true; | ||
1118 | + } | ||
1119 | + cost = model_excess_cost (insns[i], print_p); | ||
1120 | + if (cost <= 0) | ||
1121 | + { | ||
1122 | + priority = INSN_PRIORITY (insns[i]) - insn_delay (insns[i]) - cost; | ||
1123 | + priority_base = MAX (priority_base, priority); | ||
1124 | + cost = 0; | ||
1125 | + } | ||
1126 | + INSN_REG_PRESSURE_EXCESS_COST_CHANGE (insns[i]) = cost; | ||
1127 | + } | ||
1128 | + if (print_p) | ||
1129 | + fprintf (sched_dump, MODEL_BAR); | ||
1130 | + | ||
1131 | + /* Use MAX (baseECC, 0) and baseP to calculcate ECC for each | ||
1132 | + instruction. */ | ||
1133 | + for (i = 0; i < count; i++) | ||
1134 | + { | ||
1135 | + cost = INSN_REG_PRESSURE_EXCESS_COST_CHANGE (insns[i]); | ||
1136 | + priority = INSN_PRIORITY (insns[i]) - insn_delay (insns[i]); | ||
1137 | + if (cost > 0 && priority > priority_base) | ||
1138 | + { | ||
1139 | + cost += priority_base - priority; | ||
1140 | + INSN_REG_PRESSURE_EXCESS_COST_CHANGE (insns[i]) = MAX (cost, 0); | ||
1141 | + } | ||
1142 | + } | ||
1143 | +} | ||
1144 | + | ||
1145 | /* Returns a positive value if x is preferred; returns a negative value if | ||
1146 | y is preferred. Should never return 0, since that will make the sort | ||
1147 | unstable. */ | ||
1148 | @@ -1170,23 +1948,20 @@ | ||
1149 | /* Make sure that priority of TMP and TMP2 are initialized. */ | ||
1150 | gcc_assert (INSN_PRIORITY_KNOWN (tmp) && INSN_PRIORITY_KNOWN (tmp2)); | ||
1151 | |||
1152 | - if (sched_pressure_p) | ||
1153 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
1154 | { | ||
1155 | int diff; | ||
1156 | |||
1157 | /* Prefer insn whose scheduling results in the smallest register | ||
1158 | pressure excess. */ | ||
1159 | if ((diff = (INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp) | ||
1160 | - + (INSN_TICK (tmp) > clock_var | ||
1161 | - ? INSN_TICK (tmp) - clock_var : 0) | ||
1162 | + + insn_delay (tmp) | ||
1163 | - INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp2) | ||
1164 | - - (INSN_TICK (tmp2) > clock_var | ||
1165 | - ? INSN_TICK (tmp2) - clock_var : 0))) != 0) | ||
1166 | + - insn_delay (tmp2)))) | ||
1167 | return diff; | ||
1168 | } | ||
1169 | |||
1170 | - | ||
1171 | - if (sched_pressure_p | ||
1172 | + if (sched_pressure != SCHED_PRESSURE_NONE | ||
1173 | && (INSN_TICK (tmp2) > clock_var || INSN_TICK (tmp) > clock_var)) | ||
1174 | { | ||
1175 | if (INSN_TICK (tmp) <= clock_var) | ||
1176 | @@ -1277,11 +2052,22 @@ | ||
1177 | return val; | ||
1178 | } | ||
1179 | |||
1180 | + /* Prefer instructions that occur earlier in the model schedule. */ | ||
1181 | + if (sched_pressure == SCHED_PRESSURE_MODEL) | ||
1182 | + { | ||
1183 | + int diff; | ||
1184 | + | ||
1185 | + diff = model_index (tmp) - model_index (tmp2); | ||
1186 | + if (diff != 0) | ||
1187 | + return diff; | ||
1188 | + } | ||
1189 | + | ||
1190 | /* Prefer the insn which has more later insns that depend on it. | ||
1191 | This gives the scheduler more freedom when scheduling later | ||
1192 | instructions at the expense of added register pressure. */ | ||
1193 | |||
1194 | - val = (dep_list_size (tmp2) - dep_list_size (tmp)); | ||
1195 | + val = (dep_list_size (tmp2, SD_LIST_FORW) | ||
1196 | + - dep_list_size (tmp, SD_LIST_FORW)); | ||
1197 | |||
1198 | if (flag_sched_dep_count_heuristic && val != 0) | ||
1199 | return val; | ||
1200 | @@ -1480,12 +2266,15 @@ | ||
1201 | int i; | ||
1202 | rtx *first = ready_lastpos (ready); | ||
1203 | |||
1204 | - if (sched_pressure_p) | ||
1205 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED) | ||
1206 | { | ||
1207 | for (i = 0; i < ready->n_ready; i++) | ||
1208 | if (!DEBUG_INSN_P (first[i])) | ||
1209 | setup_insn_reg_pressure_info (first[i]); | ||
1210 | } | ||
1211 | + if (sched_pressure == SCHED_PRESSURE_MODEL | ||
1212 | + && model_curr_point < model_num_insns) | ||
1213 | + model_set_excess_costs (first, ready->n_ready); | ||
1214 | SCHED_SORT (first, ready->n_ready); | ||
1215 | } | ||
1216 | |||
1217 | @@ -1551,10 +2340,12 @@ | ||
1218 | gcc_checking_assert (!DEBUG_INSN_P (insn)); | ||
1219 | |||
1220 | for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use) | ||
1221 | - if (dying_use_p (use) && bitmap_bit_p (curr_reg_live, use->regno)) | ||
1222 | - mark_regno_birth_or_death (use->regno, false); | ||
1223 | + if (dying_use_p (use)) | ||
1224 | + mark_regno_birth_or_death (curr_reg_live, curr_reg_pressure, | ||
1225 | + use->regno, false); | ||
1226 | for (set = INSN_REG_SET_LIST (insn); set != NULL; set = set->next_insn_set) | ||
1227 | - mark_regno_birth_or_death (set->regno, true); | ||
1228 | + mark_regno_birth_or_death (curr_reg_live, curr_reg_pressure, | ||
1229 | + set->regno, true); | ||
1230 | } | ||
1231 | |||
1232 | /* Set up or update (if UPDATE_P) max register pressure (see its | ||
1233 | @@ -1626,11 +2417,618 @@ | ||
1234 | void | ||
1235 | sched_setup_bb_reg_pressure_info (basic_block bb, rtx after) | ||
1236 | { | ||
1237 | - gcc_assert (sched_pressure_p); | ||
1238 | + gcc_assert (sched_pressure == SCHED_PRESSURE_WEIGHTED); | ||
1239 | initiate_bb_reg_pressure_info (bb); | ||
1240 | setup_insn_max_reg_pressure (after, false); | ||
1241 | } | ||
1242 | - | ||
1243 | + | ||
1244 | +/* Return (in order): | ||
1245 | + | ||
1246 | + - positive if INSN adversely affects the pressure on one | ||
1247 | + register class | ||
1248 | + | ||
1249 | + - negative if INSN reduces the pressure on one register class | ||
1250 | + | ||
1251 | + - 0 if INSN doesn't affect the pressure on any register class. */ | ||
1252 | + | ||
1253 | +static int | ||
1254 | +model_classify_pressure (struct model_insn_info *insn) | ||
1255 | +{ | ||
1256 | + struct reg_pressure_data *reg_pressure; | ||
1257 | + int death[N_REG_CLASSES]; | ||
1258 | + int cci, cl, sum; | ||
1259 | + | ||
1260 | + calculate_reg_deaths (insn->insn, death); | ||
1261 | + reg_pressure = INSN_REG_PRESSURE (insn->insn); | ||
1262 | + sum = 0; | ||
1263 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
1264 | + { | ||
1265 | + cl = ira_reg_class_cover[cci]; | ||
1266 | + if (death[cl] < reg_pressure[cci].set_increase) | ||
1267 | + return 1; | ||
1268 | + sum += reg_pressure[cci].set_increase - death[cl]; | ||
1269 | + } | ||
1270 | + return sum; | ||
1271 | +} | ||
1272 | + | ||
1273 | +/* Return true if INSN1 should come before INSN2 in the model schedule. */ | ||
1274 | + | ||
1275 | +static int | ||
1276 | +model_order_p (struct model_insn_info *insn1, struct model_insn_info *insn2) | ||
1277 | +{ | ||
1278 | + unsigned int height1, height2; | ||
1279 | + unsigned int priority1, priority2; | ||
1280 | + | ||
1281 | + /* Prefer instructions with a higher model priority. */ | ||
1282 | + if (insn1->model_priority != insn2->model_priority) | ||
1283 | + return insn1->model_priority > insn2->model_priority; | ||
1284 | + | ||
1285 | + /* Combine the length of the longest path of satisfied true dependencies | ||
1286 | + that leads to each instruction (depth) with the length of the longest | ||
1287 | + path of any dependencies that leads from the instruction (alap). | ||
1288 | + Prefer instructions with the greatest combined length. If the combined | ||
1289 | + lengths are equal, prefer instructions with the greatest depth. | ||
1290 | + | ||
1291 | + The idea is that, if we have a set S of "equal" instructions that each | ||
1292 | + have ALAP value X, and we pick one such instruction I, any true-dependent | ||
1293 | + successors of I that have ALAP value X - 1 should be preferred over S. | ||
1294 | + This encourages the schedule to be "narrow" rather than "wide". | ||
1295 | + However, if I is a low-priority instruction that we decided to | ||
1296 | + schedule because of its model_classify_pressure, and if there | ||
1297 | + is a set of higher-priority instructions T, the aforementioned | ||
1298 | + successors of I should not have the edge over T. */ | ||
1299 | + height1 = insn1->depth + insn1->alap; | ||
1300 | + height2 = insn2->depth + insn2->alap; | ||
1301 | + if (height1 != height2) | ||
1302 | + return height1 > height2; | ||
1303 | + if (insn1->depth != insn2->depth) | ||
1304 | + return insn1->depth > insn2->depth; | ||
1305 | + | ||
1306 | + /* We have no real preference between INSN1 an INSN2 as far as attempts | ||
1307 | + to reduce pressure go. Prefer instructions with higher priorities. */ | ||
1308 | + priority1 = INSN_PRIORITY (insn1->insn); | ||
1309 | + priority2 = INSN_PRIORITY (insn2->insn); | ||
1310 | + if (priority1 != priority2) | ||
1311 | + return priority1 > priority2; | ||
1312 | + | ||
1313 | + /* Use the original rtl sequence as a tie-breaker. */ | ||
1314 | + return insn1 < insn2; | ||
1315 | +} | ||
1316 | + | ||
1317 | +/* Add INSN to the model worklist immediately after PREV. Add it to the | ||
1318 | + beginning of the list if PREV is null. */ | ||
1319 | + | ||
1320 | +static void | ||
1321 | +model_add_to_worklist_at (struct model_insn_info *insn, | ||
1322 | + struct model_insn_info *prev) | ||
1323 | +{ | ||
1324 | + gcc_assert (QUEUE_INDEX (insn->insn) == QUEUE_NOWHERE); | ||
1325 | + QUEUE_INDEX (insn->insn) = QUEUE_READY; | ||
1326 | + | ||
1327 | + insn->prev = prev; | ||
1328 | + if (prev) | ||
1329 | + { | ||
1330 | + insn->next = prev->next; | ||
1331 | + prev->next = insn; | ||
1332 | + } | ||
1333 | + else | ||
1334 | + { | ||
1335 | + insn->next = model_worklist; | ||
1336 | + model_worklist = insn; | ||
1337 | + } | ||
1338 | + if (insn->next) | ||
1339 | + insn->next->prev = insn; | ||
1340 | +} | ||
1341 | + | ||
1342 | +/* Remove INSN from the model worklist. */ | ||
1343 | + | ||
1344 | +static void | ||
1345 | +model_remove_from_worklist (struct model_insn_info *insn) | ||
1346 | +{ | ||
1347 | + gcc_assert (QUEUE_INDEX (insn->insn) == QUEUE_READY); | ||
1348 | + QUEUE_INDEX (insn->insn) = QUEUE_NOWHERE; | ||
1349 | + | ||
1350 | + if (insn->prev) | ||
1351 | + insn->prev->next = insn->next; | ||
1352 | + else | ||
1353 | + model_worklist = insn->next; | ||
1354 | + if (insn->next) | ||
1355 | + insn->next->prev = insn->prev; | ||
1356 | +} | ||
1357 | + | ||
1358 | +/* Add INSN to the model worklist. Start looking for a suitable position | ||
1359 | + between neighbors PREV and NEXT, testing at most MAX_SCHED_READY_INSNS | ||
1360 | + insns either side. A null PREV indicates the beginning of the list and | ||
1361 | + a null NEXT indicates the end. */ | ||
1362 | + | ||
1363 | +static void | ||
1364 | +model_add_to_worklist (struct model_insn_info *insn, | ||
1365 | + struct model_insn_info *prev, | ||
1366 | + struct model_insn_info *next) | ||
1367 | +{ | ||
1368 | + int count; | ||
1369 | + | ||
1370 | + count = MAX_SCHED_READY_INSNS; | ||
1371 | + if (count > 0 && prev && model_order_p (insn, prev)) | ||
1372 | + do | ||
1373 | + { | ||
1374 | + count--; | ||
1375 | + prev = prev->prev; | ||
1376 | + } | ||
1377 | + while (count > 0 && prev && model_order_p (insn, prev)); | ||
1378 | + else | ||
1379 | + while (count > 0 && next && model_order_p (next, insn)) | ||
1380 | + { | ||
1381 | + count--; | ||
1382 | + prev = next; | ||
1383 | + next = next->next; | ||
1384 | + } | ||
1385 | + model_add_to_worklist_at (insn, prev); | ||
1386 | +} | ||
1387 | + | ||
1388 | +/* INSN may now have a higher priority (in the model_order_p sense) | ||
1389 | + than before. Move it up the worklist if necessary. */ | ||
1390 | + | ||
1391 | +static void | ||
1392 | +model_promote_insn (struct model_insn_info *insn) | ||
1393 | +{ | ||
1394 | + struct model_insn_info *prev; | ||
1395 | + int count; | ||
1396 | + | ||
1397 | + prev = insn->prev; | ||
1398 | + count = MAX_SCHED_READY_INSNS; | ||
1399 | + while (count > 0 && prev && model_order_p (insn, prev)) | ||
1400 | + { | ||
1401 | + count--; | ||
1402 | + prev = prev->prev; | ||
1403 | + } | ||
1404 | + if (prev != insn->prev) | ||
1405 | + { | ||
1406 | + model_remove_from_worklist (insn); | ||
1407 | + model_add_to_worklist_at (insn, prev); | ||
1408 | + } | ||
1409 | +} | ||
1410 | + | ||
1411 | +/* Add INSN to the end of the model schedule. */ | ||
1412 | + | ||
1413 | +static void | ||
1414 | +model_add_to_schedule (rtx insn) | ||
1415 | +{ | ||
1416 | + unsigned int point; | ||
1417 | + | ||
1418 | + gcc_assert (QUEUE_INDEX (insn) == QUEUE_NOWHERE); | ||
1419 | + QUEUE_INDEX (insn) = QUEUE_SCHEDULED; | ||
1420 | + | ||
1421 | + point = VEC_length (rtx, model_schedule); | ||
1422 | + VEC_quick_push (rtx, model_schedule, insn); | ||
1423 | + INSN_MODEL_INDEX (insn) = point + 1; | ||
1424 | +} | ||
1425 | + | ||
1426 | +/* Analyze the instructions that are to be scheduled, setting up | ||
1427 | + MODEL_INSN_INFO (...) and model_num_insns accordingly. Add ready | ||
1428 | + instructions to model_worklist. */ | ||
1429 | + | ||
1430 | +static void | ||
1431 | +model_analyze_insns (void) | ||
1432 | +{ | ||
1433 | + rtx start, end, iter; | ||
1434 | + sd_iterator_def sd_it; | ||
1435 | + dep_t dep; | ||
1436 | + struct model_insn_info *insn, *con; | ||
1437 | + | ||
1438 | + model_num_insns = 0; | ||
1439 | + start = PREV_INSN (current_sched_info->next_tail); | ||
1440 | + end = current_sched_info->prev_head; | ||
1441 | + for (iter = start; iter != end; iter = PREV_INSN (iter)) | ||
1442 | + if (NONDEBUG_INSN_P (iter)) | ||
1443 | + { | ||
1444 | + insn = MODEL_INSN_INFO (iter); | ||
1445 | + insn->insn = iter; | ||
1446 | + FOR_EACH_DEP (iter, SD_LIST_FORW, sd_it, dep) | ||
1447 | + { | ||
1448 | + con = MODEL_INSN_INFO (DEP_CON (dep)); | ||
1449 | + if (con->insn && insn->alap < con->alap + 1) | ||
1450 | + insn->alap = con->alap + 1; | ||
1451 | + } | ||
1452 | + | ||
1453 | + insn->old_queue = QUEUE_INDEX (iter); | ||
1454 | + QUEUE_INDEX (iter) = QUEUE_NOWHERE; | ||
1455 | + | ||
1456 | + insn->unscheduled_preds = dep_list_size (iter, SD_LIST_HARD_BACK); | ||
1457 | + if (insn->unscheduled_preds == 0) | ||
1458 | + model_add_to_worklist (insn, NULL, model_worklist); | ||
1459 | + | ||
1460 | + model_num_insns++; | ||
1461 | + } | ||
1462 | +} | ||
1463 | + | ||
1464 | +/* The global state describes the register pressure at the start of the | ||
1465 | + model schedule. Initialize GROUP accordingly. */ | ||
1466 | + | ||
1467 | +static void | ||
1468 | +model_init_pressure_group (struct model_pressure_group *group) | ||
1469 | +{ | ||
1470 | + int cci, cl; | ||
1471 | + | ||
1472 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
1473 | + { | ||
1474 | + cl = ira_reg_class_cover[cci]; | ||
1475 | + group->limits[cci].pressure = curr_reg_pressure[cl]; | ||
1476 | + group->limits[cci].point = 0; | ||
1477 | + } | ||
1478 | + /* Use index model_num_insns to record the state after the last | ||
1479 | + instruction in the model schedule. */ | ||
1480 | + group->model = XNEWVEC (struct model_pressure_data, | ||
1481 | + (model_num_insns + 1) * ira_reg_class_cover_size); | ||
1482 | +} | ||
1483 | + | ||
1484 | +/* Record that MODEL_REF_PRESSURE (GROUP, POINT, CCI) is PRESSURE. | ||
1485 | + Update the maximum pressure for the whole schedule. */ | ||
1486 | + | ||
1487 | +static void | ||
1488 | +model_record_pressure (struct model_pressure_group *group, | ||
1489 | + int point, int cci, int pressure) | ||
1490 | +{ | ||
1491 | + MODEL_REF_PRESSURE (group, point, cci) = pressure; | ||
1492 | + if (group->limits[cci].pressure < pressure) | ||
1493 | + { | ||
1494 | + group->limits[cci].pressure = pressure; | ||
1495 | + group->limits[cci].point = point; | ||
1496 | + } | ||
1497 | +} | ||
1498 | + | ||
1499 | +/* INSN has just been added to the end of the model schedule. Record its | ||
1500 | + register-pressure information. */ | ||
1501 | + | ||
1502 | +static void | ||
1503 | +model_record_pressures (struct model_insn_info *insn) | ||
1504 | +{ | ||
1505 | + struct reg_pressure_data *reg_pressure; | ||
1506 | + int point, cci, cl, delta; | ||
1507 | + int death[N_REG_CLASSES]; | ||
1508 | + | ||
1509 | + point = model_index (insn->insn); | ||
1510 | + if (sched_verbose >= 2) | ||
1511 | + { | ||
1512 | + char buf[2048]; | ||
1513 | + | ||
1514 | + if (point == 0) | ||
1515 | + { | ||
1516 | + fprintf (sched_dump, "\n;;\tModel schedule:\n;;\n"); | ||
1517 | + fprintf (sched_dump, ";;\t| idx insn | mpri hght dpth prio |\n"); | ||
1518 | + } | ||
1519 | + print_pattern (buf, PATTERN (insn->insn), 0); | ||
1520 | + fprintf (sched_dump, ";;\t| %3d %4d | %4d %4d %4d %4d | %-30s ", | ||
1521 | + point, INSN_UID (insn->insn), insn->model_priority, | ||
1522 | + insn->depth + insn->alap, insn->depth, | ||
1523 | + INSN_PRIORITY (insn->insn), buf); | ||
1524 | + } | ||
1525 | + calculate_reg_deaths (insn->insn, death); | ||
1526 | + reg_pressure = INSN_REG_PRESSURE (insn->insn); | ||
1527 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
1528 | + { | ||
1529 | + cl = ira_reg_class_cover[cci]; | ||
1530 | + delta = reg_pressure[cci].set_increase - death[cl]; | ||
1531 | + if (sched_verbose >= 2) | ||
1532 | + fprintf (sched_dump, " %s:[%d,%+d]", reg_class_names[cl], | ||
1533 | + curr_reg_pressure[cl], delta); | ||
1534 | + model_record_pressure (&model_before_pressure, point, cci, | ||
1535 | + curr_reg_pressure[cl]); | ||
1536 | + } | ||
1537 | + if (sched_verbose >= 2) | ||
1538 | + fprintf (sched_dump, "\n"); | ||
1539 | +} | ||
1540 | + | ||
1541 | +/* All instructions have been added to the model schedule. Record the | ||
1542 | + final register pressure in GROUP and set up all MODEL_MAX_PRESSUREs. */ | ||
1543 | + | ||
1544 | +static void | ||
1545 | +model_record_final_pressures (struct model_pressure_group *group) | ||
1546 | +{ | ||
1547 | + int point, cci, max_pressure, ref_pressure, cl; | ||
1548 | + | ||
1549 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
1550 | + { | ||
1551 | + /* Record the final pressure for this class. */ | ||
1552 | + cl = ira_reg_class_cover[cci]; | ||
1553 | + point = model_num_insns; | ||
1554 | + ref_pressure = curr_reg_pressure[cl]; | ||
1555 | + model_record_pressure (group, point, cci, ref_pressure); | ||
1556 | + | ||
1557 | + /* Record the original maximum pressure. */ | ||
1558 | + group->limits[cci].orig_pressure = group->limits[cci].pressure; | ||
1559 | + | ||
1560 | + /* Update the MODEL_MAX_PRESSURE for every point of the schedule. */ | ||
1561 | + max_pressure = ref_pressure; | ||
1562 | + MODEL_MAX_PRESSURE (group, point, cci) = max_pressure; | ||
1563 | + while (point > 0) | ||
1564 | + { | ||
1565 | + point--; | ||
1566 | + ref_pressure = MODEL_REF_PRESSURE (group, point, cci); | ||
1567 | + max_pressure = MAX (max_pressure, ref_pressure); | ||
1568 | + MODEL_MAX_PRESSURE (group, point, cci) = max_pressure; | ||
1569 | + } | ||
1570 | + } | ||
1571 | +} | ||
1572 | + | ||
1573 | +/* Update all successors of INSN, given that INSN has just been scheduled. */ | ||
1574 | + | ||
1575 | +static void | ||
1576 | +model_add_successors_to_worklist (struct model_insn_info *insn) | ||
1577 | +{ | ||
1578 | + sd_iterator_def sd_it; | ||
1579 | + struct model_insn_info *con; | ||
1580 | + dep_t dep; | ||
1581 | + | ||
1582 | + FOR_EACH_DEP (insn->insn, SD_LIST_FORW, sd_it, dep) | ||
1583 | + { | ||
1584 | + con = MODEL_INSN_INFO (DEP_CON (dep)); | ||
1585 | + /* Ignore debug instructions, and instructions from other blocks. */ | ||
1586 | + if (con->insn) | ||
1587 | + { | ||
1588 | + con->unscheduled_preds--; | ||
1589 | + | ||
1590 | + /* Update the depth field of each true-dependent successor. | ||
1591 | + Increasing the depth gives them a higher priority than | ||
1592 | + before. */ | ||
1593 | + if (DEP_TYPE (dep) == REG_DEP_TRUE && con->depth < insn->depth + 1) | ||
1594 | + { | ||
1595 | + con->depth = insn->depth + 1; | ||
1596 | + if (QUEUE_INDEX (con->insn) == QUEUE_READY) | ||
1597 | + model_promote_insn (con); | ||
1598 | + } | ||
1599 | + | ||
1600 | + /* If this is a true dependency, or if there are no remaining | ||
1601 | + dependencies for CON (meaning that CON only had non-true | ||
1602 | + dependencies), make sure that CON is on the worklist. | ||
1603 | + We don't bother otherwise because it would tend to fill the | ||
1604 | + worklist with a lot of low-priority instructions that are not | ||
1605 | + yet ready to issue. */ | ||
1606 | + if ((con->depth > 0 || con->unscheduled_preds == 0) | ||
1607 | + && QUEUE_INDEX (con->insn) == QUEUE_NOWHERE) | ||
1608 | + model_add_to_worklist (con, insn, insn->next); | ||
1609 | + } | ||
1610 | + } | ||
1611 | +} | ||
1612 | + | ||
1613 | +/* Give INSN a higher priority than any current instruction, then give | ||
1614 | + unscheduled predecessors of INSN a higher priority still. If any of | ||
1615 | + those predecessors are not on the model worklist, do the same for its | ||
1616 | + predecessors, and so on. */ | ||
1617 | + | ||
1618 | +static void | ||
1619 | +model_promote_predecessors (struct model_insn_info *insn) | ||
1620 | +{ | ||
1621 | + struct model_insn_info *pro, *first; | ||
1622 | + sd_iterator_def sd_it; | ||
1623 | + dep_t dep; | ||
1624 | + | ||
1625 | + if (sched_verbose >= 7) | ||
1626 | + fprintf (sched_dump, ";;\t+--- priority of %d = %d, priority of", | ||
1627 | + INSN_UID (insn->insn), model_next_priority); | ||
1628 | + insn->model_priority = model_next_priority++; | ||
1629 | + model_remove_from_worklist (insn); | ||
1630 | + model_add_to_worklist_at (insn, NULL); | ||
1631 | + | ||
1632 | + first = NULL; | ||
1633 | + for (;;) | ||
1634 | + { | ||
1635 | + FOR_EACH_DEP (insn->insn, SD_LIST_HARD_BACK, sd_it, dep) | ||
1636 | + { | ||
1637 | + pro = MODEL_INSN_INFO (DEP_PRO (dep)); | ||
1638 | + /* The first test is to ignore debug instructions, and instructions | ||
1639 | + from other blocks. */ | ||
1640 | + if (pro->insn | ||
1641 | + && pro->model_priority != model_next_priority | ||
1642 | + && QUEUE_INDEX (pro->insn) != QUEUE_SCHEDULED) | ||
1643 | + { | ||
1644 | + pro->model_priority = model_next_priority; | ||
1645 | + if (sched_verbose >= 7) | ||
1646 | + fprintf (sched_dump, " %d", INSN_UID (pro->insn)); | ||
1647 | + if (QUEUE_INDEX (pro->insn) == QUEUE_READY) | ||
1648 | + { | ||
1649 | + /* PRO is already in the worklist, but it now has | ||
1650 | + a higher priority than before. Move it at the | ||
1651 | + appropriate place. */ | ||
1652 | + model_remove_from_worklist (pro); | ||
1653 | + model_add_to_worklist (pro, NULL, model_worklist); | ||
1654 | + } | ||
1655 | + else | ||
1656 | + { | ||
1657 | + /* PRO isn't in the worklist. Recursively process | ||
1658 | + its predecessors until we find one that is. */ | ||
1659 | + pro->next = first; | ||
1660 | + first = pro; | ||
1661 | + } | ||
1662 | + } | ||
1663 | + } | ||
1664 | + if (!first) | ||
1665 | + break; | ||
1666 | + insn = first; | ||
1667 | + first = insn->next; | ||
1668 | + } | ||
1669 | + if (sched_verbose >= 7) | ||
1670 | + fprintf (sched_dump, " = %d\n", model_next_priority); | ||
1671 | + model_next_priority++; | ||
1672 | +} | ||
1673 | + | ||
1674 | +/* Pick one instruction from model_worklist and process it. */ | ||
1675 | + | ||
1676 | +static void | ||
1677 | +model_choose_insn (void) | ||
1678 | +{ | ||
1679 | + struct model_insn_info *insn, *fallback; | ||
1680 | + int count; | ||
1681 | + | ||
1682 | + if (sched_verbose >= 7) | ||
1683 | + { | ||
1684 | + fprintf (sched_dump, ";;\t+--- worklist:\n"); | ||
1685 | + insn = model_worklist; | ||
1686 | + count = MAX_SCHED_READY_INSNS; | ||
1687 | + while (count > 0 && insn) | ||
1688 | + { | ||
1689 | + fprintf (sched_dump, ";;\t+--- %d [%d, %d, %d, %d]\n", | ||
1690 | + INSN_UID (insn->insn), insn->model_priority, | ||
1691 | + insn->depth + insn->alap, insn->depth, | ||
1692 | + INSN_PRIORITY (insn->insn)); | ||
1693 | + count--; | ||
1694 | + insn = insn->next; | ||
1695 | + } | ||
1696 | + } | ||
1697 | + | ||
1698 | + /* Look for a ready instruction whose model_classify_priority is zero | ||
1699 | + or negative, picking the highest-priority one. Adding such an | ||
1700 | + instruction to the schedule now should do no harm, and may actually | ||
1701 | + do some good. | ||
1702 | + | ||
1703 | + Failing that, see whether there is an instruction with the highest | ||
1704 | + extant model_priority that is not yet ready, but which would reduce | ||
1705 | + pressure if it became ready. This is designed to catch cases like: | ||
1706 | + | ||
1707 | + (set (mem (reg R1)) (reg R2)) | ||
1708 | + | ||
1709 | + where the instruction is the last remaining use of R1 and where the | ||
1710 | + value of R2 is not yet available (or vice versa). The death of R1 | ||
1711 | + means that this instruction already reduces pressure. It is of | ||
1712 | + course possible that the computation of R2 involves other registers | ||
1713 | + that are hard to kill, but such cases are rare enough for this | ||
1714 | + heuristic to be a win in general. | ||
1715 | + | ||
1716 | + Failing that, just pick the highest-priority instruction in the | ||
1717 | + worklist. */ | ||
1718 | + count = MAX_SCHED_READY_INSNS; | ||
1719 | + insn = model_worklist; | ||
1720 | + fallback = 0; | ||
1721 | + for (;;) | ||
1722 | + { | ||
1723 | + if (count == 0 || !insn) | ||
1724 | + { | ||
1725 | + insn = fallback ? fallback : model_worklist; | ||
1726 | + break; | ||
1727 | + } | ||
1728 | + if (insn->unscheduled_preds) | ||
1729 | + { | ||
1730 | + if (model_worklist->model_priority == insn->model_priority | ||
1731 | + && !fallback | ||
1732 | + && model_classify_pressure (insn) < 0) | ||
1733 | + fallback = insn; | ||
1734 | + } | ||
1735 | + else | ||
1736 | + { | ||
1737 | + if (model_classify_pressure (insn) <= 0) | ||
1738 | + break; | ||
1739 | + } | ||
1740 | + count--; | ||
1741 | + insn = insn->next; | ||
1742 | + } | ||
1743 | + | ||
1744 | + if (sched_verbose >= 7 && insn != model_worklist) | ||
1745 | + { | ||
1746 | + if (insn->unscheduled_preds) | ||
1747 | + fprintf (sched_dump, ";;\t+--- promoting insn %d, with dependencies\n", | ||
1748 | + INSN_UID (insn->insn)); | ||
1749 | + else | ||
1750 | + fprintf (sched_dump, ";;\t+--- promoting insn %d, which is ready\n", | ||
1751 | + INSN_UID (insn->insn)); | ||
1752 | + } | ||
1753 | + if (insn->unscheduled_preds) | ||
1754 | + /* INSN isn't yet ready to issue. Give all its predecessors the | ||
1755 | + highest priority. */ | ||
1756 | + model_promote_predecessors (insn); | ||
1757 | + else | ||
1758 | + { | ||
1759 | + /* INSN is ready. Add it to the end of model_schedule and | ||
1760 | + process its successors. */ | ||
1761 | + model_add_successors_to_worklist (insn); | ||
1762 | + model_remove_from_worklist (insn); | ||
1763 | + model_add_to_schedule (insn->insn); | ||
1764 | + model_record_pressures (insn); | ||
1765 | + update_register_pressure (insn->insn); | ||
1766 | + } | ||
1767 | +} | ||
1768 | + | ||
1769 | +/* Restore all QUEUE_INDEXs to the values that they had before | ||
1770 | + model_start_schedule was called. */ | ||
1771 | + | ||
1772 | +static void | ||
1773 | +model_reset_queue_indices (void) | ||
1774 | +{ | ||
1775 | + unsigned int i; | ||
1776 | + rtx insn; | ||
1777 | + | ||
1778 | + FOR_EACH_VEC_ELT (rtx, model_schedule, i, insn) | ||
1779 | + QUEUE_INDEX (insn) = MODEL_INSN_INFO (insn)->old_queue; | ||
1780 | +} | ||
1781 | + | ||
1782 | +/* We have calculated the model schedule and spill costs. Print a summary | ||
1783 | + to sched_dump. */ | ||
1784 | + | ||
1785 | +static void | ||
1786 | +model_dump_pressure_summary (void) | ||
1787 | +{ | ||
1788 | + int cci, cl; | ||
1789 | + | ||
1790 | + fprintf (sched_dump, ";; Pressure summary:"); | ||
1791 | + for (cci = 0; cci < ira_reg_class_cover_size; cci++) | ||
1792 | + { | ||
1793 | + cl = ira_reg_class_cover[cci]; | ||
1794 | + fprintf (sched_dump, " %s:%d", reg_class_names[cl], | ||
1795 | + model_before_pressure.limits[cci].pressure); | ||
1796 | + } | ||
1797 | + fprintf (sched_dump, "\n\n"); | ||
1798 | +} | ||
1799 | + | ||
1800 | +/* Initialize the SCHED_PRESSURE_MODEL information for the current | ||
1801 | + scheduling region. */ | ||
1802 | + | ||
1803 | +static void | ||
1804 | +model_start_schedule (void) | ||
1805 | +{ | ||
1806 | + basic_block bb; | ||
1807 | + | ||
1808 | + model_next_priority = 1; | ||
1809 | + model_schedule = VEC_alloc (rtx, heap, sched_max_luid); | ||
1810 | + model_insns = XCNEWVEC (struct model_insn_info, sched_max_luid); | ||
1811 | + | ||
1812 | + bb = BLOCK_FOR_INSN (NEXT_INSN (current_sched_info->prev_head)); | ||
1813 | + initiate_reg_pressure_info (df_get_live_in (bb)); | ||
1814 | + | ||
1815 | + model_analyze_insns (); | ||
1816 | + model_init_pressure_group (&model_before_pressure); | ||
1817 | + while (model_worklist) | ||
1818 | + model_choose_insn (); | ||
1819 | + gcc_assert (model_num_insns == (int) VEC_length (rtx, model_schedule)); | ||
1820 | + if (sched_verbose >= 2) | ||
1821 | + fprintf (sched_dump, "\n"); | ||
1822 | + | ||
1823 | + model_record_final_pressures (&model_before_pressure); | ||
1824 | + model_reset_queue_indices (); | ||
1825 | + | ||
1826 | + XDELETEVEC (model_insns); | ||
1827 | + | ||
1828 | + model_curr_point = 0; | ||
1829 | + initiate_reg_pressure_info (df_get_live_in (bb)); | ||
1830 | + if (sched_verbose >= 1) | ||
1831 | + model_dump_pressure_summary (); | ||
1832 | +} | ||
1833 | + | ||
1834 | +/* Free the information associated with GROUP. */ | ||
1835 | + | ||
1836 | +static void | ||
1837 | +model_finalize_pressure_group (struct model_pressure_group *group) | ||
1838 | +{ | ||
1839 | + XDELETEVEC (group->model); | ||
1840 | +} | ||
1841 | + | ||
1842 | +/* Free the information created by model_start_schedule. */ | ||
1843 | + | ||
1844 | +static void | ||
1845 | +model_end_schedule (void) | ||
1846 | +{ | ||
1847 | + model_finalize_pressure_group (&model_before_pressure); | ||
1848 | + VEC_free (rtx, heap, model_schedule); | ||
1849 | +} | ||
1850 | + | ||
1851 | /* INSN is the "currently executing insn". Launch each insn which was | ||
1852 | waiting on INSN. READY is the ready list which contains the insns | ||
1853 | that are ready to fire. CLOCK is the current cycle. The function | ||
1854 | @@ -1667,10 +3065,14 @@ | ||
1855 | reg_class_names[ira_reg_class_cover[i]], | ||
1856 | pressure_info[i].set_increase, pressure_info[i].change); | ||
1857 | } | ||
1858 | + if (sched_pressure == SCHED_PRESSURE_MODEL | ||
1859 | + && model_curr_point < model_num_insns | ||
1860 | + && model_index (insn) == model_curr_point) | ||
1861 | + fprintf (sched_dump, ":model %d", model_curr_point); | ||
1862 | fputc ('\n', sched_dump); | ||
1863 | } | ||
1864 | |||
1865 | - if (sched_pressure_p && !DEBUG_INSN_P (insn)) | ||
1866 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED && !DEBUG_INSN_P (insn)) | ||
1867 | update_reg_and_insn_max_reg_pressure (insn); | ||
1868 | |||
1869 | /* Scheduling instruction should have all its dependencies resolved and | ||
1870 | @@ -1728,6 +3130,24 @@ | ||
1871 | gcc_assert (QUEUE_INDEX (insn) == QUEUE_NOWHERE); | ||
1872 | QUEUE_INDEX (insn) = QUEUE_SCHEDULED; | ||
1873 | |||
1874 | + if (sched_pressure == SCHED_PRESSURE_MODEL | ||
1875 | + && model_curr_point < model_num_insns | ||
1876 | + && NONDEBUG_INSN_P (insn)) | ||
1877 | + { | ||
1878 | + if (model_index (insn) == model_curr_point) | ||
1879 | + do | ||
1880 | + model_curr_point++; | ||
1881 | + while (model_curr_point < model_num_insns | ||
1882 | + && (QUEUE_INDEX (MODEL_INSN (model_curr_point)) | ||
1883 | + == QUEUE_SCHEDULED)); | ||
1884 | + else | ||
1885 | + model_recompute (insn); | ||
1886 | + model_update_limit_points (); | ||
1887 | + update_register_pressure (insn); | ||
1888 | + if (sched_verbose >= 2) | ||
1889 | + print_curr_reg_pressure (); | ||
1890 | + } | ||
1891 | + | ||
1892 | gcc_assert (INSN_TICK (insn) >= MIN_TICK); | ||
1893 | if (INSN_TICK (insn) > clock_var) | ||
1894 | /* INSN has been prematurely moved from the queue to the ready list. | ||
1895 | @@ -2056,7 +3476,16 @@ | ||
1896 | /* If the ready list is full, delay the insn for 1 cycle. | ||
1897 | See the comment in schedule_block for the rationale. */ | ||
1898 | if (!reload_completed | ||
1899 | - && ready->n_ready - ready->n_debug > MAX_SCHED_READY_INSNS | ||
1900 | + && (ready->n_ready - ready->n_debug > MAX_SCHED_READY_INSNS | ||
1901 | + || (sched_pressure == SCHED_PRESSURE_MODEL | ||
1902 | + /* Limit pressure recalculations to MAX_SCHED_READY_INSNS | ||
1903 | + instructions too. */ | ||
1904 | + && model_index (insn) > (model_curr_point | ||
1905 | + + MAX_SCHED_READY_INSNS))) | ||
1906 | + && !(sched_pressure == SCHED_PRESSURE_MODEL | ||
1907 | + && model_curr_point < model_num_insns | ||
1908 | + /* Always allow the next model instruction to issue. */ | ||
1909 | + && model_index (insn) == model_curr_point) | ||
1910 | && !SCHED_GROUP_P (insn) | ||
1911 | && insn != skip_insn) | ||
1912 | { | ||
1913 | @@ -2293,12 +3722,12 @@ | ||
1914 | fprintf (sched_dump, " %s:%d", | ||
1915 | (*current_sched_info->print_insn) (p[i], 0), | ||
1916 | INSN_LUID (p[i])); | ||
1917 | - if (sched_pressure_p) | ||
1918 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
1919 | fprintf (sched_dump, "(cost=%d", | ||
1920 | INSN_REG_PRESSURE_EXCESS_COST_CHANGE (p[i])); | ||
1921 | if (INSN_TICK (p[i]) > clock_var) | ||
1922 | fprintf (sched_dump, ":delay=%d", INSN_TICK (p[i]) - clock_var); | ||
1923 | - if (sched_pressure_p) | ||
1924 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
1925 | fprintf (sched_dump, ")"); | ||
1926 | } | ||
1927 | fprintf (sched_dump, "\n"); | ||
1928 | @@ -2609,8 +4038,8 @@ | ||
1929 | { | ||
1930 | if (state_dead_lock_p (state) | ||
1931 | || insn_finishes_cycle_p (insn)) | ||
1932 | - /* We won't issue any more instructions in the next | ||
1933 | - choice_state. */ | ||
1934 | + /* We won't issue any more instructions in the next | ||
1935 | + choice_state. */ | ||
1936 | top->rest = 0; | ||
1937 | else | ||
1938 | top->rest--; | ||
1939 | @@ -2813,6 +4242,59 @@ | ||
1940 | } | ||
1941 | } | ||
1942 | |||
1943 | +/* Examine all insns on the ready list and queue those which can't be | ||
1944 | + issued in this cycle. TEMP_STATE is temporary scheduler state we | ||
1945 | + can use as scratch space. If FIRST_CYCLE_INSN_P is true, no insns | ||
1946 | + have been issued for the current cycle, which means it is valid to | ||
1947 | + issue an asm statement. */ | ||
1948 | + | ||
1949 | +static void | ||
1950 | +prune_ready_list (state_t temp_state, bool first_cycle_insn_p) | ||
1951 | +{ | ||
1952 | + int i; | ||
1953 | + | ||
1954 | + restart: | ||
1955 | + for (i = 0; i < ready.n_ready; i++) | ||
1956 | + { | ||
1957 | + rtx insn = ready_element (&ready, i); | ||
1958 | + int cost = 0; | ||
1959 | + | ||
1960 | + if (recog_memoized (insn) < 0) | ||
1961 | + { | ||
1962 | + if (!first_cycle_insn_p | ||
1963 | + && (GET_CODE (PATTERN (insn)) == ASM_INPUT | ||
1964 | + || asm_noperands (PATTERN (insn)) >= 0)) | ||
1965 | + cost = 1; | ||
1966 | + } | ||
1967 | + else if (sched_pressure != SCHED_PRESSURE_NONE) | ||
1968 | + { | ||
1969 | + if (sched_pressure == SCHED_PRESSURE_MODEL | ||
1970 | + && INSN_TICK (insn) <= clock_var) | ||
1971 | + { | ||
1972 | + memcpy (temp_state, curr_state, dfa_state_size); | ||
1973 | + if (state_transition (temp_state, insn) >= 0) | ||
1974 | + INSN_TICK (insn) = clock_var + 1; | ||
1975 | + } | ||
1976 | + cost = 0; | ||
1977 | + } | ||
1978 | + else | ||
1979 | + { | ||
1980 | + memcpy (temp_state, curr_state, dfa_state_size); | ||
1981 | + cost = state_transition (temp_state, insn); | ||
1982 | + if (cost < 0) | ||
1983 | + cost = 0; | ||
1984 | + else if (cost == 0) | ||
1985 | + cost = 1; | ||
1986 | + } | ||
1987 | + if (cost >= 1) | ||
1988 | + { | ||
1989 | + ready_remove (&ready, i); | ||
1990 | + queue_insn (insn, cost); | ||
1991 | + goto restart; | ||
1992 | + } | ||
1993 | + } | ||
1994 | +} | ||
1995 | + | ||
1996 | /* Use forward list scheduling to rearrange insns of block pointed to by | ||
1997 | TARGET_BB, possibly bringing insns from subsequent blocks in the same | ||
1998 | region. */ | ||
1999 | @@ -2882,6 +4364,9 @@ | ||
2000 | in try_ready () (which is called through init_ready_list ()). */ | ||
2001 | (*current_sched_info->init_ready_list) (); | ||
2002 | |||
2003 | + if (sched_pressure == SCHED_PRESSURE_MODEL) | ||
2004 | + model_start_schedule (); | ||
2005 | + | ||
2006 | /* The algorithm is O(n^2) in the number of ready insns at any given | ||
2007 | time in the worst case. Before reload we are more likely to have | ||
2008 | big lists so truncate them to a reasonable size. */ | ||
2009 | @@ -2963,6 +4448,10 @@ | ||
2010 | } | ||
2011 | while (advance > 0); | ||
2012 | |||
2013 | + prune_ready_list (temp_state, true); | ||
2014 | + if (ready.n_ready == 0) | ||
2015 | + continue; | ||
2016 | + | ||
2017 | if (sort_p) | ||
2018 | { | ||
2019 | /* Sort the ready list based on priority. */ | ||
2020 | @@ -3040,7 +4529,7 @@ | ||
2021 | fprintf (sched_dump, ";;\tReady list (t = %3d): ", | ||
2022 | clock_var); | ||
2023 | debug_ready_list (&ready); | ||
2024 | - if (sched_pressure_p) | ||
2025 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED) | ||
2026 | print_curr_reg_pressure (); | ||
2027 | } | ||
2028 | |||
2029 | @@ -3084,7 +4573,8 @@ | ||
2030 | else | ||
2031 | insn = ready_remove_first (&ready); | ||
2032 | |||
2033 | - if (sched_pressure_p && INSN_TICK (insn) > clock_var) | ||
2034 | + if (sched_pressure != SCHED_PRESSURE_NONE | ||
2035 | + && INSN_TICK (insn) > clock_var) | ||
2036 | { | ||
2037 | ready_add (&ready, insn, true); | ||
2038 | advance = 1; | ||
2039 | @@ -3112,44 +4602,6 @@ | ||
2040 | } | ||
2041 | |||
2042 | sort_p = TRUE; | ||
2043 | - memcpy (temp_state, curr_state, dfa_state_size); | ||
2044 | - if (recog_memoized (insn) < 0) | ||
2045 | - { | ||
2046 | - asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT | ||
2047 | - || asm_noperands (PATTERN (insn)) >= 0); | ||
2048 | - if (!first_cycle_insn_p && asm_p) | ||
2049 | - /* This is asm insn which is tried to be issued on the | ||
2050 | - cycle not first. Issue it on the next cycle. */ | ||
2051 | - cost = 1; | ||
2052 | - else | ||
2053 | - /* A USE insn, or something else we don't need to | ||
2054 | - understand. We can't pass these directly to | ||
2055 | - state_transition because it will trigger a | ||
2056 | - fatal error for unrecognizable insns. */ | ||
2057 | - cost = 0; | ||
2058 | - } | ||
2059 | - else if (sched_pressure_p) | ||
2060 | - cost = 0; | ||
2061 | - else | ||
2062 | - { | ||
2063 | - cost = state_transition (temp_state, insn); | ||
2064 | - if (cost < 0) | ||
2065 | - cost = 0; | ||
2066 | - else if (cost == 0) | ||
2067 | - cost = 1; | ||
2068 | - } | ||
2069 | - | ||
2070 | - if (cost >= 1) | ||
2071 | - { | ||
2072 | - queue_insn (insn, cost); | ||
2073 | - if (SCHED_GROUP_P (insn)) | ||
2074 | - { | ||
2075 | - advance = cost; | ||
2076 | - break; | ||
2077 | - } | ||
2078 | - | ||
2079 | - continue; | ||
2080 | - } | ||
2081 | |||
2082 | if (current_sched_info->can_schedule_ready_p | ||
2083 | && ! (*current_sched_info->can_schedule_ready_p) (insn)) | ||
2084 | @@ -3200,11 +4652,17 @@ | ||
2085 | reemit_notes (insn); | ||
2086 | last_scheduled_insn = insn; | ||
2087 | |||
2088 | - if (memcmp (curr_state, temp_state, dfa_state_size) != 0) | ||
2089 | - { | ||
2090 | - cycle_issued_insns++; | ||
2091 | - memcpy (curr_state, temp_state, dfa_state_size); | ||
2092 | - } | ||
2093 | + if (recog_memoized (insn) >= 0) | ||
2094 | + { | ||
2095 | + cost = state_transition (curr_state, insn); | ||
2096 | + if (sched_pressure != SCHED_PRESSURE_WEIGHTED) | ||
2097 | + gcc_assert (cost < 0); | ||
2098 | + cycle_issued_insns++; | ||
2099 | + asm_p = false; | ||
2100 | + } | ||
2101 | + else | ||
2102 | + asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT | ||
2103 | + || asm_noperands (PATTERN (insn)) >= 0); | ||
2104 | |||
2105 | if (targetm.sched.variable_issue) | ||
2106 | can_issue_more = | ||
2107 | @@ -3225,6 +4683,9 @@ | ||
2108 | |||
2109 | first_cycle_insn_p = false; | ||
2110 | |||
2111 | + if (ready.n_ready > 0) | ||
2112 | + prune_ready_list (temp_state, false); | ||
2113 | + | ||
2114 | /* Sort the ready list based on priority. This must be | ||
2115 | redone here, as schedule_insn may have readied additional | ||
2116 | insns that will not be sorted correctly. */ | ||
2117 | @@ -3321,6 +4782,9 @@ | ||
2118 | } | ||
2119 | } | ||
2120 | |||
2121 | + if (sched_pressure == SCHED_PRESSURE_MODEL) | ||
2122 | + model_end_schedule (); | ||
2123 | + | ||
2124 | if (sched_verbose) | ||
2125 | fprintf (sched_dump, ";; total time = %d\n", clock_var); | ||
2126 | |||
2127 | @@ -3424,10 +4888,14 @@ | ||
2128 | if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON)) | ||
2129 | targetm.sched.dispatch_do (NULL_RTX, DISPATCH_INIT); | ||
2130 | |||
2131 | - sched_pressure_p = (flag_sched_pressure && ! reload_completed | ||
2132 | - && common_sched_info->sched_pass_id == SCHED_RGN_PASS); | ||
2133 | + if (flag_sched_pressure | ||
2134 | + && !reload_completed | ||
2135 | + && common_sched_info->sched_pass_id == SCHED_RGN_PASS) | ||
2136 | + sched_pressure = flag_sched_pressure_algorithm; | ||
2137 | + else | ||
2138 | + sched_pressure = SCHED_PRESSURE_NONE; | ||
2139 | |||
2140 | - if (sched_pressure_p) | ||
2141 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
2142 | ira_setup_eliminable_regset (); | ||
2143 | |||
2144 | /* Initialize SPEC_INFO. */ | ||
2145 | @@ -3504,7 +4972,7 @@ | ||
2146 | if (targetm.sched.init_global) | ||
2147 | targetm.sched.init_global (sched_dump, sched_verbose, get_max_uid () + 1); | ||
2148 | |||
2149 | - if (sched_pressure_p) | ||
2150 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
2151 | { | ||
2152 | int i, max_regno = max_reg_num (); | ||
2153 | |||
2154 | @@ -3517,8 +4985,11 @@ | ||
2155 | ? ira_class_translate[REGNO_REG_CLASS (i)] | ||
2156 | : reg_cover_class (i)); | ||
2157 | curr_reg_live = BITMAP_ALLOC (NULL); | ||
2158 | - saved_reg_live = BITMAP_ALLOC (NULL); | ||
2159 | - region_ref_regs = BITMAP_ALLOC (NULL); | ||
2160 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED) | ||
2161 | + { | ||
2162 | + saved_reg_live = BITMAP_ALLOC (NULL); | ||
2163 | + region_ref_regs = BITMAP_ALLOC (NULL); | ||
2164 | + } | ||
2165 | } | ||
2166 | |||
2167 | curr_state = xmalloc (dfa_state_size); | ||
2168 | @@ -3618,12 +5089,15 @@ | ||
2169 | sched_finish (void) | ||
2170 | { | ||
2171 | haifa_finish_h_i_d (); | ||
2172 | - if (sched_pressure_p) | ||
2173 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
2174 | { | ||
2175 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED) | ||
2176 | + { | ||
2177 | + BITMAP_FREE (region_ref_regs); | ||
2178 | + BITMAP_FREE (saved_reg_live); | ||
2179 | + } | ||
2180 | + BITMAP_FREE (curr_reg_live); | ||
2181 | free (sched_regno_cover_class); | ||
2182 | - BITMAP_FREE (region_ref_regs); | ||
2183 | - BITMAP_FREE (saved_reg_live); | ||
2184 | - BITMAP_FREE (curr_reg_live); | ||
2185 | } | ||
2186 | free (curr_state); | ||
2187 | |||
2188 | @@ -3936,7 +5410,7 @@ | ||
2189 | INSN_TICK (next) = tick; | ||
2190 | |||
2191 | delay = tick - clock_var; | ||
2192 | - if (delay <= 0 || sched_pressure_p) | ||
2193 | + if (delay <= 0 || sched_pressure != SCHED_PRESSURE_NONE) | ||
2194 | delay = QUEUE_READY; | ||
2195 | |||
2196 | change_queue_index (next, delay); | ||
2197 | @@ -5185,7 +6659,7 @@ | ||
2198 | if (insn == jump) | ||
2199 | break; | ||
2200 | |||
2201 | - if (dep_list_size (insn) == 0) | ||
2202 | + if (dep_list_size (insn, SD_LIST_FORW) == 0) | ||
2203 | { | ||
2204 | dep_def _new_dep, *new_dep = &_new_dep; | ||
2205 | |||
2206 | @@ -5556,6 +7030,7 @@ | ||
2207 | |||
2208 | FOR_EACH_VEC_ELT (haifa_insn_data_def, h_i_d, i, data) | ||
2209 | { | ||
2210 | + free (data->max_reg_pressure); | ||
2211 | if (data->reg_pressure != NULL) | ||
2212 | free (data->reg_pressure); | ||
2213 | for (use = data->reg_use_list; use != NULL; use = next) | ||
2214 | |||
2215 | === modified file 'gcc/sched-deps.c' | ||
2216 | --- old/gcc/sched-deps.c 2011-12-08 13:33:58 +0000 | ||
2217 | +++ new/gcc/sched-deps.c 2012-02-08 23:39:45 +0000 | ||
2218 | @@ -450,7 +450,7 @@ | ||
2219 | static void add_dependence_list_and_free (struct deps_desc *, rtx, | ||
2220 | rtx *, int, enum reg_note); | ||
2221 | static void delete_all_dependences (rtx); | ||
2222 | -static void fixup_sched_groups (rtx); | ||
2223 | +static void chain_to_prev_insn (rtx); | ||
2224 | |||
2225 | static void flush_pending_lists (struct deps_desc *, rtx, int, int); | ||
2226 | static void sched_analyze_1 (struct deps_desc *, rtx, rtx); | ||
2227 | @@ -1490,7 +1490,7 @@ | ||
2228 | the previous nonnote insn. */ | ||
2229 | |||
2230 | static void | ||
2231 | -fixup_sched_groups (rtx insn) | ||
2232 | +chain_to_prev_insn (rtx insn) | ||
2233 | { | ||
2234 | sd_iterator_def sd_it; | ||
2235 | dep_t dep; | ||
2236 | @@ -1999,7 +1999,7 @@ | ||
2237 | static struct reg_pressure_data *pressure_info; | ||
2238 | rtx link; | ||
2239 | |||
2240 | - gcc_assert (sched_pressure_p); | ||
2241 | + gcc_assert (sched_pressure != SCHED_PRESSURE_NONE); | ||
2242 | |||
2243 | if (! INSN_P (insn)) | ||
2244 | return; | ||
2245 | @@ -2030,8 +2030,9 @@ | ||
2246 | len = sizeof (struct reg_pressure_data) * ira_reg_class_cover_size; | ||
2247 | pressure_info | ||
2248 | = INSN_REG_PRESSURE (insn) = (struct reg_pressure_data *) xmalloc (len); | ||
2249 | - INSN_MAX_REG_PRESSURE (insn) = (int *) xcalloc (ira_reg_class_cover_size | ||
2250 | - * sizeof (int), 1); | ||
2251 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED) | ||
2252 | + INSN_MAX_REG_PRESSURE (insn) = (int *) xcalloc (ira_reg_class_cover_size | ||
2253 | + * sizeof (int), 1); | ||
2254 | for (i = 0; i < ira_reg_class_cover_size; i++) | ||
2255 | { | ||
2256 | cl = ira_reg_class_cover[i]; | ||
2257 | @@ -2775,7 +2776,7 @@ | ||
2258 | || (NONJUMP_INSN_P (insn) && control_flow_insn_p (insn))) | ||
2259 | reg_pending_barrier = MOVE_BARRIER; | ||
2260 | |||
2261 | - if (sched_pressure_p) | ||
2262 | + if (sched_pressure != SCHED_PRESSURE_NONE) | ||
2263 | { | ||
2264 | setup_insn_reg_uses (deps, insn); | ||
2265 | setup_insn_reg_pressure_info (insn); | ||
2266 | @@ -3076,7 +3077,7 @@ | ||
2267 | instructions that follow seem like they should be part | ||
2268 | of the call group. | ||
2269 | |||
2270 | - Also, if we did, fixup_sched_groups() would move the | ||
2271 | + Also, if we did, chain_to_prev_insn would move the | ||
2272 | deps of the debug insn to the call insn, modifying | ||
2273 | non-debug post-dependency counts of the debug insn | ||
2274 | dependencies and otherwise messing with the scheduling | ||
2275 | @@ -3222,6 +3223,37 @@ | ||
2276 | return true; | ||
2277 | } | ||
2278 | |||
2279 | +/* Return true if INSN should be made dependent on the previous instruction | ||
2280 | + group, and if all INSN's dependencies should be moved to the first | ||
2281 | + instruction of that group. */ | ||
2282 | + | ||
2283 | +static bool | ||
2284 | +chain_to_prev_insn_p (rtx insn) | ||
2285 | +{ | ||
2286 | + rtx prev, x; | ||
2287 | + | ||
2288 | + /* INSN forms a group with the previous instruction. */ | ||
2289 | + if (SCHED_GROUP_P (insn)) | ||
2290 | + return true; | ||
2291 | + | ||
2292 | + /* If the previous instruction clobbers a register R and this one sets | ||
2293 | + part of R, the clobber was added specifically to help us track the | ||
2294 | + liveness of R. There's no point scheduling the clobber and leaving | ||
2295 | + INSN behind, especially if we move the clobber to another block. */ | ||
2296 | + prev = prev_nonnote_nondebug_insn (insn); | ||
2297 | + if (prev | ||
2298 | + && INSN_P (prev) | ||
2299 | + && BLOCK_FOR_INSN (prev) == BLOCK_FOR_INSN (insn) | ||
2300 | + && GET_CODE (PATTERN (prev)) == CLOBBER) | ||
2301 | + { | ||
2302 | + x = XEXP (PATTERN (prev), 0); | ||
2303 | + if (set_of (x, insn)) | ||
2304 | + return true; | ||
2305 | + } | ||
2306 | + | ||
2307 | + return false; | ||
2308 | +} | ||
2309 | + | ||
2310 | /* Analyze INSN with DEPS as a context. */ | ||
2311 | void | ||
2312 | deps_analyze_insn (struct deps_desc *deps, rtx insn) | ||
2313 | @@ -3358,8 +3390,9 @@ | ||
2314 | |||
2315 | /* Fixup the dependencies in the sched group. */ | ||
2316 | if ((NONJUMP_INSN_P (insn) || JUMP_P (insn)) | ||
2317 | - && SCHED_GROUP_P (insn) && !sel_sched_p ()) | ||
2318 | - fixup_sched_groups (insn); | ||
2319 | + && chain_to_prev_insn_p (insn) | ||
2320 | + && !sel_sched_p ()) | ||
2321 | + chain_to_prev_insn (insn); | ||
2322 | } | ||
2323 | |||
2324 | /* Initialize DEPS for the new block beginning with HEAD. */ | ||
2325 | |||
2326 | === modified file 'gcc/sched-int.h' | ||
2327 | --- old/gcc/sched-int.h 2011-02-02 04:31:35 +0000 | ||
2328 | +++ new/gcc/sched-int.h 2012-02-08 23:39:02 +0000 | ||
2329 | @@ -651,7 +651,7 @@ | ||
2330 | |||
2331 | /* Do register pressure sensitive insn scheduling if the flag is set | ||
2332 | up. */ | ||
2333 | -extern bool sched_pressure_p; | ||
2334 | +extern enum sched_pressure_algorithm sched_pressure; | ||
2335 | |||
2336 | /* Map regno -> its cover class. The map defined only when | ||
2337 | SCHED_PRESSURE_P is true. */ | ||
2338 | @@ -773,16 +773,16 @@ | ||
2339 | |||
2340 | short cost; | ||
2341 | |||
2342 | + /* '> 0' if priority is valid, | ||
2343 | + '== 0' if priority was not yet computed, | ||
2344 | + '< 0' if priority in invalid and should be recomputed. */ | ||
2345 | + signed char priority_status; | ||
2346 | + | ||
2347 | /* Set if there's DEF-USE dependence between some speculatively | ||
2348 | moved load insn and this one. */ | ||
2349 | unsigned int fed_by_spec_load : 1; | ||
2350 | unsigned int is_load_insn : 1; | ||
2351 | |||
2352 | - /* '> 0' if priority is valid, | ||
2353 | - '== 0' if priority was not yet computed, | ||
2354 | - '< 0' if priority in invalid and should be recomputed. */ | ||
2355 | - signed char priority_status; | ||
2356 | - | ||
2357 | /* What speculations are necessary to apply to schedule the instruction. */ | ||
2358 | ds_t todo_spec; | ||
2359 | |||
2360 | @@ -817,6 +817,7 @@ | ||
2361 | /* Info about how scheduling the insn changes cost of register | ||
2362 | pressure excess (between source and target). */ | ||
2363 | int reg_pressure_excess_cost_change; | ||
2364 | + int model_index; | ||
2365 | }; | ||
2366 | |||
2367 | typedef struct _haifa_insn_data haifa_insn_data_def; | ||
2368 | @@ -839,6 +840,7 @@ | ||
2369 | #define INSN_REG_PRESSURE_EXCESS_COST_CHANGE(INSN) \ | ||
2370 | (HID (INSN)->reg_pressure_excess_cost_change) | ||
2371 | #define INSN_PRIORITY_STATUS(INSN) (HID (INSN)->priority_status) | ||
2372 | +#define INSN_MODEL_INDEX(INSN) (HID (INSN)->model_index) | ||
2373 | |||
2374 | typedef struct _haifa_deps_insn_data haifa_deps_insn_data_def; | ||
2375 | typedef haifa_deps_insn_data_def *haifa_deps_insn_data_t; | ||
2376 | |||
2377 | === modified file 'gcc/sched-rgn.c' | ||
2378 | --- old/gcc/sched-rgn.c 2011-06-04 10:15:48 +0000 | ||
2379 | +++ new/gcc/sched-rgn.c 2012-02-08 23:38:13 +0000 | ||
2380 | @@ -2943,7 +2943,7 @@ | ||
2381 | |||
2382 | sched_extend_ready_list (rgn_n_insns); | ||
2383 | |||
2384 | - if (sched_pressure_p) | ||
2385 | + if (sched_pressure == SCHED_PRESSURE_WEIGHTED) | ||
2386 | { | ||
2387 | sched_init_region_reg_pressure_info (); | ||
2388 | for (bb = 0; bb < current_nr_blocks; bb++) | ||
2389 | |||