]>
Commit | Line | Data |
---|---|---|
7b82b5da | 1 | /* Register renaming for the GNU compiler. |
c75c517d SB |
2 | Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, |
3 | 2010 Free Software Foundation, Inc. | |
7b82b5da | 4 | |
1322177d | 5 | This file is part of GCC. |
7b82b5da | 6 | |
1322177d LB |
7 | GCC is free software; you can redistribute it and/or modify it |
8 | under the terms of the GNU General Public License as published by | |
9dcd6f09 | 9 | the Free Software Foundation; either version 3, or (at your option) |
7b82b5da SC |
10 | any later version. |
11 | ||
1322177d LB |
12 | GCC is distributed in the hope that it will be useful, but WITHOUT |
13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
15 | License for more details. | |
7b82b5da SC |
16 | |
17 | You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ | |
7b82b5da SC |
20 | |
21 | #include "config.h" | |
22 | #include "system.h" | |
4977bab6 ZW |
23 | #include "coretypes.h" |
24 | #include "tm.h" | |
0cbd9993 | 25 | #include "rtl-error.h" |
541f7d56 | 26 | #include "tm_p.h" |
7b82b5da SC |
27 | #include "insn-config.h" |
28 | #include "regs.h" | |
c4963a0a | 29 | #include "addresses.h" |
541f7d56 BS |
30 | #include "hard-reg-set.h" |
31 | #include "basic-block.h" | |
32 | #include "reload.h" | |
7b82b5da SC |
33 | #include "output.h" |
34 | #include "function.h" | |
35 | #include "recog.h" | |
541f7d56 BS |
36 | #include "flags.h" |
37 | #include "obstack.h" | |
ef330312 PB |
38 | #include "timevar.h" |
39 | #include "tree-pass.h" | |
6fb5fa3c | 40 | #include "df.h" |
541f7d56 | 41 | |
d435810e BS |
42 | #if HOST_BITS_PER_WIDE_INT <= MAX_RECOG_OPERANDS |
43 | #error "Use a different bitmap implementation for untracked_operands." | |
44 | #endif | |
45 | ||
9d324dde BS |
46 | /* We keep linked lists of DU_HEAD structures, each of which describes |
47 | a chain of occurrences of a reg. */ | |
48 | struct du_head | |
49 | { | |
50 | /* The next chain. */ | |
51 | struct du_head *next_chain; | |
52 | /* The first and last elements of this chain. */ | |
53 | struct du_chain *first, *last; | |
54 | /* Describes the register being tracked. */ | |
55 | unsigned regno, nregs; | |
a96caf80 BS |
56 | |
57 | /* A unique id to be used as an index into the conflicts bitmaps. */ | |
58 | unsigned id; | |
59 | /* A bitmap to record conflicts with other chains. */ | |
60 | bitmap_head conflicts; | |
61 | /* Conflicts with untracked hard registers. */ | |
62 | HARD_REG_SET hard_conflicts; | |
63 | ||
64 | /* Nonzero if the chain is finished; zero if it is still open. */ | |
65 | unsigned int terminated:1; | |
9d324dde BS |
66 | /* Nonzero if the chain crosses a call. */ |
67 | unsigned int need_caller_save_reg:1; | |
a96caf80 BS |
68 | /* Nonzero if the register is used in a way that prevents renaming, |
69 | such as the SET_DEST of a CALL_INSN or an asm operand that used | |
70 | to be a hard register. */ | |
71 | unsigned int cannot_rename:1; | |
9d324dde BS |
72 | }; |
73 | ||
74 | /* This struct describes a single occurrence of a register. */ | |
541f7d56 | 75 | struct du_chain |
7b82b5da | 76 | { |
9d324dde | 77 | /* Links to the next occurrence of the register. */ |
541f7d56 | 78 | struct du_chain *next_use; |
7b82b5da | 79 | |
9d324dde | 80 | /* The insn where the register appears. */ |
541f7d56 | 81 | rtx insn; |
9d324dde | 82 | /* The location inside the insn. */ |
541f7d56 | 83 | rtx *loc; |
9d324dde | 84 | /* The register class required by the insn at this location. */ |
e3a64162 | 85 | ENUM_BITFIELD(reg_class) cl : 16; |
541f7d56 | 86 | }; |
7b82b5da | 87 | |
541f7d56 BS |
88 | enum scan_actions |
89 | { | |
541f7d56 BS |
90 | terminate_write, |
91 | terminate_dead, | |
a96caf80 | 92 | mark_all_read, |
541f7d56 | 93 | mark_read, |
cb110f3d AM |
94 | mark_write, |
95 | /* mark_access is for marking the destination regs in | |
96 | REG_FRAME_RELATED_EXPR notes (as if they were read) so that the | |
97 | note is updated properly. */ | |
98 | mark_access | |
541f7d56 BS |
99 | }; |
100 | ||
101 | static const char * const scan_actions_name[] = | |
102 | { | |
541f7d56 BS |
103 | "terminate_write", |
104 | "terminate_dead", | |
a96caf80 | 105 | "mark_all_read", |
541f7d56 | 106 | "mark_read", |
cb110f3d AM |
107 | "mark_write", |
108 | "mark_access" | |
541f7d56 BS |
109 | }; |
110 | ||
111 | static struct obstack rename_obstack; | |
112 | ||
9d324dde | 113 | static void do_replace (struct du_head *, int); |
0c20a65f | 114 | static void scan_rtx_reg (rtx, rtx *, enum reg_class, |
6bda9bdf | 115 | enum scan_actions, enum op_type); |
0c20a65f AJ |
116 | static void scan_rtx_address (rtx, rtx *, enum reg_class, |
117 | enum scan_actions, enum machine_mode); | |
118 | static void scan_rtx (rtx, rtx *, enum reg_class, enum scan_actions, | |
6bda9bdf | 119 | enum op_type); |
9d324dde BS |
120 | static struct du_head *build_def_use (basic_block); |
121 | static void dump_def_use_chain (struct du_head *); | |
fe08a886 | 122 | |
a96caf80 BS |
123 | typedef struct du_head *du_head_p; |
124 | DEF_VEC_P (du_head_p); | |
125 | DEF_VEC_ALLOC_P (du_head_p, heap); | |
126 | static VEC(du_head_p, heap) *id_to_chain; | |
fe08a886 BS |
127 | |
128 | static void | |
a96caf80 | 129 | free_chain_data (void) |
fe08a886 | 130 | { |
a96caf80 BS |
131 | int i; |
132 | du_head_p ptr; | |
133 | for (i = 0; VEC_iterate(du_head_p, id_to_chain, i, ptr); i++) | |
134 | bitmap_clear (&ptr->conflicts); | |
226c62c7 | 135 | |
a96caf80 | 136 | VEC_free (du_head_p, heap, id_to_chain); |
fe08a886 BS |
137 | } |
138 | ||
a96caf80 BS |
139 | /* For a def-use chain HEAD, find which registers overlap its lifetime and |
140 | set the corresponding bits in *PSET. */ | |
fe08a886 BS |
141 | |
142 | static void | |
a96caf80 | 143 | merge_overlapping_regs (HARD_REG_SET *pset, struct du_head *head) |
fe08a886 | 144 | { |
a96caf80 BS |
145 | bitmap_iterator bi; |
146 | unsigned i; | |
147 | IOR_HARD_REG_SET (*pset, head->hard_conflicts); | |
148 | EXECUTE_IF_SET_IN_BITMAP (&head->conflicts, 0, i, bi) | |
32fc3abf | 149 | { |
a96caf80 BS |
150 | du_head_p other = VEC_index (du_head_p, id_to_chain, i); |
151 | unsigned j = other->nregs; | |
152 | while (j-- > 0) | |
153 | SET_HARD_REG_BIT (*pset, other->regno + j); | |
fe08a886 BS |
154 | } |
155 | } | |
156 | ||
157 | /* Perform register renaming on the current function. */ | |
7b82b5da | 158 | |
fac41238 | 159 | static unsigned int |
0c20a65f | 160 | regrename_optimize (void) |
541f7d56 | 161 | { |
fe08a886 BS |
162 | int tick[FIRST_PSEUDO_REGISTER]; |
163 | int this_tick = 0; | |
e0082a72 | 164 | basic_block bb; |
541f7d56 | 165 | char *first_obj; |
7b82b5da | 166 | |
6fb5fa3c DB |
167 | df_set_flags (DF_LR_RUN_DCE); |
168 | df_note_add_problem (); | |
169 | df_analyze (); | |
8e4bf5c7 KZ |
170 | df_set_flags (DF_DEFER_INSN_RESCAN); |
171 | ||
fe08a886 BS |
172 | memset (tick, 0, sizeof tick); |
173 | ||
541f7d56 | 174 | gcc_obstack_init (&rename_obstack); |
1634b18f | 175 | first_obj = XOBNEWVAR (&rename_obstack, char, 0); |
7b82b5da | 176 | |
e0082a72 | 177 | FOR_EACH_BB (bb) |
541f7d56 | 178 | { |
9d324dde | 179 | struct du_head *all_chains = 0; |
541f7d56 | 180 | HARD_REG_SET unavailable; |
0f900dfa | 181 | #if 0 |
541f7d56 | 182 | HARD_REG_SET regs_seen; |
0f900dfa JJ |
183 | CLEAR_HARD_REG_SET (regs_seen); |
184 | #endif | |
7b82b5da | 185 | |
a96caf80 BS |
186 | id_to_chain = VEC_alloc (du_head_p, heap, 0); |
187 | ||
541f7d56 | 188 | CLEAR_HARD_REG_SET (unavailable); |
7b82b5da | 189 | |
c263766c RH |
190 | if (dump_file) |
191 | fprintf (dump_file, "\nBasic block %d:\n", bb->index); | |
7b82b5da | 192 | |
fe08a886 | 193 | all_chains = build_def_use (bb); |
7b82b5da | 194 | |
c263766c | 195 | if (dump_file) |
541f7d56 | 196 | dump_def_use_chain (all_chains); |
7b82b5da | 197 | |
fe08a886 | 198 | CLEAR_HARD_REG_SET (unavailable); |
541f7d56 BS |
199 | /* Don't clobber traceback for noreturn functions. */ |
200 | if (frame_pointer_needed) | |
201 | { | |
09e18274 | 202 | add_to_hard_reg_set (&unavailable, Pmode, FRAME_POINTER_REGNUM); |
e3339d0f | 203 | #if !HARD_FRAME_POINTER_IS_FRAME_POINTER |
09e18274 | 204 | add_to_hard_reg_set (&unavailable, Pmode, HARD_FRAME_POINTER_REGNUM); |
541f7d56 BS |
205 | #endif |
206 | } | |
7b82b5da | 207 | |
541f7d56 BS |
208 | while (all_chains) |
209 | { | |
a96caf80 | 210 | int new_reg, best_new_reg, best_nregs; |
541f7d56 | 211 | int n_uses; |
9d324dde | 212 | struct du_head *this_head = all_chains; |
b5b8b0ac | 213 | struct du_chain *tmp; |
541f7d56 | 214 | HARD_REG_SET this_unavailable; |
9d324dde | 215 | int reg = this_head->regno; |
85941a0a | 216 | int i; |
7b82b5da | 217 | |
9d324dde | 218 | all_chains = this_head->next_chain; |
3b03c671 | 219 | |
a96caf80 BS |
220 | if (this_head->cannot_rename) |
221 | continue; | |
222 | ||
62551c66 | 223 | best_new_reg = reg; |
a96caf80 | 224 | best_nregs = this_head->nregs; |
62551c66 | 225 | |
fe08a886 | 226 | #if 0 /* This just disables optimization opportunities. */ |
541f7d56 BS |
227 | /* Only rename once we've seen the reg more than once. */ |
228 | if (! TEST_HARD_REG_BIT (regs_seen, reg)) | |
1a43c33f | 229 | { |
541f7d56 BS |
230 | SET_HARD_REG_BIT (regs_seen, reg); |
231 | continue; | |
232 | } | |
fe08a886 | 233 | #endif |
1a43c33f | 234 | |
f4d578da | 235 | if (fixed_regs[reg] || global_regs[reg] |
e3339d0f | 236 | #if !HARD_FRAME_POINTER_IS_FRAME_POINTER |
f4d578da BS |
237 | || (frame_pointer_needed && reg == HARD_FRAME_POINTER_REGNUM) |
238 | #else | |
239 | || (frame_pointer_needed && reg == FRAME_POINTER_REGNUM) | |
240 | #endif | |
241 | ) | |
541f7d56 | 242 | continue; |
1a43c33f | 243 | |
541f7d56 | 244 | COPY_HARD_REG_SET (this_unavailable, unavailable); |
1a43c33f | 245 | |
b5b8b0ac | 246 | /* Count number of uses, and narrow the set of registers we can |
541f7d56 BS |
247 | use for renaming. */ |
248 | n_uses = 0; | |
9d324dde | 249 | for (tmp = this_head->first; tmp; tmp = tmp->next_use) |
541f7d56 | 250 | { |
b5b8b0ac AO |
251 | if (DEBUG_INSN_P (tmp->insn)) |
252 | continue; | |
541f7d56 BS |
253 | n_uses++; |
254 | IOR_COMPL_HARD_REG_SET (this_unavailable, | |
b5b8b0ac | 255 | reg_class_contents[tmp->cl]); |
1a43c33f | 256 | } |
7b82b5da | 257 | |
b5b8b0ac AO |
258 | if (n_uses < 2) |
259 | continue; | |
7b82b5da | 260 | |
9d324dde | 261 | if (this_head->need_caller_save_reg) |
541f7d56 BS |
262 | IOR_HARD_REG_SET (this_unavailable, call_used_reg_set); |
263 | ||
a96caf80 | 264 | merge_overlapping_regs (&this_unavailable, this_head); |
fe08a886 | 265 | |
541f7d56 BS |
266 | /* Now potential_regs is a reasonable approximation, let's |
267 | have a closer look at each register still in there. */ | |
4e812700 | 268 | for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++) |
1a43c33f | 269 | { |
9d324dde BS |
270 | enum machine_mode mode = GET_MODE (*this_head->first->loc); |
271 | int nregs = hard_regno_nregs[new_reg][mode]; | |
4e812700 | 272 | |
85941a0a | 273 | for (i = nregs - 1; i >= 0; --i) |
fe08a886 BS |
274 | if (TEST_HARD_REG_BIT (this_unavailable, new_reg + i) |
275 | || fixed_regs[new_reg + i] | |
276 | || global_regs[new_reg + i] | |
85941a0a | 277 | /* Can't use regs which aren't saved by the prologue. */ |
6fb5fa3c | 278 | || (! df_regs_ever_live_p (new_reg + i) |
fe08a886 | 279 | && ! call_used_regs[new_reg + i]) |
b2a8b026 | 280 | #ifdef LEAF_REGISTERS |
3b03c671 | 281 | /* We can't use a non-leaf register if we're in a |
b2a8b026 | 282 | leaf function. */ |
3b03c671 | 283 | || (current_function_is_leaf |
b2a8b026 MM |
284 | && !LEAF_REGISTERS[new_reg + i]) |
285 | #endif | |
541f7d56 | 286 | #ifdef HARD_REGNO_RENAME_OK |
fe08a886 | 287 | || ! HARD_REGNO_RENAME_OK (reg + i, new_reg + i) |
541f7d56 | 288 | #endif |
85941a0a RH |
289 | ) |
290 | break; | |
291 | if (i >= 0) | |
541f7d56 | 292 | continue; |
1a43c33f | 293 | |
85941a0a RH |
294 | /* See whether it accepts all modes that occur in |
295 | definition and uses. */ | |
9d324dde | 296 | for (tmp = this_head->first; tmp; tmp = tmp->next_use) |
b5b8b0ac AO |
297 | if ((! HARD_REGNO_MODE_OK (new_reg, GET_MODE (*tmp->loc)) |
298 | && ! DEBUG_INSN_P (tmp->insn)) | |
9d324dde | 299 | || (this_head->need_caller_save_reg |
66df7a98 AO |
300 | && ! (HARD_REGNO_CALL_PART_CLOBBERED |
301 | (reg, GET_MODE (*tmp->loc))) | |
302 | && (HARD_REGNO_CALL_PART_CLOBBERED | |
303 | (new_reg, GET_MODE (*tmp->loc))))) | |
541f7d56 BS |
304 | break; |
305 | if (! tmp) | |
fe08a886 | 306 | { |
62551c66 | 307 | if (tick[best_new_reg] > tick[new_reg]) |
a96caf80 BS |
308 | { |
309 | best_new_reg = new_reg; | |
310 | best_nregs = nregs; | |
311 | } | |
fe08a886 | 312 | } |
1a43c33f | 313 | } |
7b82b5da | 314 | |
c263766c | 315 | if (dump_file) |
541f7d56 | 316 | { |
c263766c | 317 | fprintf (dump_file, "Register %s in insn %d", |
9d324dde BS |
318 | reg_names[reg], INSN_UID (this_head->first->insn)); |
319 | if (this_head->need_caller_save_reg) | |
c263766c | 320 | fprintf (dump_file, " crosses a call"); |
3b03c671 | 321 | } |
1a43c33f | 322 | |
62551c66 | 323 | if (best_new_reg == reg) |
541f7d56 | 324 | { |
62551c66 | 325 | tick[reg] = ++this_tick; |
c263766c RH |
326 | if (dump_file) |
327 | fprintf (dump_file, "; no available better choice\n"); | |
7b82b5da | 328 | continue; |
541f7d56 | 329 | } |
7b82b5da | 330 | |
b21b850e SB |
331 | if (dump_file) |
332 | fprintf (dump_file, ", renamed as %s\n", reg_names[best_new_reg]); | |
333 | ||
9d324dde | 334 | do_replace (this_head, best_new_reg); |
a96caf80 BS |
335 | this_head->regno = best_new_reg; |
336 | this_head->nregs = best_nregs; | |
62551c66 | 337 | tick[best_new_reg] = ++this_tick; |
6fb5fa3c | 338 | df_set_regs_ever_live (best_new_reg, true); |
541f7d56 | 339 | } |
1a43c33f | 340 | |
a96caf80 | 341 | free_chain_data (); |
541f7d56 BS |
342 | obstack_free (&rename_obstack, first_obj); |
343 | } | |
1a43c33f | 344 | |
541f7d56 | 345 | obstack_free (&rename_obstack, NULL); |
7b82b5da | 346 | |
c263766c RH |
347 | if (dump_file) |
348 | fputc ('\n', dump_file); | |
fac41238 PB |
349 | |
350 | return 0; | |
7b82b5da SC |
351 | } |
352 | ||
7b82b5da | 353 | static void |
9d324dde | 354 | do_replace (struct du_head *head, int reg) |
7b82b5da | 355 | { |
9d324dde BS |
356 | struct du_chain *chain; |
357 | unsigned int base_regno = head->regno; | |
a96caf80 | 358 | bool found_note = false; |
b5b8b0ac | 359 | |
9d324dde | 360 | gcc_assert (! DEBUG_INSN_P (head->first->insn)); |
b5b8b0ac | 361 | |
9d324dde | 362 | for (chain = head->first; chain; chain = chain->next_use) |
7b82b5da | 363 | { |
08394eef | 364 | unsigned int regno = ORIGINAL_REGNO (*chain->loc); |
9d324dde | 365 | struct reg_attrs *attr = REG_ATTRS (*chain->loc); |
b41310e2 | 366 | int reg_ptr = REG_POINTER (*chain->loc); |
d1d3c9a6 | 367 | |
b5b8b0ac AO |
368 | if (DEBUG_INSN_P (chain->insn) && REGNO (*chain->loc) != base_regno) |
369 | INSN_VAR_LOCATION_LOC (chain->insn) = gen_rtx_UNKNOWN_VAR_LOC (); | |
370 | else | |
371 | { | |
af94453d CB |
372 | rtx note; |
373 | ||
b5b8b0ac AO |
374 | *chain->loc = gen_raw_REG (GET_MODE (*chain->loc), reg); |
375 | if (regno >= FIRST_PSEUDO_REGISTER) | |
376 | ORIGINAL_REGNO (*chain->loc) = regno; | |
377 | REG_ATTRS (*chain->loc) = attr; | |
378 | REG_POINTER (*chain->loc) = reg_ptr; | |
af94453d CB |
379 | |
380 | for (note = REG_NOTES (chain->insn); note; note = XEXP (note, 1)) | |
381 | { | |
a96caf80 BS |
382 | enum reg_note kind = REG_NOTE_KIND (note); |
383 | if (kind == REG_DEAD || kind == REG_UNUSED) | |
af94453d CB |
384 | { |
385 | rtx reg = XEXP (note, 0); | |
386 | gcc_assert (HARD_REGISTER_P (reg)); | |
b8698a0f L |
387 | |
388 | if (REGNO (reg) == base_regno) | |
a96caf80 BS |
389 | { |
390 | found_note = true; | |
391 | if (kind == REG_DEAD | |
392 | && reg_set_p (*chain->loc, chain->insn)) | |
393 | remove_note (chain->insn, note); | |
394 | else | |
395 | XEXP (note, 0) = *chain->loc; | |
396 | break; | |
397 | } | |
af94453d CB |
398 | } |
399 | } | |
b5b8b0ac AO |
400 | } |
401 | ||
8e4bf5c7 | 402 | df_insn_rescan (chain->insn); |
7b82b5da | 403 | } |
a96caf80 BS |
404 | if (!found_note) |
405 | { | |
406 | /* If the chain's first insn is the same as the last, we should have | |
407 | found a REG_UNUSED note. */ | |
408 | gcc_assert (head->first->insn != head->last->insn); | |
409 | if (!reg_set_p (*head->last->loc, head->last->insn)) | |
410 | add_reg_note (head->last->insn, REG_DEAD, *head->last->loc); | |
411 | } | |
7b82b5da SC |
412 | } |
413 | ||
7b82b5da | 414 | |
a96caf80 BS |
415 | /* Walk all chains starting with CHAINS and record that they conflict with |
416 | another chain whose id is ID. */ | |
417 | ||
418 | static void | |
419 | mark_conflict (struct du_head *chains, unsigned id) | |
420 | { | |
421 | while (chains) | |
422 | { | |
423 | bitmap_set_bit (&chains->conflicts, id); | |
424 | chains = chains->next_chain; | |
425 | } | |
426 | } | |
427 | ||
428 | /* True if we found a register with a size mismatch, which means that we | |
429 | can't track its lifetime accurately. If so, we abort the current block | |
430 | without renaming. */ | |
431 | static bool fail_current_block; | |
432 | ||
433 | /* The id to be given to the next opened chain. */ | |
434 | static unsigned current_id; | |
435 | ||
436 | /* List of currently open chains, and closed chains that can be renamed. */ | |
9d324dde BS |
437 | static struct du_head *open_chains; |
438 | static struct du_head *closed_chains; | |
541f7d56 | 439 | |
d435810e | 440 | /* Bitmap of open chains. The bits set always match the list found in |
a96caf80 BS |
441 | open_chains. */ |
442 | static bitmap_head open_chains_set; | |
a96caf80 | 443 | |
d435810e | 444 | /* Record the registers being tracked in open_chains. */ |
1f924675 BS |
445 | static HARD_REG_SET live_in_chains; |
446 | ||
d435810e BS |
447 | /* Record the registers that are live but not tracked. The intersection |
448 | between this and live_in_chains is empty. */ | |
449 | static HARD_REG_SET live_hard_regs; | |
450 | ||
451 | /* Return true if OP is a reg for which all bits are set in PSET, false | |
452 | if all bits are clear. | |
453 | In other cases, set fail_current_block and return false. */ | |
1f924675 BS |
454 | |
455 | static bool | |
d435810e | 456 | verify_reg_in_set (rtx op, HARD_REG_SET *pset) |
1f924675 BS |
457 | { |
458 | unsigned regno, nregs; | |
459 | bool all_live, all_dead; | |
460 | if (!REG_P (op)) | |
461 | return false; | |
462 | ||
463 | regno = REGNO (op); | |
464 | nregs = hard_regno_nregs[regno][GET_MODE (op)]; | |
465 | all_live = all_dead = true; | |
466 | while (nregs-- > 0) | |
d435810e | 467 | if (TEST_HARD_REG_BIT (*pset, regno + nregs)) |
1f924675 BS |
468 | all_dead = false; |
469 | else | |
470 | all_live = false; | |
471 | if (!all_dead && !all_live) | |
472 | { | |
473 | fail_current_block = true; | |
474 | return false; | |
475 | } | |
d435810e BS |
476 | return all_live; |
477 | } | |
1f924675 | 478 | |
d435810e BS |
479 | /* Return true if OP is a reg that is being tracked already in some form. |
480 | May set fail_current_block if it sees an unhandled case of overlap. */ | |
1f924675 | 481 | |
d435810e BS |
482 | static bool |
483 | verify_reg_tracked (rtx op) | |
484 | { | |
485 | return (verify_reg_in_set (op, &live_hard_regs) | |
486 | || verify_reg_in_set (op, &live_in_chains)); | |
1f924675 BS |
487 | } |
488 | ||
a96caf80 BS |
489 | /* Called through note_stores. DATA points to a rtx_code, either SET or |
490 | CLOBBER, which tells us which kind of rtx to look at. If we have a | |
491 | match, record the set register in live_hard_regs and in the hard_conflicts | |
492 | bitmap of open chains. */ | |
493 | ||
494 | static void | |
495 | note_sets_clobbers (rtx x, const_rtx set, void *data) | |
496 | { | |
497 | enum rtx_code code = *(enum rtx_code *)data; | |
498 | struct du_head *chain; | |
499 | ||
500 | if (GET_CODE (x) == SUBREG) | |
501 | x = SUBREG_REG (x); | |
502 | if (!REG_P (x) || GET_CODE (set) != code) | |
503 | return; | |
504 | /* There must not be pseudos at this point. */ | |
505 | gcc_assert (HARD_REGISTER_P (x)); | |
506 | add_to_hard_reg_set (&live_hard_regs, GET_MODE (x), REGNO (x)); | |
507 | for (chain = open_chains; chain; chain = chain->next_chain) | |
508 | add_to_hard_reg_set (&chain->hard_conflicts, GET_MODE (x), REGNO (x)); | |
509 | } | |
510 | ||
e33c42db BS |
511 | /* Create a new chain for THIS_NREGS registers starting at THIS_REGNO, |
512 | and record its occurrence in *LOC, which is being written to in INSN. | |
513 | This access requires a register of class CL. */ | |
514 | ||
515 | static void | |
516 | create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc, | |
517 | rtx insn, enum reg_class cl) | |
518 | { | |
519 | struct du_head *head = XOBNEW (&rename_obstack, struct du_head); | |
520 | struct du_chain *this_du; | |
521 | int nregs; | |
522 | ||
523 | head->next_chain = open_chains; | |
524 | open_chains = head; | |
525 | head->regno = this_regno; | |
526 | head->nregs = this_nregs; | |
527 | head->need_caller_save_reg = 0; | |
528 | head->cannot_rename = 0; | |
529 | head->terminated = 0; | |
530 | ||
531 | VEC_safe_push (du_head_p, heap, id_to_chain, head); | |
532 | head->id = current_id++; | |
533 | ||
534 | bitmap_initialize (&head->conflicts, &bitmap_default_obstack); | |
535 | bitmap_copy (&head->conflicts, &open_chains_set); | |
536 | mark_conflict (open_chains, head->id); | |
537 | ||
538 | /* Since we're tracking this as a chain now, remove it from the | |
539 | list of conflicting live hard registers and track it in | |
540 | live_in_chains instead. */ | |
541 | nregs = head->nregs; | |
542 | while (nregs-- > 0) | |
543 | { | |
544 | SET_HARD_REG_BIT (live_in_chains, head->regno + nregs); | |
545 | CLEAR_HARD_REG_BIT (live_hard_regs, head->regno + nregs); | |
546 | } | |
547 | ||
548 | COPY_HARD_REG_SET (head->hard_conflicts, live_hard_regs); | |
549 | bitmap_set_bit (&open_chains_set, head->id); | |
550 | ||
551 | open_chains = head; | |
552 | ||
553 | if (dump_file) | |
554 | { | |
555 | fprintf (dump_file, "Creating chain %s (%d)", | |
556 | reg_names[head->regno], head->id); | |
557 | if (insn != NULL_RTX) | |
558 | fprintf (dump_file, " at insn %d", INSN_UID (insn)); | |
559 | fprintf (dump_file, "\n"); | |
560 | } | |
561 | ||
562 | if (insn == NULL_RTX) | |
563 | { | |
564 | head->first = head->last = NULL; | |
565 | return; | |
566 | } | |
567 | ||
568 | this_du = XOBNEW (&rename_obstack, struct du_chain); | |
569 | head->first = head->last = this_du; | |
570 | ||
571 | this_du->next_use = 0; | |
572 | this_du->loc = loc; | |
573 | this_du->insn = insn; | |
574 | this_du->cl = cl; | |
575 | } | |
576 | ||
541f7d56 | 577 | static void |
6bda9bdf BS |
578 | scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action, |
579 | enum op_type type) | |
7b82b5da | 580 | { |
9d324dde | 581 | struct du_head **p; |
541f7d56 BS |
582 | rtx x = *loc; |
583 | enum machine_mode mode = GET_MODE (x); | |
9d324dde BS |
584 | unsigned this_regno = REGNO (x); |
585 | unsigned this_nregs = hard_regno_nregs[this_regno][mode]; | |
541f7d56 | 586 | |
541f7d56 | 587 | if (action == mark_write) |
7b82b5da | 588 | { |
541f7d56 | 589 | if (type == OP_OUT) |
e33c42db | 590 | create_new_chain (this_regno, this_nregs, loc, insn, cl); |
541f7d56 | 591 | return; |
7b82b5da | 592 | } |
1a43c33f | 593 | |
cb110f3d | 594 | if ((type == OP_OUT) != (action == terminate_write || action == mark_access)) |
541f7d56 | 595 | return; |
5fa41e13 | 596 | |
541f7d56 | 597 | for (p = &open_chains; *p;) |
5fa41e13 | 598 | { |
9d324dde | 599 | struct du_head *head = *p; |
a96caf80 BS |
600 | struct du_head *next = head->next_chain; |
601 | int exact_match = (head->regno == this_regno | |
602 | && head->nregs == this_nregs); | |
603 | int superset = (this_regno <= head->regno | |
604 | && this_regno + this_nregs >= head->regno + head->nregs); | |
d435810e BS |
605 | int subset = (this_regno >= head->regno |
606 | && this_regno + this_nregs <= head->regno + head->nregs); | |
a96caf80 BS |
607 | |
608 | if (head->terminated | |
609 | || head->regno + head->nregs <= this_regno | |
610 | || this_regno + this_nregs <= head->regno) | |
611 | { | |
612 | p = &head->next_chain; | |
613 | continue; | |
614 | } | |
541f7d56 | 615 | |
a96caf80 | 616 | if (action == mark_read || action == mark_access) |
3b03c671 | 617 | { |
a96caf80 BS |
618 | /* ??? Class NO_REGS can happen if the md file makes use of |
619 | EXTRA_CONSTRAINTS to match registers. Which is arguably | |
620 | wrong, but there we are. */ | |
695e4773 | 621 | |
a96caf80 | 622 | if (cl == NO_REGS || (!exact_match && !DEBUG_INSN_P (insn))) |
a125d855 | 623 | { |
a96caf80 BS |
624 | if (dump_file) |
625 | fprintf (dump_file, | |
626 | "Cannot rename chain %s (%d) at insn %d (%s)\n", | |
627 | reg_names[head->regno], head->id, INSN_UID (insn), | |
628 | scan_actions_name[(int) action]); | |
629 | head->cannot_rename = 1; | |
d435810e BS |
630 | if (superset) |
631 | { | |
632 | unsigned nregs = this_nregs; | |
633 | head->regno = this_regno; | |
634 | head->nregs = this_nregs; | |
635 | while (nregs-- > 0) | |
636 | SET_HARD_REG_BIT (live_in_chains, head->regno + nregs); | |
637 | if (dump_file) | |
638 | fprintf (dump_file, | |
639 | "Widening register in chain %s (%d) at insn %d\n", | |
640 | reg_names[head->regno], head->id, INSN_UID (insn)); | |
641 | } | |
642 | else if (!subset) | |
643 | { | |
644 | fail_current_block = true; | |
645 | if (dump_file) | |
646 | fprintf (dump_file, | |
647 | "Failing basic block due to unhandled overlap\n"); | |
648 | } | |
a125d855 | 649 | } |
a96caf80 | 650 | else |
541f7d56 | 651 | { |
a96caf80 BS |
652 | struct du_chain *this_du; |
653 | this_du = XOBNEW (&rename_obstack, struct du_chain); | |
654 | this_du->next_use = 0; | |
655 | this_du->loc = loc; | |
656 | this_du->insn = insn; | |
657 | this_du->cl = cl; | |
e33c42db BS |
658 | if (head->first == NULL) |
659 | head->first = this_du; | |
660 | else | |
661 | head->last->next_use = this_du; | |
a96caf80 | 662 | head->last = this_du; |
695e4773 | 663 | |
541f7d56 | 664 | } |
a96caf80 BS |
665 | /* Avoid adding the same location in a DEBUG_INSN multiple times, |
666 | which could happen with non-exact overlap. */ | |
667 | if (DEBUG_INSN_P (insn)) | |
668 | return; | |
669 | /* Otherwise, find any other chains that do not match exactly; | |
670 | ensure they all get marked unrenamable. */ | |
671 | p = &head->next_chain; | |
672 | continue; | |
673 | } | |
a125d855 | 674 | |
a96caf80 BS |
675 | /* Whether the terminated chain can be used for renaming |
676 | depends on the action and this being an exact match. | |
677 | In either case, we remove this element from open_chains. */ | |
695e4773 | 678 | |
a96caf80 BS |
679 | if ((action == terminate_dead || action == terminate_write) |
680 | && superset) | |
681 | { | |
1f924675 BS |
682 | unsigned nregs; |
683 | ||
a96caf80 BS |
684 | head->terminated = 1; |
685 | head->next_chain = closed_chains; | |
686 | closed_chains = head; | |
687 | bitmap_clear_bit (&open_chains_set, head->id); | |
1f924675 BS |
688 | |
689 | nregs = head->nregs; | |
690 | while (nregs-- > 0) | |
691 | CLEAR_HARD_REG_BIT (live_in_chains, head->regno + nregs); | |
692 | ||
a96caf80 BS |
693 | *p = next; |
694 | if (dump_file) | |
695 | fprintf (dump_file, | |
696 | "Closing chain %s (%d) at insn %d (%s)\n", | |
697 | reg_names[head->regno], head->id, INSN_UID (insn), | |
698 | scan_actions_name[(int) action]); | |
699 | } | |
700 | else if (action == terminate_dead || action == terminate_write) | |
701 | { | |
702 | /* In this case, tracking liveness gets too hard. Fail the | |
703 | entire basic block. */ | |
704 | if (dump_file) | |
705 | fprintf (dump_file, | |
706 | "Failing basic block due to unhandled overlap\n"); | |
707 | fail_current_block = true; | |
708 | return; | |
709 | } | |
710 | else | |
711 | { | |
712 | head->cannot_rename = 1; | |
713 | if (dump_file) | |
714 | fprintf (dump_file, | |
715 | "Cannot rename chain %s (%d) at insn %d (%s)\n", | |
716 | reg_names[head->regno], head->id, INSN_UID (insn), | |
717 | scan_actions_name[(int) action]); | |
718 | p = &head->next_chain; | |
541f7d56 | 719 | } |
541f7d56 | 720 | } |
7b82b5da SC |
721 | } |
722 | ||
e3a64162 | 723 | /* Adapted from find_reloads_address_1. CL is INDEX_REG_CLASS or |
541f7d56 | 724 | BASE_REG_CLASS depending on how the register is being considered. */ |
7b82b5da | 725 | |
4ca0f257 | 726 | static void |
e3a64162 | 727 | scan_rtx_address (rtx insn, rtx *loc, enum reg_class cl, |
0c20a65f | 728 | enum scan_actions action, enum machine_mode mode) |
7b82b5da | 729 | { |
541f7d56 BS |
730 | rtx x = *loc; |
731 | RTX_CODE code = GET_CODE (x); | |
732 | const char *fmt; | |
733 | int i, j; | |
7b82b5da | 734 | |
cb110f3d | 735 | if (action == mark_write || action == mark_access) |
541f7d56 | 736 | return; |
7b82b5da | 737 | |
541f7d56 | 738 | switch (code) |
7b82b5da | 739 | { |
541f7d56 BS |
740 | case PLUS: |
741 | { | |
742 | rtx orig_op0 = XEXP (x, 0); | |
743 | rtx orig_op1 = XEXP (x, 1); | |
744 | RTX_CODE code0 = GET_CODE (orig_op0); | |
745 | RTX_CODE code1 = GET_CODE (orig_op1); | |
746 | rtx op0 = orig_op0; | |
747 | rtx op1 = orig_op1; | |
748 | rtx *locI = NULL; | |
749 | rtx *locB = NULL; | |
84c9cb12 | 750 | enum rtx_code index_code = SCRATCH; |
541f7d56 BS |
751 | |
752 | if (GET_CODE (op0) == SUBREG) | |
753 | { | |
754 | op0 = SUBREG_REG (op0); | |
755 | code0 = GET_CODE (op0); | |
756 | } | |
7b82b5da | 757 | |
541f7d56 BS |
758 | if (GET_CODE (op1) == SUBREG) |
759 | { | |
760 | op1 = SUBREG_REG (op1); | |
761 | code1 = GET_CODE (op1); | |
762 | } | |
7b82b5da | 763 | |
541f7d56 BS |
764 | if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE |
765 | || code0 == ZERO_EXTEND || code1 == MEM) | |
766 | { | |
767 | locI = &XEXP (x, 0); | |
768 | locB = &XEXP (x, 1); | |
c4963a0a | 769 | index_code = GET_CODE (*locI); |
541f7d56 BS |
770 | } |
771 | else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE | |
772 | || code1 == ZERO_EXTEND || code0 == MEM) | |
773 | { | |
774 | locI = &XEXP (x, 1); | |
775 | locB = &XEXP (x, 0); | |
c4963a0a | 776 | index_code = GET_CODE (*locI); |
541f7d56 BS |
777 | } |
778 | else if (code0 == CONST_INT || code0 == CONST | |
779 | || code0 == SYMBOL_REF || code0 == LABEL_REF) | |
c4963a0a BS |
780 | { |
781 | locB = &XEXP (x, 1); | |
782 | index_code = GET_CODE (XEXP (x, 0)); | |
783 | } | |
541f7d56 BS |
784 | else if (code1 == CONST_INT || code1 == CONST |
785 | || code1 == SYMBOL_REF || code1 == LABEL_REF) | |
c4963a0a BS |
786 | { |
787 | locB = &XEXP (x, 0); | |
788 | index_code = GET_CODE (XEXP (x, 1)); | |
789 | } | |
541f7d56 BS |
790 | else if (code0 == REG && code1 == REG) |
791 | { | |
792 | int index_op; | |
c4963a0a | 793 | unsigned regno0 = REGNO (op0), regno1 = REGNO (op1); |
541f7d56 | 794 | |
bd379f73 PH |
795 | if (REGNO_OK_FOR_INDEX_P (regno1) |
796 | && regno_ok_for_base_p (regno0, mode, PLUS, REG)) | |
797 | index_op = 1; | |
798 | else if (REGNO_OK_FOR_INDEX_P (regno0) | |
799 | && regno_ok_for_base_p (regno1, mode, PLUS, REG)) | |
541f7d56 | 800 | index_op = 0; |
bd379f73 PH |
801 | else if (regno_ok_for_base_p (regno0, mode, PLUS, REG) |
802 | || REGNO_OK_FOR_INDEX_P (regno1)) | |
541f7d56 | 803 | index_op = 1; |
c4963a0a | 804 | else if (regno_ok_for_base_p (regno1, mode, PLUS, REG)) |
541f7d56 | 805 | index_op = 0; |
541f7d56 | 806 | else |
bd379f73 | 807 | index_op = 1; |
541f7d56 BS |
808 | |
809 | locI = &XEXP (x, index_op); | |
c4963a0a BS |
810 | locB = &XEXP (x, !index_op); |
811 | index_code = GET_CODE (*locI); | |
541f7d56 BS |
812 | } |
813 | else if (code0 == REG) | |
814 | { | |
815 | locI = &XEXP (x, 0); | |
816 | locB = &XEXP (x, 1); | |
c4963a0a | 817 | index_code = GET_CODE (*locI); |
541f7d56 BS |
818 | } |
819 | else if (code1 == REG) | |
820 | { | |
821 | locI = &XEXP (x, 1); | |
822 | locB = &XEXP (x, 0); | |
c4963a0a | 823 | index_code = GET_CODE (*locI); |
541f7d56 | 824 | } |
7b82b5da | 825 | |
541f7d56 | 826 | if (locI) |
85941a0a | 827 | scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode); |
541f7d56 | 828 | if (locB) |
c4963a0a | 829 | scan_rtx_address (insn, locB, base_reg_class (mode, PLUS, index_code), |
888d2cd6 | 830 | action, mode); |
c4963a0a | 831 | |
541f7d56 BS |
832 | return; |
833 | } | |
7b82b5da | 834 | |
541f7d56 BS |
835 | case POST_INC: |
836 | case POST_DEC: | |
837 | case POST_MODIFY: | |
838 | case PRE_INC: | |
839 | case PRE_DEC: | |
840 | case PRE_MODIFY: | |
841 | #ifndef AUTO_INC_DEC | |
ce73761f RH |
842 | /* If the target doesn't claim to handle autoinc, this must be |
843 | something special, like a stack push. Kill this chain. */ | |
a96caf80 | 844 | action = mark_all_read; |
541f7d56 BS |
845 | #endif |
846 | break; | |
7b82b5da | 847 | |
541f7d56 | 848 | case MEM: |
3dcc68a4 | 849 | scan_rtx_address (insn, &XEXP (x, 0), |
c4963a0a | 850 | base_reg_class (GET_MODE (x), MEM, SCRATCH), action, |
85941a0a | 851 | GET_MODE (x)); |
541f7d56 | 852 | return; |
1a43c33f | 853 | |
541f7d56 | 854 | case REG: |
6bda9bdf | 855 | scan_rtx_reg (insn, loc, cl, action, OP_IN); |
4ca0f257 | 856 | return; |
1a43c33f | 857 | |
541f7d56 BS |
858 | default: |
859 | break; | |
4ca0f257 | 860 | } |
541f7d56 BS |
861 | |
862 | fmt = GET_RTX_FORMAT (code); | |
863 | for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | |
4ca0f257 | 864 | { |
541f7d56 | 865 | if (fmt[i] == 'e') |
e3a64162 | 866 | scan_rtx_address (insn, &XEXP (x, i), cl, action, mode); |
541f7d56 BS |
867 | else if (fmt[i] == 'E') |
868 | for (j = XVECLEN (x, i) - 1; j >= 0; j--) | |
e3a64162 | 869 | scan_rtx_address (insn, &XVECEXP (x, i, j), cl, action, mode); |
4ca0f257 | 870 | } |
7b82b5da SC |
871 | } |
872 | ||
541f7d56 | 873 | static void |
6bda9bdf BS |
874 | scan_rtx (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action, |
875 | enum op_type type) | |
7b82b5da | 876 | { |
541f7d56 BS |
877 | const char *fmt; |
878 | rtx x = *loc; | |
879 | enum rtx_code code = GET_CODE (x); | |
880 | int i, j; | |
7b82b5da | 881 | |
541f7d56 BS |
882 | code = GET_CODE (x); |
883 | switch (code) | |
7b82b5da | 884 | { |
541f7d56 BS |
885 | case CONST: |
886 | case CONST_INT: | |
887 | case CONST_DOUBLE: | |
091a3ac7 | 888 | case CONST_FIXED: |
69ef87e2 | 889 | case CONST_VECTOR: |
541f7d56 BS |
890 | case SYMBOL_REF: |
891 | case LABEL_REF: | |
892 | case CC0: | |
893 | case PC: | |
894 | return; | |
055be976 | 895 | |
541f7d56 | 896 | case REG: |
6bda9bdf | 897 | scan_rtx_reg (insn, loc, cl, action, type); |
541f7d56 | 898 | return; |
7b82b5da | 899 | |
541f7d56 | 900 | case MEM: |
3dcc68a4 | 901 | scan_rtx_address (insn, &XEXP (x, 0), |
c4963a0a | 902 | base_reg_class (GET_MODE (x), MEM, SCRATCH), action, |
85941a0a | 903 | GET_MODE (x)); |
541f7d56 | 904 | return; |
7b82b5da | 905 | |
541f7d56 | 906 | case SET: |
6bda9bdf | 907 | scan_rtx (insn, &SET_SRC (x), cl, action, OP_IN); |
4e5813dd | 908 | scan_rtx (insn, &SET_DEST (x), cl, action, |
1f924675 BS |
909 | (GET_CODE (PATTERN (insn)) == COND_EXEC |
910 | && verify_reg_tracked (SET_DEST (x))) ? OP_INOUT : OP_OUT); | |
541f7d56 | 911 | return; |
7b82b5da | 912 | |
541f7d56 | 913 | case STRICT_LOW_PART: |
c4137918 BS |
914 | scan_rtx (insn, &XEXP (x, 0), cl, action, |
915 | verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT); | |
541f7d56 | 916 | return; |
7b82b5da | 917 | |
541f7d56 | 918 | case ZERO_EXTRACT: |
3b03c671 | 919 | case SIGN_EXTRACT: |
e3a64162 | 920 | scan_rtx (insn, &XEXP (x, 0), cl, action, |
c4137918 BS |
921 | (type == OP_IN ? OP_IN : |
922 | verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT)); | |
6bda9bdf BS |
923 | scan_rtx (insn, &XEXP (x, 1), cl, action, OP_IN); |
924 | scan_rtx (insn, &XEXP (x, 2), cl, action, OP_IN); | |
541f7d56 | 925 | return; |
7b82b5da | 926 | |
541f7d56 BS |
927 | case POST_INC: |
928 | case PRE_INC: | |
929 | case POST_DEC: | |
930 | case PRE_DEC: | |
931 | case POST_MODIFY: | |
932 | case PRE_MODIFY: | |
933 | /* Should only happen inside MEM. */ | |
41374e13 | 934 | gcc_unreachable (); |
541f7d56 BS |
935 | |
936 | case CLOBBER: | |
4e5813dd | 937 | scan_rtx (insn, &SET_DEST (x), cl, action, |
1f924675 BS |
938 | (GET_CODE (PATTERN (insn)) == COND_EXEC |
939 | && verify_reg_tracked (SET_DEST (x))) ? OP_INOUT : OP_OUT); | |
541f7d56 | 940 | return; |
7b82b5da | 941 | |
541f7d56 | 942 | case EXPR_LIST: |
6bda9bdf | 943 | scan_rtx (insn, &XEXP (x, 0), cl, action, type); |
541f7d56 | 944 | if (XEXP (x, 1)) |
6bda9bdf | 945 | scan_rtx (insn, &XEXP (x, 1), cl, action, type); |
541f7d56 | 946 | return; |
7b82b5da | 947 | |
541f7d56 BS |
948 | default: |
949 | break; | |
950 | } | |
7b82b5da | 951 | |
541f7d56 BS |
952 | fmt = GET_RTX_FORMAT (code); |
953 | for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | |
7b82b5da SC |
954 | { |
955 | if (fmt[i] == 'e') | |
6bda9bdf | 956 | scan_rtx (insn, &XEXP (x, i), cl, action, type); |
7b82b5da SC |
957 | else if (fmt[i] == 'E') |
958 | for (j = XVECLEN (x, i) - 1; j >= 0; j--) | |
6bda9bdf BS |
959 | scan_rtx (insn, &XVECEXP (x, i, j), cl, action, type); |
960 | } | |
961 | } | |
962 | ||
963 | /* Hide operands of the current insn (of which there are N_OPS) by | |
964 | substituting cc0 for them. | |
965 | Previous values are stored in the OLD_OPERANDS and OLD_DUPS. | |
d435810e | 966 | For every bit set in DO_NOT_HIDE, we leave the operand alone. |
a96caf80 BS |
967 | If INOUT_AND_EC_ONLY is set, we only do this for OP_INOUT type operands |
968 | and earlyclobbers. */ | |
6bda9bdf BS |
969 | |
970 | static void | |
971 | hide_operands (int n_ops, rtx *old_operands, rtx *old_dups, | |
d435810e | 972 | unsigned HOST_WIDE_INT do_not_hide, bool inout_and_ec_only) |
6bda9bdf BS |
973 | { |
974 | int i; | |
a96caf80 | 975 | int alt = which_alternative; |
6bda9bdf BS |
976 | for (i = 0; i < n_ops; i++) |
977 | { | |
978 | old_operands[i] = recog_data.operand[i]; | |
979 | /* Don't squash match_operator or match_parallel here, since | |
980 | we don't know that all of the contained registers are | |
981 | reachable by proper operands. */ | |
982 | if (recog_data.constraints[i][0] == '\0') | |
983 | continue; | |
d435810e BS |
984 | if (do_not_hide & (1 << i)) |
985 | continue; | |
a96caf80 BS |
986 | if (!inout_and_ec_only || recog_data.operand_type[i] == OP_INOUT |
987 | || recog_op_alt[i][alt].earlyclobber) | |
6bda9bdf BS |
988 | *recog_data.operand_loc[i] = cc0_rtx; |
989 | } | |
990 | for (i = 0; i < recog_data.n_dups; i++) | |
991 | { | |
992 | int opn = recog_data.dup_num[i]; | |
993 | old_dups[i] = *recog_data.dup_loc[i]; | |
d435810e BS |
994 | if (do_not_hide & (1 << opn)) |
995 | continue; | |
a96caf80 BS |
996 | if (!inout_and_ec_only || recog_data.operand_type[opn] == OP_INOUT |
997 | || recog_op_alt[opn][alt].earlyclobber) | |
6bda9bdf BS |
998 | *recog_data.dup_loc[i] = cc0_rtx; |
999 | } | |
1000 | } | |
1001 | ||
1002 | /* Undo the substitution performed by hide_operands. INSN is the insn we | |
1003 | are processing; the arguments are the same as in hide_operands. */ | |
1004 | ||
1005 | static void | |
1006 | restore_operands (rtx insn, int n_ops, rtx *old_operands, rtx *old_dups) | |
1007 | { | |
1008 | int i; | |
1009 | for (i = 0; i < recog_data.n_dups; i++) | |
1010 | *recog_data.dup_loc[i] = old_dups[i]; | |
1011 | for (i = 0; i < n_ops; i++) | |
1012 | *recog_data.operand_loc[i] = old_operands[i]; | |
1013 | if (recog_data.n_dups) | |
1014 | df_insn_rescan (insn); | |
1015 | } | |
1016 | ||
1017 | /* For each output operand of INSN, call scan_rtx to create a new | |
a96caf80 BS |
1018 | open chain. Do this only for normal or earlyclobber outputs, |
1019 | depending on EARLYCLOBBER. */ | |
6bda9bdf BS |
1020 | |
1021 | static void | |
a96caf80 | 1022 | record_out_operands (rtx insn, bool earlyclobber) |
6bda9bdf BS |
1023 | { |
1024 | int n_ops = recog_data.n_operands; | |
1025 | int alt = which_alternative; | |
1026 | ||
1027 | int i; | |
1028 | ||
1029 | for (i = 0; i < n_ops + recog_data.n_dups; i++) | |
1030 | { | |
1031 | int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops]; | |
1032 | rtx *loc = (i < n_ops | |
1033 | ? recog_data.operand_loc[opn] | |
1034 | : recog_data.dup_loc[i - n_ops]); | |
1035 | rtx op = *loc; | |
1036 | enum reg_class cl = recog_op_alt[opn][alt].cl; | |
1037 | ||
1038 | struct du_head *prev_open; | |
1039 | ||
a96caf80 BS |
1040 | if (recog_data.operand_type[opn] != OP_OUT |
1041 | || recog_op_alt[opn][alt].earlyclobber != earlyclobber) | |
6bda9bdf BS |
1042 | continue; |
1043 | ||
1044 | prev_open = open_chains; | |
1045 | scan_rtx (insn, loc, cl, mark_write, OP_OUT); | |
1046 | ||
1047 | /* ??? Many targets have output constraints on the SET_DEST | |
1048 | of a call insn, which is stupid, since these are certainly | |
1049 | ABI defined hard registers. For these, and for asm operands | |
1050 | that originally referenced hard registers, we must record that | |
1051 | the chain cannot be renamed. */ | |
1052 | if (CALL_P (insn) | |
1053 | || (asm_noperands (PATTERN (insn)) > 0 | |
1054 | && REG_P (op) | |
1055 | && REGNO (op) == ORIGINAL_REGNO (op))) | |
1056 | { | |
1057 | if (prev_open != open_chains) | |
a96caf80 | 1058 | open_chains->cannot_rename = 1; |
6bda9bdf | 1059 | } |
7b82b5da | 1060 | } |
7b82b5da SC |
1061 | } |
1062 | ||
3eae4643 | 1063 | /* Build def/use chain. */ |
7b82b5da | 1064 | |
9d324dde | 1065 | static struct du_head * |
0c20a65f | 1066 | build_def_use (basic_block bb) |
7b82b5da | 1067 | { |
541f7d56 | 1068 | rtx insn; |
a96caf80 | 1069 | df_ref *def_rec; |
d435810e | 1070 | unsigned HOST_WIDE_INT untracked_operands; |
1a43c33f | 1071 | |
541f7d56 | 1072 | open_chains = closed_chains = NULL; |
1a43c33f | 1073 | |
a96caf80 BS |
1074 | fail_current_block = false; |
1075 | ||
1076 | current_id = 0; | |
1077 | bitmap_initialize (&open_chains_set, &bitmap_default_obstack); | |
1f924675 | 1078 | CLEAR_HARD_REG_SET (live_in_chains); |
a96caf80 BS |
1079 | REG_SET_TO_HARD_REG_SET (live_hard_regs, df_get_live_in (bb)); |
1080 | for (def_rec = df_get_artificial_defs (bb->index); *def_rec; def_rec++) | |
1081 | { | |
1082 | df_ref def = *def_rec; | |
1083 | if (DF_REF_FLAGS (def) & DF_REF_AT_TOP) | |
1084 | SET_HARD_REG_BIT (live_hard_regs, DF_REF_REGNO (def)); | |
1085 | } | |
1086 | ||
a813c111 | 1087 | for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn)) |
541f7d56 | 1088 | { |
b5b8b0ac | 1089 | if (NONDEBUG_INSN_P (insn)) |
541f7d56 BS |
1090 | { |
1091 | int n_ops; | |
1092 | rtx note; | |
1093 | rtx old_operands[MAX_RECOG_OPERANDS]; | |
1094 | rtx old_dups[MAX_DUP_OPERANDS]; | |
0f900dfa | 1095 | int i; |
541f7d56 BS |
1096 | int alt; |
1097 | int predicated; | |
a96caf80 BS |
1098 | enum rtx_code set_code = SET; |
1099 | enum rtx_code clobber_code = CLOBBER; | |
541f7d56 | 1100 | |
541f7d56 | 1101 | /* Process the insn, determining its effect on the def-use |
a96caf80 BS |
1102 | chains and live hard registers. We perform the following |
1103 | steps with the register references in the insn, simulating | |
1104 | its effect: | |
1105 | (1) Deal with earlyclobber operands and CLOBBERs of non-operands | |
1106 | by creating chains and marking hard regs live. | |
541f7d56 | 1107 | (2) Any read outside an operand causes any chain it overlaps |
a96caf80 | 1108 | with to be marked unrenamable. |
541f7d56 BS |
1109 | (3) Any read inside an operand is added if there's already |
1110 | an open chain for it. | |
1111 | (4) For any REG_DEAD note we find, close open chains that | |
1112 | overlap it. | |
a96caf80 BS |
1113 | (5) For any non-earlyclobber write we find, close open chains |
1114 | that overlap it. | |
1115 | (6) For any non-earlyclobber write we find in an operand, make | |
1116 | a new chain or mark the hard register as live. | |
1117 | (7) For any REG_UNUSED, close any chains we just opened. | |
1118 | ||
1119 | We cannot deal with situations where we track a reg in one mode | |
1120 | and see a reference in another mode; these will cause the chain | |
1121 | to be marked unrenamable or even cause us to abort the entire | |
1122 | basic block. */ | |
541f7d56 BS |
1123 | |
1124 | extract_insn (insn); | |
4be9e9cb | 1125 | if (! constrain_operands (1)) |
3b03c671 | 1126 | fatal_insn_not_found (insn); |
541f7d56 BS |
1127 | preprocess_constraints (); |
1128 | alt = which_alternative; | |
1129 | n_ops = recog_data.n_operands; | |
d435810e | 1130 | untracked_operands = 0; |
541f7d56 BS |
1131 | |
1132 | /* Simplify the code below by rewriting things to reflect | |
1f924675 BS |
1133 | matching constraints. Also promote OP_OUT to OP_INOUT in |
1134 | predicated instructions, but only for register operands | |
1135 | that are already tracked, so that we can create a chain | |
1136 | when the first SET makes a register live. */ | |
541f7d56 BS |
1137 | |
1138 | predicated = GET_CODE (PATTERN (insn)) == COND_EXEC; | |
1139 | for (i = 0; i < n_ops; ++i) | |
7b82b5da | 1140 | { |
e33c42db | 1141 | rtx op = recog_data.operand[i]; |
541f7d56 BS |
1142 | int matches = recog_op_alt[i][alt].matches; |
1143 | if (matches >= 0) | |
e3a64162 | 1144 | recog_op_alt[i][alt].cl = recog_op_alt[matches][alt].cl; |
541f7d56 | 1145 | if (matches >= 0 || recog_op_alt[i][alt].matched >= 0 |
e33c42db | 1146 | || (predicated && recog_data.operand_type[i] == OP_OUT)) |
a96caf80 BS |
1147 | { |
1148 | recog_data.operand_type[i] = OP_INOUT; | |
d435810e BS |
1149 | /* A special case to deal with instruction patterns that |
1150 | have matching operands with different modes. If we're | |
1151 | not already tracking such a reg, we won't start here, | |
1152 | and we must instead make sure to make the operand visible | |
1153 | to the machinery that tracks hard registers. */ | |
a96caf80 BS |
1154 | if (matches >= 0 |
1155 | && (GET_MODE_SIZE (recog_data.operand_mode[i]) | |
d435810e BS |
1156 | != GET_MODE_SIZE (recog_data.operand_mode[matches])) |
1157 | && !verify_reg_in_set (op, &live_in_chains)) | |
1158 | { | |
1159 | untracked_operands |= 1 << i; | |
1160 | untracked_operands |= 1 << matches; | |
1161 | } | |
a96caf80 | 1162 | } |
c4137918 | 1163 | /* If there's an in-out operand with a register that is not |
e33c42db | 1164 | being tracked at all yet, open a chain. */ |
c4137918 BS |
1165 | if (recog_data.operand_type[i] == OP_INOUT |
1166 | && !(untracked_operands & (1 << i)) | |
e33c42db BS |
1167 | && REG_P (op) |
1168 | && !verify_reg_tracked (op)) | |
c4137918 | 1169 | { |
e33c42db BS |
1170 | enum machine_mode mode = GET_MODE (op); |
1171 | unsigned this_regno = REGNO (op); | |
1172 | unsigned this_nregs = hard_regno_nregs[this_regno][mode]; | |
1173 | create_new_chain (this_regno, this_nregs, NULL, NULL_RTX, | |
1174 | NO_REGS); | |
c4137918 | 1175 | } |
7b82b5da | 1176 | } |
1a43c33f | 1177 | |
a96caf80 BS |
1178 | if (fail_current_block) |
1179 | break; | |
1180 | ||
1181 | /* Step 1a: Mark hard registers that are clobbered in this insn, | |
1182 | outside an operand, as live. */ | |
d435810e BS |
1183 | hide_operands (n_ops, old_operands, old_dups, untracked_operands, |
1184 | false); | |
a96caf80 BS |
1185 | note_stores (PATTERN (insn), note_sets_clobbers, &clobber_code); |
1186 | restore_operands (insn, n_ops, old_operands, old_dups); | |
1187 | ||
1188 | /* Step 1b: Begin new chains for earlyclobbered writes inside | |
1189 | operands. */ | |
1190 | record_out_operands (insn, true); | |
1a43c33f | 1191 | |
a96caf80 BS |
1192 | /* Step 2: Mark chains for which we have reads outside operands |
1193 | as unrenamable. | |
3b03c671 | 1194 | We do this by munging all operands into CC0, and closing |
541f7d56 | 1195 | everything remaining. */ |
7b82b5da | 1196 | |
d435810e BS |
1197 | hide_operands (n_ops, old_operands, old_dups, untracked_operands, |
1198 | false); | |
a96caf80 | 1199 | scan_rtx (insn, &PATTERN (insn), NO_REGS, mark_all_read, OP_IN); |
6bda9bdf | 1200 | restore_operands (insn, n_ops, old_operands, old_dups); |
7b82b5da | 1201 | |
541f7d56 | 1202 | /* Step 2B: Can't rename function call argument registers. */ |
4b4bf941 | 1203 | if (CALL_P (insn) && CALL_INSN_FUNCTION_USAGE (insn)) |
541f7d56 | 1204 | scan_rtx (insn, &CALL_INSN_FUNCTION_USAGE (insn), |
a96caf80 | 1205 | NO_REGS, mark_all_read, OP_IN); |
7b82b5da | 1206 | |
3ada20ee RH |
1207 | /* Step 2C: Can't rename asm operands that were originally |
1208 | hard registers. */ | |
1209 | if (asm_noperands (PATTERN (insn)) > 0) | |
1210 | for (i = 0; i < n_ops; i++) | |
1211 | { | |
1212 | rtx *loc = recog_data.operand_loc[i]; | |
1213 | rtx op = *loc; | |
1214 | ||
f8cfc6aa | 1215 | if (REG_P (op) |
3ada20ee RH |
1216 | && REGNO (op) == ORIGINAL_REGNO (op) |
1217 | && (recog_data.operand_type[i] == OP_IN | |
1218 | || recog_data.operand_type[i] == OP_INOUT)) | |
a96caf80 | 1219 | scan_rtx (insn, loc, NO_REGS, mark_all_read, OP_IN); |
3ada20ee RH |
1220 | } |
1221 | ||
541f7d56 BS |
1222 | /* Step 3: Append to chains for reads inside operands. */ |
1223 | for (i = 0; i < n_ops + recog_data.n_dups; i++) | |
1224 | { | |
1225 | int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops]; | |
1226 | rtx *loc = (i < n_ops | |
1227 | ? recog_data.operand_loc[opn] | |
1228 | : recog_data.dup_loc[i - n_ops]); | |
e3a64162 | 1229 | enum reg_class cl = recog_op_alt[opn][alt].cl; |
541f7d56 BS |
1230 | enum op_type type = recog_data.operand_type[opn]; |
1231 | ||
1232 | /* Don't scan match_operand here, since we've no reg class | |
1233 | information to pass down. Any operands that we could | |
1234 | substitute in will be represented elsewhere. */ | |
d435810e BS |
1235 | if (recog_data.constraints[opn][0] == '\0' |
1236 | || untracked_operands & (1 << opn)) | |
541f7d56 | 1237 | continue; |
7b82b5da | 1238 | |
541f7d56 | 1239 | if (recog_op_alt[opn][alt].is_address) |
e3a64162 | 1240 | scan_rtx_address (insn, loc, cl, mark_read, VOIDmode); |
541f7d56 | 1241 | else |
6bda9bdf | 1242 | scan_rtx (insn, loc, cl, mark_read, type); |
541f7d56 | 1243 | } |
7b82b5da | 1244 | |
cb110f3d AM |
1245 | /* Step 3B: Record updates for regs in REG_INC notes, and |
1246 | source regs in REG_FRAME_RELATED_EXPR notes. */ | |
541f7d56 | 1247 | for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) |
cb110f3d AM |
1248 | if (REG_NOTE_KIND (note) == REG_INC |
1249 | || REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR) | |
1250 | scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_read, | |
6bda9bdf | 1251 | OP_INOUT); |
cb110f3d AM |
1252 | |
1253 | /* Step 4: Close chains for registers that die here. */ | |
1254 | for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) | |
1255 | if (REG_NOTE_KIND (note) == REG_DEAD) | |
a96caf80 BS |
1256 | { |
1257 | remove_from_hard_reg_set (&live_hard_regs, | |
1258 | GET_MODE (XEXP (note, 0)), | |
1259 | REGNO (XEXP (note, 0))); | |
1260 | scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead, | |
1261 | OP_IN); | |
1262 | } | |
1a43c33f | 1263 | |
541f7d56 BS |
1264 | /* Step 4B: If this is a call, any chain live at this point |
1265 | requires a caller-saved reg. */ | |
4b4bf941 | 1266 | if (CALL_P (insn)) |
541f7d56 | 1267 | { |
9d324dde | 1268 | struct du_head *p; |
541f7d56 | 1269 | for (p = open_chains; p; p = p->next_chain) |
fe08a886 | 1270 | p->need_caller_save_reg = 1; |
541f7d56 | 1271 | } |
7b82b5da | 1272 | |
541f7d56 BS |
1273 | /* Step 5: Close open chains that overlap writes. Similar to |
1274 | step 2, we hide in-out operands, since we do not want to | |
a96caf80 BS |
1275 | close these chains. We also hide earlyclobber operands, |
1276 | since we've opened chains for them in step 1, and earlier | |
1277 | chains they would overlap with must have been closed at | |
1278 | the previous insn at the latest, as such operands cannot | |
1279 | possibly overlap with any input operands. */ | |
7b82b5da | 1280 | |
d435810e BS |
1281 | hide_operands (n_ops, old_operands, old_dups, untracked_operands, |
1282 | true); | |
6bda9bdf BS |
1283 | scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_write, OP_IN); |
1284 | restore_operands (insn, n_ops, old_operands, old_dups); | |
7b82b5da | 1285 | |
a96caf80 BS |
1286 | /* Step 6a: Mark hard registers that are set in this insn, |
1287 | outside an operand, as live. */ | |
d435810e BS |
1288 | hide_operands (n_ops, old_operands, old_dups, untracked_operands, |
1289 | false); | |
a96caf80 BS |
1290 | note_stores (PATTERN (insn), note_sets_clobbers, &set_code); |
1291 | restore_operands (insn, n_ops, old_operands, old_dups); | |
7b82b5da | 1292 | |
a96caf80 BS |
1293 | /* Step 6b: Begin new chains for writes inside operands. */ |
1294 | record_out_operands (insn, false); | |
1295 | ||
1296 | /* Step 6c: Record destination regs in REG_FRAME_RELATED_EXPR | |
cb110f3d AM |
1297 | notes for update. */ |
1298 | for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) | |
1299 | if (REG_NOTE_KIND (note) == REG_FRAME_RELATED_EXPR) | |
1300 | scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_access, | |
6bda9bdf | 1301 | OP_INOUT); |
cb110f3d | 1302 | |
541f7d56 BS |
1303 | /* Step 7: Close chains for registers that were never |
1304 | really used here. */ | |
1305 | for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) | |
1306 | if (REG_NOTE_KIND (note) == REG_UNUSED) | |
a96caf80 BS |
1307 | { |
1308 | remove_from_hard_reg_set (&live_hard_regs, | |
1309 | GET_MODE (XEXP (note, 0)), | |
1310 | REGNO (XEXP (note, 0))); | |
1311 | scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead, | |
1312 | OP_IN); | |
1313 | } | |
541f7d56 | 1314 | } |
b5b8b0ac AO |
1315 | else if (DEBUG_INSN_P (insn) |
1316 | && !VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (insn))) | |
1317 | { | |
1318 | scan_rtx (insn, &INSN_VAR_LOCATION_LOC (insn), | |
6bda9bdf | 1319 | ALL_REGS, mark_read, OP_IN); |
b5b8b0ac | 1320 | } |
a813c111 | 1321 | if (insn == BB_END (bb)) |
541f7d56 BS |
1322 | break; |
1323 | } | |
7b82b5da | 1324 | |
a96caf80 BS |
1325 | bitmap_clear (&open_chains_set); |
1326 | ||
1327 | if (fail_current_block) | |
1328 | return NULL; | |
1329 | ||
541f7d56 BS |
1330 | /* Since we close every chain when we find a REG_DEAD note, anything that |
1331 | is still open lives past the basic block, so it can't be renamed. */ | |
1332 | return closed_chains; | |
1333 | } | |
7b82b5da | 1334 | |
c263766c | 1335 | /* Dump all def/use chains in CHAINS to DUMP_FILE. They are |
541f7d56 | 1336 | printed in reverse order as that's how we build them. */ |
7b82b5da | 1337 | |
541f7d56 | 1338 | static void |
9d324dde | 1339 | dump_def_use_chain (struct du_head *head) |
541f7d56 | 1340 | { |
9d324dde | 1341 | while (head) |
1a43c33f | 1342 | { |
9d324dde BS |
1343 | struct du_chain *this_du = head->first; |
1344 | fprintf (dump_file, "Register %s (%d):", | |
1345 | reg_names[head->regno], head->nregs); | |
d858f359 | 1346 | while (this_du) |
541f7d56 | 1347 | { |
d858f359 KG |
1348 | fprintf (dump_file, " %d [%s]", INSN_UID (this_du->insn), |
1349 | reg_class_names[this_du->cl]); | |
1350 | this_du = this_du->next_use; | |
541f7d56 | 1351 | } |
c263766c | 1352 | fprintf (dump_file, "\n"); |
9d324dde | 1353 | head = head->next_chain; |
1a43c33f | 1354 | } |
7b82b5da | 1355 | } |
752ae914 | 1356 | |
ef330312 PB |
1357 | \f |
1358 | static bool | |
1359 | gate_handle_regrename (void) | |
1360 | { | |
6fb5fa3c | 1361 | return (optimize > 0 && (flag_rename_registers)); |
ef330312 PB |
1362 | } |
1363 | ||
8ddbbcae | 1364 | struct rtl_opt_pass pass_regrename = |
ef330312 | 1365 | { |
8ddbbcae JH |
1366 | { |
1367 | RTL_PASS, | |
ef330312 PB |
1368 | "rnreg", /* name */ |
1369 | gate_handle_regrename, /* gate */ | |
fac41238 | 1370 | regrename_optimize, /* execute */ |
ef330312 PB |
1371 | NULL, /* sub */ |
1372 | NULL, /* next */ | |
1373 | 0, /* static_pass_number */ | |
1374 | TV_RENAME_REGISTERS, /* tv_id */ | |
1375 | 0, /* properties_required */ | |
1376 | 0, /* properties_provided */ | |
1377 | 0, /* properties_destroyed */ | |
1378 | 0, /* todo_flags_start */ | |
a36b8a1e | 1379 | TODO_df_finish | TODO_verify_rtl_sharing | |
8ddbbcae JH |
1380 | TODO_dump_func /* todo_flags_finish */ |
1381 | } | |
6fb5fa3c DB |
1382 | }; |
1383 |