Mercurial > hg > CbC > GCC_original
annotate gcc/sel-sched-ir.c @ 16:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
rev | line source |
---|---|
0 | 1 /* Instruction scheduling pass. Selective scheduler and pipeliner. |
16 | 2 Copyright (C) 2006-2017 Free Software Foundation, Inc. |
0 | 3 |
4 This file is part of GCC. | |
5 | |
6 GCC is free software; you can redistribute it and/or modify it under | |
7 the terms of the GNU General Public License as published by the Free | |
8 Software Foundation; either version 3, or (at your option) any later | |
9 version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 #include "config.h" | |
21 #include "system.h" | |
22 #include "coretypes.h" | |
16 | 23 #include "backend.h" |
24 #include "cfghooks.h" | |
25 #include "tree.h" | |
0 | 26 #include "rtl.h" |
16 | 27 #include "df.h" |
28 #include "memmodel.h" | |
0 | 29 #include "tm_p.h" |
16 | 30 #include "cfgrtl.h" |
31 #include "cfganal.h" | |
32 #include "cfgbuild.h" | |
0 | 33 #include "insn-config.h" |
34 #include "insn-attr.h" | |
35 #include "recog.h" | |
36 #include "params.h" | |
37 #include "target.h" | |
38 #include "sched-int.h" | |
14
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
39 #include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */ |
0 | 40 |
41 #ifdef INSN_SCHEDULING | |
16 | 42 #include "regset.h" |
43 #include "cfgloop.h" | |
0 | 44 #include "sel-sched-ir.h" |
45 /* We don't have to use it except for sel_print_insn. */ | |
46 #include "sel-sched-dump.h" | |
47 | |
48 /* A vector holding bb info for whole scheduling pass. */ | |
16 | 49 vec<sel_global_bb_info_def> sel_global_bb_info; |
0 | 50 |
51 /* A vector holding bb info. */ | |
16 | 52 vec<sel_region_bb_info_def> sel_region_bb_info; |
0 | 53 |
54 /* A pool for allocating all lists. */ | |
16 | 55 object_allocator<_list_node> sched_lists_pool ("sel-sched-lists"); |
0 | 56 |
57 /* This contains information about successors for compute_av_set. */ | |
58 struct succs_info current_succs; | |
59 | |
60 /* Data structure to describe interaction with the generic scheduler utils. */ | |
61 static struct common_sched_info_def sel_common_sched_info; | |
62 | |
63 /* The loop nest being pipelined. */ | |
64 struct loop *current_loop_nest; | |
65 | |
66 /* LOOP_NESTS is a vector containing the corresponding loop nest for | |
67 each region. */ | |
16 | 68 static vec<loop_p> loop_nests; |
0 | 69 |
70 /* Saves blocks already in loop regions, indexed by bb->index. */ | |
71 static sbitmap bbs_in_loop_rgns = NULL; | |
72 | |
73 /* CFG hooks that are saved before changing create_basic_block hook. */ | |
74 static struct cfg_hooks orig_cfg_hooks; | |
75 | |
76 | |
77 /* Array containing reverse topological index of function basic blocks, | |
78 indexed by BB->INDEX. */ | |
79 static int *rev_top_order_index = NULL; | |
80 | |
81 /* Length of the above array. */ | |
82 static int rev_top_order_index_len = -1; | |
83 | |
84 /* A regset pool structure. */ | |
85 static struct | |
86 { | |
87 /* The stack to which regsets are returned. */ | |
88 regset *v; | |
89 | |
90 /* Its pointer. */ | |
91 int n; | |
92 | |
93 /* Its size. */ | |
94 int s; | |
95 | |
96 /* In VV we save all generated regsets so that, when destructing the | |
97 pool, we can compare it with V and check that every regset was returned | |
98 back to pool. */ | |
99 regset *vv; | |
100 | |
101 /* The pointer of VV stack. */ | |
102 int nn; | |
103 | |
104 /* Its size. */ | |
105 int ss; | |
106 | |
107 /* The difference between allocated and returned regsets. */ | |
108 int diff; | |
109 } regset_pool = { NULL, 0, 0, NULL, 0, 0, 0 }; | |
110 | |
111 /* This represents the nop pool. */ | |
112 static struct | |
113 { | |
114 /* The vector which holds previously emitted nops. */ | |
115 insn_t *v; | |
116 | |
117 /* Its pointer. */ | |
118 int n; | |
119 | |
120 /* Its size. */ | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
121 int s; |
0 | 122 } nop_pool = { NULL, 0, 0 }; |
123 | |
124 /* The pool for basic block notes. */ | |
16 | 125 static vec<rtx_note *> bb_note_pool; |
0 | 126 |
127 /* A NOP pattern used to emit placeholder insns. */ | |
128 rtx nop_pattern = NULL_RTX; | |
129 /* A special instruction that resides in EXIT_BLOCK. | |
130 EXIT_INSN is successor of the insns that lead to EXIT_BLOCK. */ | |
16 | 131 rtx_insn *exit_insn = NULL; |
0 | 132 |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
133 /* TRUE if while scheduling current region, which is loop, its preheader |
0 | 134 was removed. */ |
135 bool preheader_removed = false; | |
136 | |
137 | |
138 /* Forward static declarations. */ | |
139 static void fence_clear (fence_t); | |
140 | |
141 static void deps_init_id (idata_t, insn_t, bool); | |
142 static void init_id_from_df (idata_t, insn_t, bool); | |
143 static expr_t set_insn_init (expr_t, vinsn_t, int); | |
144 | |
145 static void cfg_preds (basic_block, insn_t **, int *); | |
146 static void prepare_insn_expr (insn_t, int); | |
16 | 147 static void free_history_vect (vec<expr_history_def> &); |
0 | 148 |
149 static void move_bb_info (basic_block, basic_block); | |
150 static void remove_empty_bb (basic_block, bool); | |
14
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
151 static void sel_merge_blocks (basic_block, basic_block); |
0 | 152 static void sel_remove_loop_preheader (void); |
14
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
153 static bool bb_has_removable_jump_to_p (basic_block, basic_block); |
0 | 154 |
155 static bool insn_is_the_only_one_in_bb_p (insn_t); | |
156 static void create_initial_data_sets (basic_block); | |
157 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
158 static void free_av_set (basic_block); |
0 | 159 static void invalidate_av_set (basic_block); |
160 static void extend_insn_data (void); | |
16 | 161 static void sel_init_new_insn (insn_t, int, int = -1); |
0 | 162 static void finish_insns (void); |
163 | |
164 /* Various list functions. */ | |
165 | |
166 /* Copy an instruction list L. */ | |
167 ilist_t | |
168 ilist_copy (ilist_t l) | |
169 { | |
170 ilist_t head = NULL, *tailp = &head; | |
171 | |
172 while (l) | |
173 { | |
174 ilist_add (tailp, ILIST_INSN (l)); | |
175 tailp = &ILIST_NEXT (*tailp); | |
176 l = ILIST_NEXT (l); | |
177 } | |
178 | |
179 return head; | |
180 } | |
181 | |
182 /* Invert an instruction list L. */ | |
183 ilist_t | |
184 ilist_invert (ilist_t l) | |
185 { | |
186 ilist_t res = NULL; | |
187 | |
188 while (l) | |
189 { | |
190 ilist_add (&res, ILIST_INSN (l)); | |
191 l = ILIST_NEXT (l); | |
192 } | |
193 | |
194 return res; | |
195 } | |
196 | |
197 /* Add a new boundary to the LP list with parameters TO, PTR, and DC. */ | |
198 void | |
199 blist_add (blist_t *lp, insn_t to, ilist_t ptr, deps_t dc) | |
200 { | |
201 bnd_t bnd; | |
202 | |
203 _list_add (lp); | |
204 bnd = BLIST_BND (*lp); | |
205 | |
206 BND_TO (bnd) = to; | |
207 BND_PTR (bnd) = ptr; | |
208 BND_AV (bnd) = NULL; | |
209 BND_AV1 (bnd) = NULL; | |
210 BND_DC (bnd) = dc; | |
211 } | |
212 | |
213 /* Remove the list note pointed to by LP. */ | |
214 void | |
215 blist_remove (blist_t *lp) | |
216 { | |
217 bnd_t b = BLIST_BND (*lp); | |
218 | |
219 av_set_clear (&BND_AV (b)); | |
220 av_set_clear (&BND_AV1 (b)); | |
221 ilist_clear (&BND_PTR (b)); | |
222 | |
223 _list_remove (lp); | |
224 } | |
225 | |
226 /* Init a fence tail L. */ | |
227 void | |
228 flist_tail_init (flist_tail_t l) | |
229 { | |
230 FLIST_TAIL_HEAD (l) = NULL; | |
231 FLIST_TAIL_TAILP (l) = &FLIST_TAIL_HEAD (l); | |
232 } | |
233 | |
234 /* Try to find fence corresponding to INSN in L. */ | |
235 fence_t | |
236 flist_lookup (flist_t l, insn_t insn) | |
237 { | |
238 while (l) | |
239 { | |
240 if (FENCE_INSN (FLIST_FENCE (l)) == insn) | |
241 return FLIST_FENCE (l); | |
242 | |
243 l = FLIST_NEXT (l); | |
244 } | |
245 | |
246 return NULL; | |
247 } | |
248 | |
249 /* Init the fields of F before running fill_insns. */ | |
250 static void | |
251 init_fence_for_scheduling (fence_t f) | |
252 { | |
253 FENCE_BNDS (f) = NULL; | |
254 FENCE_PROCESSED_P (f) = false; | |
255 FENCE_SCHEDULED_P (f) = false; | |
256 } | |
257 | |
258 /* Add new fence consisting of INSN and STATE to the list pointed to by LP. */ | |
259 static void | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
260 flist_add (flist_t *lp, insn_t insn, state_t state, deps_t dc, void *tc, |
16 | 261 insn_t last_scheduled_insn, vec<rtx_insn *, va_gc> *executing_insns, |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
262 int *ready_ticks, int ready_ticks_size, insn_t sched_next, |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
263 int cycle, int cycle_issued_insns, int issue_more, |
0 | 264 bool starts_cycle_p, bool after_stall_p) |
265 { | |
266 fence_t f; | |
267 | |
268 _list_add (lp); | |
269 f = FLIST_FENCE (*lp); | |
270 | |
271 FENCE_INSN (f) = insn; | |
272 | |
273 gcc_assert (state != NULL); | |
274 FENCE_STATE (f) = state; | |
275 | |
276 FENCE_CYCLE (f) = cycle; | |
277 FENCE_ISSUED_INSNS (f) = cycle_issued_insns; | |
278 FENCE_STARTS_CYCLE_P (f) = starts_cycle_p; | |
279 FENCE_AFTER_STALL_P (f) = after_stall_p; | |
280 | |
281 gcc_assert (dc != NULL); | |
282 FENCE_DC (f) = dc; | |
283 | |
284 gcc_assert (tc != NULL || targetm.sched.alloc_sched_context == NULL); | |
285 FENCE_TC (f) = tc; | |
286 | |
287 FENCE_LAST_SCHEDULED_INSN (f) = last_scheduled_insn; | |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
288 FENCE_ISSUE_MORE (f) = issue_more; |
0 | 289 FENCE_EXECUTING_INSNS (f) = executing_insns; |
290 FENCE_READY_TICKS (f) = ready_ticks; | |
291 FENCE_READY_TICKS_SIZE (f) = ready_ticks_size; | |
292 FENCE_SCHED_NEXT (f) = sched_next; | |
293 | |
294 init_fence_for_scheduling (f); | |
295 } | |
296 | |
297 /* Remove the head node of the list pointed to by LP. */ | |
298 static void | |
299 flist_remove (flist_t *lp) | |
300 { | |
301 if (FENCE_INSN (FLIST_FENCE (*lp))) | |
302 fence_clear (FLIST_FENCE (*lp)); | |
303 _list_remove (lp); | |
304 } | |
305 | |
306 /* Clear the fence list pointed to by LP. */ | |
307 void | |
308 flist_clear (flist_t *lp) | |
309 { | |
310 while (*lp) | |
311 flist_remove (lp); | |
312 } | |
313 | |
314 /* Add ORIGINAL_INSN the def list DL honoring CROSSES_CALL. */ | |
315 void | |
316 def_list_add (def_list_t *dl, insn_t original_insn, bool crosses_call) | |
317 { | |
318 def_t d; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
319 |
0 | 320 _list_add (dl); |
321 d = DEF_LIST_DEF (*dl); | |
322 | |
323 d->orig_insn = original_insn; | |
324 d->crosses_call = crosses_call; | |
325 } | |
326 | |
327 | |
328 /* Functions to work with target contexts. */ | |
329 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
330 /* Bulk target context. It is convenient for debugging purposes to ensure |
0 | 331 that there are no uninitialized (null) target contexts. */ |
332 static tc_t bulk_tc = (tc_t) 1; | |
333 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
334 /* Target hooks wrappers. In the future we can provide some default |
0 | 335 implementations for them. */ |
336 | |
337 /* Allocate a store for the target context. */ | |
338 static tc_t | |
339 alloc_target_context (void) | |
340 { | |
341 return (targetm.sched.alloc_sched_context | |
342 ? targetm.sched.alloc_sched_context () : bulk_tc); | |
343 } | |
344 | |
345 /* Init target context TC. | |
346 If CLEAN_P is true, then make TC as it is beginning of the scheduler. | |
347 Overwise, copy current backend context to TC. */ | |
348 static void | |
349 init_target_context (tc_t tc, bool clean_p) | |
350 { | |
351 if (targetm.sched.init_sched_context) | |
352 targetm.sched.init_sched_context (tc, clean_p); | |
353 } | |
354 | |
355 /* Allocate and initialize a target context. Meaning of CLEAN_P is the same as | |
356 int init_target_context (). */ | |
357 tc_t | |
358 create_target_context (bool clean_p) | |
359 { | |
360 tc_t tc = alloc_target_context (); | |
361 | |
362 init_target_context (tc, clean_p); | |
363 return tc; | |
364 } | |
365 | |
366 /* Copy TC to the current backend context. */ | |
367 void | |
368 set_target_context (tc_t tc) | |
369 { | |
370 if (targetm.sched.set_sched_context) | |
371 targetm.sched.set_sched_context (tc); | |
372 } | |
373 | |
374 /* TC is about to be destroyed. Free any internal data. */ | |
375 static void | |
376 clear_target_context (tc_t tc) | |
377 { | |
378 if (targetm.sched.clear_sched_context) | |
379 targetm.sched.clear_sched_context (tc); | |
380 } | |
381 | |
382 /* Clear and free it. */ | |
383 static void | |
384 delete_target_context (tc_t tc) | |
385 { | |
386 clear_target_context (tc); | |
387 | |
388 if (targetm.sched.free_sched_context) | |
389 targetm.sched.free_sched_context (tc); | |
390 } | |
391 | |
392 /* Make a copy of FROM in TO. | |
393 NB: May be this should be a hook. */ | |
394 static void | |
395 copy_target_context (tc_t to, tc_t from) | |
396 { | |
397 tc_t tmp = create_target_context (false); | |
398 | |
399 set_target_context (from); | |
400 init_target_context (to, false); | |
401 | |
402 set_target_context (tmp); | |
403 delete_target_context (tmp); | |
404 } | |
405 | |
406 /* Create a copy of TC. */ | |
407 static tc_t | |
408 create_copy_of_target_context (tc_t tc) | |
409 { | |
410 tc_t copy = alloc_target_context (); | |
411 | |
412 copy_target_context (copy, tc); | |
413 | |
414 return copy; | |
415 } | |
416 | |
417 /* Clear TC and initialize it according to CLEAN_P. The meaning of CLEAN_P | |
418 is the same as in init_target_context (). */ | |
419 void | |
420 reset_target_context (tc_t tc, bool clean_p) | |
421 { | |
422 clear_target_context (tc); | |
423 init_target_context (tc, clean_p); | |
424 } | |
425 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
426 /* Functions to work with dependence contexts. |
14
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
427 Dc (aka deps context, aka deps_t, aka struct deps_desc *) is short for dependence |
0 | 428 context. It accumulates information about processed insns to decide if |
429 current insn is dependent on the processed ones. */ | |
430 | |
431 /* Make a copy of FROM in TO. */ | |
432 static void | |
433 copy_deps_context (deps_t to, deps_t from) | |
434 { | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
435 init_deps (to, false); |
0 | 436 deps_join (to, from); |
437 } | |
438 | |
439 /* Allocate store for dep context. */ | |
440 static deps_t | |
441 alloc_deps_context (void) | |
442 { | |
14
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
443 return XNEW (struct deps_desc); |
0 | 444 } |
445 | |
446 /* Allocate and initialize dep context. */ | |
447 static deps_t | |
448 create_deps_context (void) | |
449 { | |
450 deps_t dc = alloc_deps_context (); | |
451 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
452 init_deps (dc, false); |
0 | 453 return dc; |
454 } | |
455 | |
456 /* Create a copy of FROM. */ | |
457 static deps_t | |
458 create_copy_of_deps_context (deps_t from) | |
459 { | |
460 deps_t to = alloc_deps_context (); | |
461 | |
462 copy_deps_context (to, from); | |
463 return to; | |
464 } | |
465 | |
466 /* Clean up internal data of DC. */ | |
467 static void | |
468 clear_deps_context (deps_t dc) | |
469 { | |
470 free_deps (dc); | |
471 } | |
472 | |
473 /* Clear and free DC. */ | |
474 static void | |
475 delete_deps_context (deps_t dc) | |
476 { | |
477 clear_deps_context (dc); | |
478 free (dc); | |
479 } | |
480 | |
481 /* Clear and init DC. */ | |
482 static void | |
483 reset_deps_context (deps_t dc) | |
484 { | |
485 clear_deps_context (dc); | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
486 init_deps (dc, false); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
487 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
488 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
489 /* This structure describes the dependence analysis hooks for advancing |
0 | 490 dependence context. */ |
491 static struct sched_deps_info_def advance_deps_context_sched_deps_info = | |
492 { | |
493 NULL, | |
494 | |
495 NULL, /* start_insn */ | |
496 NULL, /* finish_insn */ | |
497 NULL, /* start_lhs */ | |
498 NULL, /* finish_lhs */ | |
499 NULL, /* start_rhs */ | |
500 NULL, /* finish_rhs */ | |
501 haifa_note_reg_set, | |
502 haifa_note_reg_clobber, | |
503 haifa_note_reg_use, | |
504 NULL, /* note_mem_dep */ | |
505 NULL, /* note_dep */ | |
506 | |
507 0, 0, 0 | |
508 }; | |
509 | |
510 /* Process INSN and add its impact on DC. */ | |
511 void | |
512 advance_deps_context (deps_t dc, insn_t insn) | |
513 { | |
514 sched_deps_info = &advance_deps_context_sched_deps_info; | |
515 deps_analyze_insn (dc, insn); | |
516 } | |
517 | |
518 | |
519 /* Functions to work with DFA states. */ | |
520 | |
521 /* Allocate store for a DFA state. */ | |
522 static state_t | |
523 state_alloc (void) | |
524 { | |
525 return xmalloc (dfa_state_size); | |
526 } | |
527 | |
528 /* Allocate and initialize DFA state. */ | |
529 static state_t | |
530 state_create (void) | |
531 { | |
532 state_t state = state_alloc (); | |
533 | |
534 state_reset (state); | |
535 advance_state (state); | |
536 return state; | |
537 } | |
538 | |
539 /* Free DFA state. */ | |
540 static void | |
541 state_free (state_t state) | |
542 { | |
543 free (state); | |
544 } | |
545 | |
546 /* Make a copy of FROM in TO. */ | |
547 static void | |
548 state_copy (state_t to, state_t from) | |
549 { | |
550 memcpy (to, from, dfa_state_size); | |
551 } | |
552 | |
553 /* Create a copy of FROM. */ | |
554 static state_t | |
555 state_create_copy (state_t from) | |
556 { | |
557 state_t to = state_alloc (); | |
558 | |
559 state_copy (to, from); | |
560 return to; | |
561 } | |
562 | |
563 | |
564 /* Functions to work with fences. */ | |
565 | |
566 /* Clear the fence. */ | |
567 static void | |
568 fence_clear (fence_t f) | |
569 { | |
570 state_t s = FENCE_STATE (f); | |
571 deps_t dc = FENCE_DC (f); | |
572 void *tc = FENCE_TC (f); | |
573 | |
574 ilist_clear (&FENCE_BNDS (f)); | |
575 | |
576 gcc_assert ((s != NULL && dc != NULL && tc != NULL) | |
577 || (s == NULL && dc == NULL && tc == NULL)); | |
578 | |
16 | 579 free (s); |
0 | 580 |
581 if (dc != NULL) | |
582 delete_deps_context (dc); | |
583 | |
584 if (tc != NULL) | |
585 delete_target_context (tc); | |
16 | 586 vec_free (FENCE_EXECUTING_INSNS (f)); |
0 | 587 free (FENCE_READY_TICKS (f)); |
588 FENCE_READY_TICKS (f) = NULL; | |
589 } | |
590 | |
591 /* Init a list of fences with successors of OLD_FENCE. */ | |
592 void | |
593 init_fences (insn_t old_fence) | |
594 { | |
595 insn_t succ; | |
596 succ_iterator si; | |
597 bool first = true; | |
598 int ready_ticks_size = get_max_uid () + 1; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
599 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
600 FOR_EACH_SUCC_1 (succ, si, old_fence, |
0 | 601 SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS) |
602 { | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
603 |
0 | 604 if (first) |
605 first = false; | |
606 else | |
607 gcc_assert (flag_sel_sched_pipelining_outer_loops); | |
608 | |
609 flist_add (&fences, succ, | |
610 state_create (), | |
611 create_deps_context () /* dc */, | |
612 create_target_context (true) /* tc */, | |
16 | 613 NULL /* last_scheduled_insn */, |
0 | 614 NULL, /* executing_insns */ |
615 XCNEWVEC (int, ready_ticks_size), /* ready_ticks */ | |
616 ready_ticks_size, | |
16 | 617 NULL /* sched_next */, |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
618 1 /* cycle */, 0 /* cycle_issued_insns */, |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
619 issue_rate, /* issue_more */ |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
620 1 /* starts_cycle_p */, 0 /* after_stall_p */); |
0 | 621 } |
622 } | |
623 | |
624 /* Merges two fences (filling fields of fence F with resulting values) by | |
625 following rules: 1) state, target context and last scheduled insn are | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
626 propagated from fallthrough edge if it is available; |
0 | 627 2) deps context and cycle is propagated from more probable edge; |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
628 3) all other fields are set to corresponding constant values. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
629 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
630 INSN, STATE, DC, TC, LAST_SCHEDULED_INSN, EXECUTING_INSNS, |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
631 READY_TICKS, READY_TICKS_SIZE, SCHED_NEXT, CYCLE, ISSUE_MORE |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
632 and AFTER_STALL_P are the corresponding fields of the second fence. */ |
0 | 633 static void |
634 merge_fences (fence_t f, insn_t insn, | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
635 state_t state, deps_t dc, void *tc, |
16 | 636 rtx_insn *last_scheduled_insn, |
637 vec<rtx_insn *, va_gc> *executing_insns, | |
0 | 638 int *ready_ticks, int ready_ticks_size, |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
639 rtx sched_next, int cycle, int issue_more, bool after_stall_p) |
0 | 640 { |
641 insn_t last_scheduled_insn_old = FENCE_LAST_SCHEDULED_INSN (f); | |
642 | |
643 gcc_assert (sel_bb_head_p (FENCE_INSN (f)) | |
644 && !sched_next && !FENCE_SCHED_NEXT (f)); | |
645 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
646 /* Check if we can decide which path fences came. |
0 | 647 If we can't (or don't want to) - reset all. */ |
648 if (last_scheduled_insn == NULL | |
649 || last_scheduled_insn_old == NULL | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
650 /* This is a case when INSN is reachable on several paths from |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
651 one insn (this can happen when pipelining of outer loops is on and |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
652 there are two edges: one going around of inner loop and the other - |
0 | 653 right through it; in such case just reset everything). */ |
654 || last_scheduled_insn == last_scheduled_insn_old) | |
655 { | |
656 state_reset (FENCE_STATE (f)); | |
657 state_free (state); | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
658 |
0 | 659 reset_deps_context (FENCE_DC (f)); |
660 delete_deps_context (dc); | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
661 |
0 | 662 reset_target_context (FENCE_TC (f), true); |
663 delete_target_context (tc); | |
664 | |
665 if (cycle > FENCE_CYCLE (f)) | |
666 FENCE_CYCLE (f) = cycle; | |
667 | |
668 FENCE_LAST_SCHEDULED_INSN (f) = NULL; | |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
669 FENCE_ISSUE_MORE (f) = issue_rate; |
16 | 670 vec_free (executing_insns); |
0 | 671 free (ready_ticks); |
672 if (FENCE_EXECUTING_INSNS (f)) | |
16 | 673 FENCE_EXECUTING_INSNS (f)->block_remove (0, |
674 FENCE_EXECUTING_INSNS (f)->length ()); | |
0 | 675 if (FENCE_READY_TICKS (f)) |
676 memset (FENCE_READY_TICKS (f), 0, FENCE_READY_TICKS_SIZE (f)); | |
677 } | |
678 else | |
679 { | |
680 edge edge_old = NULL, edge_new = NULL; | |
681 edge candidate; | |
682 succ_iterator si; | |
683 insn_t succ; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
684 |
0 | 685 /* Find fallthrough edge. */ |
686 gcc_assert (BLOCK_FOR_INSN (insn)->prev_bb); | |
14
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
687 candidate = find_fallthru_edge_from (BLOCK_FOR_INSN (insn)->prev_bb); |
0 | 688 |
689 if (!candidate | |
690 || (candidate->src != BLOCK_FOR_INSN (last_scheduled_insn) | |
691 && candidate->src != BLOCK_FOR_INSN (last_scheduled_insn_old))) | |
692 { | |
693 /* No fallthrough edge leading to basic block of INSN. */ | |
694 state_reset (FENCE_STATE (f)); | |
695 state_free (state); | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
696 |
0 | 697 reset_target_context (FENCE_TC (f), true); |
698 delete_target_context (tc); | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
699 |
0 | 700 FENCE_LAST_SCHEDULED_INSN (f) = NULL; |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
701 FENCE_ISSUE_MORE (f) = issue_rate; |
0 | 702 } |
703 else | |
704 if (candidate->src == BLOCK_FOR_INSN (last_scheduled_insn)) | |
705 { | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
706 /* Would be weird if same insn is successor of several fallthrough |
0 | 707 edges. */ |
708 gcc_assert (BLOCK_FOR_INSN (insn)->prev_bb | |
709 != BLOCK_FOR_INSN (last_scheduled_insn_old)); | |
710 | |
711 state_free (FENCE_STATE (f)); | |
712 FENCE_STATE (f) = state; | |
713 | |
714 delete_target_context (FENCE_TC (f)); | |
715 FENCE_TC (f) = tc; | |
716 | |
717 FENCE_LAST_SCHEDULED_INSN (f) = last_scheduled_insn; | |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
718 FENCE_ISSUE_MORE (f) = issue_more; |
0 | 719 } |
720 else | |
721 { | |
722 /* Leave STATE, TC and LAST_SCHEDULED_INSN fields untouched. */ | |
723 state_free (state); | |
724 delete_target_context (tc); | |
725 | |
726 gcc_assert (BLOCK_FOR_INSN (insn)->prev_bb | |
727 != BLOCK_FOR_INSN (last_scheduled_insn)); | |
728 } | |
729 | |
730 /* Find edge of first predecessor (last_scheduled_insn_old->insn). */ | |
731 FOR_EACH_SUCC_1 (succ, si, last_scheduled_insn_old, | |
732 SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS) | |
733 { | |
734 if (succ == insn) | |
735 { | |
736 /* No same successor allowed from several edges. */ | |
737 gcc_assert (!edge_old); | |
738 edge_old = si.e1; | |
739 } | |
740 } | |
741 /* Find edge of second predecessor (last_scheduled_insn->insn). */ | |
742 FOR_EACH_SUCC_1 (succ, si, last_scheduled_insn, | |
743 SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS) | |
744 { | |
745 if (succ == insn) | |
746 { | |
747 /* No same successor allowed from several edges. */ | |
748 gcc_assert (!edge_new); | |
749 edge_new = si.e1; | |
750 } | |
751 } | |
752 | |
753 /* Check if we can choose most probable predecessor. */ | |
754 if (edge_old == NULL || edge_new == NULL) | |
755 { | |
756 reset_deps_context (FENCE_DC (f)); | |
757 delete_deps_context (dc); | |
16 | 758 vec_free (executing_insns); |
0 | 759 free (ready_ticks); |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
760 |
0 | 761 FENCE_CYCLE (f) = MAX (FENCE_CYCLE (f), cycle); |
762 if (FENCE_EXECUTING_INSNS (f)) | |
16 | 763 FENCE_EXECUTING_INSNS (f)->block_remove (0, |
764 FENCE_EXECUTING_INSNS (f)->length ()); | |
0 | 765 if (FENCE_READY_TICKS (f)) |
766 memset (FENCE_READY_TICKS (f), 0, FENCE_READY_TICKS_SIZE (f)); | |
767 } | |
768 else | |
769 if (edge_new->probability > edge_old->probability) | |
770 { | |
771 delete_deps_context (FENCE_DC (f)); | |
772 FENCE_DC (f) = dc; | |
16 | 773 vec_free (FENCE_EXECUTING_INSNS (f)); |
0 | 774 FENCE_EXECUTING_INSNS (f) = executing_insns; |
775 free (FENCE_READY_TICKS (f)); | |
776 FENCE_READY_TICKS (f) = ready_ticks; | |
777 FENCE_READY_TICKS_SIZE (f) = ready_ticks_size; | |
778 FENCE_CYCLE (f) = cycle; | |
779 } | |
780 else | |
781 { | |
782 /* Leave DC and CYCLE untouched. */ | |
783 delete_deps_context (dc); | |
16 | 784 vec_free (executing_insns); |
0 | 785 free (ready_ticks); |
786 } | |
787 } | |
788 | |
789 /* Fill remaining invariant fields. */ | |
790 if (after_stall_p) | |
791 FENCE_AFTER_STALL_P (f) = 1; | |
792 | |
793 FENCE_ISSUED_INSNS (f) = 0; | |
794 FENCE_STARTS_CYCLE_P (f) = 1; | |
795 FENCE_SCHED_NEXT (f) = NULL; | |
796 } | |
797 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
798 /* Add a new fence to NEW_FENCES list, initializing it from all |
0 | 799 other parameters. */ |
800 static void | |
801 add_to_fences (flist_tail_t new_fences, insn_t insn, | |
16 | 802 state_t state, deps_t dc, void *tc, |
803 rtx_insn *last_scheduled_insn, | |
804 vec<rtx_insn *, va_gc> *executing_insns, int *ready_ticks, | |
805 int ready_ticks_size, rtx_insn *sched_next, int cycle, | |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
806 int cycle_issued_insns, int issue_rate, |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
807 bool starts_cycle_p, bool after_stall_p) |
0 | 808 { |
809 fence_t f = flist_lookup (FLIST_TAIL_HEAD (new_fences), insn); | |
810 | |
811 if (! f) | |
812 { | |
813 flist_add (FLIST_TAIL_TAILP (new_fences), insn, state, dc, tc, | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
814 last_scheduled_insn, executing_insns, ready_ticks, |
0 | 815 ready_ticks_size, sched_next, cycle, cycle_issued_insns, |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
816 issue_rate, starts_cycle_p, after_stall_p); |
0 | 817 |
818 FLIST_TAIL_TAILP (new_fences) | |
819 = &FLIST_NEXT (*FLIST_TAIL_TAILP (new_fences)); | |
820 } | |
821 else | |
822 { | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
823 merge_fences (f, insn, state, dc, tc, last_scheduled_insn, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
824 executing_insns, ready_ticks, ready_ticks_size, |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
825 sched_next, cycle, issue_rate, after_stall_p); |
0 | 826 } |
827 } | |
828 | |
829 /* Move the first fence in the OLD_FENCES list to NEW_FENCES. */ | |
830 void | |
831 move_fence_to_fences (flist_t old_fences, flist_tail_t new_fences) | |
832 { | |
833 fence_t f, old; | |
834 flist_t *tailp = FLIST_TAIL_TAILP (new_fences); | |
835 | |
836 old = FLIST_FENCE (old_fences); | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
837 f = flist_lookup (FLIST_TAIL_HEAD (new_fences), |
0 | 838 FENCE_INSN (FLIST_FENCE (old_fences))); |
839 if (f) | |
840 { | |
841 merge_fences (f, old->insn, old->state, old->dc, old->tc, | |
842 old->last_scheduled_insn, old->executing_insns, | |
843 old->ready_ticks, old->ready_ticks_size, | |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
844 old->sched_next, old->cycle, old->issue_more, |
0 | 845 old->after_stall_p); |
846 } | |
847 else | |
848 { | |
849 _list_add (tailp); | |
850 FLIST_TAIL_TAILP (new_fences) = &FLIST_NEXT (*tailp); | |
851 *FLIST_FENCE (*tailp) = *old; | |
852 init_fence_for_scheduling (FLIST_FENCE (*tailp)); | |
853 } | |
854 FENCE_INSN (old) = NULL; | |
855 } | |
856 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
857 /* Add a new fence to NEW_FENCES list and initialize most of its data |
0 | 858 as a clean one. */ |
859 void | |
860 add_clean_fence_to_fences (flist_tail_t new_fences, insn_t succ, fence_t fence) | |
861 { | |
862 int ready_ticks_size = get_max_uid () + 1; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
863 |
0 | 864 add_to_fences (new_fences, |
865 succ, state_create (), create_deps_context (), | |
866 create_target_context (true), | |
16 | 867 NULL, NULL, |
0 | 868 XCNEWVEC (int, ready_ticks_size), ready_ticks_size, |
16 | 869 NULL, FENCE_CYCLE (fence) + 1, |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
870 0, issue_rate, 1, FENCE_AFTER_STALL_P (fence)); |
0 | 871 } |
872 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
873 /* Add a new fence to NEW_FENCES list and initialize all of its data |
0 | 874 from FENCE and SUCC. */ |
875 void | |
876 add_dirty_fence_to_fences (flist_tail_t new_fences, insn_t succ, fence_t fence) | |
877 { | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
878 int * new_ready_ticks |
0 | 879 = XNEWVEC (int, FENCE_READY_TICKS_SIZE (fence)); |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
880 |
0 | 881 memcpy (new_ready_ticks, FENCE_READY_TICKS (fence), |
882 FENCE_READY_TICKS_SIZE (fence) * sizeof (int)); | |
883 add_to_fences (new_fences, | |
884 succ, state_create_copy (FENCE_STATE (fence)), | |
885 create_copy_of_deps_context (FENCE_DC (fence)), | |
886 create_copy_of_target_context (FENCE_TC (fence)), | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
887 FENCE_LAST_SCHEDULED_INSN (fence), |
16 | 888 vec_safe_copy (FENCE_EXECUTING_INSNS (fence)), |
0 | 889 new_ready_ticks, |
890 FENCE_READY_TICKS_SIZE (fence), | |
891 FENCE_SCHED_NEXT (fence), | |
892 FENCE_CYCLE (fence), | |
893 FENCE_ISSUED_INSNS (fence), | |
11
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
9
diff
changeset
|
894 FENCE_ISSUE_MORE (fence), |
0 | 895 FENCE_STARTS_CYCLE_P (fence), |
896 FENCE_AFTER_STALL_P (fence)); | |
897 } | |
898 | |
899 | |
900 /* Functions to work with regset and nop pools. */ | |
901 | |
902 /* Returns the new regset from pool. It might have some of the bits set | |
903 from the previous usage. */ | |
904 regset | |
905 get_regset_from_pool (void) | |
906 { | |
907 regset rs; | |
908 | |
909 if (regset_pool.n != 0) | |
910 rs = regset_pool.v[--regset_pool.n]; | |
911 else | |
912 /* We need to create the regset. */ | |
913 { | |
914 rs = ALLOC_REG_SET (®_obstack); | |
915 | |
916 if (regset_pool.nn == regset_pool.ss) | |
917 regset_pool.vv = XRESIZEVEC (regset, regset_pool.vv, | |
918 (regset_pool.ss = 2 * regset_pool.ss + 1)); | |
919 regset_pool.vv[regset_pool.nn++] = rs; | |
920 } | |
921 | |
922 regset_pool.diff++; | |
923 | |
924 return rs; | |
925 } | |
926 | |
927 /* Same as above, but returns the empty regset. */ | |
928 regset | |
929 get_clear_regset_from_pool (void) | |
930 { | |
931 regset rs = get_regset_from_pool (); | |
932 | |
933 CLEAR_REG_SET (rs); | |
934 return rs; | |
935 } | |
936 | |
937 /* Return regset RS to the pool for future use. */ | |
938 void | |
939 return_regset_to_pool (regset rs) | |
940 { | |
14
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
941 gcc_assert (rs); |
0 | 942 regset_pool.diff--; |
943 | |
944 if (regset_pool.n == regset_pool.s) | |
945 regset_pool.v = XRESIZEVEC (regset, regset_pool.v, | |
946 (regset_pool.s = 2 * regset_pool.s + 1)); | |
947 regset_pool.v[regset_pool.n++] = rs; | |
948 } | |
949 | |
950 /* This is used as a qsort callback for sorting regset pool stacks. | |
951 X and XX are addresses of two regsets. They are never equal. */ | |
952 static int | |
953 cmp_v_in_regset_pool (const void *x, const void *xx) | |
954 { | |
16 | 955 uintptr_t r1 = (uintptr_t) *((const regset *) x); |
956 uintptr_t r2 = (uintptr_t) *((const regset *) xx); | |
957 if (r1 > r2) | |
958 return 1; | |
959 else if (r1 < r2) | |
960 return -1; | |
961 gcc_unreachable (); | |
962 } | |
963 | |
964 /* Free the regset pool possibly checking for memory leaks. */ | |
0 | 965 void |
966 free_regset_pool (void) | |
967 { | |
16 | 968 if (flag_checking) |
969 { | |
970 regset *v = regset_pool.v; | |
971 int i = 0; | |
972 int n = regset_pool.n; | |
973 | |
974 regset *vv = regset_pool.vv; | |
975 int ii = 0; | |
976 int nn = regset_pool.nn; | |
977 | |
978 int diff = 0; | |
979 | |
980 gcc_assert (n <= nn); | |
981 | |
982 /* Sort both vectors so it will be possible to compare them. */ | |
983 qsort (v, n, sizeof (*v), cmp_v_in_regset_pool); | |
984 qsort (vv, nn, sizeof (*vv), cmp_v_in_regset_pool); | |
985 | |
986 while (ii < nn) | |
987 { | |
988 if (v[i] == vv[ii]) | |
989 i++; | |
990 else | |
991 /* VV[II] was lost. */ | |
992 diff++; | |
993 | |
994 ii++; | |
995 } | |
996 | |
997 gcc_assert (diff == regset_pool.diff); | |
998 } | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
999 |
0 | 1000 /* If not true - we have a memory leak. */ |
1001 gcc_assert (regset_pool.diff == 0); | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1002 |
0 | 1003 while (regset_pool.n) |
1004 { | |
1005 --regset_pool.n; | |
1006 FREE_REG_SET (regset_pool.v[regset_pool.n]); | |
1007 } | |
1008 | |
1009 free (regset_pool.v); | |
1010 regset_pool.v = NULL; | |
1011 regset_pool.s = 0; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1012 |
0 | 1013 free (regset_pool.vv); |
1014 regset_pool.vv = NULL; | |
1015 regset_pool.nn = 0; | |
1016 regset_pool.ss = 0; | |
1017 | |
1018 regset_pool.diff = 0; | |
1019 } | |
1020 | |
1021 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1022 /* Functions to work with nop pools. NOP insns are used as temporary |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1023 placeholders of the insns being scheduled to allow correct update of |
0 | 1024 the data sets. When update is finished, NOPs are deleted. */ |
1025 | |
1026 /* A vinsn that is used to represent a nop. This vinsn is shared among all | |
1027 nops sel-sched generates. */ | |
1028 static vinsn_t nop_vinsn = NULL; | |
1029 | |
1030 /* Emit a nop before INSN, taking it from pool. */ | |
1031 insn_t | |
1032 get_nop_from_pool (insn_t insn) | |
1033 { | |
16 | 1034 rtx nop_pat; |
0 | 1035 insn_t nop; |
1036 bool old_p = nop_pool.n != 0; | |
1037 int flags; | |
1038 | |
1039 if (old_p) | |
16 | 1040 nop_pat = nop_pool.v[--nop_pool.n]; |
0 | 1041 else |
16 | 1042 nop_pat = nop_pattern; |
1043 | |
1044 nop = emit_insn_before (nop_pat, insn); | |
0 | 1045 |
1046 if (old_p) | |
1047 flags = INSN_INIT_TODO_SSID; | |
1048 else | |
1049 flags = INSN_INIT_TODO_LUID | INSN_INIT_TODO_SSID; | |
1050 | |
1051 set_insn_init (INSN_EXPR (insn), nop_vinsn, INSN_SEQNO (insn)); | |
1052 sel_init_new_insn (nop, flags); | |
1053 | |
1054 return nop; | |
1055 } | |
1056 | |
1057 /* Remove NOP from the instruction stream and return it to the pool. */ | |
1058 void | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1059 return_nop_to_pool (insn_t nop, bool full_tidying) |
0 | 1060 { |
1061 gcc_assert (INSN_IN_STREAM_P (nop)); | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1062 sel_remove_insn (nop, false, full_tidying); |
0 | 1063 |
16 | 1064 /* We'll recycle this nop. */ |
1065 nop->set_undeleted (); | |
1066 | |
0 | 1067 if (nop_pool.n == nop_pool.s) |
16 | 1068 nop_pool.v = XRESIZEVEC (rtx_insn *, nop_pool.v, |
0 | 1069 (nop_pool.s = 2 * nop_pool.s + 1)); |
1070 nop_pool.v[nop_pool.n++] = nop; | |
1071 } | |
1072 | |
1073 /* Free the nop pool. */ | |
1074 void | |
1075 free_nop_pool (void) | |
1076 { | |
1077 nop_pool.n = 0; | |
1078 nop_pool.s = 0; | |
1079 free (nop_pool.v); | |
1080 nop_pool.v = NULL; | |
1081 } | |
1082 | |
1083 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1084 /* Skip unspec to support ia64 speculation. Called from rtx_equal_p_cb. |
0 | 1085 The callback is given two rtxes XX and YY and writes the new rtxes |
1086 to NX and NY in case some needs to be skipped. */ | |
1087 static int | |
1088 skip_unspecs_callback (const_rtx *xx, const_rtx *yy, rtx *nx, rtx* ny) | |
1089 { | |
1090 const_rtx x = *xx; | |
1091 const_rtx y = *yy; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1092 |
0 | 1093 if (GET_CODE (x) == UNSPEC |
1094 && (targetm.sched.skip_rtx_p == NULL | |
1095 || targetm.sched.skip_rtx_p (x))) | |
1096 { | |
1097 *nx = XVECEXP (x, 0, 0); | |
1098 *ny = CONST_CAST_RTX (y); | |
1099 return 1; | |
1100 } | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1101 |
0 | 1102 if (GET_CODE (y) == UNSPEC |
1103 && (targetm.sched.skip_rtx_p == NULL | |
1104 || targetm.sched.skip_rtx_p (y))) | |
1105 { | |
1106 *nx = CONST_CAST_RTX (x); | |
1107 *ny = XVECEXP (y, 0, 0); | |
1108 return 1; | |
1109 } | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1110 |
0 | 1111 return 0; |
1112 } | |
1113 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1114 /* Callback, called from hash_rtx_cb. Helps to hash UNSPEC rtx X in a correct way |
0 | 1115 to support ia64 speculation. When changes are needed, new rtx X and new mode |
1116 NMODE are written, and the callback returns true. */ | |
1117 static int | |
16 | 1118 hash_with_unspec_callback (const_rtx x, machine_mode mode ATTRIBUTE_UNUSED, |
1119 rtx *nx, machine_mode* nmode) | |
0 | 1120 { |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1121 if (GET_CODE (x) == UNSPEC |
0 | 1122 && targetm.sched.skip_rtx_p |
1123 && targetm.sched.skip_rtx_p (x)) | |
1124 { | |
1125 *nx = XVECEXP (x, 0 ,0); | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1126 *nmode = VOIDmode; |
0 | 1127 return 1; |
1128 } | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1129 |
0 | 1130 return 0; |
1131 } | |
1132 | |
1133 /* Returns LHS and RHS are ok to be scheduled separately. */ | |
1134 static bool | |
1135 lhs_and_rhs_separable_p (rtx lhs, rtx rhs) | |
1136 { | |
1137 if (lhs == NULL || rhs == NULL) | |
1138 return false; | |
1139 | |
16 | 1140 /* Do not schedule constants as rhs: no point to use reg, if const |
1141 can be used. Moreover, scheduling const as rhs may lead to mode | |
1142 mismatch cause consts don't have modes but they could be merged | |
1143 from branches where the same const used in different modes. */ | |
0 | 1144 if (CONSTANT_P (rhs)) |
1145 return false; | |
1146 | |
1147 /* ??? Do not rename predicate registers to avoid ICEs in bundling. */ | |
1148 if (COMPARISON_P (rhs)) | |
1149 return false; | |
1150 | |
1151 /* Do not allow single REG to be an rhs. */ | |
1152 if (REG_P (rhs)) | |
1153 return false; | |
1154 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1155 /* See comment at find_used_regs_1 (*1) for explanation of this |
0 | 1156 restriction. */ |
1157 /* FIXME: remove this later. */ | |
1158 if (MEM_P (lhs)) | |
1159 return false; | |
1160 | |
1161 /* This will filter all tricky things like ZERO_EXTRACT etc. | |
1162 For now we don't handle it. */ | |
1163 if (!REG_P (lhs) && !MEM_P (lhs)) | |
1164 return false; | |
1165 | |
1166 return true; | |
1167 } | |
1168 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1169 /* Initialize vinsn VI for INSN. Only for use from vinsn_create (). When |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1170 FORCE_UNIQUE_P is true, the resulting vinsn will not be clonable. This is |
0 | 1171 used e.g. for insns from recovery blocks. */ |
1172 static void | |
1173 vinsn_init (vinsn_t vi, insn_t insn, bool force_unique_p) | |
1174 { | |
1175 hash_rtx_callback_function hrcf; | |
1176 int insn_class; | |
1177 | |
1178 VINSN_INSN_RTX (vi) = insn; | |
1179 VINSN_COUNT (vi) = 0; | |
1180 vi->cost = -1; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1181 |
14
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
1182 if (INSN_NOP_P (insn)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
1183 return; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
1184 |
0 | 1185 if (DF_INSN_UID_SAFE_GET (INSN_UID (insn)) != NULL) |
1186 init_id_from_df (VINSN_ID (vi), insn, force_unique_p); | |
1187 else | |
1188 deps_init_id (VINSN_ID (vi), insn, force_unique_p); | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1189 |
0 | 1190 /* Hash vinsn depending on whether it is separable or not. */ |
1191 hrcf = targetm.sched.skip_rtx_p ? hash_with_unspec_callback : NULL; | |
1192 if (VINSN_SEPARABLE_P (vi)) | |
1193 { | |
1194 rtx rhs = VINSN_RHS (vi); | |
1195 | |
1196 VINSN_HASH (vi) = hash_rtx_cb (rhs, GET_MODE (rhs), | |
1197 NULL, NULL, false, hrcf); | |
1198 VINSN_HASH_RTX (vi) = hash_rtx_cb (VINSN_PATTERN (vi), | |
1199 VOIDmode, NULL, NULL, | |
1200 false, hrcf); | |
1201 } | |
1202 else | |
1203 { | |
1204 VINSN_HASH (vi) = hash_rtx_cb (VINSN_PATTERN (vi), VOIDmode, | |
1205 NULL, NULL, false, hrcf); | |
1206 VINSN_HASH_RTX (vi) = VINSN_HASH (vi); | |
1207 } | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1208 |
0 | 1209 insn_class = haifa_classify_insn (insn); |
1210 if (insn_class >= 2 | |
1211 && (!targetm.sched.get_insn_spec_ds | |
1212 || ((targetm.sched.get_insn_spec_ds (insn) & BEGIN_CONTROL) | |
1213 == 0))) | |
1214 VINSN_MAY_TRAP_P (vi) = true; | |
1215 else | |
1216 VINSN_MAY_TRAP_P (vi) = false; | |
1217 } | |
1218 | |
1219 /* Indicate that VI has become the part of an rtx object. */ | |
1220 void | |
1221 vinsn_attach (vinsn_t vi) | |
1222 { | |
1223 /* Assert that VI is not pending for deletion. */ | |
1224 gcc_assert (VINSN_INSN_RTX (vi)); | |
1225 | |
1226 VINSN_COUNT (vi)++; | |
1227 } | |
1228 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1229 /* Create and init VI from the INSN. Use UNIQUE_P for determining the correct |
0 | 1230 VINSN_TYPE (VI). */ |
1231 static vinsn_t | |
1232 vinsn_create (insn_t insn, bool force_unique_p) | |
1233 { | |
1234 vinsn_t vi = XCNEW (struct vinsn_def); | |
1235 | |
1236 vinsn_init (vi, insn, force_unique_p); | |
1237 return vi; | |
1238 } | |
1239 | |
1240 /* Return a copy of VI. When REATTACH_P is true, detach VI and attach | |
1241 the copy. */ | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1242 vinsn_t |
0 | 1243 vinsn_copy (vinsn_t vi, bool reattach_p) |
1244 { | |
16 | 1245 rtx_insn *copy; |
0 | 1246 bool unique = VINSN_UNIQUE_P (vi); |
1247 vinsn_t new_vi; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1248 |
0 | 1249 copy = create_copy_of_insn_rtx (VINSN_INSN_RTX (vi)); |
1250 new_vi = create_vinsn_from_insn_rtx (copy, unique); | |
1251 if (reattach_p) | |
1252 { | |
1253 vinsn_detach (vi); | |
1254 vinsn_attach (new_vi); | |
1255 } | |
1256 | |
1257 return new_vi; | |
1258 } | |
1259 | |
1260 /* Delete the VI vinsn and free its data. */ | |
1261 static void | |
1262 vinsn_delete (vinsn_t vi) | |
1263 { | |
1264 gcc_assert (VINSN_COUNT (vi) == 0); | |
1265 | |
14
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
1266 if (!INSN_NOP_P (VINSN_INSN_RTX (vi))) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
1267 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
1268 return_regset_to_pool (VINSN_REG_SETS (vi)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
1269 return_regset_to_pool (VINSN_REG_USES (vi)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
1270 return_regset_to_pool (VINSN_REG_CLOBBERS (vi)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
1271 } |
0 | 1272 |
1273 free (vi); | |
1274 } | |
1275 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1276 /* Indicate that VI is no longer a part of some rtx object. |
0 | 1277 Remove VI if it is no longer needed. */ |
1278 void | |
1279 vinsn_detach (vinsn_t vi) | |
1280 { | |
1281 gcc_assert (VINSN_COUNT (vi) > 0); | |
1282 | |
1283 if (--VINSN_COUNT (vi) == 0) | |
1284 vinsn_delete (vi); | |
1285 } | |
1286 | |
1287 /* Returns TRUE if VI is a branch. */ | |
1288 bool | |
1289 vinsn_cond_branch_p (vinsn_t vi) | |
1290 { | |
1291 insn_t insn; | |
1292 | |
1293 if (!VINSN_UNIQUE_P (vi)) | |
1294 return false; | |
1295 | |
1296 insn = VINSN_INSN_RTX (vi); | |
1297 if (BB_END (BLOCK_FOR_INSN (insn)) != insn) | |
1298 return false; | |
1299 | |
1300 return control_flow_insn_p (insn); | |
1301 } | |
1302 | |
1303 /* Return latency of INSN. */ | |
1304 static int | |
16 | 1305 sel_insn_rtx_cost (rtx_insn *insn) |
0 | 1306 { |
1307 int cost; | |
1308 | |
1309 /* A USE insn, or something else we don't need to | |
1310 understand. We can't pass these directly to | |
1311 result_ready_cost or insn_default_latency because it will | |
1312 trigger a fatal error for unrecognizable insns. */ | |
1313 if (recog_memoized (insn) < 0) | |
1314 cost = 0; | |
1315 else | |
1316 { | |
1317 cost = insn_default_latency (insn); | |
1318 | |
1319 if (cost < 0) | |
1320 cost = 0; | |
1321 } | |
1322 | |
1323 return cost; | |
1324 } | |
1325 | |
1326 /* Return the cost of the VI. | |
16 | 1327 !!! FIXME: Unify with haifa-sched.c: insn_sched_cost (). */ |
0 | 1328 int |
1329 sel_vinsn_cost (vinsn_t vi) | |
1330 { | |
1331 int cost = vi->cost; | |
1332 | |
1333 if (cost < 0) | |
1334 { | |
1335 cost = sel_insn_rtx_cost (VINSN_INSN_RTX (vi)); | |
1336 vi->cost = cost; | |
1337 } | |
1338 | |
1339 return cost; | |
1340 } | |
1341 | |
1342 | |
1343 /* Functions for insn emitting. */ | |
1344 | |
1345 /* Emit new insn after AFTER based on PATTERN and initialize its data from | |
1346 EXPR and SEQNO. */ | |
1347 insn_t | |
1348 sel_gen_insn_from_rtx_after (rtx pattern, expr_t expr, int seqno, insn_t after) | |
1349 { | |
1350 insn_t new_insn; | |
1351 | |
1352 gcc_assert (EXPR_TARGET_AVAILABLE (expr) == true); | |
1353 | |
1354 new_insn = emit_insn_after (pattern, after); | |
1355 set_insn_init (expr, NULL, seqno); | |
1356 sel_init_new_insn (new_insn, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SSID); | |
1357 | |
1358 return new_insn; | |
1359 } | |
1360 | |
1361 /* Force newly generated vinsns to be unique. */ | |
1362 static bool init_insn_force_unique_p = false; | |
1363 | |
1364 /* Emit new speculation recovery insn after AFTER based on PATTERN and | |
1365 initialize its data from EXPR and SEQNO. */ | |
1366 insn_t | |
1367 sel_gen_recovery_insn_from_rtx_after (rtx pattern, expr_t expr, int seqno, | |
1368 insn_t after) | |
1369 { | |
1370 insn_t insn; | |
1371 | |
1372 gcc_assert (!init_insn_force_unique_p); | |
1373 | |
1374 init_insn_force_unique_p = true; | |
1375 insn = sel_gen_insn_from_rtx_after (pattern, expr, seqno, after); | |
1376 CANT_MOVE (insn) = 1; | |
1377 init_insn_force_unique_p = false; | |
1378 | |
1379 return insn; | |
1380 } | |
1381 | |
1382 /* Emit new insn after AFTER based on EXPR and SEQNO. If VINSN is not NULL, | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1383 take it as a new vinsn instead of EXPR's vinsn. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1384 We simplify insns later, after scheduling region in |
0 | 1385 simplify_changed_insns. */ |
1386 insn_t | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1387 sel_gen_insn_from_expr_after (expr_t expr, vinsn_t vinsn, int seqno, |
0 | 1388 insn_t after) |
1389 { | |
1390 expr_t emit_expr; | |
1391 insn_t insn; | |
1392 int flags; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1393 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1394 emit_expr = set_insn_init (expr, vinsn ? vinsn : EXPR_VINSN (expr), |
0 | 1395 seqno); |
1396 insn = EXPR_INSN_RTX (emit_expr); | |
16 | 1397 |
1398 /* The insn may come from the transformation cache, which may hold already | |
1399 deleted insns, so mark it as not deleted. */ | |
1400 insn->set_undeleted (); | |
1401 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1402 add_insn_after (insn, after, BLOCK_FOR_INSN (insn)); |
0 | 1403 |
1404 flags = INSN_INIT_TODO_SSID; | |
1405 if (INSN_LUID (insn) == 0) | |
1406 flags |= INSN_INIT_TODO_LUID; | |
1407 sel_init_new_insn (insn, flags); | |
1408 | |
1409 return insn; | |
1410 } | |
1411 | |
1412 /* Move insn from EXPR after AFTER. */ | |
1413 insn_t | |
1414 sel_move_insn (expr_t expr, int seqno, insn_t after) | |
1415 { | |
1416 insn_t insn = EXPR_INSN_RTX (expr); | |
1417 basic_block bb = BLOCK_FOR_INSN (after); | |
1418 insn_t next = NEXT_INSN (after); | |
1419 | |
1420 /* Assert that in move_op we disconnected this insn properly. */ | |
1421 gcc_assert (EXPR_VINSN (INSN_EXPR (insn)) != NULL); | |
16 | 1422 SET_PREV_INSN (insn) = after; |
1423 SET_NEXT_INSN (insn) = next; | |
1424 | |
1425 SET_NEXT_INSN (after) = insn; | |
1426 SET_PREV_INSN (next) = insn; | |
0 | 1427 |
1428 /* Update links from insn to bb and vice versa. */ | |
1429 df_insn_change_bb (insn, bb); | |
1430 if (BB_END (bb) == after) | |
1431 BB_END (bb) = insn; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1432 |
0 | 1433 prepare_insn_expr (insn, seqno); |
1434 return insn; | |
1435 } | |
1436 | |
1437 | |
1438 /* Functions to work with right-hand sides. */ | |
1439 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1440 /* Search for a hash value determined by UID/NEW_VINSN in a sorted vector |
0 | 1441 VECT and return true when found. Use NEW_VINSN for comparison only when |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1442 COMPARE_VINSNS is true. Write to INDP the index on which |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1443 the search has stopped, such that inserting the new element at INDP will |
0 | 1444 retain VECT's sort order. */ |
1445 static bool | |
16 | 1446 find_in_history_vect_1 (vec<expr_history_def> vect, |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1447 unsigned uid, vinsn_t new_vinsn, |
0 | 1448 bool compare_vinsns, int *indp) |
1449 { | |
1450 expr_history_def *arr; | |
16 | 1451 int i, j, len = vect.length (); |
0 | 1452 |
1453 if (len == 0) | |
1454 { | |
1455 *indp = 0; | |
1456 return false; | |
1457 } | |
1458 | |
16 | 1459 arr = vect.address (); |
0 | 1460 i = 0, j = len - 1; |
1461 | |
1462 while (i <= j) | |
1463 { | |
1464 unsigned auid = arr[i].uid; | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1465 vinsn_t avinsn = arr[i].new_expr_vinsn; |
0 | 1466 |
1467 if (auid == uid | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1468 /* When undoing transformation on a bookkeeping copy, the new vinsn |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1469 may not be exactly equal to the one that is saved in the vector. |
0 | 1470 This is because the insn whose copy we're checking was possibly |
1471 substituted itself. */ | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1472 && (! compare_vinsns |
0 | 1473 || vinsn_equal_p (avinsn, new_vinsn))) |
1474 { | |
1475 *indp = i; | |
1476 return true; | |
1477 } | |
1478 else if (auid > uid) | |
1479 break; | |
1480 i++; | |
1481 } | |
1482 | |
1483 *indp = i; | |
1484 return false; | |
1485 } | |
1486 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1487 /* Search for a uid of INSN and NEW_VINSN in a sorted vector VECT. Return |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1488 the position found or -1, if no such value is in vector. |
0 | 1489 Search also for UIDs of insn's originators, if ORIGINATORS_P is true. */ |
1490 int | |
16 | 1491 find_in_history_vect (vec<expr_history_def> vect, rtx insn, |
0 | 1492 vinsn_t new_vinsn, bool originators_p) |
1493 { | |
1494 int ind; | |
1495 | |
9
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1496 if (find_in_history_vect_1 (vect, INSN_UID (insn), new_vinsn, |
0 | 1497 false, &ind)) |
1498 return ind; | |
1499 | |
1500 if (INSN_ORIGINATORS (insn) && originators_p) | |
a06113de4d67
first co |