Mercurial > hg > CbC > CbC_gcc
annotate gcc/postreload.c @ 144:8f4e72ab4e11
fix segmentation fault caused by nothing next cur_op to end
author | Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 23 Dec 2018 21:23:56 +0900 |
parents | 84e7813d76e9 |
children | 1830386684a0 |
rev | line source |
---|---|
0 | 1 /* Perform simple optimizations to clean up the result of reload. |
131 | 2 Copyright (C) 1987-2018 Free Software Foundation, Inc. |
0 | 3 |
4 This file is part of GCC. | |
5 | |
6 GCC is free software; you can redistribute it and/or modify it under | |
7 the terms of the GNU General Public License as published by the Free | |
8 Software Foundation; either version 3, or (at your option) any later | |
9 version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 #include "config.h" | |
21 #include "system.h" | |
22 #include "coretypes.h" | |
111 | 23 #include "backend.h" |
24 #include "target.h" | |
0 | 25 #include "rtl.h" |
111 | 26 #include "tree.h" |
27 #include "predict.h" | |
28 #include "df.h" | |
29 #include "memmodel.h" | |
0 | 30 #include "tm_p.h" |
31 #include "optabs.h" | |
32 #include "regs.h" | |
111 | 33 #include "emit-rtl.h" |
34 #include "recog.h" | |
35 | |
36 #include "cfgrtl.h" | |
37 #include "cfgbuild.h" | |
38 #include "cfgcleanup.h" | |
0 | 39 #include "reload.h" |
40 #include "cselib.h" | |
41 #include "tree-pass.h" | |
42 #include "dbgcnt.h" | |
43 | |
44 static int reload_cse_noop_set_p (rtx); | |
111 | 45 static bool reload_cse_simplify (rtx_insn *, rtx); |
46 static void reload_cse_regs_1 (void); | |
47 static int reload_cse_simplify_set (rtx, rtx_insn *); | |
48 static int reload_cse_simplify_operands (rtx_insn *, rtx); | |
0 | 49 |
50 static void reload_combine (void); | |
111 | 51 static void reload_combine_note_use (rtx *, rtx_insn *, int, rtx); |
0 | 52 static void reload_combine_note_store (rtx, const_rtx, void *); |
53 | |
111 | 54 static bool reload_cse_move2add (rtx_insn *); |
0 | 55 static void move2add_note_store (rtx, const_rtx, void *); |
56 | |
57 /* Call cse / combine like post-reload optimization phases. | |
58 FIRST is the first instruction. */ | |
111 | 59 |
60 static void | |
61 reload_cse_regs (rtx_insn *first ATTRIBUTE_UNUSED) | |
0 | 62 { |
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
|
63 bool moves_converted; |
111 | 64 reload_cse_regs_1 (); |
0 | 65 reload_combine (); |
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
|
66 moves_converted = reload_cse_move2add (first); |
0 | 67 if (flag_expensive_optimizations) |
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
|
68 { |
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
|
69 if (moves_converted) |
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
|
70 reload_combine (); |
111 | 71 reload_cse_regs_1 (); |
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
|
72 } |
0 | 73 } |
74 | |
75 /* See whether a single set SET is a noop. */ | |
76 static int | |
77 reload_cse_noop_set_p (rtx set) | |
78 { | |
79 if (cselib_reg_set_mode (SET_DEST (set)) != GET_MODE (SET_DEST (set))) | |
80 return 0; | |
81 | |
82 return rtx_equal_for_cselib_p (SET_DEST (set), SET_SRC (set)); | |
83 } | |
84 | |
111 | 85 /* Try to simplify INSN. Return true if the CFG may have changed. */ |
86 static bool | |
87 reload_cse_simplify (rtx_insn *insn, rtx testreg) | |
0 | 88 { |
89 rtx body = PATTERN (insn); | |
111 | 90 basic_block insn_bb = BLOCK_FOR_INSN (insn); |
91 unsigned insn_bb_succs = EDGE_COUNT (insn_bb->succs); | |
92 | |
93 /* If NO_FUNCTION_CSE has been set by the target, then we should not try | |
94 to cse function calls. */ | |
95 if (NO_FUNCTION_CSE && CALL_P (insn)) | |
96 return false; | |
0 | 97 |
98 if (GET_CODE (body) == SET) | |
99 { | |
100 int count = 0; | |
101 | |
102 /* Simplify even if we may think it is a no-op. | |
103 We may think a memory load of a value smaller than WORD_SIZE | |
104 is redundant because we haven't taken into account possible | |
105 implicit extension. reload_cse_simplify_set() will bring | |
106 this out, so it's safer to simplify before we delete. */ | |
107 count += reload_cse_simplify_set (body, insn); | |
108 | |
109 if (!count && reload_cse_noop_set_p (body)) | |
110 { | |
111 | 111 if (check_for_inc_dec (insn)) |
112 delete_insn_and_edges (insn); | |
113 /* We're done with this insn. */ | |
114 goto done; | |
0 | 115 } |
116 | |
117 if (count > 0) | |
118 apply_change_group (); | |
119 else | |
120 reload_cse_simplify_operands (insn, testreg); | |
121 } | |
122 else if (GET_CODE (body) == PARALLEL) | |
123 { | |
124 int i; | |
125 int count = 0; | |
126 rtx value = NULL_RTX; | |
127 | |
128 /* Registers mentioned in the clobber list for an asm cannot be reused | |
129 within the body of the asm. Invalidate those registers now so that | |
130 we don't try to substitute values for them. */ | |
131 if (asm_noperands (body) >= 0) | |
132 { | |
133 for (i = XVECLEN (body, 0) - 1; i >= 0; --i) | |
134 { | |
135 rtx part = XVECEXP (body, 0, i); | |
131 | 136 /* asms can only have full clobbers, not clobber_highs. */ |
137 gcc_assert (GET_CODE (part) != CLOBBER_HIGH); | |
0 | 138 if (GET_CODE (part) == CLOBBER && REG_P (XEXP (part, 0))) |
139 cselib_invalidate_rtx (XEXP (part, 0)); | |
140 } | |
141 } | |
142 | |
143 /* If every action in a PARALLEL is a noop, we can delete | |
144 the entire PARALLEL. */ | |
145 for (i = XVECLEN (body, 0) - 1; i >= 0; --i) | |
146 { | |
147 rtx part = XVECEXP (body, 0, i); | |
148 if (GET_CODE (part) == SET) | |
149 { | |
150 if (! reload_cse_noop_set_p (part)) | |
151 break; | |
152 if (REG_P (SET_DEST (part)) | |
153 && REG_FUNCTION_VALUE_P (SET_DEST (part))) | |
154 { | |
155 if (value) | |
156 break; | |
157 value = SET_DEST (part); | |
158 } | |
159 } | |
111 | 160 else if (GET_CODE (part) != CLOBBER |
131 | 161 && GET_CODE (part) != CLOBBER_HIGH |
111 | 162 && GET_CODE (part) != USE) |
0 | 163 break; |
164 } | |
165 | |
166 if (i < 0) | |
167 { | |
111 | 168 if (check_for_inc_dec (insn)) |
169 delete_insn_and_edges (insn); | |
0 | 170 /* We're done with this insn. */ |
111 | 171 goto done; |
0 | 172 } |
173 | |
174 /* It's not a no-op, but we can try to simplify it. */ | |
175 for (i = XVECLEN (body, 0) - 1; i >= 0; --i) | |
176 if (GET_CODE (XVECEXP (body, 0, i)) == SET) | |
177 count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn); | |
178 | |
179 if (count > 0) | |
180 apply_change_group (); | |
181 else | |
182 reload_cse_simplify_operands (insn, testreg); | |
183 } | |
111 | 184 |
185 done: | |
186 return (EDGE_COUNT (insn_bb->succs) != insn_bb_succs); | |
0 | 187 } |
188 | |
189 /* Do a very simple CSE pass over the hard registers. | |
190 | |
191 This function detects no-op moves where we happened to assign two | |
192 different pseudo-registers to the same hard register, and then | |
193 copied one to the other. Reload will generate a useless | |
194 instruction copying a register to itself. | |
195 | |
196 This function also detects cases where we load a value from memory | |
197 into two different registers, and (if memory is more expensive than | |
198 registers) changes it to simply copy the first register into the | |
199 second register. | |
200 | |
201 Another optimization is performed that scans the operands of each | |
202 instruction to see whether the value is already available in a | |
203 hard register. It then replaces the operand with the hard register | |
204 if possible, much like an optional reload would. */ | |
205 | |
206 static void | |
111 | 207 reload_cse_regs_1 (void) |
0 | 208 { |
111 | 209 bool cfg_changed = false; |
210 basic_block bb; | |
211 rtx_insn *insn; | |
212 rtx testreg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1); | |
0 | 213 |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
214 cselib_init (CSELIB_RECORD_MEMORY); |
0 | 215 init_alias_analysis (); |
216 | |
111 | 217 FOR_EACH_BB_FN (bb, cfun) |
218 FOR_BB_INSNS (bb, insn) | |
219 { | |
220 if (INSN_P (insn)) | |
221 cfg_changed |= reload_cse_simplify (insn, testreg); | |
0 | 222 |
111 | 223 cselib_process_insn (insn); |
224 } | |
0 | 225 |
226 /* Clean up. */ | |
227 end_alias_analysis (); | |
228 cselib_finish (); | |
111 | 229 if (cfg_changed) |
230 cleanup_cfg (0); | |
0 | 231 } |
232 | |
233 /* Try to simplify a single SET instruction. SET is the set pattern. | |
234 INSN is the instruction it came from. | |
235 This function only handles one case: if we set a register to a value | |
236 which is not a register, we try to find that value in some other register | |
237 and change the set into a register copy. */ | |
238 | |
239 static int | |
111 | 240 reload_cse_simplify_set (rtx set, rtx_insn *insn) |
0 | 241 { |
242 int did_change = 0; | |
243 int dreg; | |
244 rtx src; | |
111 | 245 reg_class_t dclass; |
0 | 246 int old_cost; |
247 cselib_val *val; | |
248 struct elt_loc_list *l; | |
249 enum rtx_code extend_op = UNKNOWN; | |
250 bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); | |
251 | |
252 dreg = true_regnum (SET_DEST (set)); | |
253 if (dreg < 0) | |
254 return 0; | |
255 | |
256 src = SET_SRC (set); | |
257 if (side_effects_p (src) || true_regnum (src) >= 0) | |
258 return 0; | |
259 | |
260 dclass = REGNO_REG_CLASS (dreg); | |
261 | |
262 /* When replacing a memory with a register, we need to honor assumptions | |
263 that combine made wrt the contents of sign bits. We'll do this by | |
264 generating an extend instruction instead of a reg->reg copy. Thus | |
265 the destination must be a register that we can widen. */ | |
266 if (MEM_P (src) | |
111 | 267 && (extend_op = load_extend_op (GET_MODE (src))) != UNKNOWN |
0 | 268 && !REG_P (SET_DEST (set))) |
269 return 0; | |
270 | |
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
|
271 val = cselib_lookup (src, GET_MODE (SET_DEST (set)), 0, VOIDmode); |
0 | 272 if (! val) |
273 return 0; | |
274 | |
275 /* If memory loads are cheaper than register copies, don't change them. */ | |
276 if (MEM_P (src)) | |
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
|
277 old_cost = memory_move_cost (GET_MODE (src), dclass, true); |
0 | 278 else if (REG_P (src)) |
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
|
279 old_cost = register_move_cost (GET_MODE (src), |
0 | 280 REGNO_REG_CLASS (REGNO (src)), dclass); |
281 else | |
111 | 282 old_cost = set_src_cost (src, GET_MODE (SET_DEST (set)), speed); |
0 | 283 |
284 for (l = val->locs; l; l = l->next) | |
285 { | |
286 rtx this_rtx = l->loc; | |
287 int this_cost; | |
288 | |
289 if (CONSTANT_P (this_rtx) && ! references_value_p (this_rtx, 0)) | |
290 { | |
291 if (extend_op != UNKNOWN) | |
292 { | |
111 | 293 wide_int result; |
0 | 294 |
111 | 295 if (!CONST_SCALAR_INT_P (this_rtx)) |
0 | 296 continue; |
297 | |
298 switch (extend_op) | |
299 { | |
300 case ZERO_EXTEND: | |
111 | 301 result = wide_int::from (rtx_mode_t (this_rtx, |
302 GET_MODE (src)), | |
303 BITS_PER_WORD, UNSIGNED); | |
0 | 304 break; |
305 case SIGN_EXTEND: | |
111 | 306 result = wide_int::from (rtx_mode_t (this_rtx, |
307 GET_MODE (src)), | |
308 BITS_PER_WORD, SIGNED); | |
309 break; | |
0 | 310 default: |
311 gcc_unreachable (); | |
312 } | |
111 | 313 this_rtx = immed_wide_int_const (result, word_mode); |
0 | 314 } |
111 | 315 |
316 this_cost = set_src_cost (this_rtx, GET_MODE (SET_DEST (set)), speed); | |
0 | 317 } |
318 else if (REG_P (this_rtx)) | |
319 { | |
320 if (extend_op != UNKNOWN) | |
321 { | |
322 this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx); | |
111 | 323 this_cost = set_src_cost (this_rtx, word_mode, speed); |
0 | 324 } |
325 else | |
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
|
326 this_cost = register_move_cost (GET_MODE (this_rtx), |
0 | 327 REGNO_REG_CLASS (REGNO (this_rtx)), |
328 dclass); | |
329 } | |
330 else | |
331 continue; | |
332 | |
333 /* If equal costs, prefer registers over anything else. That | |
334 tends to lead to smaller instructions on some machines. */ | |
335 if (this_cost < old_cost | |
336 || (this_cost == old_cost | |
337 && REG_P (this_rtx) | |
338 && !REG_P (SET_SRC (set)))) | |
339 { | |
111 | 340 if (extend_op != UNKNOWN |
341 && REG_CAN_CHANGE_MODE_P (REGNO (SET_DEST (set)), | |
342 GET_MODE (SET_DEST (set)), word_mode)) | |
0 | 343 { |
344 rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set))); | |
345 ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set)); | |
346 validate_change (insn, &SET_DEST (set), wide_dest, 1); | |
347 } | |
348 | |
349 validate_unshare_change (insn, &SET_SRC (set), this_rtx, 1); | |
350 old_cost = this_cost, did_change = 1; | |
351 } | |
352 } | |
353 | |
354 return did_change; | |
355 } | |
356 | |
357 /* Try to replace operands in INSN with equivalent values that are already | |
358 in registers. This can be viewed as optional reloading. | |
359 | |
360 For each non-register operand in the insn, see if any hard regs are | |
361 known to be equivalent to that operand. Record the alternatives which | |
362 can accept these hard registers. Among all alternatives, select the | |
363 ones which are better or equal to the one currently matching, where | |
364 "better" is in terms of '?' and '!' constraints. Among the remaining | |
365 alternatives, select the one which replaces most operands with | |
366 hard registers. */ | |
367 | |
368 static int | |
111 | 369 reload_cse_simplify_operands (rtx_insn *insn, rtx testreg) |
0 | 370 { |
371 int i, j; | |
372 | |
373 /* For each operand, all registers that are equivalent to it. */ | |
374 HARD_REG_SET equiv_regs[MAX_RECOG_OPERANDS]; | |
375 | |
376 const char *constraints[MAX_RECOG_OPERANDS]; | |
377 | |
378 /* Vector recording how bad an alternative is. */ | |
379 int *alternative_reject; | |
380 /* Vector recording how many registers can be introduced by choosing | |
381 this alternative. */ | |
382 int *alternative_nregs; | |
383 /* Array of vectors recording, for each operand and each alternative, | |
384 which hard register to substitute, or -1 if the operand should be | |
385 left as it is. */ | |
386 int *op_alt_regno[MAX_RECOG_OPERANDS]; | |
387 /* Array of alternatives, sorted in order of decreasing desirability. */ | |
388 int *alternative_order; | |
389 | |
111 | 390 extract_constrain_insn (insn); |
0 | 391 |
392 if (recog_data.n_alternatives == 0 || recog_data.n_operands == 0) | |
393 return 0; | |
394 | |
395 alternative_reject = XALLOCAVEC (int, recog_data.n_alternatives); | |
396 alternative_nregs = XALLOCAVEC (int, recog_data.n_alternatives); | |
397 alternative_order = XALLOCAVEC (int, recog_data.n_alternatives); | |
398 memset (alternative_reject, 0, recog_data.n_alternatives * sizeof (int)); | |
399 memset (alternative_nregs, 0, recog_data.n_alternatives * sizeof (int)); | |
400 | |
401 /* For each operand, find out which regs are equivalent. */ | |
402 for (i = 0; i < recog_data.n_operands; i++) | |
403 { | |
404 cselib_val *v; | |
405 struct elt_loc_list *l; | |
406 rtx op; | |
407 | |
408 CLEAR_HARD_REG_SET (equiv_regs[i]); | |
409 | |
410 /* cselib blows up on CODE_LABELs. Trying to fix that doesn't seem | |
111 | 411 right, so avoid the problem here. Similarly NOTE_INSN_DELETED_LABEL. |
412 Likewise if we have a constant and the insn pattern doesn't tell us | |
413 the mode we need. */ | |
0 | 414 if (LABEL_P (recog_data.operand[i]) |
111 | 415 || (NOTE_P (recog_data.operand[i]) |
416 && NOTE_KIND (recog_data.operand[i]) == NOTE_INSN_DELETED_LABEL) | |
0 | 417 || (CONSTANT_P (recog_data.operand[i]) |
418 && recog_data.operand_mode[i] == VOIDmode)) | |
419 continue; | |
420 | |
421 op = recog_data.operand[i]; | |
111 | 422 if (MEM_P (op) && load_extend_op (GET_MODE (op)) != UNKNOWN) |
0 | 423 { |
424 rtx set = single_set (insn); | |
425 | |
426 /* We might have multiple sets, some of which do implicit | |
427 extension. Punt on this for now. */ | |
428 if (! set) | |
429 continue; | |
430 /* If the destination is also a MEM or a STRICT_LOW_PART, no | |
431 extension applies. | |
432 Also, if there is an explicit extension, we don't have to | |
433 worry about an implicit one. */ | |
434 else if (MEM_P (SET_DEST (set)) | |
435 || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART | |
436 || GET_CODE (SET_SRC (set)) == ZERO_EXTEND | |
437 || GET_CODE (SET_SRC (set)) == SIGN_EXTEND) | |
438 ; /* Continue ordinary processing. */ | |
439 /* If the register cannot change mode to word_mode, it follows that | |
440 it cannot have been used in word_mode. */ | |
441 else if (REG_P (SET_DEST (set)) | |
111 | 442 && !REG_CAN_CHANGE_MODE_P (REGNO (SET_DEST (set)), |
443 GET_MODE (SET_DEST (set)), | |
444 word_mode)) | |
0 | 445 ; /* Continue ordinary processing. */ |
446 /* If this is a straight load, make the extension explicit. */ | |
447 else if (REG_P (SET_DEST (set)) | |
448 && recog_data.n_operands == 2 | |
449 && SET_SRC (set) == op | |
450 && SET_DEST (set) == recog_data.operand[1-i]) | |
451 { | |
452 validate_change (insn, recog_data.operand_loc[i], | |
111 | 453 gen_rtx_fmt_e (load_extend_op (GET_MODE (op)), |
0 | 454 word_mode, op), |
455 1); | |
456 validate_change (insn, recog_data.operand_loc[1-i], | |
457 gen_rtx_REG (word_mode, REGNO (SET_DEST (set))), | |
458 1); | |
459 if (! apply_change_group ()) | |
460 return 0; | |
461 return reload_cse_simplify_operands (insn, testreg); | |
462 } | |
463 else | |
464 /* ??? There might be arithmetic operations with memory that are | |
465 safe to optimize, but is it worth the trouble? */ | |
466 continue; | |
467 } | |
111 | 468 |
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
|
469 if (side_effects_p (op)) |
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
|
470 continue; |
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
|
471 v = cselib_lookup (op, recog_data.operand_mode[i], 0, VOIDmode); |
0 | 472 if (! v) |
473 continue; | |
474 | |
475 for (l = v->locs; l; l = l->next) | |
476 if (REG_P (l->loc)) | |
477 SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc)); | |
478 } | |
479 | |
111 | 480 alternative_mask preferred = get_preferred_alternatives (insn); |
0 | 481 for (i = 0; i < recog_data.n_operands; i++) |
482 { | |
111 | 483 machine_mode mode; |
0 | 484 int regno; |
485 const char *p; | |
486 | |
487 op_alt_regno[i] = XALLOCAVEC (int, recog_data.n_alternatives); | |
488 for (j = 0; j < recog_data.n_alternatives; j++) | |
489 op_alt_regno[i][j] = -1; | |
490 | |
491 p = constraints[i] = recog_data.constraints[i]; | |
492 mode = recog_data.operand_mode[i]; | |
493 | |
494 /* Add the reject values for each alternative given by the constraints | |
495 for this operand. */ | |
496 j = 0; | |
497 while (*p != '\0') | |
498 { | |
499 char c = *p++; | |
500 if (c == ',') | |
501 j++; | |
502 else if (c == '?') | |
503 alternative_reject[j] += 3; | |
504 else if (c == '!') | |
505 alternative_reject[j] += 300; | |
506 } | |
507 | |
508 /* We won't change operands which are already registers. We | |
509 also don't want to modify output operands. */ | |
510 regno = true_regnum (recog_data.operand[i]); | |
511 if (regno >= 0 | |
512 || constraints[i][0] == '=' | |
513 || constraints[i][0] == '+') | |
514 continue; | |
515 | |
516 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) | |
517 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
518 enum reg_class rclass = NO_REGS; |
0 | 519 |
520 if (! TEST_HARD_REG_BIT (equiv_regs[i], regno)) | |
521 continue; | |
522 | |
111 | 523 set_mode_and_regno (testreg, mode, regno); |
0 | 524 |
525 /* We found a register equal to this operand. Now look for all | |
526 alternatives that can accept this register and have not been | |
527 assigned a register they can use yet. */ | |
528 j = 0; | |
529 p = constraints[i]; | |
530 for (;;) | |
531 { | |
532 char c = *p; | |
533 | |
534 switch (c) | |
535 { | |
111 | 536 case 'g': |
537 rclass = reg_class_subunion[rclass][GENERAL_REGS]; | |
0 | 538 break; |
539 | |
540 default: | |
541 rclass | |
542 = (reg_class_subunion | |
111 | 543 [rclass] |
544 [reg_class_for_constraint (lookup_constraint (p))]); | |
0 | 545 break; |
546 | |
547 case ',': case '\0': | |
548 /* See if REGNO fits this alternative, and set it up as the | |
549 replacement register if we don't have one for this | |
550 alternative yet and the operand being replaced is not | |
551 a cheap CONST_INT. */ | |
552 if (op_alt_regno[i][j] == -1 | |
111 | 553 && TEST_BIT (preferred, j) |
0 | 554 && reg_fits_class_p (testreg, rclass, 0, mode) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
555 && (!CONST_INT_P (recog_data.operand[i]) |
111 | 556 || (set_src_cost (recog_data.operand[i], mode, |
557 optimize_bb_for_speed_p | |
558 (BLOCK_FOR_INSN (insn))) | |
559 > set_src_cost (testreg, mode, | |
560 optimize_bb_for_speed_p | |
561 (BLOCK_FOR_INSN (insn)))))) | |
0 | 562 { |
563 alternative_nregs[j]++; | |
564 op_alt_regno[i][j] = regno; | |
565 } | |
566 j++; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
567 rclass = NO_REGS; |
0 | 568 break; |
569 } | |
570 p += CONSTRAINT_LEN (c, p); | |
571 | |
572 if (c == '\0') | |
573 break; | |
574 } | |
575 } | |
576 } | |
577 | |
578 /* Record all alternatives which are better or equal to the currently | |
579 matching one in the alternative_order array. */ | |
580 for (i = j = 0; i < recog_data.n_alternatives; i++) | |
581 if (alternative_reject[i] <= alternative_reject[which_alternative]) | |
582 alternative_order[j++] = i; | |
583 recog_data.n_alternatives = j; | |
584 | |
585 /* Sort it. Given a small number of alternatives, a dumb algorithm | |
586 won't hurt too much. */ | |
587 for (i = 0; i < recog_data.n_alternatives - 1; i++) | |
588 { | |
589 int best = i; | |
590 int best_reject = alternative_reject[alternative_order[i]]; | |
591 int best_nregs = alternative_nregs[alternative_order[i]]; | |
592 | |
593 for (j = i + 1; j < recog_data.n_alternatives; j++) | |
594 { | |
595 int this_reject = alternative_reject[alternative_order[j]]; | |
596 int this_nregs = alternative_nregs[alternative_order[j]]; | |
597 | |
598 if (this_reject < best_reject | |
599 || (this_reject == best_reject && this_nregs > best_nregs)) | |
600 { | |
601 best = j; | |
602 best_reject = this_reject; | |
603 best_nregs = this_nregs; | |
604 } | |
605 } | |
606 | |
111 | 607 std::swap (alternative_order[best], alternative_order[i]); |
0 | 608 } |
609 | |
610 /* Substitute the operands as determined by op_alt_regno for the best | |
611 alternative. */ | |
612 j = alternative_order[0]; | |
613 | |
614 for (i = 0; i < recog_data.n_operands; i++) | |
615 { | |
111 | 616 machine_mode mode = recog_data.operand_mode[i]; |
0 | 617 if (op_alt_regno[i][j] == -1) |
618 continue; | |
619 | |
620 validate_change (insn, recog_data.operand_loc[i], | |
621 gen_rtx_REG (mode, op_alt_regno[i][j]), 1); | |
622 } | |
623 | |
624 for (i = recog_data.n_dups - 1; i >= 0; i--) | |
625 { | |
626 int op = recog_data.dup_num[i]; | |
111 | 627 machine_mode mode = recog_data.operand_mode[op]; |
0 | 628 |
629 if (op_alt_regno[op][j] == -1) | |
630 continue; | |
631 | |
632 validate_change (insn, recog_data.dup_loc[i], | |
633 gen_rtx_REG (mode, op_alt_regno[op][j]), 1); | |
634 } | |
635 | |
636 return apply_change_group (); | |
637 } | |
638 | |
639 /* If reload couldn't use reg+reg+offset addressing, try to use reg+reg | |
640 addressing now. | |
641 This code might also be useful when reload gave up on reg+reg addressing | |
642 because of clashes between the return register and INDEX_REG_CLASS. */ | |
643 | |
644 /* The maximum number of uses of a register we can keep track of to | |
645 replace them with reg+reg addressing. */ | |
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
|
646 #define RELOAD_COMBINE_MAX_USES 16 |
0 | 647 |
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
|
648 /* Describes a recorded use of a register. */ |
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
|
649 struct reg_use |
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
|
650 { |
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
|
651 /* The insn where a register has been used. */ |
111 | 652 rtx_insn *insn; |
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
|
653 /* Points to the memory reference enclosing the use, if any, NULL_RTX |
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
|
654 otherwise. */ |
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
|
655 rtx containing_mem; |
111 | 656 /* Location of the register within INSN. */ |
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
|
657 rtx *usep; |
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
|
658 /* The reverse uid of the 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
|
659 int ruid; |
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
|
660 }; |
0 | 661 |
662 /* If the register is used in some unknown fashion, USE_INDEX is negative. | |
663 If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID | |
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
|
664 indicates where it is first set or clobbered. |
0 | 665 Otherwise, USE_INDEX is the index of the last encountered use of the |
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
|
666 register (which is first among these we have seen since we scan backwards). |
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
|
667 USE_RUID indicates the first encountered, i.e. last, of these uses. |
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
|
668 If ALL_OFFSETS_MATCH is true, all encountered uses were inside a PLUS |
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
|
669 with a constant offset; OFFSET contains this constant in that case. |
0 | 670 STORE_RUID is always meaningful if we only want to use a value in a |
671 register in a different place: it denotes the next insn in the insn | |
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
|
672 stream (i.e. the last encountered) that sets or clobbers the register. |
131 | 673 REAL_STORE_RUID is similar, but clobbers are ignored when updating it. |
674 EXPR is the expression used when storing the register. */ | |
0 | 675 static struct |
676 { | |
677 struct reg_use reg_use[RELOAD_COMBINE_MAX_USES]; | |
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
|
678 rtx offset; |
0 | 679 int use_index; |
680 int store_ruid; | |
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
|
681 int real_store_ruid; |
0 | 682 int use_ruid; |
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
|
683 bool all_offsets_match; |
131 | 684 rtx expr; |
0 | 685 } reg_state[FIRST_PSEUDO_REGISTER]; |
686 | |
687 /* Reverse linear uid. This is increased in reload_combine while scanning | |
688 the instructions from last to first. It is used to set last_label_ruid | |
689 and the store_ruid / use_ruid fields in reg_state. */ | |
690 static int reload_combine_ruid; | |
691 | |
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
|
692 /* The RUID of the last label we encountered in reload_combine. */ |
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
|
693 static int last_label_ruid; |
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
|
694 |
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
|
695 /* The RUID of the last jump we encountered in reload_combine. */ |
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
|
696 static int last_jump_ruid; |
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
|
697 |
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
|
698 /* The register numbers of the first and last index register. A value of |
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
|
699 -1 in LAST_INDEX_REG indicates that we've previously computed these |
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
|
700 values and found no suitable index registers. */ |
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
|
701 static int first_index_reg = -1; |
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
|
702 static int last_index_reg; |
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
|
703 |
0 | 704 #define LABEL_LIVE(LABEL) \ |
705 (label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno]) | |
706 | |
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
|
707 /* Subroutine of reload_combine_split_ruids, called to fix up a single |
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
|
708 ruid pointed to by *PRUID if it is higher than SPLIT_RUID. */ |
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
|
709 |
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
|
710 static inline void |
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
|
711 reload_combine_split_one_ruid (int *pruid, int split_ruid) |
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
|
712 { |
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
|
713 if (*pruid > split_ruid) |
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
|
714 (*pruid)++; |
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
|
715 } |
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
|
716 |
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
|
717 /* Called when we insert a new insn in a position we've already passed in |
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
|
718 the scan. Examine all our state, increasing all ruids that are higher |
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
|
719 than SPLIT_RUID by one in order to make room for a new 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
|
720 |
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
|
721 static void |
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
|
722 reload_combine_split_ruids (int split_ruid) |
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
|
723 { |
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
|
724 unsigned i; |
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
|
725 |
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
|
726 reload_combine_split_one_ruid (&reload_combine_ruid, split_ruid); |
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
|
727 reload_combine_split_one_ruid (&last_label_ruid, split_ruid); |
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
|
728 reload_combine_split_one_ruid (&last_jump_ruid, split_ruid); |
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
|
729 |
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
|
730 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
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
|
731 { |
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
|
732 int j, idx = reg_state[i].use_index; |
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
|
733 reload_combine_split_one_ruid (®_state[i].use_ruid, split_ruid); |
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
|
734 reload_combine_split_one_ruid (®_state[i].store_ruid, split_ruid); |
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
|
735 reload_combine_split_one_ruid (®_state[i].real_store_ruid, |
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
|
736 split_ruid); |
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
|
737 if (idx < 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
|
738 continue; |
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
|
739 for (j = idx; j < RELOAD_COMBINE_MAX_USES; j++) |
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
|
740 { |
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
|
741 reload_combine_split_one_ruid (®_state[i].reg_use[j].ruid, |
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
|
742 split_ruid); |
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
|
743 } |
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
|
744 } |
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
|
745 } |
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
|
746 |
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
|
747 /* Called when we are about to rescan a previously encountered insn with |
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
|
748 reload_combine_note_use after modifying some part of it. This clears all |
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
|
749 information about uses in that particular 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
|
750 |
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
|
751 static void |
111 | 752 reload_combine_purge_insn_uses (rtx_insn *insn) |
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
|
753 { |
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
|
754 unsigned i; |
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
|
755 |
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
|
756 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
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
|
757 { |
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
|
758 int j, k, idx = reg_state[i].use_index; |
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
|
759 if (idx < 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
|
760 continue; |
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
|
761 j = k = RELOAD_COMBINE_MAX_USES; |
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
|
762 while (j-- > idx) |
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
|
763 { |
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
|
764 if (reg_state[i].reg_use[j].insn != 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
|
765 { |
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
|
766 k--; |
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
|
767 if (k != j) |
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
|
768 reg_state[i].reg_use[k] = reg_state[i].reg_use[j]; |
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
|
769 } |
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
|
770 } |
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
|
771 reg_state[i].use_index = k; |
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
|
772 } |
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
|
773 } |
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
|
774 |
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
|
775 /* Called when we need to forget about all uses of REGNO after an 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
|
776 which is identified by RUID. */ |
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
|
777 |
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
|
778 static void |
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
|
779 reload_combine_purge_reg_uses_after_ruid (unsigned regno, int ruid) |
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
|
780 { |
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
|
781 int j, k, idx = reg_state[regno].use_index; |
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
|
782 if (idx < 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
|
783 return; |
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
|
784 j = k = RELOAD_COMBINE_MAX_USES; |
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
|
785 while (j-- > idx) |
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
|
786 { |
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
|
787 if (reg_state[regno].reg_use[j].ruid >= ruid) |
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
|
788 { |
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
|
789 k--; |
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
|
790 if (k != j) |
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
|
791 reg_state[regno].reg_use[k] = reg_state[regno].reg_use[j]; |
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
|
792 } |
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
|
793 } |
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
|
794 reg_state[regno].use_index = k; |
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
|
795 } |
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
|
796 |
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
|
797 /* Find the use of REGNO with the ruid that is highest among those |
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
|
798 lower than RUID_LIMIT, and return it if it is the only use of this |
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
|
799 reg in the insn. Return NULL otherwise. */ |
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
|
800 |
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
|
801 static struct reg_use * |
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
|
802 reload_combine_closest_single_use (unsigned regno, int ruid_limit) |
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
|
803 { |
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
|
804 int i, best_ruid = 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
|
805 int use_idx = reg_state[regno].use_index; |
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
|
806 struct reg_use *retval; |
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
|
807 |
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
|
808 if (use_idx < 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
|
809 return NULL; |
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
|
810 retval = NULL; |
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
|
811 for (i = use_idx; i < RELOAD_COMBINE_MAX_USES; i++) |
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
|
812 { |
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
|
813 struct reg_use *use = reg_state[regno].reg_use + i; |
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
|
814 int this_ruid = use->ruid; |
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
|
815 if (this_ruid >= ruid_limit) |
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
|
816 continue; |
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
|
817 if (this_ruid > best_ruid) |
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
|
818 { |
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
|
819 best_ruid = this_ruid; |
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
|
820 retval = use; |
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
|
821 } |
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
|
822 else if (this_ruid == best_ruid) |
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
|
823 retval = NULL; |
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
|
824 } |
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
|
825 if (last_label_ruid >= best_ruid) |
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
|
826 return NULL; |
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
|
827 return retval; |
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
|
828 } |
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
|
829 |
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
|
830 /* After we've moved an add insn, fix up any debug insns that occur |
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
|
831 between the old location of the add and the new location. REG is |
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
|
832 the destination register of the add insn; REPLACEMENT is the |
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
|
833 SET_SRC of the add. FROM and TO specify the range in which we |
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
|
834 should make this change on debug insns. */ |
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
|
835 |
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
|
836 static void |
111 | 837 fixup_debug_insns (rtx reg, rtx replacement, rtx_insn *from, rtx_insn *to) |
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
|
838 { |
111 | 839 rtx_insn *insn; |
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
|
840 for (insn = from; insn != to; insn = NEXT_INSN (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
|
841 { |
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
|
842 rtx t; |
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
|
843 |
131 | 844 if (!DEBUG_BIND_INSN_P (insn)) |
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
|
845 continue; |
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
|
846 |
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
|
847 t = INSN_VAR_LOCATION_LOC (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
|
848 t = simplify_replace_rtx (t, reg, replacement); |
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
|
849 validate_change (insn, &INSN_VAR_LOCATION_LOC (insn), t, 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
|
850 } |
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
|
851 } |
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
|
852 |
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
|
853 /* Subroutine of reload_combine_recognize_const_pattern. Try to replace REG |
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
|
854 with SRC in the insn described by USE, taking costs into account. Return |
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
|
855 true if we made the replacement. */ |
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
|
856 |
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
|
857 static bool |
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
|
858 try_replace_in_use (struct reg_use *use, rtx reg, rtx 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
|
859 { |
111 | 860 rtx_insn *use_insn = use->insn; |
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
|
861 rtx mem = use->containing_mem; |
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
|
862 bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_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
|
863 |
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
|
864 if (mem != NULL_RTX) |
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
|
865 { |
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
|
866 addr_space_t as = MEM_ADDR_SPACE (mem); |
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
|
867 rtx oldaddr = XEXP (mem, 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
|
868 rtx newaddr = NULL_RTX; |
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
|
869 int old_cost = address_cost (oldaddr, GET_MODE (mem), as, speed); |
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
|
870 int new_cost; |
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
|
871 |
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
|
872 newaddr = simplify_replace_rtx (oldaddr, reg, 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
|
873 if (memory_address_addr_space_p (GET_MODE (mem), newaddr, as)) |
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
|
874 { |
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
|
875 XEXP (mem, 0) = newaddr; |
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
|
876 new_cost = address_cost (newaddr, GET_MODE (mem), as, speed); |
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
|
877 XEXP (mem, 0) = oldaddr; |
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
|
878 if (new_cost <= old_cost |
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
|
879 && validate_change (use_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
|
880 &XEXP (mem, 0), newaddr, 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
|
881 return true; |
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
|
882 } |
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
|
883 } |
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
|
884 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
|
885 { |
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
|
886 rtx new_set = single_set (use_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
|
887 if (new_set |
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
|
888 && REG_P (SET_DEST (new_set)) |
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
|
889 && GET_CODE (SET_SRC (new_set)) == PLUS |
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
|
890 && REG_P (XEXP (SET_SRC (new_set), 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
|
891 && CONSTANT_P (XEXP (SET_SRC (new_set), 1))) |
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
|
892 { |
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
|
893 rtx new_src; |
111 | 894 machine_mode mode = GET_MODE (SET_DEST (new_set)); |
895 int old_cost = set_src_cost (SET_SRC (new_set), mode, speed); | |
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
|
896 |
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
|
897 gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg)); |
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
|
898 new_src = simplify_replace_rtx (SET_SRC (new_set), reg, 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
|
899 |
111 | 900 if (set_src_cost (new_src, mode, speed) <= old_cost |
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
|
901 && validate_change (use_insn, &SET_SRC (new_set), |
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
|
902 new_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
|
903 return true; |
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
|
904 } |
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
|
905 } |
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
|
906 return false; |
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
|
907 } |
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
|
908 |
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
|
909 /* Called by reload_combine when scanning INSN. This function tries to detect |
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
|
910 patterns where a constant is added to a register, and the result is used |
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
|
911 in an address. |
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
|
912 Return true if no further processing is needed on INSN; false if it wasn't |
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
|
913 recognized and should be handled normally. */ |
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
|
914 |
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
|
915 static bool |
111 | 916 reload_combine_recognize_const_pattern (rtx_insn *insn) |
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
|
917 { |
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
|
918 int from_ruid = reload_combine_ruid; |
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
|
919 rtx set, pat, reg, src, addreg; |
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
|
920 unsigned int regno; |
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
|
921 struct reg_use *use; |
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
|
922 bool must_move_add; |
111 | 923 rtx_insn *add_moved_after_insn = NULL; |
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
|
924 int add_moved_after_ruid = 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
|
925 int clobbered_regno = -1; |
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
|
926 |
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
|
927 set = single_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
|
928 if (set == NULL_RTX) |
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
|
929 return false; |
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
|
930 |
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
|
931 reg = SET_DEST (set); |
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
|
932 src = SET_SRC (set); |
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
|
933 if (!REG_P (reg) |
111 | 934 || REG_NREGS (reg) != 1 |
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
|
935 || GET_MODE (reg) != Pmode |
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
|
936 || reg == stack_pointer_rtx) |
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
|
937 return false; |
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
|
938 |
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
|
939 regno = REGNO (reg); |
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
|
940 |
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
|
941 /* We look for a REG1 = REG2 + CONSTANT insn, followed by either |
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
|
942 uses of REG1 inside an address, or inside another add insn. If |
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
|
943 possible and profitable, merge the addition into subsequent |
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
|
944 uses. */ |
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
|
945 if (GET_CODE (src) != PLUS |
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
|
946 || !REG_P (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
|
947 || !CONSTANT_P (XEXP (src, 1))) |
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
|
948 return false; |
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
|
949 |
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
|
950 addreg = 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
|
951 must_move_add = rtx_equal_p (reg, addreg); |
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
|
952 |
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
|
953 pat = PATTERN (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
|
954 if (must_move_add && set != pat) |
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
|
955 { |
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
|
956 /* We have to be careful when moving the add; apart from the |
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
|
957 single_set there may also be clobbers. Recognize one special |
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
|
958 case, that of one clobber alongside the set (likely a clobber |
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
|
959 of the CC register). */ |
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
|
960 gcc_assert (GET_CODE (PATTERN (insn)) == PARALLEL); |
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
|
961 if (XVECLEN (pat, 0) != 2 || XVECEXP (pat, 0, 0) != set |
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
|
962 || GET_CODE (XVECEXP (pat, 0, 1)) != CLOBBER |
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
|
963 || !REG_P (XEXP (XVECEXP (pat, 0, 1), 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
|
964 return false; |
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
|
965 clobbered_regno = REGNO (XEXP (XVECEXP (pat, 0, 1), 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
|
966 } |
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
|
967 |
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
|
968 do |
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
|
969 { |
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
|
970 use = reload_combine_closest_single_use (regno, from_ruid); |
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
|
971 |
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
|
972 if (use) |
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
|
973 /* Start the search for the next use from here. */ |
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
|
974 from_ruid = use->ruid; |
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
|
975 |
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
|
976 if (use && GET_MODE (*use->usep) == Pmode) |
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
|
977 { |
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
|
978 bool delete_add = false; |
111 | 979 rtx_insn *use_insn = use->insn; |
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
|
980 int use_ruid = use->ruid; |
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
|
981 |
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
|
982 /* Avoid moving the add insn past a jump. */ |
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
|
983 if (must_move_add && use_ruid <= last_jump_ruid) |
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
|
984 break; |
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
|
985 |
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
|
986 /* If the add clobbers another hard reg in parallel, don't move |
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
|
987 it past a real set of this hard reg. */ |
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
|
988 if (must_move_add && clobbered_regno >= 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
|
989 && reg_state[clobbered_regno].real_store_ruid >= use_ruid) |
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
|
990 break; |
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
|
991 |
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
|
992 /* Do not separate cc0 setter and cc0 user on HAVE_cc0 targets. */ |
111 | 993 if (HAVE_cc0 && must_move_add && sets_cc0_p (PATTERN (use_insn))) |
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
|
994 break; |
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
|
995 |
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
|
996 gcc_assert (reg_state[regno].store_ruid <= use_ruid); |
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
|
997 /* Avoid moving a use of ADDREG past a point where it is stored. */ |
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
|
998 if (reg_state[REGNO (addreg)].store_ruid > use_ruid) |
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
|
999 break; |
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
|
1000 |
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
|
1001 /* We also must not move the addition past an insn that sets |
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
|
1002 the same register, unless we can combine two add insns. */ |
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
|
1003 if (must_move_add && reg_state[regno].store_ruid == use_ruid) |
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
|
1004 { |
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
|
1005 if (use->containing_mem == NULL_RTX) |
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
|
1006 delete_add = true; |
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
|
1007 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
|
1008 break; |
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
|
1009 } |
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
|
1010 |
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
|
1011 if (try_replace_in_use (use, reg, 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
|
1012 { |
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
|
1013 reload_combine_purge_insn_uses (use_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
|
1014 reload_combine_note_use (&PATTERN (use_insn), use_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
|
1015 use_ruid, NULL_RTX); |
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
|
1016 |
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
|
1017 if (delete_add) |
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
|
1018 { |
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
|
1019 fixup_debug_insns (reg, src, insn, use_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
|
1020 delete_insn (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
|
1021 return true; |
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
|
1022 } |
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
|
1023 if (must_move_add) |
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
|
1024 { |
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
|
1025 add_moved_after_insn = use_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
|
1026 add_moved_after_ruid = use_ruid; |
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
|
1027 } |
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
|
1028 continue; |
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
|
1029 } |
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
|
1030 } |
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
|
1031 /* If we get here, we couldn't handle this use. */ |
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
|
1032 if (must_move_add) |
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
|
1033 break; |
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
|
1034 } |
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
|
1035 while (use); |
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
|
1036 |
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
|
1037 if (!must_move_add || add_moved_after_insn == NULL_RTX) |
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
|
1038 /* Process the add normally. */ |
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
|
1039 return false; |
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
|
1040 |
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
|
1041 fixup_debug_insns (reg, src, insn, add_moved_after_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
|
1042 |
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
|
1043 reorder_insns (insn, insn, add_moved_after_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
|
1044 reload_combine_purge_reg_uses_after_ruid (regno, add_moved_after_ruid); |
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
|
1045 reload_combine_split_ruids (add_moved_after_ruid - 1); |
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
|
1046 reload_combine_note_use (&PATTERN (insn), 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
|
1047 add_moved_after_ruid, NULL_RTX); |
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
|
1048 reg_state[regno].store_ruid = add_moved_after_ruid; |
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
|
1049 |
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
|
1050 return true; |
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
|
1051 } |
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
|
1052 |
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
|
1053 /* Called by reload_combine when scanning INSN. Try to detect a pattern we |
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
|
1054 can handle and improve. Return true if no further processing is needed on |
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
|
1055 INSN; false if it wasn't recognized and should be handled normally. */ |
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
|
1056 |
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
|
1057 static bool |
111 | 1058 reload_combine_recognize_pattern (rtx_insn *insn) |
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
|
1059 { |
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
|
1060 rtx set, reg, 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
|
1061 |
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
|
1062 set = single_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
|
1063 if (set == NULL_RTX) |
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
|
1064 return false; |
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
|
1065 |
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
|
1066 reg = SET_DEST (set); |
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
|
1067 src = SET_SRC (set); |
111 | 1068 if (!REG_P (reg) || REG_NREGS (reg) != 1) |
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
|
1069 return false; |
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
|
1070 |
111 | 1071 unsigned int regno = REGNO (reg); |
1072 machine_mode mode = GET_MODE (reg); | |
1073 | |
1074 if (reg_state[regno].use_index < 0 | |
1075 || reg_state[regno].use_index >= RELOAD_COMBINE_MAX_USES) | |
1076 return false; | |
1077 | |
1078 for (int i = reg_state[regno].use_index; | |
1079 i < RELOAD_COMBINE_MAX_USES; i++) | |
1080 { | |
1081 struct reg_use *use = reg_state[regno].reg_use + i; | |
1082 if (GET_MODE (*use->usep) != mode) | |
1083 return false; | |
1084 } | |
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
|
1085 |
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
|
1086 /* Look for (set (REGX) (CONST_INT)) |
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
|
1087 (set (REGX) (PLUS (REGX) (REGY))) |
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
|
1088 ... |
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
|
1089 ... (MEM (REGX)) ... |
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
|
1090 and convert it to |
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
|
1091 (set (REGZ) (CONST_INT)) |
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
|
1092 ... |
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
|
1093 ... (MEM (PLUS (REGZ) (REGY)))... . |
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
|
1094 |
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
|
1095 First, check that we have (set (REGX) (PLUS (REGX) (REGY))) |
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
|
1096 and that we know all uses of REGX before it dies. |
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
|
1097 Also, explicitly check that REGX != REGY; our life information |
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
|
1098 does not yet show whether REGY changes in this 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
|
1099 |
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
|
1100 if (GET_CODE (src) == PLUS |
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
|
1101 && reg_state[regno].all_offsets_match |
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
|
1102 && last_index_reg != -1 |
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
|
1103 && REG_P (XEXP (src, 1)) |
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
|
1104 && rtx_equal_p (XEXP (src, 0), reg) |
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
|
1105 && !rtx_equal_p (XEXP (src, 1), reg) |
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
|
1106 && last_label_ruid < reg_state[regno].use_ruid) |
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
|
1107 { |
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
|
1108 rtx base = XEXP (src, 1); |
111 | 1109 rtx_insn *prev = prev_nonnote_nondebug_insn (insn); |
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
|
1110 rtx prev_set = prev ? single_set (prev) : NULL_RTX; |
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
|
1111 rtx index_reg = NULL_RTX; |
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
|
1112 rtx reg_sum = NULL_RTX; |
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
|
1113 int i; |
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
|
1114 |
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
|
1115 /* Now we need to set INDEX_REG to an index register (denoted as |
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
|
1116 REGZ in the illustration above) and REG_SUM to the expression |
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
|
1117 register+register that we want to use to substitute uses of REG |
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
|
1118 (typically in MEMs) with. First check REG and BASE for being |
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
|
1119 index registers; we can use them even if they are not dead. */ |
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
|
1120 if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno) |
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
|
1121 || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], |
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
|
1122 REGNO (base))) |
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
|
1123 { |
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
|
1124 index_reg = reg; |
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
|
1125 reg_sum = 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
|
1126 } |
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
|
1127 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
|
1128 { |
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
|
1129 /* Otherwise, look for a free index register. Since we have |
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
|
1130 checked above that neither REG nor BASE are index registers, |
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
|
1131 if we find anything at all, it will be different from these |
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
|
1132 two registers. */ |
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
|
1133 for (i = first_index_reg; i <= last_index_reg; i++) |
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
|
1134 { |
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
|
1135 if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i) |
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
|
1136 && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES |
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
|
1137 && reg_state[i].store_ruid <= reg_state[regno].use_ruid |
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
|
1138 && (call_used_regs[i] || df_regs_ever_live_p (i)) |
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
|
1139 && (!frame_pointer_needed || i != HARD_FRAME_POINTER_REGNUM) |
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
|
1140 && !fixed_regs[i] && !global_regs[i] |
111 | 1141 && hard_regno_nregs (i, GET_MODE (reg)) == 1 |
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
|
1142 && targetm.hard_regno_scratch_ok (i)) |
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
|
1143 { |
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
|
1144 index_reg = gen_rtx_REG (GET_MODE (reg), i); |
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
|
1145 reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base); |
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
|
1146 break; |
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
|
1147 } |
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
|
1148 } |
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
|
1149 } |
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
|
1150 |
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
|
1151 /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that |
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
|
1152 (REGY), i.e. BASE, is not clobbered before the last use we'll |
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
|
1153 create. */ |
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
|
1154 if (reg_sum |
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
|
1155 && prev_set |
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
|
1156 && CONST_INT_P (SET_SRC (prev_set)) |
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
|
1157 && rtx_equal_p (SET_DEST (prev_set), reg) |
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
|
1158 && (reg_state[REGNO (base)].store_ruid |
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
|
1159 <= reg_state[regno].use_ruid)) |
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
|
1160 { |
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
|
1161 /* Change destination register and, if necessary, the constant |
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
|
1162 value in PREV, the constant loading instruction. */ |
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
|
1163 validate_change (prev, &SET_DEST (prev_set), index_reg, 1); |
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
|
1164 if (reg_state[regno].offset != const0_rtx) |
131 | 1165 { |
1166 HOST_WIDE_INT c | |
1167 = trunc_int_for_mode (UINTVAL (SET_SRC (prev_set)) | |
1168 + UINTVAL (reg_state[regno].offset), | |
1169 GET_MODE (index_reg)); | |
1170 validate_change (prev, &SET_SRC (prev_set), GEN_INT (c), 1); | |
1171 } | |
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
|
1172 |
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
|
1173 /* Now for every use of REG that we have recorded, replace REG |
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
|
1174 with REG_SUM. */ |
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
|
1175 for (i = reg_state[regno].use_index; |
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
|
1176 i < RELOAD_COMBINE_MAX_USES; i++) |
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
|
1177 validate_unshare_change (reg_state[regno].reg_use[i].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
|
1178 reg_state[regno].reg_use[i].usep, |
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
|
1179 /* Each change must have its own |
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
|
1180 replacement. */ |
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
|
1181 reg_sum, 1); |
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
|
1182 |
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
|
1183 if (apply_change_group ()) |
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
|
1184 { |
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
|
1185 struct reg_use *lowest_ruid = NULL; |
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
|
1186 |
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
|
1187 /* For every new use of REG_SUM, we have to record the use |
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
|
1188 of BASE therein, i.e. operand 1. */ |
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
|
1189 for (i = reg_state[regno].use_index; |
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
|
1190 i < RELOAD_COMBINE_MAX_USES; i++) |
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
|
1191 { |
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
|
1192 struct reg_use *use = reg_state[regno].reg_use + i; |
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
|
1193 reload_combine_note_use (&XEXP (*use->usep, 1), use->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
|
1194 use->ruid, use->containing_mem); |
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
|
1195 if (lowest_ruid == NULL || use->ruid < lowest_ruid->ruid) |
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
|
1196 lowest_ruid = use; |
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
|
1197 } |
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
|
1198 |
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
|
1199 fixup_debug_insns (reg, reg_sum, insn, lowest_ruid->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
|
1200 |
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
|
1201 /* Delete the reg-reg addition. */ |
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
|
1202 delete_insn (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
|
1203 |
111 | 1204 if (reg_state[regno].offset != const0_rtx |
1205 /* Previous REG_EQUIV / REG_EQUAL notes for PREV | |
1206 are now invalid. */ | |
1207 && remove_reg_equal_equiv_notes (prev)) | |
1208 df_notes_rescan (prev); | |
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
|
1209 |
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
|
1210 reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES; |
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
|
1211 return true; |
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
|
1212 } |
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
|
1213 } |
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
|
1214 } |
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
|
1215 return false; |
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
|
1216 } |
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
|
1217 |
0 | 1218 static void |
1219 reload_combine (void) | |
1220 { | |
111 | 1221 rtx_insn *insn, *prev; |
0 | 1222 basic_block bb; |
1223 unsigned int r; | |
1224 int min_labelno, n_labels; | |
1225 HARD_REG_SET ever_live_at_start, *label_live; | |
1226 | |
1227 /* To avoid wasting too much time later searching for an index register, | |
1228 determine the minimum and maximum index register numbers. */ | |
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
|
1229 if (INDEX_REG_CLASS == NO_REGS) |
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
|
1230 last_index_reg = -1; |
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
|
1231 else if (first_index_reg == -1 && last_index_reg == 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
|
1232 { |
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
|
1233 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) |
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
|
1234 if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r)) |
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
|
1235 { |
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
|
1236 if (first_index_reg == -1) |
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
|
1237 first_index_reg = r; |
0 | 1238 |
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
|
1239 last_index_reg = r; |
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
|
1240 } |
0 | 1241 |
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
|
1242 /* If no index register is available, we can quit now. Set LAST_INDEX_REG |
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
|
1243 to -1 so we'll know to quit early the next time we get here. */ |
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
|
1244 if (first_index_reg == -1) |
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
|
1245 { |
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
|
1246 last_index_reg = -1; |
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
|
1247 return; |
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
|
1248 } |
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
|
1249 } |
0 | 1250 |
1251 /* Set up LABEL_LIVE and EVER_LIVE_AT_START. The register lifetime | |
1252 information is a bit fuzzy immediately after reload, but it's | |
1253 still good enough to determine which registers are live at a jump | |
1254 destination. */ | |
1255 min_labelno = get_first_label_num (); | |
1256 n_labels = max_label_num () - min_labelno; | |
1257 label_live = XNEWVEC (HARD_REG_SET, n_labels); | |
1258 CLEAR_HARD_REG_SET (ever_live_at_start); | |
1259 | |
111 | 1260 FOR_EACH_BB_REVERSE_FN (bb, cfun) |
0 | 1261 { |
1262 insn = BB_HEAD (bb); | |
1263 if (LABEL_P (insn)) | |
1264 { | |
1265 HARD_REG_SET live; | |
1266 bitmap live_in = df_get_live_in (bb); | |
1267 | |
1268 REG_SET_TO_HARD_REG_SET (live, live_in); | |
1269 compute_use_by_pseudos (&live, live_in); | |
1270 COPY_HARD_REG_SET (LABEL_LIVE (insn), live); | |
1271 IOR_HARD_REG_SET (ever_live_at_start, live); | |
1272 } | |
1273 } | |
1274 | |
1275 /* Initialize last_label_ruid, reload_combine_ruid and reg_state. */ | |
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
|
1276 last_label_ruid = last_jump_ruid = reload_combine_ruid = 0; |
0 | 1277 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) |
1278 { | |
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
|
1279 reg_state[r].store_ruid = 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
|
1280 reg_state[r].real_store_ruid = 0; |
0 | 1281 if (fixed_regs[r]) |
1282 reg_state[r].use_index = -1; | |
1283 else | |
1284 reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; | |
1285 } | |
1286 | |
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
|
1287 for (insn = get_last_insn (); insn; insn = prev) |
0 | 1288 { |
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
|
1289 bool control_flow_insn; |
0 | 1290 rtx note; |
1291 | |
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
|
1292 prev = PREV_INSN (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
|
1293 |
0 | 1294 /* We cannot do our optimization across labels. Invalidating all the use |
1295 information we have would be costly, so we just note where the label | |
1296 is and then later disable any optimization that would cross it. */ | |
1297 if (LABEL_P (insn)) | |
1298 last_label_ruid = reload_combine_ruid; | |
1299 else if (BARRIER_P (insn)) | |
111 | 1300 { |
1301 /* Crossing a barrier resets all the use information. */ | |
1302 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) | |
1303 if (! fixed_regs[r]) | |
1304 reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; | |
1305 } | |
1306 else if (INSN_P (insn) && volatile_insn_p (PATTERN (insn))) | |
1307 /* Optimizations across insns being marked as volatile must be | |
1308 prevented. All the usage information is invalidated | |
1309 here. */ | |
0 | 1310 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) |
111 | 1311 if (! fixed_regs[r] |
1312 && reg_state[r].use_index != RELOAD_COMBINE_MAX_USES) | |
1313 reg_state[r].use_index = -1; | |
0 | 1314 |
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
|
1315 if (! NONDEBUG_INSN_P (insn)) |
0 | 1316 continue; |
1317 | |
1318 reload_combine_ruid++; | |
1319 | |
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
|
1320 control_flow_insn = control_flow_insn_p (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
|
1321 if (control_flow_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
|
1322 last_jump_ruid = reload_combine_ruid; |
0 | 1323 |
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
|
1324 if (reload_combine_recognize_const_pattern (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
|
1325 || reload_combine_recognize_pattern (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
|
1326 continue; |
0 | 1327 |
1328 note_stores (PATTERN (insn), reload_combine_note_store, NULL); | |
1329 | |
1330 if (CALL_P (insn)) | |
1331 { | |
1332 rtx link; | |
111 | 1333 HARD_REG_SET used_regs; |
1334 | |
1335 get_call_reg_set_usage (insn, &used_regs, call_used_reg_set); | |
0 | 1336 |
1337 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) | |
111 | 1338 if (TEST_HARD_REG_BIT (used_regs, r)) |
0 | 1339 { |
1340 reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; | |
1341 reg_state[r].store_ruid = reload_combine_ruid; | |
1342 } | |
1343 | |
1344 for (link = CALL_INSN_FUNCTION_USAGE (insn); link; | |
1345 link = XEXP (link, 1)) | |
1346 { | |
111 | 1347 rtx setuse = XEXP (link, 0); |
1348 rtx usage_rtx = XEXP (setuse, 0); | |
131 | 1349 /* We could support CLOBBER_HIGH and treat it in the same way as |
1350 HARD_REGNO_CALL_PART_CLOBBERED, but no port needs that yet. */ | |
1351 gcc_assert (GET_CODE (setuse) != CLOBBER_HIGH); | |
1352 | |
111 | 1353 if ((GET_CODE (setuse) == USE || GET_CODE (setuse) == CLOBBER) |
1354 && REG_P (usage_rtx)) | |
0 | 1355 { |
111 | 1356 unsigned int end_regno = END_REGNO (usage_rtx); |
1357 for (unsigned int i = REGNO (usage_rtx); i < end_regno; ++i) | |
0 | 1358 if (GET_CODE (XEXP (link, 0)) == CLOBBER) |
1359 { | |
1360 reg_state[i].use_index = RELOAD_COMBINE_MAX_USES; | |
1361 reg_state[i].store_ruid = reload_combine_ruid; | |
1362 } | |
1363 else | |
1364 reg_state[i].use_index = -1; | |
1365 } | |
1366 } | |
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
|
1367 } |
0 | 1368 |
111 | 1369 if (control_flow_insn && !ANY_RETURN_P (PATTERN (insn))) |
0 | 1370 { |
1371 /* Non-spill registers might be used at the call destination in | |
1372 some unknown fashion, so we have to mark the unknown use. */ | |
1373 HARD_REG_SET *live; | |
1374 | |
1375 if ((condjump_p (insn) || condjump_in_parallel_p (insn)) | |
1376 && JUMP_LABEL (insn)) | |
111 | 1377 { |
1378 if (ANY_RETURN_P (JUMP_LABEL (insn))) | |
1379 live = NULL; | |
1380 else | |
1381 live = &LABEL_LIVE (JUMP_LABEL (insn)); | |
1382 } | |
0 | 1383 else |
1384 live = &ever_live_at_start; | |
1385 | |
111 | 1386 if (live) |
1387 for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) | |
1388 if (TEST_HARD_REG_BIT (*live, r)) | |
1389 reg_state[r].use_index = -1; | |
0 | 1390 } |
1391 | |
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
|
1392 reload_combine_note_use (&PATTERN (insn), insn, reload_combine_ruid, |
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
|
1393 NULL_RTX); |
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
|
1394 |
0 | 1395 for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) |
1396 { | |
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
|
1397 if (REG_NOTE_KIND (note) == REG_INC && REG_P (XEXP (note, 0))) |
0 | 1398 { |
1399 int regno = REGNO (XEXP (note, 0)); | |
1400 reg_state[regno].store_ruid = reload_combine_ruid; | |
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
|
1401 reg_state[regno].real_store_ruid = reload_combine_ruid; |
0 | 1402 reg_state[regno].use_index = -1; |
1403 } | |
1404 } | |
1405 } | |
1406 | |
1407 free (label_live); | |
1408 } | |
1409 | |
1410 /* Check if DST is a register or a subreg of a register; if it is, | |
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
|
1411 update store_ruid, real_store_ruid and use_index in the reg_state |
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
|
1412 structure accordingly. Called via note_stores from reload_combine. */ |
0 | 1413 |
1414 static void | |
1415 reload_combine_note_store (rtx dst, const_rtx set, void *data ATTRIBUTE_UNUSED) | |
1416 { | |
1417 int regno = 0; | |
1418 int i; | |
111 | 1419 machine_mode mode = GET_MODE (dst); |
0 | 1420 |
1421 if (GET_CODE (dst) == SUBREG) | |
1422 { | |
1423 regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)), | |
1424 GET_MODE (SUBREG_REG (dst)), | |
1425 SUBREG_BYTE (dst), | |
1426 GET_MODE (dst)); | |
1427 dst = SUBREG_REG (dst); | |
1428 } | |
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
|
1429 |
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
|
1430 /* Some targets do argument pushes without adding REG_INC notes. */ |
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
|
1431 |
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
|
1432 if (MEM_P (dst)) |
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
|
1433 { |
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
|
1434 dst = XEXP (dst, 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
|
1435 if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC |
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
|
1436 || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC |
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
|
1437 || GET_CODE (dst) == PRE_MODIFY || GET_CODE (dst) == POST_MODIFY) |
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
|
1438 { |
111 | 1439 unsigned int end_regno = END_REGNO (XEXP (dst, 0)); |
1440 for (unsigned int i = REGNO (XEXP (dst, 0)); i < end_regno; ++i) | |
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
|
1441 { |
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
|
1442 /* We could probably do better, but for now mark the register |
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
|
1443 as used in an unknown fashion and set/clobbered at this |
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
|
1444 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
|
1445 reg_state[i].use_index = -1; |
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
|
1446 reg_state[i].store_ruid = reload_combine_ruid; |
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
|
1447 reg_state[i].real_store_ruid = reload_combine_ruid; |
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
|
1448 } |
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
|
1449 } |
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
|
1450 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
|
1451 return; |
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
|
1452 } |
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
|
1453 |
0 | 1454 if (!REG_P (dst)) |
1455 return; | |
1456 regno += REGNO (dst); | |
1457 | |
1458 /* note_stores might have stripped a STRICT_LOW_PART, so we have to be | |
1459 careful with registers / register parts that are not full words. | |
1460 Similarly for ZERO_EXTRACT. */ | |
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
|
1461 if (GET_CODE (SET_DEST (set)) == ZERO_EXTRACT |
0 | 1462 || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART) |
1463 { | |
111 | 1464 for (i = end_hard_regno (mode, regno) - 1; i >= regno; i--) |
0 | 1465 { |
1466 reg_state[i].use_index = -1; | |
1467 reg_state[i].store_ruid = reload_combine_ruid; | |
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
|
1468 reg_state[i].real_store_ruid = reload_combine_ruid; |
0 | 1469 } |
1470 } | |
1471 else | |
1472 { | |
111 | 1473 for (i = end_hard_regno (mode, regno) - 1; i >= regno; i--) |
0 | 1474 { |
1475 reg_state[i].store_ruid = reload_combine_ruid; | |
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
|
1476 if (GET_CODE (set) == SET) |
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
|
1477 reg_state[i].real_store_ruid = reload_combine_ruid; |
0 | 1478 reg_state[i].use_index = RELOAD_COMBINE_MAX_USES; |
1479 } | |
1480 } | |
1481 } | |
1482 | |
1483 /* XP points to a piece of rtl that has to be checked for any uses of | |
1484 registers. | |
1485 *XP is the pattern of INSN, or a part of it. | |
1486 Called from reload_combine, and recursively by itself. */ | |
1487 static void | |
111 | 1488 reload_combine_note_use (rtx *xp, rtx_insn *insn, int ruid, rtx containing_mem) |
0 | 1489 { |
1490 rtx x = *xp; | |
1491 enum rtx_code code = x->code; | |
1492 const char *fmt; | |
1493 int i, j; | |
1494 rtx offset = const0_rtx; /* For the REG case below. */ | |
1495 | |
1496 switch (code) | |
1497 { | |
1498 case SET: | |
1499 if (REG_P (SET_DEST (x))) | |
1500 { | |
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
|
1501 reload_combine_note_use (&SET_SRC (x), insn, ruid, NULL_RTX); |
0 | 1502 return; |
1503 } | |
1504 break; | |
1505 | |
1506 case USE: | |
1507 /* If this is the USE of a return value, we can't change it. */ | |
1508 if (REG_P (XEXP (x, 0)) && REG_FUNCTION_VALUE_P (XEXP (x, 0))) | |
1509 { | |
111 | 1510 /* Mark the return register as used in an unknown fashion. */ |
0 | 1511 rtx reg = XEXP (x, 0); |
111 | 1512 unsigned int end_regno = END_REGNO (reg); |
1513 for (unsigned int regno = REGNO (reg); regno < end_regno; ++regno) | |
1514 reg_state[regno].use_index = -1; | |
0 | 1515 return; |
1516 } | |
1517 break; | |
1518 | |
1519 case CLOBBER: | |
1520 if (REG_P (SET_DEST (x))) | |
1521 { | |
1522 /* No spurious CLOBBERs of pseudo registers may remain. */ | |
1523 gcc_assert (REGNO (SET_DEST (x)) < FIRST_PSEUDO_REGISTER); | |
1524 return; | |
1525 } | |
1526 break; | |
1527 | |
131 | 1528 case CLOBBER_HIGH: |
1529 gcc_assert (REG_P (SET_DEST (x))); | |
1530 return; | |
1531 | |
0 | 1532 case PLUS: |
1533 /* We are interested in (plus (reg) (const_int)) . */ | |
1534 if (!REG_P (XEXP (x, 0)) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1535 || !CONST_INT_P (XEXP (x, 1))) |
0 | 1536 break; |
1537 offset = XEXP (x, 1); | |
1538 x = XEXP (x, 0); | |
1539 /* Fall through. */ | |
1540 case REG: | |
1541 { | |
1542 int regno = REGNO (x); | |
1543 int use_index; | |
1544 int nregs; | |
1545 | |
1546 /* No spurious USEs of pseudo registers may remain. */ | |
1547 gcc_assert (regno < FIRST_PSEUDO_REGISTER); | |
1548 | |
111 | 1549 nregs = REG_NREGS (x); |
0 | 1550 |
1551 /* We can't substitute into multi-hard-reg uses. */ | |
1552 if (nregs > 1) | |
1553 { | |
1554 while (--nregs >= 0) | |
1555 reg_state[regno + nregs].use_index = -1; | |
1556 return; | |
1557 } | |
1558 | |
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
|
1559 /* We may be called to update uses in previously seen insns. |
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
|
1560 Don't add uses beyond the last store we saw. */ |
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
|
1561 if (ruid < reg_state[regno].store_ruid) |
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
|
1562 return; |
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
|
1563 |
0 | 1564 /* If this register is already used in some unknown fashion, we |
1565 can't do anything. | |
1566 If we decrement the index from zero to -1, we can't store more | |
1567 uses, so this register becomes used in an unknown fashion. */ | |
1568 use_index = --reg_state[regno].use_index; | |
1569 if (use_index < 0) | |
1570 return; | |
1571 | |
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
|
1572 if (use_index == RELOAD_COMBINE_MAX_USES - 1) |
0 | 1573 { |
1574 /* This is the first use of this register we have seen since we | |
1575 marked it as dead. */ | |
1576 reg_state[regno].offset = offset; | |
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
|
1577 reg_state[regno].all_offsets_match = true; |
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
|
1578 reg_state[regno].use_ruid = ruid; |
0 | 1579 } |
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
|
1580 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
|
1581 { |
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
|
1582 if (reg_state[regno].use_ruid > ruid) |
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
|
1583 reg_state[regno].use_ruid = ruid; |
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
|
1584 |
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
|
1585 if (! rtx_equal_p (offset, reg_state[regno].offset)) |
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
|
1586 reg_state[regno].all_offsets_match = false; |
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
|
1587 } |
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
|
1588 |
0 | 1589 reg_state[regno].reg_use[use_index].insn = insn; |
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
|
1590 reg_state[regno].reg_use[use_index].ruid = ruid; |
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
|
1591 reg_state[regno].reg_use[use_index].containing_mem = containing_mem; |
0 | 1592 reg_state[regno].reg_use[use_index].usep = xp; |
1593 return; | |
1594 } | |
1595 | |
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
|
1596 case MEM: |
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
|
1597 containing_mem = x; |
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
|
1598 break; |
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
|
1599 |
0 | 1600 default: |
1601 break; | |
1602 } | |
1603 | |
1604 /* Recursively process the components of X. */ | |
1605 fmt = GET_RTX_FORMAT (code); | |
1606 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | |
1607 { | |
1608 if (fmt[i] == 'e') | |
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
|
1609 reload_combine_note_use (&XEXP (x, i), insn, ruid, containing_mem); |
0 | 1610 else if (fmt[i] == 'E') |
1611 { | |
1612 for (j = XVECLEN (x, i) - 1; j >= 0; j--) | |
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
|
1613 reload_combine_note_use (&XVECEXP (x, i, j), insn, ruid, |
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
|
1614 containing_mem); |
0 | 1615 } |
1616 } | |
1617 } | |
1618 | |
1619 /* See if we can reduce the cost of a constant by replacing a move | |
1620 with an add. We track situations in which a register is set to a | |
1621 constant or to a register plus a constant. */ | |
1622 /* We cannot do our optimization across labels. Invalidating all the | |
1623 information about register contents we have would be costly, so we | |
1624 use move2add_last_label_luid to note where the label is and then | |
1625 later disable any optimization that would cross it. | |
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
|
1626 reg_offset[n] / reg_base_reg[n] / reg_symbol_ref[n] / reg_mode[n] |
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
|
1627 are only valid if reg_set_luid[n] is greater than |
111 | 1628 move2add_last_label_luid. |
1629 For a set that established a new (potential) base register with | |
1630 non-constant value, we use move2add_luid from the place where the | |
1631 setting insn is encountered; registers based off that base then | |
1632 get the same reg_set_luid. Constants all get | |
1633 move2add_last_label_luid + 1 as their reg_set_luid. */ | |
0 | 1634 static int reg_set_luid[FIRST_PSEUDO_REGISTER]; |
1635 | |
1636 /* If reg_base_reg[n] is negative, register n has been set to | |
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
|
1637 reg_offset[n] or reg_symbol_ref[n] + reg_offset[n] in mode reg_mode[n]. |
0 | 1638 If reg_base_reg[n] is non-negative, register n has been set to the |
1639 sum of reg_offset[n] and the value of register reg_base_reg[n] | |
111 | 1640 before reg_set_luid[n], calculated in mode reg_mode[n] . |
1641 For multi-hard-register registers, all but the first one are | |
1642 recorded as BLKmode in reg_mode. Setting reg_mode to VOIDmode | |
1643 marks it as invalid. */ | |
0 | 1644 static HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER]; |
1645 static int reg_base_reg[FIRST_PSEUDO_REGISTER]; | |
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
|
1646 static rtx reg_symbol_ref[FIRST_PSEUDO_REGISTER]; |
111 | 1647 static machine_mode reg_mode[FIRST_PSEUDO_REGISTER]; |
0 | 1648 |
1649 /* move2add_luid is linearly increased while scanning the instructions | |
1650 from first to last. It is used to set reg_set_luid in | |
1651 reload_cse_move2add and move2add_note_store. */ | |
1652 static int move2add_luid; | |
1653 | |
1654 /* move2add_last_label_luid is set whenever a label is found. Labels | |
1655 invalidate all previously collected reg_offset data. */ | |
1656 static int move2add_last_label_luid; | |
1657 | |
1658 /* ??? We don't know how zero / sign extension is handled, hence we | |
1659 can't go from a narrower to a wider mode. */ | |
1660 #define MODES_OK_FOR_MOVE2ADD(OUTMODE, INMODE) \ | |
1661 (GET_MODE_SIZE (OUTMODE) == GET_MODE_SIZE (INMODE) \ | |
1662 || (GET_MODE_SIZE (OUTMODE) <= GET_MODE_SIZE (INMODE) \ | |
111 | 1663 && TRULY_NOOP_TRUNCATION_MODES_P (OUTMODE, INMODE))) |
1664 | |
1665 /* Record that REG is being set to a value with the mode of REG. */ | |
1666 | |
1667 static void | |
1668 move2add_record_mode (rtx reg) | |
1669 { | |
1670 int regno, nregs; | |
1671 machine_mode mode = GET_MODE (reg); | |
1672 | |
1673 if (GET_CODE (reg) == SUBREG) | |
1674 { | |
1675 regno = subreg_regno (reg); | |
1676 nregs = subreg_nregs (reg); | |
1677 } | |
1678 else if (REG_P (reg)) | |
1679 { | |
1680 regno = REGNO (reg); | |
1681 nregs = REG_NREGS (reg); | |
1682 } | |
1683 else | |
1684 gcc_unreachable (); | |
1685 for (int i = nregs - 1; i > 0; i--) | |
1686 reg_mode[regno + i] = BLKmode; | |
1687 reg_mode[regno] = mode; | |
1688 } | |
1689 | |
1690 /* Record that REG is being set to the sum of SYM and OFF. */ | |
1691 | |
1692 static void | |
1693 move2add_record_sym_value (rtx reg, rtx sym, rtx off) | |
1694 { | |
1695 int regno = REGNO (reg); | |
0 | 1696 |
111 | 1697 move2add_record_mode (reg); |
1698 reg_set_luid[regno] = move2add_luid; | |
1699 reg_base_reg[regno] = -1; | |
1700 reg_symbol_ref[regno] = sym; | |
1701 reg_offset[regno] = INTVAL (off); | |
1702 } | |
1703 | |
1704 /* Check if REGNO contains a valid value in MODE. */ | |
1705 | |
1706 static bool | |
1707 move2add_valid_value_p (int regno, scalar_int_mode mode) | |
1708 { | |
1709 if (reg_set_luid[regno] <= move2add_last_label_luid) | |
1710 return false; | |
1711 | |
1712 if (mode != reg_mode[regno]) | |
1713 { | |
1714 scalar_int_mode old_mode; | |
1715 if (!is_a <scalar_int_mode> (reg_mode[regno], &old_mode) | |
1716 || !MODES_OK_FOR_MOVE2ADD (mode, old_mode)) | |
1717 return false; | |
1718 /* The value loaded into regno in reg_mode[regno] is also valid in | |
1719 mode after truncation only if (REG:mode regno) is the lowpart of | |
1720 (REG:reg_mode[regno] regno). Now, for big endian, the starting | |
1721 regno of the lowpart might be different. */ | |
131 | 1722 poly_int64 s_off = subreg_lowpart_offset (mode, old_mode); |
111 | 1723 s_off = subreg_regno_offset (regno, old_mode, s_off, mode); |
131 | 1724 if (maybe_ne (s_off, 0)) |
111 | 1725 /* We could in principle adjust regno, check reg_mode[regno] to be |
1726 BLKmode, and return s_off to the caller (vs. -1 for failure), | |
1727 but we currently have no callers that could make use of this | |
1728 information. */ | |
1729 return false; | |
1730 } | |
1731 | |
1732 for (int i = end_hard_regno (mode, regno) - 1; i > regno; i--) | |
1733 if (reg_mode[i] != BLKmode) | |
1734 return false; | |
1735 return true; | |
1736 } | |
1737 | |
1738 /* This function is called with INSN that sets REG (of mode MODE) | |
1739 to (SYM + OFF), while REG is known to already have value (SYM + offset). | |
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
|
1740 This function tries to change INSN into an add instruction |
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
|
1741 (set (REG) (plus (REG) (OFF - offset))) using the known value. |
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
|
1742 It also updates the information about REG's known value. |
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
|
1743 Return true if we made a change. */ |
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
|
1744 |
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
|
1745 static bool |
111 | 1746 move2add_use_add2_insn (scalar_int_mode mode, rtx reg, rtx sym, rtx off, |
1747 rtx_insn *insn) | |
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
|
1748 { |
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
|
1749 rtx pat = PATTERN (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
|
1750 rtx src = SET_SRC (pat); |
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
|
1751 int regno = REGNO (reg); |
111 | 1752 rtx new_src = gen_int_mode (UINTVAL (off) - reg_offset[regno], mode); |
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
|
1753 bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (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
|
1754 bool changed = false; |
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
|
1755 |
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
|
1756 /* (set (reg) (plus (reg) (const_int 0))) is not canonical; |
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
|
1757 use (set (reg) (reg)) instead. |
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
|
1758 We don't delete this insn, nor do we convert it into a |
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
|
1759 note, to avoid losing register notes or the return |
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
|
1760 value flag. jump2 already knows how to get rid of |
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
|
1761 no-op moves. */ |
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
|
1762 if (new_src == const0_rtx) |
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
|
1763 { |
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
|
1764 /* If the constants are different, this is a |
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
|
1765 truncation, that, if turned into (set (reg) |
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
|
1766 (reg)), would be discarded. Maybe we should |
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
|
1767 try a truncMN pattern? */ |
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
|
1768 if (INTVAL (off) == reg_offset [regno]) |
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
|
1769 changed = validate_change (insn, &SET_SRC (pat), reg, 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
|
1770 } |
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
|
1771 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
|
1772 { |
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
|
1773 struct full_rtx_costs oldcst, newcst; |
111 | 1774 rtx tem = gen_rtx_PLUS (mode, reg, new_src); |
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
|
1775 |
111 | 1776 get_full_set_rtx_cost (pat, &oldcst); |
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
|
1777 SET_SRC (pat) = tem; |
111 | 1778 get_full_set_rtx_cost (pat, &newcst); |
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
|
1779 SET_SRC (pat) = 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
|
1780 |
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
|
1781 if (costs_lt_p (&newcst, &oldcst, speed) |
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
|
1782 && have_add2_insn (reg, new_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
|
1783 changed = validate_change (insn, &SET_SRC (pat), tem, 0); |
111 | 1784 else if (sym == NULL_RTX && mode != BImode) |
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
|
1785 { |
111 | 1786 scalar_int_mode narrow_mode; |
1787 FOR_EACH_MODE_UNTIL (narrow_mode, mode) | |
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
|
1788 { |
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
|
1789 if (have_insn_for (STRICT_LOW_PART, narrow_mode) |
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
|
1790 && ((reg_offset[regno] & ~GET_MODE_MASK (narrow_mode)) |
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
|
1791 == (INTVAL (off) & ~GET_MODE_MASK (narrow_mode)))) |
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
|
1792 { |
111 | 1793 rtx narrow_reg = gen_lowpart_common (narrow_mode, reg); |
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
|
1794 rtx narrow_src = gen_int_mode (INTVAL (off), |
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
|
1795 narrow_mode); |
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
|
1796 rtx new_set |
111 | 1797 = gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, |
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
|
1798 narrow_reg), |
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
|
1799 narrow_src); |
111 | 1800 get_full_set_rtx_cost (new_set, &newcst); |
1801 if (costs_lt_p (&newcst, &oldcst, speed)) | |
1802 { | |
1803 changed = validate_change (insn, &PATTERN (insn), | |
1804 new_set, 0); | |
1805 if (changed) | |
1806 break; | |
1807 } | |
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
|
1808 } |
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
|
1809 } |
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
|
1810 } |
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
|
1811 } |
111 | 1812 move2add_record_sym_value (reg, sym, off); |
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
|
1813 return changed; |
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
|
1814 } |
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
|
1815 |
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
|
1816 |
111 | 1817 /* This function is called with INSN that sets REG (of mode MODE) to |
1818 (SYM + OFF), but REG doesn't have known value (SYM + offset). This | |
1819 function tries to find another register which is known to already have | |
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
|
1820 value (SYM + offset) and change INSN into an add instruction |
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
|
1821 (set (REG) (plus (the found register) (OFF - offset))) if such |
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
|
1822 a register is found. It also updates the information about |
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
|
1823 REG's known value. |
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
|
1824 Return true iff we made a change. */ |
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
|
1825 |
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
|
1826 static bool |
111 | 1827 move2add_use_add3_insn (scalar_int_mode mode, rtx reg, rtx sym, rtx off, |
1828 rtx_insn *insn) | |
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
|
1829 { |
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
|
1830 rtx pat = PATTERN (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
|
1831 rtx src = SET_SRC (pat); |
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
|
1832 int regno = REGNO (reg); |
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
|
1833 int min_regno = 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
|
1834 bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (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
|
1835 int i; |
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
|
1836 bool changed = false; |
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
|
1837 struct full_rtx_costs oldcst, newcst, mincst; |
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
|
1838 rtx plus_expr; |
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
|
1839 |
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
|
1840 init_costs_to_max (&mincst); |
111 | 1841 get_full_set_rtx_cost (pat, &oldcst); |
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
|
1842 |
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
|
1843 plus_expr = gen_rtx_PLUS (GET_MODE (reg), reg, const0_rtx); |
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
|
1844 SET_SRC (pat) = plus_expr; |
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
|
1845 |
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
|
1846 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
111 | 1847 if (move2add_valid_value_p (i, mode) |
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
|
1848 && reg_base_reg[i] < 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
|
1849 && reg_symbol_ref[i] != NULL_RTX |
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
|
1850 && rtx_equal_p (sym, reg_symbol_ref[i])) |
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
|
1851 { |
111 | 1852 rtx new_src = gen_int_mode (UINTVAL (off) - reg_offset[i], |
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
|
1853 GET_MODE (reg)); |
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
|
1854 /* (set (reg) (plus (reg) (const_int 0))) is not canonical; |
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
|
1855 use (set (reg) (reg)) instead. |
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
|
1856 We don't delete this insn, nor do we convert it into a |
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
|
1857 note, to avoid losing register notes or the return |
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
|
1858 value flag. jump2 already knows how to get rid of |
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
|
1859 no-op moves. */ |
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
|
1860 if (new_src == const0_rtx) |
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
|
1861 { |
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
|
1862 init_costs_to_zero (&mincst); |
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
|
1863 min_regno = i; |
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
|
1864 break; |
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
|
1865 } |
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
|
1866 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
|
1867 { |
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
|
1868 XEXP (plus_expr, 1) = new_src; |
111 | 1869 get_full_set_rtx_cost (pat, &newcst); |
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
|
1870 |
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
|
1871 if (costs_lt_p (&newcst, &mincst, speed)) |
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
|
1872 { |
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
|
1873 mincst = newcst; |
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
|
1874 min_regno = i; |
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
|
1875 } |
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
|
1876 } |
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
|
1877 } |
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
|
1878 SET_SRC (pat) = 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
|
1879 |
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
|
1880 if (costs_lt_p (&mincst, &oldcst, speed)) |
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
|
1881 { |
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
|
1882 rtx tem; |
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
|
1883 |
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
|
1884 tem = gen_rtx_REG (GET_MODE (reg), min_regno); |
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
|
1885 if (i != min_regno) |
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
|
1886 { |
111 | 1887 rtx new_src = gen_int_mode (UINTVAL (off) - reg_offset[min_regno], |
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
|
1888 GET_MODE (reg)); |
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
|
1889 tem = gen_rtx_PLUS (GET_MODE (reg), tem, new_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
|
1890 } |
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
|
1891 if (validate_change (insn, &SET_SRC (pat), tem, 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
|
1892 changed = true; |
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
|
1893 } |
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
|
1894 reg_set_luid[regno] = move2add_luid; |
111 | 1895 move2add_record_sym_value (reg, sym, off); |
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
|
1896 return changed; |
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
|
1897 } |
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
|
1898 |
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
|
1899 /* Convert move insns with constant inputs to additions if they are cheaper. |
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
|
1900 Return true if any changes were made. */ |
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
|
1901 static bool |
111 | 1902 reload_cse_move2add (rtx_insn *first) |
0 | 1903 { |
1904 int i; | |
111 | 1905 rtx_insn *insn; |
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
|
1906 bool changed = false; |
0 | 1907 |
1908 for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--) | |
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
|
1909 { |
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
|
1910 reg_set_luid[i] = 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
|
1911 reg_offset[i] = 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
|
1912 reg_base_reg[i] = 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
|
1913 reg_symbol_ref[i] = NULL_RTX; |
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
|
1914 reg_mode[i] = VOIDmode; |
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
|
1915 } |
0 | 1916 |
1917 move2add_last_label_luid = 0; | |
1918 move2add_luid = 2; | |
1919 for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++) | |
1920 { | |
1921 rtx pat, note; | |
1922 | |
1923 if (LABEL_P (insn)) | |
1924 { | |
1925 move2add_last_label_luid = move2add_luid; | |
1926 /* We're going to increment move2add_luid twice after a | |
1927 label, so that we can use move2add_last_label_luid + 1 as | |
1928 the luid for constants. */ | |
1929 move2add_luid++; | |
1930 continue; | |
1931 } | |
1932 if (! INSN_P (insn)) | |
1933 continue; | |
1934 pat = PATTERN (insn); | |
1935 /* For simplicity, we only perform this optimization on | |
1936 straightforward SETs. */ | |
111 | 1937 scalar_int_mode mode; |
0 | 1938 if (GET_CODE (pat) == SET |
111 | 1939 && REG_P (SET_DEST (pat)) |
1940 && is_a <scalar_int_mode> (GET_MODE (SET_DEST (pat)), &mode)) | |
0 | 1941 { |
1942 rtx reg = SET_DEST (pat); | |
1943 int regno = REGNO (reg); | |
1944 rtx src = SET_SRC (pat); | |
1945 | |
1946 /* Check if we have valid information on the contents of this | |
1947 register in the mode of REG. */ | |
111 | 1948 if (move2add_valid_value_p (regno, mode) |
0 | 1949 && dbg_cnt (cse2_move2add)) |
1950 { | |
1951 /* Try to transform (set (REGX) (CONST_INT A)) | |
1952 ... | |
1953 (set (REGX) (CONST_INT B)) | |
1954 to | |
1955 (set (REGX) (CONST_INT A)) | |
1956 ... | |
1957 (set (REGX) (plus (REGX) (CONST_INT B-A))) | |
1958 or | |
1959 (set (REGX) (CONST_INT A)) | |
1960 ... | |
1961 (set (STRICT_LOW_PART (REGX)) (CONST_INT B)) | |
1962 */ | |
1963 | |
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
|
1964 if (CONST_INT_P (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
|
1965 && reg_base_reg[regno] < 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
|
1966 && reg_symbol_ref[regno] == NULL_RTX) |
0 | 1967 { |
111 | 1968 changed |= move2add_use_add2_insn (mode, reg, NULL_RTX, |
1969 src, insn); | |
0 | 1970 continue; |
1971 } | |
1972 | |
1973 /* Try to transform (set (REGX) (REGY)) | |
1974 (set (REGX) (PLUS (REGX) (CONST_INT A))) | |
1975 ... | |
1976 (set (REGX) (REGY)) | |
1977 (set (REGX) (PLUS (REGX) (CONST_INT B))) | |
1978 to | |
1979 (set (REGX) (REGY)) | |
1980 (set (REGX) (PLUS (REGX) (CONST_INT A))) | |
1981 ... | |
1982 (set (REGX) (plus (REGX) (CONST_INT B-A))) */ | |
1983 else if (REG_P (src) | |
1984 && reg_set_luid[regno] == reg_set_luid[REGNO (src)] | |
1985 && reg_base_reg[regno] == reg_base_reg[REGNO (src)] | |
111 | 1986 && move2add_valid_value_p (REGNO (src), mode)) |
0 | 1987 { |
111 | 1988 rtx_insn *next = next_nonnote_nondebug_insn (insn); |
0 | 1989 rtx set = NULL_RTX; |
1990 if (next) | |
1991 set = single_set (next); | |
1992 if (set | |
1993 && SET_DEST (set) == reg | |
1994 && GET_CODE (SET_SRC (set)) == PLUS | |
1995 && XEXP (SET_SRC (set), 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
|
1996 && CONST_INT_P (XEXP (SET_SRC (set), 1))) |
0 | 1997 { |
1998 rtx src3 = XEXP (SET_SRC (set), 1); | |
111 | 1999 unsigned HOST_WIDE_INT added_offset = UINTVAL (src3); |
0 | 2000 HOST_WIDE_INT base_offset = reg_offset[REGNO (src)]; |
2001 HOST_WIDE_INT regno_offset = reg_offset[regno]; | |
2002 rtx new_src = | |
2003 gen_int_mode (added_offset | |
2004 + base_offset | |
2005 - regno_offset, | |
111 | 2006 mode); |
0 | 2007 bool success = false; |
2008 bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); | |
2009 | |
2010 if (new_src == const0_rtx) | |
2011 /* See above why we create (set (reg) (reg)) here. */ | |
2012 success | |
2013 = validate_change (next, &SET_SRC (set), reg, 0); | |
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
|
2014 else |
0 | 2015 { |
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
|
2016 rtx old_src = SET_SRC (set); |
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
|
2017 struct full_rtx_costs oldcst, newcst; |
111 | 2018 rtx tem = gen_rtx_PLUS (mode, reg, new_src); |
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
|
2019 |
111 | 2020 get_full_set_rtx_cost (set, &oldcst); |
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
|
2021 SET_SRC (set) = tem; |
111 | 2022 get_full_set_src_cost (tem, mode, &newcst); |
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
|
2023 SET_SRC (set) = old_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
|
2024 costs_add_n_insns (&oldcst, 1); |
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
|
2025 |
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
|
2026 if (costs_lt_p (&newcst, &oldcst, speed) |
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
|
2027 && have_add2_insn (reg, new_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
|
2028 { |
111 | 2029 rtx newpat = gen_rtx_SET (reg, tem); |
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
|
2030 success |
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
|
2031 = validate_change (next, &PATTERN (next), |
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
|
2032 newpat, 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
|
2033 } |
0 | 2034 } |
2035 if (success) | |
2036 delete_insn (insn); | |
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
|
2037 changed |= success; |
0 | 2038 insn = next; |
111 | 2039 move2add_record_mode (reg); |
2040 reg_offset[regno] | |
2041 = trunc_int_for_mode (added_offset + base_offset, | |
2042 mode); | |
0 | 2043 continue; |
2044 } | |
2045 } | |
2046 } | |
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
|
2047 |
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
|
2048 /* Try to transform |
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
|
2049 (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A)))) |
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
|
2050 ... |
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
|
2051 (set (REGY) (CONST (PLUS (SYMBOL_REF) (CONST_INT B)))) |
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
|
2052 to |
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
|
2053 (set (REGX) (CONST (PLUS (SYMBOL_REF) (CONST_INT A)))) |
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
|
2054 ... |
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
|
2055 (set (REGY) (CONST (PLUS (REGX) (CONST_INT B-A)))) */ |
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
|
2056 if ((GET_CODE (src) == SYMBOL_REF |
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
|
2057 || (GET_CODE (src) == CONST |
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
|
2058 && GET_CODE (XEXP (src, 0)) == PLUS |
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
|
2059 && GET_CODE (XEXP (XEXP (src, 0), 0)) == SYMBOL_REF |
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
|
2060 && CONST_INT_P (XEXP (XEXP (src, 0), 1)))) |
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
|
2061 && dbg_cnt (cse2_move2add)) |
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
|
2062 { |
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
|
2063 rtx sym, off; |
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
|
2064 |
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
|
2065 if (GET_CODE (src) == SYMBOL_REF) |
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
|
2066 { |
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
|
2067 sym = 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
|
2068 off = const0_rtx; |
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
|
2069 } |
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
|
2070 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
|
2071 { |
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
|
2072 sym = XEXP (XEXP (src, 0), 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
|
2073 off = XEXP (XEXP (src, 0), 1); |
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
|
2074 } |
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
|
2075 |
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
|
2076 /* If the reg already contains the value which is sum of |
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
|
2077 sym and some constant value, we can use an add2 insn. */ |
111 | 2078 if (move2add_valid_value_p (regno, mode) |
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
|
2079 && reg_base_reg[regno] < 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
|
2080 && reg_symbol_ref[regno] != NULL_RTX |
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
|
2081 && rtx_equal_p (sym, reg_symbol_ref[regno])) |
111 | 2082 changed |= move2add_use_add2_insn (mode, reg, sym, off, insn); |
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
|
2083 |
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
|
2084 /* Otherwise, we have to find a register whose value is sum |
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
|
2085 of sym and some constant value. */ |
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
|
2086 else |
111 | 2087 changed |= move2add_use_add3_insn (mode, reg, sym, off, insn); |
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
|
2088 |
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
|
2089 continue; |
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
|
2090 } |
0 | 2091 } |
2092 | |
2093 for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) | |
2094 { | |
2095 if (REG_NOTE_KIND (note) == REG_INC | |
2096 && REG_P (XEXP (note, 0))) | |
2097 { | |
2098 /* Reset the information about this register. */ | |
2099 int regno = REGNO (XEXP (note, 0)); | |
2100 if (regno < FIRST_PSEUDO_REGISTER) | |
111 | 2101 { |
2102 move2add_record_mode (XEXP (note, 0)); | |
2103 reg_mode[regno] = VOIDmode; | |
2104 } | |
0 | 2105 } |
2106 } | |
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
|
2107 note_stores (PATTERN (insn), move2add_note_store, insn); |
0 | 2108 |
2109 /* If INSN is a conditional branch, we try to extract an | |
2110 implicit set out of it. */ | |
2111 if (any_condjump_p (insn)) | |
2112 { | |
2113 rtx cnd = fis_get_condition (insn); | |
2114 | |
2115 if (cnd != NULL_RTX | |
2116 && GET_CODE (cnd) == NE | |
2117 && REG_P (XEXP (cnd, 0)) | |
2118 && !reg_set_p (XEXP (cnd, 0), insn) | |
2119 /* The following two checks, which are also in | |
2120 move2add_note_store, are intended to reduce the | |
2121 number of calls to gen_rtx_SET to avoid memory | |
2122 allocation if possible. */ | |
2123 && SCALAR_INT_MODE_P (GET_MODE (XEXP (cnd, 0))) | |
111 | 2124 && REG_NREGS (XEXP (cnd, 0)) == 1 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2125 && CONST_INT_P (XEXP (cnd, 1))) |
0 | 2126 { |
2127 rtx implicit_set = | |
111 | 2128 gen_rtx_SET (XEXP (cnd, 0), XEXP (cnd, 1)); |
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
|
2129 move2add_note_store (SET_DEST (implicit_set), implicit_set, insn); |
0 | 2130 } |
2131 } | |
2132 | |
2133 /* If this is a CALL_INSN, all call used registers are stored with | |
2134 unknown values. */ | |
2135 if (CALL_P (insn)) | |
2136 { | |
111 | 2137 rtx link; |
2138 | |
0 | 2139 for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--) |
2140 { | |
2141 if (call_used_regs[i]) | |
2142 /* Reset the information about this register. */ | |
111 | 2143 reg_mode[i] = VOIDmode; |
2144 } | |
2145 | |
2146 for (link = CALL_INSN_FUNCTION_USAGE (insn); link; | |
2147 link = XEXP (link, 1)) | |
2148 { | |
2149 rtx setuse = XEXP (link, 0); | |
2150 rtx usage_rtx = XEXP (setuse, 0); | |
131 | 2151 /* CALL_INSN_FUNCTION_USAGEs can only have full clobbers, not |
2152 clobber_highs. */ | |
2153 gcc_assert (GET_CODE (setuse) != CLOBBER_HIGH); | |
111 | 2154 if (GET_CODE (setuse) == CLOBBER |
2155 && REG_P (usage_rtx)) | |
2156 { | |
2157 unsigned int end_regno = END_REGNO (usage_rtx); | |
2158 for (unsigned int r = REGNO (usage_rtx); r < end_regno; ++r) | |
2159 /* Reset the information about this register. */ | |
2160 reg_mode[r] = VOIDmode; | |
2161 } | |
0 | 2162 } |
2163 } | |
2164 } | |
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
|
2165 return changed; |
0 | 2166 } |
2167 | |
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
|
2168 /* SET is a SET or CLOBBER that sets DST. DATA is the insn which |
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
|
2169 contains SET. |
0 | 2170 Update reg_set_luid, reg_offset and reg_base_reg accordingly. |
2171 Called from reload_cse_move2add via note_stores. */ | |
2172 | |
2173 static void | |
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
|
2174 move2add_note_store (rtx dst, const_rtx set, void *data) |
0 | 2175 { |
111 | 2176 rtx_insn *insn = (rtx_insn *) data; |
0 | 2177 unsigned int regno = 0; |
111 | 2178 scalar_int_mode mode; |
0 | 2179 |
2180 /* Some targets do argument pushes without adding REG_INC notes. */ | |
2181 | |
2182 if (MEM_P (dst)) | |
2183 { | |
2184 dst = XEXP (dst, 0); | |
2185 if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC | |
2186 || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC) | |
111 | 2187 reg_mode[REGNO (XEXP (dst, 0))] = VOIDmode; |
0 | 2188 return; |
2189 } | |
111 | 2190 |
2191 if (GET_CODE (dst) == SUBREG) | |
2192 regno = subreg_regno (dst); | |
2193 else if (REG_P (dst)) | |
2194 regno = REGNO (dst); | |
2195 else | |
0 | 2196 return; |
2197 | |
111 | 2198 if (!is_a <scalar_int_mode> (GET_MODE (dst), &mode)) |
2199 goto invalidate; | |
0 | 2200 |
111 | 2201 if (GET_CODE (set) == SET) |
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
|
2202 { |
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
|
2203 rtx note, sym = NULL_RTX; |
111 | 2204 rtx off; |
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
|
2205 |
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
|
2206 note = find_reg_equal_equiv_note (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
|
2207 if (note && GET_CODE (XEXP (note, 0)) == SYMBOL_REF) |
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
|
2208 { |
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
|
2209 sym = XEXP (note, 0); |
111 | 2210 off = const0_rtx; |
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
|
2211 } |
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
|
2212 else if (note && GET_CODE (XEXP (note, 0)) == CONST |
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
|
2213 && GET_CODE (XEXP (XEXP (note, 0), 0)) == PLUS |
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
|
2214 && GET_CODE (XEXP (XEXP (XEXP (note, 0), 0), 0)) == SYMBOL_REF |
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
|
2215 && CONST_INT_P (XEXP (XEXP (XEXP (note, 0), 0), 1))) |
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
|
2216 { |
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
|
2217 sym = XEXP (XEXP (XEXP (note, 0), 0), 0); |
111 | 2218 off = XEXP (XEXP (XEXP (note, 0), 0), 1); |
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
|
2219 } |
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
|
2220 |
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
|
2221 if (sym != NULL_RTX) |
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
|
2222 { |
111 | 2223 move2add_record_sym_value (dst, sym, off); |
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
|
2224 return; |
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
|
2225 } |
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
|
2226 } |
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
|
2227 |
111 | 2228 if (GET_CODE (set) == SET |
0 | 2229 && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT |
2230 && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART) | |
2231 { | |
2232 rtx src = SET_SRC (set); | |
2233 rtx base_reg; | |
111 | 2234 unsigned HOST_WIDE_INT offset; |
0 | 2235 int base_regno; |
2236 | |
2237 switch (GET_CODE (src)) | |
2238 { | |
2239 case PLUS: | |
2240 if (REG_P (XEXP (src, 0))) | |
2241 { | |
2242 base_reg = XEXP (src, 0); | |
2243 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2244 if (CONST_INT_P (XEXP (src, 1))) |
111 | 2245 offset = UINTVAL (XEXP (src, 1)); |
0 | 2246 else if (REG_P (XEXP (src, 1)) |
111 | 2247 && move2add_valid_value_p (REGNO (XEXP (src, 1)), mode)) |
0 | 2248 { |
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
|
2249 if (reg_base_reg[REGNO (XEXP (src, 1))] < 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
|
2250 && reg_symbol_ref[REGNO (XEXP (src, 1))] == NULL_RTX) |
0 | 2251 offset = reg_offset[REGNO (XEXP (src, 1))]; |
2252 /* Maybe the first register is known to be a | |
2253 constant. */ | |
111 | 2254 else if (move2add_valid_value_p (REGNO (base_reg), mode) |
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
|
2255 && reg_base_reg[REGNO (base_reg)] < 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
|
2256 && reg_symbol_ref[REGNO (base_reg)] == NULL_RTX) |
0 | 2257 { |
2258 offset = reg_offset[REGNO (base_reg)]; | |
2259 base_reg = XEXP (src, 1); | |
2260 } | |
2261 else | |
2262 goto invalidate; | |
2263 } | |
2264 else | |
2265 goto invalidate; | |
2266 | |
2267 break; | |
2268 } | |
2269 | |
2270 goto invalidate; | |
2271 | |
2272 case REG: | |
2273 base_reg = src; | |
2274 offset = 0; | |
2275 break; | |
2276 | |
2277 case CONST_INT: | |
2278 /* Start tracking the register as a constant. */ | |
2279 reg_base_reg[regno] = -1; | |
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
|
2280 reg_symbol_ref[regno] = NULL_RTX; |
0 | 2281 reg_offset[regno] = INTVAL (SET_SRC (set)); |
2282 /* We assign the same luid to all registers set to constants. */ | |
2283 reg_set_luid[regno] = move2add_last_label_luid + 1; | |
111 | 2284 move2add_record_mode (dst); |
0 | 2285 return; |
2286 | |
2287 default: | |
111 | 2288 goto invalidate; |
0 | 2289 } |
2290 | |
2291 base_regno = REGNO (base_reg); | |
2292 /* If information about the base register is not valid, set it | |
2293 up as a new base register, pretending its value is known | |
2294 starting from the current insn. */ | |
111 | 2295 if (!move2add_valid_value_p (base_regno, mode)) |
0 | 2296 { |
2297 reg_base_reg[base_regno] = base_regno; | |
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
|
2298 reg_symbol_ref[base_regno] = NULL_RTX; |
0 | 2299 reg_offset[base_regno] = 0; |
2300 reg_set_luid[base_regno] = move2add_luid; | |
111 | 2301 gcc_assert (GET_MODE (base_reg) == mode); |
2302 move2add_record_mode (base_reg); | |
0 | 2303 } |
2304 | |
2305 /* Copy base information from our base register. */ | |
2306 reg_set_luid[regno] = reg_set_luid[base_regno]; | |
2307 reg_base_reg[regno] = reg_base_reg[base_regno]; | |
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
|
2308 reg_symbol_ref[regno] = reg_symbol_ref[base_regno]; |
0 | 2309 |
2310 /* Compute the sum of the offsets or constants. */ | |
111 | 2311 reg_offset[regno] |
2312 = trunc_int_for_mode (offset + reg_offset[base_regno], mode); | |
2313 | |
2314 move2add_record_mode (dst); | |
0 | 2315 } |
131 | 2316 else if (GET_CODE (set) == CLOBBER_HIGH) |
2317 { | |
2318 /* Only invalidate if actually clobbered. */ | |
2319 if (reg_mode[regno] == BLKmode | |
2320 || reg_is_clobbered_by_clobber_high (regno, reg_mode[regno], dst)) | |
2321 goto invalidate; | |
2322 } | |
0 | 2323 else |
2324 { | |
111 | 2325 invalidate: |
2326 /* Invalidate the contents of the register. */ | |
2327 move2add_record_mode (dst); | |
2328 reg_mode[regno] = VOIDmode; | |
0 | 2329 } |
2330 } | |
2331 | |
111 | 2332 namespace { |
2333 | |
2334 const pass_data pass_data_postreload_cse = | |
0 | 2335 { |
111 | 2336 RTL_PASS, /* type */ |
2337 "postreload", /* name */ | |
2338 OPTGROUP_NONE, /* optinfo_flags */ | |
2339 TV_RELOAD_CSE_REGS, /* tv_id */ | |
2340 0, /* properties_required */ | |
2341 0, /* properties_provided */ | |
2342 0, /* properties_destroyed */ | |
2343 0, /* todo_flags_start */ | |
2344 TODO_df_finish, /* todo_flags_finish */ | |
2345 }; | |
0 | 2346 |
111 | 2347 class pass_postreload_cse : public rtl_opt_pass |
2348 { | |
2349 public: | |
2350 pass_postreload_cse (gcc::context *ctxt) | |
2351 : rtl_opt_pass (pass_data_postreload_cse, ctxt) | |
2352 {} | |
0 | 2353 |
111 | 2354 /* opt_pass methods: */ |
2355 virtual bool gate (function *) { return (optimize > 0 && reload_completed); } | |
2356 | |
2357 virtual unsigned int execute (function *); | |
2358 | |
2359 }; // class pass_postreload_cse | |
2360 | |
2361 unsigned int | |
2362 pass_postreload_cse::execute (function *fun) | |
0 | 2363 { |
2364 if (!dbg_cnt (postreload_cse)) | |
2365 return 0; | |
2366 | |
2367 /* Do a very simple CSE pass over just the hard registers. */ | |
2368 reload_cse_regs (get_insns ()); | |
2369 /* Reload_cse_regs can eliminate potentially-trapping MEMs. | |
2370 Remove any EH edges associated with them. */ | |
111 | 2371 if (fun->can_throw_non_call_exceptions |
2372 && purge_all_dead_edges ()) | |
2373 cleanup_cfg (0); | |
0 | 2374 |
2375 return 0; | |
2376 } | |
2377 | |
111 | 2378 } // anon namespace |
2379 | |
2380 rtl_opt_pass * | |
2381 make_pass_postreload_cse (gcc::context *ctxt) | |
0 | 2382 { |
111 | 2383 return new pass_postreload_cse (ctxt); |
2384 } |