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