]>
Commit | Line | Data |
---|---|---|
8c660648 | 1 | /* Move registers around to reduce number of move instructions needed. |
6fb5fa3c | 2 | Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, |
66647d44 | 3 | 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
6fb5fa3c | 4 | Free Software Foundation, Inc. |
8c660648 | 5 | |
1322177d | 6 | This file is part of GCC. |
8c660648 | 7 | |
1322177d LB |
8 | GCC is free software; you can redistribute it and/or modify it under |
9 | the terms of the GNU General Public License as published by the Free | |
9dcd6f09 | 10 | Software Foundation; either version 3, or (at your option) any later |
1322177d | 11 | version. |
8c660648 | 12 | |
1322177d LB |
13 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | for more details. | |
8c660648 JL |
17 | |
18 | You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
19 | along with GCC; see the file COPYING3. If not see |
20 | <http://www.gnu.org/licenses/>. */ | |
8c660648 JL |
21 | |
22 | ||
2af2dbdc VM |
23 | /* This module makes some simple RTL code transformations which |
24 | improve the subsequent register allocation. */ | |
8c660648 JL |
25 | |
26 | #include "config.h" | |
670ee920 | 27 | #include "system.h" |
4977bab6 ZW |
28 | #include "coretypes.h" |
29 | #include "tm.h" | |
789f983a | 30 | #include "rtl.h" /* stdio.h must precede rtl.h for FFS. */ |
6baf1cc8 | 31 | #include "tm_p.h" |
8c660648 JL |
32 | #include "insn-config.h" |
33 | #include "recog.h" | |
34 | #include "output.h" | |
8c660648 | 35 | #include "regs.h" |
184bb750 R |
36 | #include "hard-reg-set.h" |
37 | #include "flags.h" | |
49ad7cfa | 38 | #include "function.h" |
184bb750 | 39 | #include "expr.h" |
ddc8bed2 | 40 | #include "basic-block.h" |
1a5428f7 | 41 | #include "except.h" |
2e107e9e | 42 | #include "toplev.h" |
8461e984 | 43 | #include "reload.h" |
ef330312 PB |
44 | #include "timevar.h" |
45 | #include "tree-pass.h" | |
6fb5fa3c | 46 | #include "df.h" |
595c2290 | 47 | |
0c20a65f AJ |
48 | static int optimize_reg_copy_1 (rtx, rtx, rtx); |
49 | static void optimize_reg_copy_2 (rtx, rtx, rtx); | |
50 | static void optimize_reg_copy_3 (rtx, rtx, rtx); | |
a78f3e71 | 51 | static void copy_src_to_dest (rtx, rtx, rtx); |
8c660648 | 52 | |
24b97832 ILT |
53 | enum match_use |
54 | { | |
55 | READ, | |
56 | WRITE, | |
57 | READWRITE | |
58 | }; | |
59 | ||
184bb750 R |
60 | struct match { |
61 | int with[MAX_RECOG_OPERANDS]; | |
24b97832 | 62 | enum match_use use[MAX_RECOG_OPERANDS]; |
184bb750 R |
63 | int commutative[MAX_RECOG_OPERANDS]; |
64 | int early_clobber[MAX_RECOG_OPERANDS]; | |
65 | }; | |
66 | ||
0c20a65f | 67 | static int find_matches (rtx, struct match *); |
10d22567 | 68 | static int fixup_match_2 (rtx, rtx, rtx, rtx); |
8c660648 | 69 | |
40f03658 | 70 | /* Return nonzero if registers with CLASS1 and CLASS2 can be merged without |
3bb806ed R |
71 | causing too much register allocation problems. */ |
72 | static int | |
bbbbb16a | 73 | regclass_compatible_p (enum reg_class class0, enum reg_class class1) |
3bb806ed R |
74 | { |
75 | return (class0 == class1 | |
76 | || (reg_class_subset_p (class0, class1) | |
77 | && ! CLASS_LIKELY_SPILLED_P (class0)) | |
78 | || (reg_class_subset_p (class1, class0) | |
79 | && ! CLASS_LIKELY_SPILLED_P (class1))); | |
80 | } | |
81 | ||
dc2cb191 | 82 | \f |
2af2dbdc VM |
83 | #ifdef AUTO_INC_DEC |
84 | ||
85 | /* Find the place in the rtx X where REG is used as a memory address. | |
86 | Return the MEM rtx that so uses it. | |
87 | If PLUSCONST is nonzero, search instead for a memory address equivalent to | |
88 | (plus REG (const_int PLUSCONST)). | |
89 | ||
90 | If such an address does not appear, return 0. | |
91 | If REG appears more than once, or is used other than in such an address, | |
92 | return (rtx) 1. */ | |
93 | ||
94 | static rtx | |
95 | find_use_as_address (rtx x, rtx reg, HOST_WIDE_INT plusconst) | |
184bb750 | 96 | { |
2af2dbdc VM |
97 | enum rtx_code code = GET_CODE (x); |
98 | const char * const fmt = GET_RTX_FORMAT (code); | |
99 | int i; | |
100 | rtx value = 0; | |
101 | rtx tem; | |
184bb750 | 102 | |
2af2dbdc VM |
103 | if (code == MEM && XEXP (x, 0) == reg && plusconst == 0) |
104 | return x; | |
184bb750 | 105 | |
2af2dbdc VM |
106 | if (code == MEM && GET_CODE (XEXP (x, 0)) == PLUS |
107 | && XEXP (XEXP (x, 0), 0) == reg | |
481683e1 | 108 | && CONST_INT_P (XEXP (XEXP (x, 0), 1)) |
2af2dbdc VM |
109 | && INTVAL (XEXP (XEXP (x, 0), 1)) == plusconst) |
110 | return x; | |
184bb750 | 111 | |
2af2dbdc VM |
112 | if (code == SIGN_EXTRACT || code == ZERO_EXTRACT) |
113 | { | |
114 | /* If REG occurs inside a MEM used in a bit-field reference, | |
115 | that is unacceptable. */ | |
116 | if (find_use_as_address (XEXP (x, 0), reg, 0) != 0) | |
117 | return (rtx) (size_t) 1; | |
118 | } | |
184bb750 | 119 | |
2af2dbdc VM |
120 | if (x == reg) |
121 | return (rtx) (size_t) 1; | |
184bb750 | 122 | |
2af2dbdc VM |
123 | for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) |
124 | { | |
125 | if (fmt[i] == 'e') | |
126 | { | |
127 | tem = find_use_as_address (XEXP (x, i), reg, plusconst); | |
128 | if (value == 0) | |
129 | value = tem; | |
130 | else if (tem != 0) | |
131 | return (rtx) (size_t) 1; | |
132 | } | |
133 | else if (fmt[i] == 'E') | |
134 | { | |
135 | int j; | |
136 | for (j = XVECLEN (x, i) - 1; j >= 0; j--) | |
137 | { | |
138 | tem = find_use_as_address (XVECEXP (x, i, j), reg, plusconst); | |
139 | if (value == 0) | |
140 | value = tem; | |
141 | else if (tem != 0) | |
142 | return (rtx) (size_t) 1; | |
143 | } | |
144 | } | |
145 | } | |
184bb750 | 146 | |
2af2dbdc | 147 | return value; |
184bb750 | 148 | } |
2af2dbdc VM |
149 | |
150 | ||
151 | /* INC_INSN is an instruction that adds INCREMENT to REG. | |
152 | Try to fold INC_INSN as a post/pre in/decrement into INSN. | |
153 | Iff INC_INSN_SET is nonzero, inc_insn has a destination different from src. | |
154 | Return nonzero for success. */ | |
155 | static int | |
156 | try_auto_increment (rtx insn, rtx inc_insn, rtx inc_insn_set, rtx reg, | |
157 | HOST_WIDE_INT increment, int pre) | |
158 | { | |
159 | enum rtx_code inc_code; | |
160 | ||
161 | rtx pset = single_set (insn); | |
162 | if (pset) | |
163 | { | |
164 | /* Can't use the size of SET_SRC, we might have something like | |
165 | (sign_extend:SI (mem:QI ... */ | |
166 | rtx use = find_use_as_address (pset, reg, 0); | |
167 | if (use != 0 && use != (rtx) (size_t) 1) | |
168 | { | |
169 | int size = GET_MODE_SIZE (GET_MODE (use)); | |
170 | if (0 | |
171 | || (HAVE_POST_INCREMENT | |
172 | && pre == 0 && (inc_code = POST_INC, increment == size)) | |
173 | || (HAVE_PRE_INCREMENT | |
174 | && pre == 1 && (inc_code = PRE_INC, increment == size)) | |
175 | || (HAVE_POST_DECREMENT | |
176 | && pre == 0 && (inc_code = POST_DEC, increment == -size)) | |
177 | || (HAVE_PRE_DECREMENT | |
178 | && pre == 1 && (inc_code = PRE_DEC, increment == -size)) | |
179 | ) | |
180 | { | |
181 | if (inc_insn_set) | |
182 | validate_change | |
183 | (inc_insn, | |
184 | &SET_SRC (inc_insn_set), | |
185 | XEXP (SET_SRC (inc_insn_set), 0), 1); | |
186 | validate_change (insn, &XEXP (use, 0), | |
187 | gen_rtx_fmt_e (inc_code, Pmode, reg), 1); | |
188 | if (apply_change_group ()) | |
189 | { | |
190 | /* If there is a REG_DEAD note on this insn, we must | |
191 | change this not to REG_UNUSED meaning that the register | |
192 | is set, but the value is dead. Failure to do so will | |
193 | result in sched1 dying -- when it recomputes lifetime | |
194 | information, the number of REG_DEAD notes will have | |
195 | changed. */ | |
196 | rtx note = find_reg_note (insn, REG_DEAD, reg); | |
197 | if (note) | |
32e8bb8e | 198 | PUT_REG_NOTE_KIND (note, REG_UNUSED); |
2af2dbdc VM |
199 | |
200 | add_reg_note (insn, REG_INC, reg); | |
201 | ||
202 | if (! inc_insn_set) | |
203 | delete_insn (inc_insn); | |
204 | return 1; | |
205 | } | |
206 | } | |
207 | } | |
208 | } | |
209 | return 0; | |
210 | } | |
211 | #endif | |
212 | ||
213 | \f | |
214 | static int *regno_src_regno; | |
215 | ||
1230327b R |
216 | /* INSN is a copy from SRC to DEST, both registers, and SRC does not die |
217 | in INSN. | |
218 | ||
219 | Search forward to see if SRC dies before either it or DEST is modified, | |
220 | but don't scan past the end of a basic block. If so, we can replace SRC | |
174fa2c4 | 221 | with DEST and let SRC die in INSN. |
1230327b R |
222 | |
223 | This will reduce the number of registers live in that range and may enable | |
224 | DEST to be tied to SRC, thus often saving one register in addition to a | |
225 | register-register copy. */ | |
226 | ||
227 | static int | |
0c20a65f | 228 | optimize_reg_copy_1 (rtx insn, rtx dest, rtx src) |
1230327b R |
229 | { |
230 | rtx p, q; | |
231 | rtx note; | |
232 | rtx dest_death = 0; | |
233 | int sregno = REGNO (src); | |
234 | int dregno = REGNO (dest); | |
0340f2ba | 235 | basic_block bb = BLOCK_FOR_INSN (insn); |
1230327b | 236 | |
dc297297 | 237 | /* We don't want to mess with hard regs if register classes are small. */ |
1230327b R |
238 | if (sregno == dregno |
239 | || (SMALL_REGISTER_CLASSES | |
240 | && (sregno < FIRST_PSEUDO_REGISTER | |
241 | || dregno < FIRST_PSEUDO_REGISTER)) | |
242 | /* We don't see all updates to SP if they are in an auto-inc memory | |
243 | reference, so we must disallow this optimization on them. */ | |
244 | || sregno == STACK_POINTER_REGNUM || dregno == STACK_POINTER_REGNUM) | |
245 | return 0; | |
246 | ||
247 | for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p)) | |
248 | { | |
0340f2ba | 249 | if (! INSN_P (p)) |
1230327b | 250 | continue; |
0340f2ba SB |
251 | if (BLOCK_FOR_INSN (p) != bb) |
252 | break; | |
1230327b R |
253 | |
254 | if (reg_set_p (src, p) || reg_set_p (dest, p) | |
51928907 HPN |
255 | /* If SRC is an asm-declared register, it must not be replaced |
256 | in any asm. Unfortunately, the REG_EXPR tree for the asm | |
257 | variable may be absent in the SRC rtx, so we can't check the | |
258 | actual register declaration easily (the asm operand will have | |
259 | it, though). To avoid complicating the test for a rare case, | |
260 | we just don't perform register replacement for a hard reg | |
261 | mentioned in an asm. */ | |
262 | || (sregno < FIRST_PSEUDO_REGISTER | |
263 | && asm_noperands (PATTERN (p)) >= 0 | |
264 | && reg_overlap_mentioned_p (src, PATTERN (p))) | |
97b69e51 DJ |
265 | /* Don't change hard registers used by a call. */ |
266 | || (CALL_P (p) && sregno < FIRST_PSEUDO_REGISTER | |
267 | && find_reg_fusage (p, USE, src)) | |
1230327b R |
268 | /* Don't change a USE of a register. */ |
269 | || (GET_CODE (PATTERN (p)) == USE | |
270 | && reg_overlap_mentioned_p (src, XEXP (PATTERN (p), 0)))) | |
271 | break; | |
272 | ||
273 | /* See if all of SRC dies in P. This test is slightly more | |
274 | conservative than it needs to be. */ | |
275 | if ((note = find_regno_note (p, REG_DEAD, sregno)) != 0 | |
276 | && GET_MODE (XEXP (note, 0)) == GET_MODE (src)) | |
277 | { | |
278 | int failed = 0; | |
1230327b | 279 | int d_length = 0; |
89098dc1 | 280 | int s_length = 0; |
1230327b | 281 | int d_n_calls = 0; |
89098dc1 | 282 | int s_n_calls = 0; |
a03c6d64 JH |
283 | int s_freq_calls = 0; |
284 | int d_freq_calls = 0; | |
1230327b R |
285 | |
286 | /* We can do the optimization. Scan forward from INSN again, | |
287 | replacing regs as we go. Set FAILED if a replacement can't | |
288 | be done. In that case, we can't move the death note for SRC. | |
289 | This should be rare. */ | |
290 | ||
291 | /* Set to stop at next insn. */ | |
292 | for (q = next_real_insn (insn); | |
293 | q != next_real_insn (p); | |
294 | q = next_real_insn (q)) | |
295 | { | |
296 | if (reg_overlap_mentioned_p (src, PATTERN (q))) | |
297 | { | |
298 | /* If SRC is a hard register, we might miss some | |
299 | overlapping registers with validate_replace_rtx, | |
300 | so we would have to undo it. We can't if DEST is | |
301 | present in the insn, so fail in that combination | |
302 | of cases. */ | |
303 | if (sregno < FIRST_PSEUDO_REGISTER | |
304 | && reg_mentioned_p (dest, PATTERN (q))) | |
305 | failed = 1; | |
040f69eb AK |
306 | |
307 | /* Attempt to replace all uses. */ | |
308 | else if (!validate_replace_rtx (src, dest, q)) | |
309 | failed = 1; | |
1230327b | 310 | |
040f69eb AK |
311 | /* If this succeeded, but some part of the register |
312 | is still present, undo the replacement. */ | |
313 | else if (sregno < FIRST_PSEUDO_REGISTER | |
314 | && reg_overlap_mentioned_p (src, PATTERN (q))) | |
1230327b R |
315 | { |
316 | validate_replace_rtx (dest, src, q); | |
317 | failed = 1; | |
318 | } | |
319 | } | |
320 | ||
89098dc1 JL |
321 | /* For SREGNO, count the total number of insns scanned. |
322 | For DREGNO, count the total number of insns scanned after | |
323 | passing the death note for DREGNO. */ | |
324 | s_length++; | |
1230327b R |
325 | if (dest_death) |
326 | d_length++; | |
327 | ||
328 | /* If the insn in which SRC dies is a CALL_INSN, don't count it | |
329 | as a call that has been crossed. Otherwise, count it. */ | |
4b4bf941 | 330 | if (q != p && CALL_P (q)) |
1230327b | 331 | { |
89098dc1 JL |
332 | /* Similarly, total calls for SREGNO, total calls beyond |
333 | the death note for DREGNO. */ | |
334 | s_n_calls++; | |
a03c6d64 | 335 | s_freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q)); |
1230327b | 336 | if (dest_death) |
a03c6d64 JH |
337 | { |
338 | d_n_calls++; | |
339 | d_freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q)); | |
340 | } | |
1230327b R |
341 | } |
342 | ||
343 | /* If DEST dies here, remove the death note and save it for | |
344 | later. Make sure ALL of DEST dies here; again, this is | |
345 | overly conservative. */ | |
346 | if (dest_death == 0 | |
347 | && (dest_death = find_regno_note (q, REG_DEAD, dregno)) != 0) | |
348 | { | |
349 | if (GET_MODE (XEXP (dest_death, 0)) != GET_MODE (dest)) | |
350 | failed = 1, dest_death = 0; | |
351 | else | |
352 | remove_note (q, dest_death); | |
353 | } | |
354 | } | |
355 | ||
356 | if (! failed) | |
357 | { | |
89098dc1 JL |
358 | /* These counters need to be updated if and only if we are |
359 | going to move the REG_DEAD note. */ | |
1230327b R |
360 | if (sregno >= FIRST_PSEUDO_REGISTER) |
361 | { | |
362 | if (REG_LIVE_LENGTH (sregno) >= 0) | |
363 | { | |
89098dc1 | 364 | REG_LIVE_LENGTH (sregno) -= s_length; |
1230327b R |
365 | /* REG_LIVE_LENGTH is only an approximation after |
366 | combine if sched is not run, so make sure that we | |
367 | still have a reasonable value. */ | |
368 | if (REG_LIVE_LENGTH (sregno) < 2) | |
369 | REG_LIVE_LENGTH (sregno) = 2; | |
370 | } | |
371 | ||
89098dc1 | 372 | REG_N_CALLS_CROSSED (sregno) -= s_n_calls; |
a03c6d64 | 373 | REG_FREQ_CALLS_CROSSED (sregno) -= s_freq_calls; |
1230327b R |
374 | } |
375 | ||
376 | /* Move death note of SRC from P to INSN. */ | |
377 | remove_note (p, note); | |
378 | XEXP (note, 1) = REG_NOTES (insn); | |
379 | REG_NOTES (insn) = note; | |
380 | } | |
381 | ||
124d535f JW |
382 | /* DEST is also dead if INSN has a REG_UNUSED note for DEST. */ |
383 | if (! dest_death | |
384 | && (dest_death = find_regno_note (insn, REG_UNUSED, dregno))) | |
385 | { | |
386 | PUT_REG_NOTE_KIND (dest_death, REG_DEAD); | |
387 | remove_note (insn, dest_death); | |
388 | } | |
389 | ||
1230327b R |
390 | /* Put death note of DEST on P if we saw it die. */ |
391 | if (dest_death) | |
392 | { | |
393 | XEXP (dest_death, 1) = REG_NOTES (p); | |
394 | REG_NOTES (p) = dest_death; | |
89098dc1 JL |
395 | |
396 | if (dregno >= FIRST_PSEUDO_REGISTER) | |
397 | { | |
398 | /* If and only if we are moving the death note for DREGNO, | |
399 | then we need to update its counters. */ | |
400 | if (REG_LIVE_LENGTH (dregno) >= 0) | |
401 | REG_LIVE_LENGTH (dregno) += d_length; | |
402 | REG_N_CALLS_CROSSED (dregno) += d_n_calls; | |
a03c6d64 | 403 | REG_FREQ_CALLS_CROSSED (dregno) += d_freq_calls; |
89098dc1 | 404 | } |
1230327b R |
405 | } |
406 | ||
407 | return ! failed; | |
408 | } | |
409 | ||
410 | /* If SRC is a hard register which is set or killed in some other | |
411 | way, we can't do this optimization. */ | |
412 | else if (sregno < FIRST_PSEUDO_REGISTER | |
413 | && dead_or_set_p (p, src)) | |
414 | break; | |
415 | } | |
416 | return 0; | |
417 | } | |
418 | \f | |
419 | /* INSN is a copy of SRC to DEST, in which SRC dies. See if we now have | |
420 | a sequence of insns that modify DEST followed by an insn that sets | |
421 | SRC to DEST in which DEST dies, with no prior modification of DEST. | |
422 | (There is no need to check if the insns in between actually modify | |
423 | DEST. We should not have cases where DEST is not modified, but | |
424 | the optimization is safe if no such modification is detected.) | |
425 | In that case, we can replace all uses of DEST, starting with INSN and | |
426 | ending with the set of SRC to DEST, with SRC. We do not do this | |
427 | optimization if a CALL_INSN is crossed unless SRC already crosses a | |
428 | call or if DEST dies before the copy back to SRC. | |
429 | ||
430 | It is assumed that DEST and SRC are pseudos; it is too complicated to do | |
431 | this for hard registers since the substitutions we may make might fail. */ | |
432 | ||
433 | static void | |
0c20a65f | 434 | optimize_reg_copy_2 (rtx insn, rtx dest, rtx src) |
1230327b R |
435 | { |
436 | rtx p, q; | |
437 | rtx set; | |
438 | int sregno = REGNO (src); | |
439 | int dregno = REGNO (dest); | |
0340f2ba | 440 | basic_block bb = BLOCK_FOR_INSN (insn); |
1230327b R |
441 | |
442 | for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p)) | |
443 | { | |
0340f2ba | 444 | if (! INSN_P (p)) |
1230327b | 445 | continue; |
0340f2ba SB |
446 | if (BLOCK_FOR_INSN (p) != bb) |
447 | break; | |
1230327b R |
448 | |
449 | set = single_set (p); | |
450 | if (set && SET_SRC (set) == dest && SET_DEST (set) == src | |
451 | && find_reg_note (p, REG_DEAD, dest)) | |
452 | { | |
453 | /* We can do the optimization. Scan forward from INSN again, | |
454 | replacing regs as we go. */ | |
455 | ||
456 | /* Set to stop at next insn. */ | |
457 | for (q = insn; q != NEXT_INSN (p); q = NEXT_INSN (q)) | |
2c3c49de | 458 | if (INSN_P (q)) |
1230327b R |
459 | { |
460 | if (reg_mentioned_p (dest, PATTERN (q))) | |
6fb5fa3c | 461 | { |
d3a5ecb5 KK |
462 | rtx note; |
463 | ||
6fb5fa3c | 464 | PATTERN (q) = replace_rtx (PATTERN (q), dest, src); |
d3a5ecb5 KK |
465 | note = FIND_REG_INC_NOTE (q, dest); |
466 | if (note) | |
467 | { | |
468 | remove_note (q, note); | |
469 | add_reg_note (q, REG_INC, src); | |
470 | } | |
6fb5fa3c DB |
471 | df_insn_rescan (q); |
472 | } | |
1230327b | 473 | |
c7a0240a SB |
474 | if (CALL_P (q)) |
475 | { | |
a03c6d64 | 476 | int freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q)); |
c7a0240a SB |
477 | REG_N_CALLS_CROSSED (dregno)--; |
478 | REG_N_CALLS_CROSSED (sregno)++; | |
a03c6d64 JH |
479 | REG_FREQ_CALLS_CROSSED (dregno) -= freq; |
480 | REG_FREQ_CALLS_CROSSED (sregno) += freq; | |
c7a0240a | 481 | } |
1230327b R |
482 | } |
483 | ||
484 | remove_note (p, find_reg_note (p, REG_DEAD, dest)); | |
485 | REG_N_DEATHS (dregno)--; | |
486 | remove_note (insn, find_reg_note (insn, REG_DEAD, src)); | |
487 | REG_N_DEATHS (sregno)--; | |
488 | return; | |
489 | } | |
490 | ||
491 | if (reg_set_p (src, p) | |
492 | || find_reg_note (p, REG_DEAD, dest) | |
4b4bf941 | 493 | || (CALL_P (p) && REG_N_CALLS_CROSSED (sregno) == 0)) |
1230327b R |
494 | break; |
495 | } | |
496 | } | |
c7a0240a | 497 | |
184bb750 R |
498 | /* INSN is a ZERO_EXTEND or SIGN_EXTEND of SRC to DEST. |
499 | Look if SRC dies there, and if it is only set once, by loading | |
3d042e77 | 500 | it from memory. If so, try to incorporate the zero/sign extension |
184bb750 R |
501 | into the memory read, change SRC to the mode of DEST, and alter |
502 | the remaining accesses to use the appropriate SUBREG. This allows | |
503 | SRC and DEST to be tied later. */ | |
504 | static void | |
0c20a65f | 505 | optimize_reg_copy_3 (rtx insn, rtx dest, rtx src) |
184bb750 R |
506 | { |
507 | rtx src_reg = XEXP (src, 0); | |
508 | int src_no = REGNO (src_reg); | |
509 | int dst_no = REGNO (dest); | |
15ee342b | 510 | rtx p, set; |
184bb750 | 511 | enum machine_mode old_mode; |
0340f2ba | 512 | basic_block bb = BLOCK_FOR_INSN (insn); |
184bb750 R |
513 | |
514 | if (src_no < FIRST_PSEUDO_REGISTER | |
515 | || dst_no < FIRST_PSEUDO_REGISTER | |
516 | || ! find_reg_note (insn, REG_DEAD, src_reg) | |
6d80a854 | 517 | || REG_N_DEATHS (src_no) != 1 |
184bb750 R |
518 | || REG_N_SETS (src_no) != 1) |
519 | return; | |
0340f2ba | 520 | |
9c07e479 | 521 | for (p = PREV_INSN (insn); p && ! reg_set_p (src_reg, p); p = PREV_INSN (p)) |
0340f2ba | 522 | if (INSN_P (p) && BLOCK_FOR_INSN (p) != bb) |
a1c1fdd0 | 523 | break; |
0340f2ba SB |
524 | |
525 | if (! p || BLOCK_FOR_INSN (p) != bb) | |
9c07e479 BK |
526 | return; |
527 | ||
184bb750 | 528 | if (! (set = single_set (p)) |
3c0cb5de | 529 | || !MEM_P (SET_SRC (set)) |
4fb3cbd7 BS |
530 | /* If there's a REG_EQUIV note, this must be an insn that loads an |
531 | argument. Prefer keeping the note over doing this optimization. */ | |
532 | || find_reg_note (p, REG_EQUIV, NULL_RTX) | |
184bb750 R |
533 | || SET_DEST (set) != src_reg) |
534 | return; | |
937e37cc | 535 | |
14b493d6 | 536 | /* Be conservative: although this optimization is also valid for |
972b320c R |
537 | volatile memory references, that could cause trouble in later passes. */ |
538 | if (MEM_VOLATILE_P (SET_SRC (set))) | |
539 | return; | |
540 | ||
937e37cc JL |
541 | /* Do not use a SUBREG to truncate from one mode to another if truncation |
542 | is not a nop. */ | |
543 | if (GET_MODE_BITSIZE (GET_MODE (src_reg)) <= GET_MODE_BITSIZE (GET_MODE (src)) | |
544 | && !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE (src)), | |
545 | GET_MODE_BITSIZE (GET_MODE (src_reg)))) | |
546 | return; | |
547 | ||
184bb750 R |
548 | old_mode = GET_MODE (src_reg); |
549 | PUT_MODE (src_reg, GET_MODE (src)); | |
550 | XEXP (src, 0) = SET_SRC (set); | |
e757da5e JL |
551 | |
552 | /* Include this change in the group so that it's easily undone if | |
553 | one of the changes in the group is invalid. */ | |
554 | validate_change (p, &SET_SRC (set), src, 1); | |
555 | ||
556 | /* Now walk forward making additional replacements. We want to be able | |
557 | to undo all the changes if a later substitution fails. */ | |
184bb750 R |
558 | while (p = NEXT_INSN (p), p != insn) |
559 | { | |
2c3c49de | 560 | if (! INSN_P (p)) |
184bb750 | 561 | continue; |
e757da5e | 562 | |
2067c116 | 563 | /* Make a tentative change. */ |
15ee342b EB |
564 | validate_replace_rtx_group (src_reg, |
565 | gen_lowpart_SUBREG (old_mode, src_reg), | |
566 | p); | |
e757da5e JL |
567 | } |
568 | ||
569 | validate_replace_rtx_group (src, src_reg, insn); | |
570 | ||
571 | /* Now see if all the changes are valid. */ | |
572 | if (! apply_change_group ()) | |
573 | { | |
574 | /* One or more changes were no good. Back out everything. */ | |
575 | PUT_MODE (src_reg, old_mode); | |
576 | XEXP (src, 0) = src_reg; | |
184bb750 | 577 | } |
4fb3cbd7 BS |
578 | else |
579 | { | |
580 | rtx note = find_reg_note (p, REG_EQUAL, NULL_RTX); | |
581 | if (note) | |
582 | remove_note (p, note); | |
583 | } | |
184bb750 R |
584 | } |
585 | ||
ddc8bed2 MM |
586 | \f |
587 | /* If we were not able to update the users of src to use dest directly, try | |
588 | instead moving the value to dest directly before the operation. */ | |
589 | ||
cab634f2 | 590 | static void |
a78f3e71 | 591 | copy_src_to_dest (rtx insn, rtx src, rtx dest) |
ddc8bed2 MM |
592 | { |
593 | rtx seq; | |
594 | rtx link; | |
595 | rtx next; | |
596 | rtx set; | |
597 | rtx move_insn; | |
598 | rtx *p_insn_notes; | |
599 | rtx *p_move_notes; | |
ddc8bed2 MM |
600 | int src_regno; |
601 | int dest_regno; | |
ddc8bed2 MM |
602 | int insn_uid; |
603 | int move_uid; | |
604 | ||
605 | /* A REG_LIVE_LENGTH of -1 indicates the register is equivalent to a constant | |
606 | or memory location and is used infrequently; a REG_LIVE_LENGTH of -2 is | |
607 | parameter when there is no frame pointer that is not allocated a register. | |
608 | For now, we just reject them, rather than incrementing the live length. */ | |
609 | ||
f8cfc6aa | 610 | if (REG_P (src) |
3ac3da71 | 611 | && REG_LIVE_LENGTH (REGNO (src)) > 0 |
f8cfc6aa | 612 | && REG_P (dest) |
3ac3da71 | 613 | && REG_LIVE_LENGTH (REGNO (dest)) > 0 |
ddc8bed2 | 614 | && (set = single_set (insn)) != NULL_RTX |
9d2106a4 R |
615 | && !reg_mentioned_p (dest, SET_SRC (set)) |
616 | && GET_MODE (src) == GET_MODE (dest)) | |
ddc8bed2 | 617 | { |
1a8fca8a R |
618 | int old_num_regs = reg_rtx_no; |
619 | ||
ddc8bed2 MM |
620 | /* Generate the src->dest move. */ |
621 | start_sequence (); | |
622 | emit_move_insn (dest, src); | |
2f937369 | 623 | seq = get_insns (); |
ddc8bed2 | 624 | end_sequence (); |
1a8fca8a R |
625 | /* If this sequence uses new registers, we may not use it. */ |
626 | if (old_num_regs != reg_rtx_no | |
627 | || ! validate_replace_rtx (src, dest, insn)) | |
628 | { | |
629 | /* We have to restore reg_rtx_no to its old value, lest | |
630 | recompute_reg_usage will try to compute the usage of the | |
631 | new regs, yet reg_n_info is not valid for them. */ | |
632 | reg_rtx_no = old_num_regs; | |
633 | return; | |
634 | } | |
ddc8bed2 MM |
635 | emit_insn_before (seq, insn); |
636 | move_insn = PREV_INSN (insn); | |
637 | p_move_notes = ®_NOTES (move_insn); | |
638 | p_insn_notes = ®_NOTES (insn); | |
639 | ||
3eae4643 | 640 | /* Move any notes mentioning src to the move instruction. */ |
ddc8bed2 MM |
641 | for (link = REG_NOTES (insn); link != NULL_RTX; link = next) |
642 | { | |
643 | next = XEXP (link, 1); | |
644 | if (XEXP (link, 0) == src) | |
645 | { | |
646 | *p_move_notes = link; | |
647 | p_move_notes = &XEXP (link, 1); | |
648 | } | |
649 | else | |
650 | { | |
651 | *p_insn_notes = link; | |
652 | p_insn_notes = &XEXP (link, 1); | |
653 | } | |
654 | } | |
655 | ||
656 | *p_move_notes = NULL_RTX; | |
657 | *p_insn_notes = NULL_RTX; | |
658 | ||
ddc8bed2 MM |
659 | insn_uid = INSN_UID (insn); |
660 | move_uid = INSN_UID (move_insn); | |
ddc8bed2 MM |
661 | |
662 | /* Update the various register tables. */ | |
663 | dest_regno = REGNO (dest); | |
6fb5fa3c | 664 | INC_REG_N_SETS (dest_regno, 1); |
ddc8bed2 | 665 | REG_LIVE_LENGTH (dest_regno)++; |
ddc8bed2 MM |
666 | src_regno = REGNO (src); |
667 | if (! find_reg_note (move_insn, REG_DEAD, src)) | |
668 | REG_LIVE_LENGTH (src_regno)++; | |
ddc8bed2 MM |
669 | } |
670 | } | |
671 | ||
65d169d9 JH |
672 | /* reg_set_in_bb[REGNO] points to basic block iff the register is set |
673 | only once in the given block and has REG_EQUAL note. */ | |
674 | ||
2af2dbdc | 675 | static basic_block *reg_set_in_bb; |
65d169d9 JH |
676 | |
677 | /* Size of reg_set_in_bb array. */ | |
678 | static unsigned int max_reg_computed; | |
679 | ||
ddc8bed2 | 680 | \f |
184bb750 R |
681 | /* Return whether REG is set in only one location, and is set to a |
682 | constant, but is set in a different basic block from INSN (an | |
683 | instructions which uses REG). In this case REG is equivalent to a | |
684 | constant, and we don't want to break that equivalence, because that | |
685 | may increase register pressure and make reload harder. If REG is | |
686 | set in the same basic block as INSN, we don't worry about it, | |
687 | because we'll probably need a register anyhow (??? but what if REG | |
a78f3e71 | 688 | is used in a different basic block as well as this one?). */ |
184bb750 | 689 | |
65d169d9 JH |
690 | static bool |
691 | reg_is_remote_constant_p (rtx reg, rtx insn) | |
184bb750 | 692 | { |
65d169d9 | 693 | basic_block bb; |
b3694847 | 694 | rtx p; |
65d169d9 | 695 | int max; |
184bb750 | 696 | |
65d169d9 | 697 | if (!reg_set_in_bb) |
184bb750 | 698 | { |
65d169d9 | 699 | max_reg_computed = max = max_reg_num (); |
1634b18f | 700 | reg_set_in_bb = XCNEWVEC (basic_block, max); |
184bb750 | 701 | |
65d169d9 | 702 | FOR_EACH_BB (bb) |
a78f3e71 SB |
703 | FOR_BB_INSNS (bb, p) |
704 | { | |
705 | rtx s; | |
706 | ||
707 | if (!INSN_P (p)) | |
708 | continue; | |
709 | s = single_set (p); | |
710 | /* This is the instruction which sets REG. If there is a | |
711 | REG_EQUAL note, then REG is equivalent to a constant. */ | |
712 | if (s != 0 | |
713 | && REG_P (SET_DEST (s)) | |
714 | && REG_N_SETS (REGNO (SET_DEST (s))) == 1 | |
715 | && find_reg_note (p, REG_EQUAL, NULL_RTX)) | |
716 | reg_set_in_bb[REGNO (SET_DEST (s))] = bb; | |
717 | } | |
184bb750 | 718 | } |
a78f3e71 | 719 | |
65d169d9 JH |
720 | gcc_assert (REGNO (reg) < max_reg_computed); |
721 | if (reg_set_in_bb[REGNO (reg)] == NULL) | |
722 | return false; | |
a78f3e71 | 723 | return (reg_set_in_bb[REGNO (reg)] != BLOCK_FOR_INSN (insn)); |
184bb750 R |
724 | } |
725 | ||
b1a7d591 JW |
726 | /* INSN is adding a CONST_INT to a REG. We search backwards looking for |
727 | another add immediate instruction with the same source and dest registers, | |
728 | and if we find one, we change INSN to an increment, and return 1. If | |
729 | no changes are made, we return 0. | |
730 | ||
731 | This changes | |
732 | (set (reg100) (plus reg1 offset1)) | |
733 | ... | |
734 | (set (reg100) (plus reg1 offset2)) | |
735 | to | |
736 | (set (reg100) (plus reg1 offset1)) | |
737 | ... | |
738 | (set (reg100) (plus reg100 offset2-offset1)) */ | |
739 | ||
740 | /* ??? What does this comment mean? */ | |
14b493d6 | 741 | /* cse disrupts preincrement / postdecrement sequences when it finds a |
184bb750 | 742 | hard register as ultimate source, like the frame pointer. */ |
b1a7d591 | 743 | |
95d75019 | 744 | static int |
10d22567 | 745 | fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset) |
184bb750 R |
746 | { |
747 | rtx p, dst_death = 0; | |
a03c6d64 | 748 | int length, num_calls = 0, freq_calls = 0; |
0340f2ba | 749 | basic_block bb = BLOCK_FOR_INSN (insn); |
184bb750 R |
750 | |
751 | /* If SRC dies in INSN, we'd have to move the death note. This is | |
752 | considered to be very unlikely, so we just skip the optimization | |
753 | in this case. */ | |
754 | if (find_regno_note (insn, REG_DEAD, REGNO (src))) | |
755 | return 0; | |
756 | ||
757 | /* Scan backward to find the first instruction that sets DST. */ | |
758 | ||
759 | for (length = 0, p = PREV_INSN (insn); p; p = PREV_INSN (p)) | |
760 | { | |
761 | rtx pset; | |
762 | ||
0340f2ba | 763 | if (! INSN_P (p)) |
a6a2274a | 764 | continue; |
0340f2ba SB |
765 | if (BLOCK_FOR_INSN (p) != bb) |
766 | break; | |
184bb750 | 767 | |
7bf825d2 JW |
768 | if (find_regno_note (p, REG_DEAD, REGNO (dst))) |
769 | dst_death = p; | |
770 | if (! dst_death) | |
771 | length++; | |
184bb750 R |
772 | |
773 | pset = single_set (p); | |
774 | if (pset && SET_DEST (pset) == dst | |
775 | && GET_CODE (SET_SRC (pset)) == PLUS | |
776 | && XEXP (SET_SRC (pset), 0) == src | |
481683e1 | 777 | && CONST_INT_P (XEXP (SET_SRC (pset), 1))) |
a6a2274a | 778 | { |
184bb750 R |
779 | HOST_WIDE_INT newconst |
780 | = INTVAL (offset) - INTVAL (XEXP (SET_SRC (pset), 1)); | |
1a29f703 R |
781 | rtx add = gen_add3_insn (dst, dst, GEN_INT (newconst)); |
782 | ||
783 | if (add && validate_change (insn, &PATTERN (insn), add, 0)) | |
184bb750 R |
784 | { |
785 | /* Remove the death note for DST from DST_DEATH. */ | |
786 | if (dst_death) | |
787 | { | |
788 | remove_death (REGNO (dst), dst_death); | |
789 | REG_LIVE_LENGTH (REGNO (dst)) += length; | |
790 | REG_N_CALLS_CROSSED (REGNO (dst)) += num_calls; | |
a03c6d64 | 791 | REG_FREQ_CALLS_CROSSED (REGNO (dst)) += freq_calls; |
184bb750 R |
792 | } |
793 | ||
10d22567 ZD |
794 | if (dump_file) |
795 | fprintf (dump_file, | |
184bb750 R |
796 | "Fixed operand of insn %d.\n", |
797 | INSN_UID (insn)); | |
798 | ||
799 | #ifdef AUTO_INC_DEC | |
800 | for (p = PREV_INSN (insn); p; p = PREV_INSN (p)) | |
801 | { | |
2c3c49de | 802 | if (! INSN_P (p)) |
e27a5106 | 803 | continue; |
0340f2ba SB |
804 | if (BLOCK_FOR_INSN (p) != bb) |
805 | break; | |
184bb750 R |
806 | if (reg_overlap_mentioned_p (dst, PATTERN (p))) |
807 | { | |
808 | if (try_auto_increment (p, insn, 0, dst, newconst, 0)) | |
809 | return 1; | |
810 | break; | |
811 | } | |
812 | } | |
813 | for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p)) | |
814 | { | |
2c3c49de | 815 | if (! INSN_P (p)) |
8543c01e | 816 | continue; |
0340f2ba SB |
817 | if (BLOCK_FOR_INSN (p) != bb) |
818 | break; | |
184bb750 R |
819 | if (reg_overlap_mentioned_p (dst, PATTERN (p))) |
820 | { | |
821 | try_auto_increment (p, insn, 0, dst, newconst, 1); | |
822 | break; | |
823 | } | |
824 | } | |
825 | #endif | |
826 | return 1; | |
827 | } | |
a6a2274a | 828 | } |
184bb750 R |
829 | |
830 | if (reg_set_p (dst, PATTERN (p))) | |
a6a2274a | 831 | break; |
184bb750 R |
832 | |
833 | /* If we have passed a call instruction, and the | |
834 | pseudo-reg SRC is not already live across a call, | |
835 | then don't perform the optimization. */ | |
836 | /* reg_set_p is overly conservative for CALL_INSNS, thinks that all | |
837 | hard regs are clobbered. Thus, we only use it for src for | |
838 | non-call insns. */ | |
4b4bf941 | 839 | if (CALL_P (p)) |
a6a2274a | 840 | { |
184bb750 | 841 | if (! dst_death) |
a03c6d64 JH |
842 | { |
843 | num_calls++; | |
844 | freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (p)); | |
845 | } | |
184bb750 | 846 | |
a6a2274a KH |
847 | if (REG_N_CALLS_CROSSED (REGNO (src)) == 0) |
848 | break; | |
184bb750 R |
849 | |
850 | if (call_used_regs [REGNO (dst)] | |
851 | || find_reg_fusage (p, CLOBBER, dst)) | |
852 | break; | |
a6a2274a | 853 | } |
184bb750 | 854 | else if (reg_set_p (src, PATTERN (p))) |
a6a2274a | 855 | break; |
8c660648 | 856 | } |
184bb750 | 857 | |
8c660648 JL |
858 | return 0; |
859 | } | |
8c660648 | 860 | |
0340f2ba | 861 | /* A forward pass. Replace output operands with input operands. */ |
3721581a | 862 | |
0340f2ba SB |
863 | static void |
864 | regmove_forward_pass (void) | |
8c660648 | 865 | { |
0340f2ba | 866 | basic_block bb; |
8c660648 | 867 | rtx insn; |
184bb750 | 868 | |
0340f2ba SB |
869 | if (! flag_expensive_optimizations) |
870 | return; | |
ddc8bed2 | 871 | |
0340f2ba SB |
872 | if (dump_file) |
873 | fprintf (dump_file, "Starting forward pass...\n"); | |
8c660648 | 874 | |
0340f2ba | 875 | FOR_EACH_BB (bb) |
8c660648 | 876 | { |
0340f2ba | 877 | FOR_BB_INSNS (bb, insn) |
8c660648 | 878 | { |
62d049cf | 879 | rtx set = single_set (insn); |
184bb750 R |
880 | if (! set) |
881 | continue; | |
8c660648 | 882 | |
62d049cf PB |
883 | if ((GET_CODE (SET_SRC (set)) == SIGN_EXTEND |
884 | || GET_CODE (SET_SRC (set)) == ZERO_EXTEND) | |
f8cfc6aa JQ |
885 | && REG_P (XEXP (SET_SRC (set), 0)) |
886 | && REG_P (SET_DEST (set))) | |
184bb750 R |
887 | optimize_reg_copy_3 (insn, SET_DEST (set), SET_SRC (set)); |
888 | ||
62d049cf | 889 | if (REG_P (SET_SRC (set)) |
f8cfc6aa | 890 | && REG_P (SET_DEST (set))) |
184bb750 R |
891 | { |
892 | /* If this is a register-register copy where SRC is not dead, | |
893 | see if we can optimize it. If this optimization succeeds, | |
894 | it will become a copy where SRC is dead. */ | |
895 | if ((find_reg_note (insn, REG_DEAD, SET_SRC (set)) | |
896 | || optimize_reg_copy_1 (insn, SET_DEST (set), SET_SRC (set))) | |
897 | && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER) | |
8c660648 | 898 | { |
184bb750 R |
899 | /* Similarly for a pseudo-pseudo copy when SRC is dead. */ |
900 | if (REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER) | |
901 | optimize_reg_copy_2 (insn, SET_DEST (set), SET_SRC (set)); | |
902 | if (regno_src_regno[REGNO (SET_DEST (set))] < 0 | |
903 | && SET_SRC (set) != SET_DEST (set)) | |
8c660648 | 904 | { |
8e2e89f7 | 905 | int srcregno = REGNO (SET_SRC (set)); |
184bb750 R |
906 | if (regno_src_regno[srcregno] >= 0) |
907 | srcregno = regno_src_regno[srcregno]; | |
908 | regno_src_regno[REGNO (SET_DEST (set))] = srcregno; | |
8c660648 JL |
909 | } |
910 | } | |
184bb750 | 911 | } |
8c660648 JL |
912 | } |
913 | } | |
0340f2ba | 914 | } |
8c660648 | 915 | |
0340f2ba SB |
916 | /* A backward pass. Replace input operands with output operands. */ |
917 | ||
918 | static void | |
919 | regmove_backward_pass (void) | |
920 | { | |
921 | basic_block bb; | |
922 | rtx insn, prev; | |
8c660648 | 923 | |
10d22567 ZD |
924 | if (dump_file) |
925 | fprintf (dump_file, "Starting backward pass...\n"); | |
8c660648 | 926 | |
0340f2ba | 927 | FOR_EACH_BB_REVERSE (bb) |
8c660648 | 928 | { |
0340f2ba SB |
929 | /* ??? Use the safe iterator because fixup_match_2 can remove |
930 | insns via try_auto_increment. */ | |
931 | FOR_BB_INSNS_REVERSE_SAFE (bb, insn, prev) | |
8c660648 | 932 | { |
0340f2ba SB |
933 | struct match match; |
934 | rtx copy_src, copy_dst; | |
0eadeb15 | 935 | int op_no, match_no; |
ddc8bed2 | 936 | int success = 0; |
0eadeb15 | 937 | |
0340f2ba SB |
938 | if (! INSN_P (insn)) |
939 | continue; | |
940 | ||
3363316f | 941 | if (! find_matches (insn, &match)) |
8c660648 JL |
942 | continue; |
943 | ||
8c660648 JL |
944 | /* Now scan through the operands looking for a destination operand |
945 | which is supposed to match a source operand. | |
946 | Then scan backward for an instruction which sets the source | |
947 | operand. If safe, then replace the source operand with the | |
948 | dest operand in both instructions. */ | |
949 | ||
ddc8bed2 MM |
950 | copy_src = NULL_RTX; |
951 | copy_dst = NULL_RTX; | |
1ccbefce | 952 | for (op_no = 0; op_no < recog_data.n_operands; op_no++) |
8c660648 | 953 | { |
184bb750 R |
954 | rtx set, p, src, dst; |
955 | rtx src_note, dst_note; | |
a03c6d64 | 956 | int num_calls = 0, freq_calls = 0; |
184bb750 R |
957 | enum reg_class src_class, dst_class; |
958 | int length; | |
8c660648 | 959 | |
0eadeb15 | 960 | match_no = match.with[op_no]; |
8c660648 | 961 | |
184bb750 | 962 | /* Nothing to do if the two operands aren't supposed to match. */ |
0eadeb15 | 963 | if (match_no < 0) |
184bb750 | 964 | continue; |
8c660648 | 965 | |
1ccbefce RH |
966 | dst = recog_data.operand[match_no]; |
967 | src = recog_data.operand[op_no]; | |
8c660648 | 968 | |
f8cfc6aa | 969 | if (!REG_P (src)) |
184bb750 | 970 | continue; |
8c660648 | 971 | |
f8cfc6aa | 972 | if (!REG_P (dst) |
184bb750 | 973 | || REGNO (dst) < FIRST_PSEUDO_REGISTER |
3721581a | 974 | || REG_LIVE_LENGTH (REGNO (dst)) < 0 |
41b3243e | 975 | || GET_MODE (src) != GET_MODE (dst)) |
184bb750 | 976 | continue; |
8c660648 | 977 | |
dc297297 | 978 | /* If the operands already match, then there is nothing to do. */ |
1ccbefce | 979 | if (operands_match_p (src, dst)) |
184bb750 | 980 | continue; |
8c660648 | 981 | |
1ccbefce RH |
982 | if (match.commutative[op_no] >= 0) |
983 | { | |
984 | rtx comm = recog_data.operand[match.commutative[op_no]]; | |
985 | if (operands_match_p (comm, dst)) | |
986 | continue; | |
987 | } | |
988 | ||
184bb750 R |
989 | set = single_set (insn); |
990 | if (! set) | |
991 | continue; | |
8c660648 | 992 | |
bb948ad3 RZ |
993 | /* Note that single_set ignores parts of a parallel set for |
994 | which one of the destinations is REG_UNUSED. We can't | |
995 | handle that here, since we can wind up rewriting things | |
996 | such that a single register is set twice within a single | |
997 | parallel. */ | |
998 | if (reg_set_p (src, insn)) | |
999 | continue; | |
1000 | ||
0eadeb15 | 1001 | /* match_no/dst must be a write-only operand, and |
184bb750 | 1002 | operand_operand/src must be a read-only operand. */ |
0eadeb15 BS |
1003 | if (match.use[op_no] != READ |
1004 | || match.use[match_no] != WRITE) | |
184bb750 | 1005 | continue; |
8c660648 | 1006 | |
0eadeb15 | 1007 | if (match.early_clobber[match_no] |
4b983fdc | 1008 | && count_occurrences (PATTERN (insn), src, 0) > 1) |
184bb750 | 1009 | continue; |
8c660648 | 1010 | |
0eadeb15 | 1011 | /* Make sure match_no is the destination. */ |
1ccbefce | 1012 | if (recog_data.operand[match_no] != SET_DEST (set)) |
184bb750 | 1013 | continue; |
8c660648 | 1014 | |
184bb750 R |
1015 | if (REGNO (src) < FIRST_PSEUDO_REGISTER) |
1016 | { | |
1017 | if (GET_CODE (SET_SRC (set)) == PLUS | |
481683e1 | 1018 | && CONST_INT_P (XEXP (SET_SRC (set), 1)) |
184bb750 R |
1019 | && XEXP (SET_SRC (set), 0) == src |
1020 | && fixup_match_2 (insn, dst, src, | |
10d22567 | 1021 | XEXP (SET_SRC (set), 1))) |
184bb750 R |
1022 | break; |
1023 | continue; | |
1024 | } | |
1025 | src_class = reg_preferred_class (REGNO (src)); | |
1026 | dst_class = reg_preferred_class (REGNO (dst)); | |
fd973d56 JH |
1027 | |
1028 | if (! (src_note = find_reg_note (insn, REG_DEAD, src))) | |
ddc8bed2 | 1029 | { |
fd973d56 JH |
1030 | /* We used to force the copy here like in other cases, but |
1031 | it produces worse code, as it eliminates no copy | |
1032 | instructions and the copy emitted will be produced by | |
1033 | reload anyway. On patterns with multiple alternatives, | |
14b493d6 | 1034 | there may be better solution available. |
fd973d56 JH |
1035 | |
1036 | In particular this change produced slower code for numeric | |
1037 | i387 programs. */ | |
1038 | ||
ddc8bed2 MM |
1039 | continue; |
1040 | } | |
8c660648 | 1041 | |
fd973d56 | 1042 | if (! regclass_compatible_p (src_class, dst_class)) |
ddc8bed2 MM |
1043 | { |
1044 | if (!copy_src) | |
1045 | { | |
1046 | copy_src = src; | |
1047 | copy_dst = dst; | |
1048 | } | |
1049 | continue; | |
1050 | } | |
1051 | ||
fd973d56 JH |
1052 | /* Can not modify an earlier insn to set dst if this insn |
1053 | uses an old value in the source. */ | |
1054 | if (reg_overlap_mentioned_p (dst, SET_SRC (set))) | |
ddc8bed2 MM |
1055 | { |
1056 | if (!copy_src) | |
1057 | { | |
1058 | copy_src = src; | |
1059 | copy_dst = dst; | |
1060 | } | |
1061 | continue; | |
1062 | } | |
8c660648 | 1063 | |
184bb750 R |
1064 | /* If src is set once in a different basic block, |
1065 | and is set equal to a constant, then do not use | |
1066 | it for this optimization, as this would make it | |
1067 | no longer equivalent to a constant. */ | |
ddc8bed2 | 1068 | |
65d169d9 | 1069 | if (reg_is_remote_constant_p (src, insn)) |
ddc8bed2 MM |
1070 | { |
1071 | if (!copy_src) | |
1072 | { | |
1073 | copy_src = src; | |
1074 | copy_dst = dst; | |
1075 | } | |
1076 | continue; | |
1077 | } | |
1078 | ||
1079 | ||
10d22567 ZD |
1080 | if (dump_file) |
1081 | fprintf (dump_file, | |
ddc8bed2 | 1082 | "Could fix operand %d of insn %d matching operand %d.\n", |
0eadeb15 | 1083 | op_no, INSN_UID (insn), match_no); |
8c660648 | 1084 | |
184bb750 R |
1085 | /* Scan backward to find the first instruction that uses |
1086 | the input operand. If the operand is set here, then | |
0eadeb15 | 1087 | replace it in both instructions with match_no. */ |
184bb750 R |
1088 | |
1089 | for (length = 0, p = PREV_INSN (insn); p; p = PREV_INSN (p)) | |
1090 | { | |
1091 | rtx pset; | |
1092 | ||
0340f2ba | 1093 | if (! INSN_P (p)) |
184bb750 | 1094 | continue; |
0340f2ba SB |
1095 | if (BLOCK_FOR_INSN (p) != bb) |
1096 | break; | |
8c660648 | 1097 | |
184bb750 | 1098 | length++; |
8c660648 | 1099 | |
184bb750 R |
1100 | /* ??? See if all of SRC is set in P. This test is much |
1101 | more conservative than it needs to be. */ | |
1102 | pset = single_set (p); | |
1103 | if (pset && SET_DEST (pset) == src) | |
1104 | { | |
1105 | /* We use validate_replace_rtx, in case there | |
1106 | are multiple identical source operands. All of | |
1107 | them have to be changed at the same time. */ | |
1108 | if (validate_replace_rtx (src, dst, insn)) | |
8c660648 | 1109 | { |
184bb750 R |
1110 | if (validate_change (p, &SET_DEST (pset), |
1111 | dst, 0)) | |
1112 | success = 1; | |
1113 | else | |
8c660648 | 1114 | { |
184bb750 R |
1115 | /* Change all source operands back. |
1116 | This modifies the dst as a side-effect. */ | |
1117 | validate_replace_rtx (dst, src, insn); | |
1118 | /* Now make sure the dst is right. */ | |
1119 | validate_change (insn, | |
1ccbefce | 1120 | recog_data.operand_loc[match_no], |
184bb750 | 1121 | dst, 0); |
8c660648 | 1122 | } |
8c660648 | 1123 | } |
184bb750 R |
1124 | break; |
1125 | } | |
1126 | ||
1e4c6dc5 SP |
1127 | /* We can't make this change if SRC is read or |
1128 | partially written in P, since we are going to | |
1129 | eliminate SRC. We can't make this change | |
1130 | if DST is mentioned at all in P, | |
1131 | since we are going to change its value. */ | |
184bb750 | 1132 | if (reg_overlap_mentioned_p (src, PATTERN (p)) |
1e4c6dc5 | 1133 | || reg_mentioned_p (dst, PATTERN (p))) |
184bb750 | 1134 | break; |
8c660648 | 1135 | |
184bb750 R |
1136 | /* If we have passed a call instruction, and the |
1137 | pseudo-reg DST is not already live across a call, | |
1138 | then don't perform the optimization. */ | |
4b4bf941 | 1139 | if (CALL_P (p)) |
184bb750 R |
1140 | { |
1141 | num_calls++; | |
a03c6d64 | 1142 | freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (p)); |
184bb750 R |
1143 | |
1144 | if (REG_N_CALLS_CROSSED (REGNO (dst)) == 0) | |
8c660648 | 1145 | break; |
184bb750 R |
1146 | } |
1147 | } | |
8c660648 | 1148 | |
184bb750 R |
1149 | if (success) |
1150 | { | |
1151 | int dstno, srcno; | |
8c660648 | 1152 | |
184bb750 R |
1153 | /* Remove the death note for SRC from INSN. */ |
1154 | remove_note (insn, src_note); | |
1155 | /* Move the death note for SRC to P if it is used | |
1156 | there. */ | |
1157 | if (reg_overlap_mentioned_p (src, PATTERN (p))) | |
1158 | { | |
1159 | XEXP (src_note, 1) = REG_NOTES (p); | |
1160 | REG_NOTES (p) = src_note; | |
8c660648 | 1161 | } |
184bb750 R |
1162 | /* If there is a REG_DEAD note for DST on P, then remove |
1163 | it, because DST is now set there. */ | |
5e9defae | 1164 | if ((dst_note = find_reg_note (p, REG_DEAD, dst))) |
184bb750 R |
1165 | remove_note (p, dst_note); |
1166 | ||
1167 | dstno = REGNO (dst); | |
1168 | srcno = REGNO (src); | |
1169 | ||
6fb5fa3c DB |
1170 | INC_REG_N_SETS (dstno, 1); |
1171 | INC_REG_N_SETS (srcno, -1); | |
8c660648 | 1172 | |
184bb750 R |
1173 | REG_N_CALLS_CROSSED (dstno) += num_calls; |
1174 | REG_N_CALLS_CROSSED (srcno) -= num_calls; | |
a03c6d64 JH |
1175 | REG_FREQ_CALLS_CROSSED (dstno) += freq_calls; |
1176 | REG_FREQ_CALLS_CROSSED (srcno) -= freq_calls; | |
184bb750 R |
1177 | |
1178 | REG_LIVE_LENGTH (dstno) += length; | |
1179 | if (REG_LIVE_LENGTH (srcno) >= 0) | |
8c660648 | 1180 | { |
184bb750 R |
1181 | REG_LIVE_LENGTH (srcno) -= length; |
1182 | /* REG_LIVE_LENGTH is only an approximation after | |
1183 | combine if sched is not run, so make sure that we | |
1184 | still have a reasonable value. */ | |
1185 | if (REG_LIVE_LENGTH (srcno) < 2) | |
1186 | REG_LIVE_LENGTH (srcno) = 2; | |
1187 | } | |
8c660648 | 1188 | |
10d22567 ZD |
1189 | if (dump_file) |
1190 | fprintf (dump_file, | |
184bb750 | 1191 | "Fixed operand %d of insn %d matching operand %d.\n", |
0eadeb15 | 1192 | op_no, INSN_UID (insn), match_no); |
8c660648 | 1193 | |
184bb750 | 1194 | break; |
8c660648 JL |
1195 | } |
1196 | } | |
ddc8bed2 MM |
1197 | |
1198 | /* If we weren't able to replace any of the alternatives, try an | |
14b493d6 | 1199 | alternative approach of copying the source to the destination. */ |
ddc8bed2 | 1200 | if (!success && copy_src != NULL_RTX) |
a78f3e71 | 1201 | copy_src_to_dest (insn, copy_src, copy_dst); |
8c660648 JL |
1202 | } |
1203 | } | |
0340f2ba SB |
1204 | } |
1205 | ||
1206 | /* Main entry for the register move optimization. */ | |
1207 | ||
1208 | static unsigned int | |
1209 | regmove_optimize (void) | |
1210 | { | |
1211 | int i; | |
1212 | int nregs = max_reg_num (); | |
1213 | ||
1214 | df_note_add_problem (); | |
1215 | df_analyze (); | |
1216 | ||
1217 | regstat_init_n_sets_and_refs (); | |
1218 | regstat_compute_ri (); | |
1219 | ||
1220 | regno_src_regno = XNEWVEC (int, nregs); | |
1221 | for (i = nregs; --i >= 0; ) | |
1222 | regno_src_regno[i] = -1; | |
1223 | ||
1224 | /* A forward pass. Replace output operands with input operands. */ | |
1225 | regmove_forward_pass (); | |
1226 | ||
1227 | /* A backward pass. Replace input operands with output operands. */ | |
1228 | regmove_backward_pass (); | |
961d4119 | 1229 | |
4da896b2 MM |
1230 | /* Clean up. */ |
1231 | free (regno_src_regno); | |
65d169d9 JH |
1232 | if (reg_set_in_bb) |
1233 | { | |
1234 | free (reg_set_in_bb); | |
1235 | reg_set_in_bb = NULL; | |
1236 | } | |
6fb5fa3c DB |
1237 | regstat_free_n_sets_and_refs (); |
1238 | regstat_free_ri (); | |
62d049cf | 1239 | return 0; |
8c660648 JL |
1240 | } |
1241 | ||
0eadeb15 BS |
1242 | /* Returns nonzero if INSN's pattern has matching constraints for any operand. |
1243 | Returns 0 if INSN can't be recognized, or if the alternative can't be | |
1244 | determined. | |
b1a7d591 JW |
1245 | |
1246 | Initialize the info in MATCHP based on the constraints. */ | |
184bb750 R |
1247 | |
1248 | static int | |
0c20a65f | 1249 | find_matches (rtx insn, struct match *matchp) |
184bb750 R |
1250 | { |
1251 | int likely_spilled[MAX_RECOG_OPERANDS]; | |
0eadeb15 | 1252 | int op_no; |
184bb750 R |
1253 | int any_matches = 0; |
1254 | ||
0eadeb15 BS |
1255 | extract_insn (insn); |
1256 | if (! constrain_operands (0)) | |
1257 | return 0; | |
184bb750 R |
1258 | |
1259 | /* Must initialize this before main loop, because the code for | |
1260 | the commutative case may set matches for operands other than | |
1261 | the current one. */ | |
1ccbefce | 1262 | for (op_no = recog_data.n_operands; --op_no >= 0; ) |
0eadeb15 | 1263 | matchp->with[op_no] = matchp->commutative[op_no] = -1; |
184bb750 | 1264 | |
1ccbefce | 1265 | for (op_no = 0; op_no < recog_data.n_operands; op_no++) |
184bb750 | 1266 | { |
9b3142b3 KG |
1267 | const char *p; |
1268 | char c; | |
184bb750 R |
1269 | int i = 0; |
1270 | ||
1ccbefce | 1271 | p = recog_data.constraints[op_no]; |
184bb750 | 1272 | |
0eadeb15 BS |
1273 | likely_spilled[op_no] = 0; |
1274 | matchp->use[op_no] = READ; | |
1275 | matchp->early_clobber[op_no] = 0; | |
184bb750 | 1276 | if (*p == '=') |
0eadeb15 | 1277 | matchp->use[op_no] = WRITE; |
184bb750 | 1278 | else if (*p == '+') |
0eadeb15 | 1279 | matchp->use[op_no] = READWRITE; |
184bb750 R |
1280 | |
1281 | for (;*p && i < which_alternative; p++) | |
1282 | if (*p == ',') | |
1283 | i++; | |
1284 | ||
97488870 R |
1285 | while ((c = *p) != '\0' && c != ',') |
1286 | { | |
1287 | switch (c) | |
84b72302 | 1288 | { |
97488870 R |
1289 | case '=': |
1290 | break; | |
1291 | case '+': | |
1292 | break; | |
1293 | case '&': | |
1294 | matchp->early_clobber[op_no] = 1; | |
1295 | break; | |
1296 | case '%': | |
1297 | matchp->commutative[op_no] = op_no + 1; | |
1298 | matchp->commutative[op_no + 1] = op_no; | |
1299 | break; | |
1300 | ||
1301 | case '0': case '1': case '2': case '3': case '4': | |
1302 | case '5': case '6': case '7': case '8': case '9': | |
1303 | { | |
1304 | char *end; | |
1305 | unsigned long match_ul = strtoul (p, &end, 10); | |
1306 | int match = match_ul; | |
2cc2d4bb | 1307 | |
97488870 | 1308 | p = end; |
84b72302 | 1309 | |
97488870 R |
1310 | if (match < op_no && likely_spilled[match]) |
1311 | continue; | |
1312 | matchp->with[op_no] = match; | |
1313 | any_matches = 1; | |
1314 | if (matchp->commutative[op_no] >= 0) | |
1315 | matchp->with[matchp->commutative[op_no]] = match; | |
1316 | } | |
1317 | continue; | |
84b72302 | 1318 | |
184bb750 R |
1319 | case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'h': |
1320 | case 'j': case 'k': case 'l': case 'p': case 'q': case 't': case 'u': | |
1321 | case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': | |
1322 | case 'C': case 'D': case 'W': case 'Y': case 'Z': | |
97488870 | 1323 | if (CLASS_LIKELY_SPILLED_P (REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p) )) |
0eadeb15 | 1324 | likely_spilled[op_no] = 1; |
184bb750 R |
1325 | break; |
1326 | } | |
97488870 R |
1327 | p += CONSTRAINT_LEN (c, p); |
1328 | } | |
184bb750 | 1329 | } |
0eadeb15 | 1330 | return any_matches; |
184bb750 R |
1331 | } |
1332 | ||
1e7f0a48 | 1333 | \f |
1e7f0a48 | 1334 | |
ef330312 PB |
1335 | static bool |
1336 | gate_handle_regmove (void) | |
1337 | { | |
1338 | return (optimize > 0 && flag_regmove); | |
1339 | } | |
1340 | ||
ef330312 | 1341 | |
8ddbbcae | 1342 | struct rtl_opt_pass pass_regmove = |
ef330312 | 1343 | { |
8ddbbcae JH |
1344 | { |
1345 | RTL_PASS, | |
ef330312 PB |
1346 | "regmove", /* name */ |
1347 | gate_handle_regmove, /* gate */ | |
62d049cf | 1348 | regmove_optimize, /* execute */ |
ef330312 PB |
1349 | NULL, /* sub */ |
1350 | NULL, /* next */ | |
1351 | 0, /* static_pass_number */ | |
1352 | TV_REGMOVE, /* tv_id */ | |
1353 | 0, /* properties_required */ | |
1354 | 0, /* properties_provided */ | |
1355 | 0, /* properties_destroyed */ | |
1356 | 0, /* todo_flags_start */ | |
a36b8a1e | 1357 | TODO_df_finish | TODO_verify_rtl_sharing | |
ef330312 | 1358 | TODO_dump_func | |
8ddbbcae JH |
1359 | TODO_ggc_collect /* todo_flags_finish */ |
1360 | } | |
ef330312 | 1361 | }; |