diff options
author | Koen Kooi <koen@dominion.thruhere.net> | 2010-12-23 14:02:13 +0100 |
---|---|---|
committer | Koen Kooi <koen@dominion.thruhere.net> | 2010-12-23 14:02:13 +0100 |
commit | 7eb7dce48ba082c30f1fceced04c275420158b9a (patch) | |
tree | d2f5b6bed38d7ffc0aad7f5c313701da4d8a8e19 /recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99429.patch | |
parent | 8bb6722b1356cc3b8494e33553240363addd2d80 (diff) | |
download | meta-openembedded-7eb7dce48ba082c30f1fceced04c275420158b9a.tar.gz |
gcc 4.5: sync with both OE and yocto
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
Diffstat (limited to 'recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99429.patch')
-rw-r--r-- | recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99429.patch | 1257 |
1 files changed, 1257 insertions, 0 deletions
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99429.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99429.patch new file mode 100644 index 0000000000..63ba95e0e3 --- /dev/null +++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99429.patch | |||
@@ -0,0 +1,1257 @@ | |||
1 | 2010-11-09 Michael Hope <michael.hope@linaro.org> | ||
2 | |||
3 | Revert: | ||
4 | |||
5 | Backport from mainline: | ||
6 | |||
7 | 2010-07-15 Bernd Schmidt <bernds@codesourcery.com> | ||
8 | |||
9 | gcc/ | ||
10 | * postreload.c (last_label_ruid, first_index_reg, last_index_reg): | ||
11 | New static variables. | ||
12 | (reload_combine_recognize_pattern): New static function, broken out | ||
13 | of reload_combine. | ||
14 | (reload_combine): Use it. Only initialize first_index_reg and | ||
15 | last_index_reg once. | ||
16 | |||
17 | 2010-07-17 Bernd Schmidt <bernds@codesourcery.com> | ||
18 | |||
19 | PR target/42235 | ||
20 | gcc/ | ||
21 | * postreload.c (reload_cse_move2add): Return bool, true if anything. | ||
22 | changed. All callers changed. | ||
23 | (move2add_use_add2_insn): Likewise. | ||
24 | (move2add_use_add3_insn): Likewise. | ||
25 | (reload_cse_regs): If reload_cse_move2add changed anything, rerun | ||
26 | reload_combine. | ||
27 | (RELOAD_COMBINE_MAX_USES): Bump to 16. | ||
28 | (last_jump_ruid): New static variable. | ||
29 | (struct reg_use): New members CONTAINING_MEM and RUID. | ||
30 | (reg_state): New members ALL_OFFSETS_MATCH and REAL_STORE_RUID. | ||
31 | (reload_combine_split_one_ruid, reload_combine_split_ruids, | ||
32 | reload_combine_purge_insn_uses, reload_combine_closest_single_use | ||
33 | reload_combine_purge_reg_uses_after_ruid, | ||
34 | reload_combine_recognize_const_pattern): New static functions. | ||
35 | (reload_combine_recognize_pattern): Verify that ALL_OFFSETS_MATCH | ||
36 | is true for our reg and that we have available index regs. | ||
37 | (reload_combine_note_use): New args RUID and CONTAINING_MEM. All | ||
38 | callers changed. Use them to initialize fields in struct reg_use. | ||
39 | (reload_combine): Initialize last_jump_ruid. Be careful when to | ||
40 | take PREV_INSN of the scanned insn. Update REAL_STORE_RUID fields. | ||
41 | Call reload_combine_recognize_const_pattern. | ||
42 | (reload_combine_note_store): Update REAL_STORE_RUID field. | ||
43 | |||
44 | gcc/testsuite/ | ||
45 | * gcc.target/arm/pr42235.c: New test. | ||
46 | |||
47 | 2010-07-19 Bernd Schmidt <bernds@codesourcery.com> | ||
48 | |||
49 | gcc/ | ||
50 | * postreload.c (reload_combine_closest_single_use): Ignore the | ||
51 | number of uses for DEBUG_INSNs. | ||
52 | (fixup_debug_insns): New static function. | ||
53 | (reload_combine_recognize_const_pattern): Use it. Don't let the | ||
54 | main loop be affected by DEBUG_INSNs. | ||
55 | Really disallow moving adds past a jump insn. | ||
56 | (reload_combine_recognize_pattern): Don't update use_ruid here. | ||
57 | (reload_combine_note_use): Do it here. | ||
58 | (reload_combine): Use control_flow_insn_p rather than JUMP_P. | ||
59 | |||
60 | 2010-07-20 Bernd Schmidt <bernds@codesourcery.com> | ||
61 | |||
62 | gcc/ | ||
63 | * postreload.c (fixup_debug_insns): Remove arg REGNO. New args | ||
64 | FROM and TO. All callers changed. Don't look for tracked uses, | ||
65 | just scan the RTL for DEBUG_INSNs and substitute. | ||
66 | (reload_combine_recognize_pattern): Call fixup_debug_insns. | ||
67 | (reload_combine): Ignore DEBUG_INSNs. | ||
68 | |||
69 | 2010-07-22 Bernd Schmidt <bernds@codesourcery.com> | ||
70 | |||
71 | PR bootstrap/44970 | ||
72 | PR middle-end/45009 | ||
73 | gcc/ | ||
74 | * postreload.c: Include "target.h". | ||
75 | (reload_combine_closest_single_use): Don't take DEBUG_INSNs | ||
76 | into account. | ||
77 | (fixup_debug_insns): Don't copy the rtx. | ||
78 | (reload_combine_recognize_const_pattern): DEBUG_INSNs can't have uses. | ||
79 | Don't copy when replacing. Call fixup_debug_insns in the case where | ||
80 | we merged one add with another. | ||
81 | (reload_combine_recognize_pattern): Fail if there aren't any uses. | ||
82 | Try harder to determine whether we're picking a valid index register. | ||
83 | Don't set store_ruid for an insn we're going to scan in the | ||
84 | next iteration. | ||
85 | (reload_combine): Remove unused code. | ||
86 | (reload_combine_note_use): When updating use information for | ||
87 | an old insn, ignore a use that occurs after store_ruid. | ||
88 | * Makefile.in (postreload.o): Update dependencies. | ||
89 | |||
90 | 2010-07-27 Bernd Schmidt <bernds@codesourcery.com> | ||
91 | |||
92 | gcc/ | ||
93 | * postreload.c (reload_combine_recognize_const_pattern): Move test | ||
94 | for limiting the insn movement to the right scope. | ||
95 | |||
96 | 2010-07-27 Bernd Schmidt <bernds@codesourcery.com> | ||
97 | |||
98 | gcc/ | ||
99 | * postreload.c (try_replace_in_use): New static function. | ||
100 | (reload_combine_recognize_const_pattern): Use it here. Allow | ||
101 | substituting into a final add insn, and substituting into a memory | ||
102 | reference in an insn that sets the reg. | ||
103 | |||
104 | === modified file 'gcc/Makefile.in' | ||
105 | --- old/gcc/Makefile.in 2010-10-14 11:25:44 +0000 | ||
106 | +++ new/gcc/Makefile.in 2010-11-08 22:08:43 +0000 | ||
107 | @@ -3155,7 +3155,7 @@ | ||
108 | $(RTL_H) $(REAL_H) $(FLAGS_H) $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) \ | ||
109 | hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) output.h \ | ||
110 | $(FUNCTION_H) $(TOPLEV_H) cselib.h $(TM_P_H) $(EXCEPT_H) $(TREE_H) $(MACHMODE_H) \ | ||
111 | - $(OBSTACK_H) $(TARGET_H) $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) | ||
112 | + $(OBSTACK_H) $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) | ||
113 | postreload-gcse.o : postreload-gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ | ||
114 | $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \ | ||
115 | $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h $(TOPLEV_H) \ | ||
116 | |||
117 | === modified file 'gcc/postreload.c' | ||
118 | --- old/gcc/postreload.c 2010-10-14 11:32:02 +0000 | ||
119 | +++ new/gcc/postreload.c 2010-11-08 22:08:43 +0000 | ||
120 | @@ -44,7 +44,6 @@ | ||
121 | #include "toplev.h" | ||
122 | #include "except.h" | ||
123 | #include "tree.h" | ||
124 | -#include "target.h" | ||
125 | #include "timevar.h" | ||
126 | #include "tree-pass.h" | ||
127 | #include "df.h" | ||
128 | @@ -57,10 +56,10 @@ | ||
129 | static int reload_cse_simplify_operands (rtx, rtx); | ||
130 | |||
131 | static void reload_combine (void); | ||
132 | -static void reload_combine_note_use (rtx *, rtx, int, rtx); | ||
133 | +static void reload_combine_note_use (rtx *, rtx); | ||
134 | static void reload_combine_note_store (rtx, const_rtx, void *); | ||
135 | |||
136 | -static bool reload_cse_move2add (rtx); | ||
137 | +static void reload_cse_move2add (rtx); | ||
138 | static void move2add_note_store (rtx, const_rtx, void *); | ||
139 | |||
140 | /* Call cse / combine like post-reload optimization phases. | ||
141 | @@ -68,16 +67,11 @@ | ||
142 | void | ||
143 | reload_cse_regs (rtx first ATTRIBUTE_UNUSED) | ||
144 | { | ||
145 | - bool moves_converted; | ||
146 | reload_cse_regs_1 (first); | ||
147 | reload_combine (); | ||
148 | - moves_converted = reload_cse_move2add (first); | ||
149 | + reload_cse_move2add (first); | ||
150 | if (flag_expensive_optimizations) | ||
151 | - { | ||
152 | - if (moves_converted) | ||
153 | - reload_combine (); | ||
154 | - reload_cse_regs_1 (first); | ||
155 | - } | ||
156 | + reload_cse_regs_1 (first); | ||
157 | } | ||
158 | |||
159 | /* See whether a single set SET is a noop. */ | ||
160 | @@ -666,43 +660,30 @@ | ||
161 | |||
162 | /* The maximum number of uses of a register we can keep track of to | ||
163 | replace them with reg+reg addressing. */ | ||
164 | -#define RELOAD_COMBINE_MAX_USES 16 | ||
165 | +#define RELOAD_COMBINE_MAX_USES 6 | ||
166 | |||
167 | -/* Describes a recorded use of a register. */ | ||
168 | -struct reg_use | ||
169 | -{ | ||
170 | - /* The insn where a register has been used. */ | ||
171 | - rtx insn; | ||
172 | - /* Points to the memory reference enclosing the use, if any, NULL_RTX | ||
173 | - otherwise. */ | ||
174 | - rtx containing_mem; | ||
175 | - /* Location of the register withing INSN. */ | ||
176 | - rtx *usep; | ||
177 | - /* The reverse uid of the insn. */ | ||
178 | - int ruid; | ||
179 | -}; | ||
180 | +/* INSN is the insn where a register has been used, and USEP points to the | ||
181 | + location of the register within the rtl. */ | ||
182 | +struct reg_use { rtx insn, *usep; }; | ||
183 | |||
184 | /* If the register is used in some unknown fashion, USE_INDEX is negative. | ||
185 | If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID | ||
186 | - indicates where it is first set or clobbered. | ||
187 | + indicates where it becomes live again. | ||
188 | Otherwise, USE_INDEX is the index of the last encountered use of the | ||
189 | - register (which is first among these we have seen since we scan backwards). | ||
190 | - USE_RUID indicates the first encountered, i.e. last, of these uses. | ||
191 | - If ALL_OFFSETS_MATCH is true, all encountered uses were inside a PLUS | ||
192 | - with a constant offset; OFFSET contains this constant in that case. | ||
193 | + register (which is first among these we have seen since we scan backwards), | ||
194 | + OFFSET contains the constant offset that is added to the register in | ||
195 | + all encountered uses, and USE_RUID indicates the first encountered, i.e. | ||
196 | + last, of these uses. | ||
197 | STORE_RUID is always meaningful if we only want to use a value in a | ||
198 | register in a different place: it denotes the next insn in the insn | ||
199 | - stream (i.e. the last encountered) that sets or clobbers the register. | ||
200 | - REAL_STORE_RUID is similar, but clobbers are ignored when updating it. */ | ||
201 | + stream (i.e. the last encountered) that sets or clobbers the register. */ | ||
202 | static struct | ||
203 | { | ||
204 | struct reg_use reg_use[RELOAD_COMBINE_MAX_USES]; | ||
205 | + int use_index; | ||
206 | rtx offset; | ||
207 | - int use_index; | ||
208 | int store_ruid; | ||
209 | - int real_store_ruid; | ||
210 | int use_ruid; | ||
211 | - bool all_offsets_match; | ||
212 | } reg_state[FIRST_PSEUDO_REGISTER]; | ||
213 | |||
214 | /* Reverse linear uid. This is increased in reload_combine while scanning | ||
215 | @@ -710,548 +691,42 @@ | ||
216 | and the store_ruid / use_ruid fields in reg_state. */ | ||
217 | static int reload_combine_ruid; | ||
218 | |||
219 | -/* The RUID of the last label we encountered in reload_combine. */ | ||
220 | -static int last_label_ruid; | ||
221 | - | ||
222 | -/* The RUID of the last jump we encountered in reload_combine. */ | ||
223 | -static int last_jump_ruid; | ||
224 | - | ||
225 | -/* The register numbers of the first and last index register. A value of | ||
226 | - -1 in LAST_INDEX_REG indicates that we've previously computed these | ||
227 | - values and found no suitable index registers. */ | ||
228 | -static int first_index_reg = -1; | ||
229 | -static int last_index_reg; | ||
230 | - | ||
231 | #define LABEL_LIVE(LABEL) \ | ||
232 | (label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno]) | ||
233 | |||
234 | -/* Subroutine of reload_combine_split_ruids, called to fix up a single | ||
235 | - ruid pointed to by *PRUID if it is higher than SPLIT_RUID. */ | ||
236 | - | ||
237 | -static inline void | ||
238 | -reload_combine_split_one_ruid (int *pruid, int split_ruid) | ||
239 | -{ | ||
240 | - if (*pruid > split_ruid) | ||
241 | - (*pruid)++; | ||
242 | -} | ||
243 | - | ||
244 | -/* Called when we insert a new insn in a position we've already passed in | ||
245 | - the scan. Examine all our state, increasing all ruids that are higher | ||
246 | - than SPLIT_RUID by one in order to make room for a new insn. */ | ||
247 | - | ||
248 | -static void | ||
249 | -reload_combine_split_ruids (int split_ruid) | ||
250 | -{ | ||
251 | - unsigned i; | ||
252 | - | ||
253 | - reload_combine_split_one_ruid (&reload_combine_ruid, split_ruid); | ||
254 | - reload_combine_split_one_ruid (&last_label_ruid, split_ruid); | ||
255 | - reload_combine_split_one_ruid (&last_jump_ruid, split_ruid); | ||
256 | - | ||
257 | - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | ||
258 | - { | ||
259 | - int j, idx = reg_state[i].use_index; | ||
260 | - reload_combine_split_one_ruid (®_state[i].use_ruid, split_ruid); | ||
261 | - reload_combine_split_one_ruid (®_state[i].store_ruid, split_ruid); | ||
262 | - reload_combine_split_one_ruid (®_state[i].real_store_ruid, | ||
263 | - split_ruid); | ||
264 | - if (idx < 0) | ||
265 | - continue; | ||
266 | - for (j = idx; j < RELOAD_COMBINE_MAX_USES; j++) | ||
267 | - { | ||
268 | - reload_combine_split_one_ruid (®_state[i].reg_use[j].ruid, | ||
269 | - split_ruid); | ||
270 | - } | ||
271 | - } | ||
272 | -} | ||
273 | - | ||
274 | -/* Called when we are about to rescan a previously encountered insn with | ||
275 | - reload_combine_note_use after modifying some part of it. This clears all | ||
276 | - information about uses in that particular insn. */ | ||
277 | - | ||
278 | -static void | ||
279 | -reload_combine_purge_insn_uses (rtx insn) | ||
280 | -{ | ||
281 | - unsigned i; | ||
282 | - | ||
283 | - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | ||
284 | - { | ||
285 | - int j, k, idx = reg_state[i].use_index; | ||
286 | - if (idx < 0) | ||
287 | - continue; | ||
288 | - j = k = RELOAD_COMBINE_MAX_USES; | ||
289 | - while (j-- > idx) | ||
290 | - { | ||
291 | - if (reg_state[i].reg_use[j].insn != insn) | ||
292 | - { | ||
293 | - k--; | ||
294 | - if (k != j) | ||
295 | - reg_state[i].reg_use[k] = reg_state[i].reg_use[j]; | ||
296 | - } | ||
297 | - } | ||
298 | - reg_state[i].use_index = k; | ||
299 | - } | ||
300 | -} | ||
301 | - | ||
302 | -/* Called when we need to forget about all uses of REGNO after an insn | ||
303 | - which is identified by RUID. */ | ||
304 | - | ||
305 | -static void | ||
306 | -reload_combine_purge_reg_uses_after_ruid (unsigned regno, int ruid) | ||
307 | -{ | ||
308 | - int j, k, idx = reg_state[regno].use_index; | ||
309 | - if (idx < 0) | ||
310 | - return; | ||
311 | - j = k = RELOAD_COMBINE_MAX_USES; | ||
312 | - while (j-- > idx) | ||
313 | - { | ||
314 | - if (reg_state[regno].reg_use[j].ruid >= ruid) | ||
315 | - { | ||
316 | - k--; | ||
317 | - if (k != j) | ||
318 | - reg_state[regno].reg_use[k] = reg_state[regno].reg_use[j]; | ||
319 | - } | ||
320 | - } | ||
321 | - reg_state[regno].use_index = k; | ||
322 | -} | ||
323 | - | ||
324 | -/* Find the use of REGNO with the ruid that is highest among those | ||
325 | - lower than RUID_LIMIT, and return it if it is the only use of this | ||
326 | - reg in the insn. Return NULL otherwise. */ | ||
327 | - | ||
328 | -static struct reg_use * | ||
329 | -reload_combine_closest_single_use (unsigned regno, int ruid_limit) | ||
330 | -{ | ||
331 | - int i, best_ruid = 0; | ||
332 | - int use_idx = reg_state[regno].use_index; | ||
333 | - struct reg_use *retval; | ||
334 | - | ||
335 | - if (use_idx < 0) | ||
336 | - return NULL; | ||
337 | - retval = NULL; | ||
338 | - for (i = use_idx; i < RELOAD_COMBINE_MAX_USES; i++) | ||
339 | - { | ||
340 | - struct reg_use *use = reg_state[regno].reg_use + i; | ||
341 | - int this_ruid = use->ruid; | ||
342 | - if (this_ruid >= ruid_limit) | ||
343 | - continue; | ||
344 | - if (this_ruid > best_ruid) | ||
345 | - { | ||
346 | - best_ruid = this_ruid; | ||
347 | - retval = use; | ||
348 | - } | ||
349 | - else if (this_ruid == best_ruid) | ||
350 | - retval = NULL; | ||
351 | - } | ||
352 | - if (last_label_ruid >= best_ruid) | ||
353 | - return NULL; | ||
354 | - return retval; | ||
355 | -} | ||
356 | - | ||
357 | -/* After we've moved an add insn, fix up any debug insns that occur | ||
358 | - between the old location of the add and the new location. REG is | ||
359 | - the destination register of the add insn; REPLACEMENT is the | ||
360 | - SET_SRC of the add. FROM and TO specify the range in which we | ||
361 | - should make this change on debug insns. */ | ||
362 | - | ||
363 | -static void | ||
364 | -fixup_debug_insns (rtx reg, rtx replacement, rtx from, rtx to) | ||
365 | -{ | ||
366 | - rtx insn; | ||
367 | - for (insn = from; insn != to; insn = NEXT_INSN (insn)) | ||
368 | - { | ||
369 | - rtx t; | ||
370 | - | ||
371 | - if (!DEBUG_INSN_P (insn)) | ||
372 | - continue; | ||
373 | - | ||
374 | - t = INSN_VAR_LOCATION_LOC (insn); | ||
375 | - t = simplify_replace_rtx (t, reg, replacement); | ||
376 | - validate_change (insn, &INSN_VAR_LOCATION_LOC (insn), t, 0); | ||
377 | - } | ||
378 | -} | ||
379 | - | ||
380 | -/* Subroutine of reload_combine_recognize_const_pattern. Try to replace REG | ||
381 | - with SRC in the insn described by USE, taking costs into account. Return | ||
382 | - true if we made the replacement. */ | ||
383 | - | ||
384 | -static bool | ||
385 | -try_replace_in_use (struct reg_use *use, rtx reg, rtx src) | ||
386 | -{ | ||
387 | - rtx use_insn = use->insn; | ||
388 | - rtx mem = use->containing_mem; | ||
389 | - bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn)); | ||
390 | - | ||
391 | - if (mem != NULL_RTX) | ||
392 | - { | ||
393 | - addr_space_t as = MEM_ADDR_SPACE (mem); | ||
394 | - rtx oldaddr = XEXP (mem, 0); | ||
395 | - rtx newaddr = NULL_RTX; | ||
396 | - int old_cost = address_cost (oldaddr, GET_MODE (mem), as, speed); | ||
397 | - int new_cost; | ||
398 | - | ||
399 | - newaddr = simplify_replace_rtx (oldaddr, reg, src); | ||
400 | - if (memory_address_addr_space_p (GET_MODE (mem), newaddr, as)) | ||
401 | - { | ||
402 | - XEXP (mem, 0) = newaddr; | ||
403 | - new_cost = address_cost (newaddr, GET_MODE (mem), as, speed); | ||
404 | - XEXP (mem, 0) = oldaddr; | ||
405 | - if (new_cost <= old_cost | ||
406 | - && validate_change (use_insn, | ||
407 | - &XEXP (mem, 0), newaddr, 0)) | ||
408 | - return true; | ||
409 | - } | ||
410 | - } | ||
411 | - else | ||
412 | - { | ||
413 | - rtx new_set = single_set (use_insn); | ||
414 | - if (new_set | ||
415 | - && REG_P (SET_DEST (new_set)) | ||
416 | - && GET_CODE (SET_SRC (new_set)) == PLUS | ||
417 | - && REG_P (XEXP (SET_SRC (new_set), 0)) | ||
418 | - && CONSTANT_P (XEXP (SET_SRC (new_set), 1))) | ||
419 | - { | ||
420 | - rtx new_src; | ||
421 | - int old_cost = rtx_cost (SET_SRC (new_set), SET, speed); | ||
422 | - | ||
423 | - gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg)); | ||
424 | - new_src = simplify_replace_rtx (SET_SRC (new_set), reg, src); | ||
425 | - | ||
426 | - if (rtx_cost (new_src, SET, speed) <= old_cost | ||
427 | - && validate_change (use_insn, &SET_SRC (new_set), | ||
428 | - new_src, 0)) | ||
429 | - return true; | ||
430 | - } | ||
431 | - } | ||
432 | - return false; | ||
433 | -} | ||
434 | - | ||
435 | -/* Called by reload_combine when scanning INSN. This function tries to detect | ||
436 | - patterns where a constant is added to a register, and the result is used | ||
437 | - in an address. | ||
438 | - Return true if no further processing is needed on INSN; false if it wasn't | ||
439 | - recognized and should be handled normally. */ | ||
440 | - | ||
441 | -static bool | ||
442 | -reload_combine_recognize_const_pattern (rtx insn) | ||
443 | -{ | ||
444 | - int from_ruid = reload_combine_ruid; | ||
445 | - rtx set, pat, reg, src, addreg; | ||
446 | - unsigned int regno; | ||
447 | - struct reg_use *use; | ||
448 | - bool must_move_add; | ||
449 | - rtx add_moved_after_insn = NULL_RTX; | ||
450 | - int add_moved_after_ruid = 0; | ||
451 | - int clobbered_regno = -1; | ||
452 | - | ||
453 | - set = single_set (insn); | ||
454 | - if (set == NULL_RTX) | ||
455 | - return false; | ||
456 | - | ||
457 | - reg = SET_DEST (set); | ||
458 | - src = SET_SRC (set); | ||
459 | - if (!REG_P (reg) | ||
460 | - || hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1 | ||
461 | - || GET_MODE (reg) != Pmode | ||
462 | - || reg == stack_pointer_rtx) | ||
463 | - return false; | ||
464 | - | ||
465 | - regno = REGNO (reg); | ||
466 | - | ||
467 | - /* We look for a REG1 = REG2 + CONSTANT insn, followed by either | ||
468 | - uses of REG1 inside an address, or inside another add insn. If | ||
469 | - possible and profitable, merge the addition into subsequent | ||
470 | - uses. */ | ||
471 | - if (GET_CODE (src) != PLUS | ||
472 | - || !REG_P (XEXP (src, 0)) | ||
473 | - || !CONSTANT_P (XEXP (src, 1))) | ||
474 | - return false; | ||
475 | - | ||
476 | - addreg = XEXP (src, 0); | ||
477 | - must_move_add = rtx_equal_p (reg, addreg); | ||
478 | - | ||
479 | - pat = PATTERN (insn); | ||
480 | - if (must_move_add && set != pat) | ||
481 | - { | ||
482 | - /* We have to be careful when moving the add; apart from the | ||
483 | - single_set there may also be clobbers. Recognize one special | ||
484 | - case, that of one clobber alongside the set (likely a clobber | ||
485 | - of the CC register). */ | ||
486 | - gcc_assert (GET_CODE (PATTERN (insn)) == PARALLEL); | ||
487 | - if (XVECLEN (pat, 0) != 2 || XVECEXP (pat, 0, 0) != set | ||
488 | - || GET_CODE (XVECEXP (pat, 0, 1)) != CLOBBER | ||
489 | - || !REG_P (XEXP (XVECEXP (pat, 0, 1), 0))) | ||
490 | - return false; | ||
491 | - clobbered_regno = REGNO (XEXP (XVECEXP (pat, 0, 1), 0)); | ||
492 | - } | ||
493 | - | ||
494 | - do | ||
495 | - { | ||
496 | - use = reload_combine_closest_single_use (regno, from_ruid); | ||
497 | - | ||
498 | - if (use) | ||
499 | - /* Start the search for the next use from here. */ | ||
500 | - from_ruid = use->ruid; | ||
501 | - | ||
502 | - if (use && GET_MODE (*use->usep) == Pmode) | ||
503 | - { | ||
504 | - bool delete_add = false; | ||
505 | - rtx use_insn = use->insn; | ||
506 | - int use_ruid = use->ruid; | ||
507 | - | ||
508 | - /* Avoid moving the add insn past a jump. */ | ||
509 | - if (must_move_add && use_ruid <= last_jump_ruid) | ||
510 | - break; | ||
511 | - | ||
512 | - /* If the add clobbers another hard reg in parallel, don't move | ||
513 | - it past a real set of this hard reg. */ | ||
514 | - if (must_move_add && clobbered_regno >= 0 | ||
515 | - && reg_state[clobbered_regno].real_store_ruid >= use_ruid) | ||
516 | - break; | ||
517 | - | ||
518 | - gcc_assert (reg_state[regno].store_ruid <= use_ruid); | ||
519 | - /* Avoid moving a use of ADDREG past a point where it is stored. */ | ||
520 | - if (reg_state[REGNO (addreg)].store_ruid > use_ruid) | ||
521 | - break; | ||
522 | - | ||
523 | - /* We also must not move the addition past an insn that sets | ||
524 | - the same register, unless we can combine two add insns. */ | ||
525 | - if (must_move_add && reg_state[regno].store_ruid == use_ruid) | ||
526 | - { | ||
527 | - if (use->containing_mem == NULL_RTX) | ||
528 | - delete_add = true; | ||
529 | - else | ||
530 | - break; | ||
531 | - } | ||
532 | - | ||
533 | - if (try_replace_in_use (use, reg, src)) | ||
534 | - { | ||
535 | - reload_combine_purge_insn_uses (use_insn); | ||
536 | - reload_combine_note_use (&PATTERN (use_insn), use_insn, | ||
537 | - use_ruid, NULL_RTX); | ||
538 | - | ||
539 | - if (delete_add) | ||
540 | - { | ||
541 | - fixup_debug_insns (reg, src, insn, use_insn); | ||
542 | - delete_insn (insn); | ||
543 | - return true; | ||
544 | - } | ||
545 | - if (must_move_add) | ||
546 | - { | ||
547 | - add_moved_after_insn = use_insn; | ||
548 | - add_moved_after_ruid = use_ruid; | ||
549 | - } | ||
550 | - continue; | ||
551 | - } | ||
552 | - } | ||
553 | - /* If we get here, we couldn't handle this use. */ | ||
554 | - if (must_move_add) | ||
555 | - break; | ||
556 | - } | ||
557 | - while (use); | ||
558 | - | ||
559 | - if (!must_move_add || add_moved_after_insn == NULL_RTX) | ||
560 | - /* Process the add normally. */ | ||
561 | - return false; | ||
562 | - | ||
563 | - fixup_debug_insns (reg, src, insn, add_moved_after_insn); | ||
564 | - | ||
565 | - reorder_insns (insn, insn, add_moved_after_insn); | ||
566 | - reload_combine_purge_reg_uses_after_ruid (regno, add_moved_after_ruid); | ||
567 | - reload_combine_split_ruids (add_moved_after_ruid - 1); | ||
568 | - reload_combine_note_use (&PATTERN (insn), insn, | ||
569 | - add_moved_after_ruid, NULL_RTX); | ||
570 | - reg_state[regno].store_ruid = add_moved_after_ruid; | ||
571 | - | ||
572 | - return true; | ||
573 | -} | ||
574 | - | ||
575 | -/* Called by reload_combine when scanning INSN. Try to detect a pattern we | ||
576 | - can handle and improve. Return true if no further processing is needed on | ||
577 | - INSN; false if it wasn't recognized and should be handled normally. */ | ||
578 | - | ||
579 | -static bool | ||
580 | -reload_combine_recognize_pattern (rtx insn) | ||
581 | -{ | ||
582 | - rtx set, reg, src; | ||
583 | - unsigned int regno; | ||
584 | - | ||
585 | - set = single_set (insn); | ||
586 | - if (set == NULL_RTX) | ||
587 | - return false; | ||
588 | - | ||
589 | - reg = SET_DEST (set); | ||
590 | - src = SET_SRC (set); | ||
591 | - if (!REG_P (reg) | ||
592 | - || hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1) | ||
593 | - return false; | ||
594 | - | ||
595 | - regno = REGNO (reg); | ||
596 | - | ||
597 | - /* Look for (set (REGX) (CONST_INT)) | ||
598 | - (set (REGX) (PLUS (REGX) (REGY))) | ||
599 | - ... | ||
600 | - ... (MEM (REGX)) ... | ||
601 | - and convert it to | ||
602 | - (set (REGZ) (CONST_INT)) | ||
603 | - ... | ||
604 | - ... (MEM (PLUS (REGZ) (REGY)))... . | ||
605 | - | ||
606 | - First, check that we have (set (REGX) (PLUS (REGX) (REGY))) | ||
607 | - and that we know all uses of REGX before it dies. | ||
608 | - Also, explicitly check that REGX != REGY; our life information | ||
609 | - does not yet show whether REGY changes in this insn. */ | ||
610 | - | ||
611 | - if (GET_CODE (src) == PLUS | ||
612 | - && reg_state[regno].all_offsets_match | ||
613 | - && last_index_reg != -1 | ||
614 | - && REG_P (XEXP (src, 1)) | ||
615 | - && rtx_equal_p (XEXP (src, 0), reg) | ||
616 | - && !rtx_equal_p (XEXP (src, 1), reg) | ||
617 | - && reg_state[regno].use_index >= 0 | ||
618 | - && reg_state[regno].use_index < RELOAD_COMBINE_MAX_USES | ||
619 | - && last_label_ruid < reg_state[regno].use_ruid) | ||
620 | - { | ||
621 | - rtx base = XEXP (src, 1); | ||
622 | - rtx prev = prev_nonnote_insn (insn); | ||
623 | - rtx prev_set = prev ? single_set (prev) : NULL_RTX; | ||
624 | - rtx index_reg = NULL_RTX; | ||
625 | - rtx reg_sum = NULL_RTX; | ||
626 | - int i; | ||
627 | - | ||
628 | - /* Now we need to set INDEX_REG to an index register (denoted as | ||
629 | - REGZ in the illustration above) and REG_SUM to the expression | ||
630 | - register+register that we want to use to substitute uses of REG | ||
631 | - (typically in MEMs) with. First check REG and BASE for being | ||
632 | - index registers; we can use them even if they are not dead. */ | ||
633 | - if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno) | ||
634 | - || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], | ||
635 | - REGNO (base))) | ||
636 | - { | ||
637 | - index_reg = reg; | ||
638 | - reg_sum = src; | ||
639 | - } | ||
640 | - else | ||
641 | - { | ||
642 | - /* Otherwise, look for a free index register. Since we have | ||
643 | - checked above that neither REG nor BASE are index registers, | ||
644 | - if we find anything at all, it will be different from these | ||
645 | - two registers. */ | ||
646 | - for (i = first_index_reg; i <= last_index_reg; i++) | ||
647 | - { | ||
648 | - if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i) | ||
649 | - && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES | ||
650 | - && reg_state[i].store_ruid <= reg_state[regno].use_ruid | ||
651 | - && (call_used_regs[i] || df_regs_ever_live_p (i)) | ||
652 | - && (!frame_pointer_needed || i != HARD_FRAME_POINTER_REGNUM) | ||
653 | - && !fixed_regs[i] && !global_regs[i] | ||
654 | - && hard_regno_nregs[i][GET_MODE (reg)] == 1 | ||
655 | - && targetm.hard_regno_scratch_ok (i)) | ||
656 | - { | ||
657 | - index_reg = gen_rtx_REG (GET_MODE (reg), i); | ||
658 | - reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base); | ||
659 | - break; | ||
660 | - } | ||
661 | - } | ||
662 | - } | ||
663 | - | ||
664 | - /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that | ||
665 | - (REGY), i.e. BASE, is not clobbered before the last use we'll | ||
666 | - create. */ | ||
667 | - if (reg_sum | ||
668 | - && prev_set | ||
669 | - && CONST_INT_P (SET_SRC (prev_set)) | ||
670 | - && rtx_equal_p (SET_DEST (prev_set), reg) | ||
671 | - && (reg_state[REGNO (base)].store_ruid | ||
672 | - <= reg_state[regno].use_ruid)) | ||
673 | - { | ||
674 | - /* Change destination register and, if necessary, the constant | ||
675 | - value in PREV, the constant loading instruction. */ | ||
676 | - validate_change (prev, &SET_DEST (prev_set), index_reg, 1); | ||
677 | - if (reg_state[regno].offset != const0_rtx) | ||
678 | - validate_change (prev, | ||
679 | - &SET_SRC (prev_set), | ||
680 | - GEN_INT (INTVAL (SET_SRC (prev_set)) | ||
681 | - + INTVAL (reg_state[regno].offset)), | ||
682 | - 1); | ||
683 | - | ||
684 | - /* Now for every use of REG that we have recorded, replace REG | ||
685 | - with REG_SUM. */ | ||
686 | - for (i = reg_state[regno].use_index; | ||
687 | - i < RELOAD_COMBINE_MAX_USES; i++) | ||
688 | - validate_unshare_change (reg_state[regno].reg_use[i].insn, | ||
689 | - reg_state[regno].reg_use[i].usep, | ||
690 | - /* Each change must have its own | ||
691 | - replacement. */ | ||
692 | - reg_sum, 1); | ||
693 | - | ||
694 | - if (apply_change_group ()) | ||
695 | - { | ||
696 | - struct reg_use *lowest_ruid = NULL; | ||
697 | - | ||
698 | - /* For every new use of REG_SUM, we have to record the use | ||
699 | - of BASE therein, i.e. operand 1. */ | ||
700 | - for (i = reg_state[regno].use_index; | ||
701 | - i < RELOAD_COMBINE_MAX_USES; i++) | ||
702 | - { | ||
703 | - struct reg_use *use = reg_state[regno].reg_use + i; | ||
704 | - reload_combine_note_use (&XEXP (*use->usep, 1), use->insn, | ||
705 | - use->ruid, use->containing_mem); | ||
706 | - if (lowest_ruid == NULL || use->ruid < lowest_ruid->ruid) | ||
707 | - lowest_ruid = use; | ||
708 | - } | ||
709 | - | ||
710 | - fixup_debug_insns (reg, reg_sum, insn, lowest_ruid->insn); | ||
711 | - | ||
712 | - /* Delete the reg-reg addition. */ | ||
713 | - delete_insn (insn); | ||
714 | - | ||
715 | - if (reg_state[regno].offset != const0_rtx) | ||
716 | - /* Previous REG_EQUIV / REG_EQUAL notes for PREV | ||
717 | - are now invalid. */ | ||
718 | - remove_reg_equal_equiv_notes (prev); | ||
719 | - | ||
720 | - reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES; | ||
721 | - return true; | ||
722 | - } | ||
723 | - } | ||
724 | - } | ||
725 | - return false; | ||
726 | -} | ||
727 | - | ||
728 | static void | ||
729 | reload_combine (void) | ||
730 | { | ||
731 | - rtx insn, prev; | ||
732 | + rtx insn, set; | ||
733 | + int first_index_reg = -1; | ||
734 | + int last_index_reg = 0; | ||
735 | int i; | ||
736 | basic_block bb; | ||
737 | unsigned int r; | ||
738 | + int last_label_ruid; | ||
739 | int min_labelno, n_labels; | ||
740 | HARD_REG_SET ever_live_at_start, *label_live; | ||
741 | |||
742 | + /* If reg+reg can be used in offsetable memory addresses, the main chunk of | ||
743 | + reload has already used it where appropriate, so there is no use in | ||
744 | + trying to generate it now. */ | ||
745 | + if (double_reg_address_ok && INDEX_REG_CLASS != NO_REGS) | ||
746 | + return; | ||
747 | + | ||
748 | /* To avoid wasting too much time later searching for an index register, | ||
749 | determine the minimum and maximum index register numbers. */ | ||
750 | - if (INDEX_REG_CLASS == NO_REGS) | ||
751 | - last_index_reg = -1; | ||
752 | - else if (first_index_reg == -1 && last_index_reg == 0) | ||
753 | - { | ||
754 | - for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) | ||
755 | - if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r)) | ||
756 | - { | ||
757 | - if (first_index_reg == -1) | ||
758 | - first_index_reg = r; | ||
759 | - | ||
760 | - last_index_reg = r; | ||
761 | - } | ||
762 | - | ||
763 | - /* If no index register is available, we can quit now. Set LAST_INDEX_REG | ||
764 | - to -1 so we'll know to quit early the next time we get here. */ | ||
765 | - if (first_index_reg == -1) | ||
766 | - { | ||
767 | - last_index_reg = -1; | ||
768 | - return; | ||
769 | - } | ||
770 | - } | ||
771 | + for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) | ||
772 | + if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r)) | ||
773 | + { | ||
774 | + if (first_index_reg == -1) | ||
775 | + first_index_reg = r; | ||
776 | + | ||
777 | + last_index_reg = r; | ||
778 | + } | ||
779 | + | ||
780 | + /* If no index register is available, we can quit now. */ | ||
781 | + if (first_index_reg == -1) | ||
782 | + return; | ||
783 | |||
784 | /* Set up LABEL_LIVE and EVER_LIVE_AT_START. The register lifetime | ||
785 | information is a bit fuzzy immediately after reload, but it's | ||
786 | @@ -1278,23 +753,20 @@ | ||
787 | } | ||
788 | |||
789 | /* Initialize last_label_ruid, reload_combine_ruid and reg_state. */ | ||
790 | - last_label_ruid = last_jump_ruid = reload_combine_ruid = 0; | ||
791 | + last_label_ruid = reload_combine_ruid = 0; | ||
792 | for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) | ||
793 | { | ||
794 | - reg_state[r].store_ruid = 0; | ||
795 | - reg_state[r].real_store_ruid = 0; | ||
796 | + reg_state[r].store_ruid = reload_combine_ruid; | ||
797 | if (fixed_regs[r]) | ||
798 | reg_state[r].use_index = -1; | ||
799 | else | ||
800 | reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; | ||
801 | } | ||
802 | |||
803 | - for (insn = get_last_insn (); insn; insn = prev) | ||
804 | + for (insn = get_last_insn (); insn; insn = PREV_INSN (insn)) | ||
805 | { | ||
806 | rtx note; | ||
807 | |||
808 | - prev = PREV_INSN (insn); | ||
809 | - | ||
810 | /* We cannot do our optimization across labels. Invalidating all the use | ||
811 | information we have would be costly, so we just note where the label | ||
812 | is and then later disable any optimization that would cross it. */ | ||
813 | @@ -1305,17 +777,141 @@ | ||
814 | if (! fixed_regs[r]) | ||
815 | reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; | ||
816 | |||
817 | - if (! NONDEBUG_INSN_P (insn)) | ||
818 | + if (! INSN_P (insn)) | ||
819 | continue; | ||
820 | |||
821 | reload_combine_ruid++; | ||
822 | |||
823 | - if (control_flow_insn_p (insn)) | ||
824 | - last_jump_ruid = reload_combine_ruid; | ||
825 | - | ||
826 | - if (reload_combine_recognize_const_pattern (insn) | ||
827 | - || reload_combine_recognize_pattern (insn)) | ||
828 | - continue; | ||
829 | + /* Look for (set (REGX) (CONST_INT)) | ||
830 | + (set (REGX) (PLUS (REGX) (REGY))) | ||
831 | + ... | ||
832 | + ... (MEM (REGX)) ... | ||
833 | + and convert it to | ||
834 | + (set (REGZ) (CONST_INT)) | ||
835 | + ... | ||
836 | + ... (MEM (PLUS (REGZ) (REGY)))... . | ||
837 | + | ||
838 | + First, check that we have (set (REGX) (PLUS (REGX) (REGY))) | ||
839 | + and that we know all uses of REGX before it dies. | ||
840 | + Also, explicitly check that REGX != REGY; our life information | ||
841 | + does not yet show whether REGY changes in this insn. */ | ||
842 | + set = single_set (insn); | ||
843 | + if (set != NULL_RTX | ||
844 | + && REG_P (SET_DEST (set)) | ||
845 | + && (hard_regno_nregs[REGNO (SET_DEST (set))] | ||
846 | + [GET_MODE (SET_DEST (set))] | ||
847 | + == 1) | ||
848 | + && GET_CODE (SET_SRC (set)) == PLUS | ||
849 | + && REG_P (XEXP (SET_SRC (set), 1)) | ||
850 | + && rtx_equal_p (XEXP (SET_SRC (set), 0), SET_DEST (set)) | ||
851 | + && !rtx_equal_p (XEXP (SET_SRC (set), 1), SET_DEST (set)) | ||
852 | + && last_label_ruid < reg_state[REGNO (SET_DEST (set))].use_ruid) | ||
853 | + { | ||
854 | + rtx reg = SET_DEST (set); | ||
855 | + rtx plus = SET_SRC (set); | ||
856 | + rtx base = XEXP (plus, 1); | ||
857 | + rtx prev = prev_nonnote_nondebug_insn (insn); | ||
858 | + rtx prev_set = prev ? single_set (prev) : NULL_RTX; | ||
859 | + unsigned int regno = REGNO (reg); | ||
860 | + rtx index_reg = NULL_RTX; | ||
861 | + rtx reg_sum = NULL_RTX; | ||
862 | + | ||
863 | + /* Now we need to set INDEX_REG to an index register (denoted as | ||
864 | + REGZ in the illustration above) and REG_SUM to the expression | ||
865 | + register+register that we want to use to substitute uses of REG | ||
866 | + (typically in MEMs) with. First check REG and BASE for being | ||
867 | + index registers; we can use them even if they are not dead. */ | ||
868 | + if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno) | ||
869 | + || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], | ||
870 | + REGNO (base))) | ||
871 | + { | ||
872 | + index_reg = reg; | ||
873 | + reg_sum = plus; | ||
874 | + } | ||
875 | + else | ||
876 | + { | ||
877 | + /* Otherwise, look for a free index register. Since we have | ||
878 | + checked above that neither REG nor BASE are index registers, | ||
879 | + if we find anything at all, it will be different from these | ||
880 | + two registers. */ | ||
881 | + for (i = first_index_reg; i <= last_index_reg; i++) | ||
882 | + { | ||
883 | + if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], | ||
884 | + i) | ||
885 | + && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES | ||
886 | + && reg_state[i].store_ruid <= reg_state[regno].use_ruid | ||
887 | + && hard_regno_nregs[i][GET_MODE (reg)] == 1) | ||
888 | + { | ||
889 | + index_reg = gen_rtx_REG (GET_MODE (reg), i); | ||
890 | + reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base); | ||
891 | + break; | ||
892 | + } | ||
893 | + } | ||
894 | + } | ||
895 | + | ||
896 | + /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that | ||
897 | + (REGY), i.e. BASE, is not clobbered before the last use we'll | ||
898 | + create. */ | ||
899 | + if (reg_sum | ||
900 | + && prev_set | ||
901 | + && CONST_INT_P (SET_SRC (prev_set)) | ||
902 | + && rtx_equal_p (SET_DEST (prev_set), reg) | ||
903 | + && reg_state[regno].use_index >= 0 | ||
904 | + && (reg_state[REGNO (base)].store_ruid | ||
905 | + <= reg_state[regno].use_ruid)) | ||
906 | + { | ||
907 | + int i; | ||
908 | + | ||
909 | + /* Change destination register and, if necessary, the constant | ||
910 | + value in PREV, the constant loading instruction. */ | ||
911 | + validate_change (prev, &SET_DEST (prev_set), index_reg, 1); | ||
912 | + if (reg_state[regno].offset != const0_rtx) | ||
913 | + validate_change (prev, | ||
914 | + &SET_SRC (prev_set), | ||
915 | + GEN_INT (INTVAL (SET_SRC (prev_set)) | ||
916 | + + INTVAL (reg_state[regno].offset)), | ||
917 | + 1); | ||
918 | + | ||
919 | + /* Now for every use of REG that we have recorded, replace REG | ||
920 | + with REG_SUM. */ | ||
921 | + for (i = reg_state[regno].use_index; | ||
922 | + i < RELOAD_COMBINE_MAX_USES; i++) | ||
923 | + validate_unshare_change (reg_state[regno].reg_use[i].insn, | ||
924 | + reg_state[regno].reg_use[i].usep, | ||
925 | + /* Each change must have its own | ||
926 | + replacement. */ | ||
927 | + reg_sum, 1); | ||
928 | + | ||
929 | + if (apply_change_group ()) | ||
930 | + { | ||
931 | + /* For every new use of REG_SUM, we have to record the use | ||
932 | + of BASE therein, i.e. operand 1. */ | ||
933 | + for (i = reg_state[regno].use_index; | ||
934 | + i < RELOAD_COMBINE_MAX_USES; i++) | ||
935 | + reload_combine_note_use | ||
936 | + (&XEXP (*reg_state[regno].reg_use[i].usep, 1), | ||
937 | + reg_state[regno].reg_use[i].insn); | ||
938 | + | ||
939 | + if (reg_state[REGNO (base)].use_ruid | ||
940 | + > reg_state[regno].use_ruid) | ||
941 | + reg_state[REGNO (base)].use_ruid | ||
942 | + = reg_state[regno].use_ruid; | ||
943 | + | ||
944 | + /* Delete the reg-reg addition. */ | ||
945 | + delete_insn (insn); | ||
946 | + | ||
947 | + if (reg_state[regno].offset != const0_rtx) | ||
948 | + /* Previous REG_EQUIV / REG_EQUAL notes for PREV | ||
949 | + are now invalid. */ | ||
950 | + remove_reg_equal_equiv_notes (prev); | ||
951 | + | ||
952 | + reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES; | ||
953 | + reg_state[REGNO (index_reg)].store_ruid | ||
954 | + = reload_combine_ruid; | ||
955 | + continue; | ||
956 | + } | ||
957 | + } | ||
958 | + } | ||
959 | |||
960 | note_stores (PATTERN (insn), reload_combine_note_store, NULL); | ||
961 | |||
962 | @@ -1371,8 +967,7 @@ | ||
963 | reg_state[i].use_index = -1; | ||
964 | } | ||
965 | |||
966 | - reload_combine_note_use (&PATTERN (insn), insn, | ||
967 | - reload_combine_ruid, NULL_RTX); | ||
968 | + reload_combine_note_use (&PATTERN (insn), insn); | ||
969 | for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) | ||
970 | { | ||
971 | if (REG_NOTE_KIND (note) == REG_INC | ||
972 | @@ -1381,7 +976,6 @@ | ||
973 | int regno = REGNO (XEXP (note, 0)); | ||
974 | |||
975 | reg_state[regno].store_ruid = reload_combine_ruid; | ||
976 | - reg_state[regno].real_store_ruid = reload_combine_ruid; | ||
977 | reg_state[regno].use_index = -1; | ||
978 | } | ||
979 | } | ||
980 | @@ -1391,8 +985,8 @@ | ||
981 | } | ||
982 | |||
983 | /* Check if DST is a register or a subreg of a register; if it is, | ||
984 | - update store_ruid, real_store_ruid and use_index in the reg_state | ||
985 | - structure accordingly. Called via note_stores from reload_combine. */ | ||
986 | + update reg_state[regno].store_ruid and reg_state[regno].use_index | ||
987 | + accordingly. Called via note_stores from reload_combine. */ | ||
988 | |||
989 | static void | ||
990 | reload_combine_note_store (rtx dst, const_rtx set, void *data ATTRIBUTE_UNUSED) | ||
991 | @@ -1416,14 +1010,14 @@ | ||
992 | /* note_stores might have stripped a STRICT_LOW_PART, so we have to be | ||
993 | careful with registers / register parts that are not full words. | ||
994 | Similarly for ZERO_EXTRACT. */ | ||
995 | - if (GET_CODE (SET_DEST (set)) == ZERO_EXTRACT | ||
996 | + if (GET_CODE (set) != SET | ||
997 | + || GET_CODE (SET_DEST (set)) == ZERO_EXTRACT | ||
998 | || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART) | ||
999 | { | ||
1000 | for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--) | ||
1001 | { | ||
1002 | reg_state[i].use_index = -1; | ||
1003 | reg_state[i].store_ruid = reload_combine_ruid; | ||
1004 | - reg_state[i].real_store_ruid = reload_combine_ruid; | ||
1005 | } | ||
1006 | } | ||
1007 | else | ||
1008 | @@ -1431,8 +1025,6 @@ | ||
1009 | for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--) | ||
1010 | { | ||
1011 | reg_state[i].store_ruid = reload_combine_ruid; | ||
1012 | - if (GET_CODE (set) == SET) | ||
1013 | - reg_state[i].real_store_ruid = reload_combine_ruid; | ||
1014 | reg_state[i].use_index = RELOAD_COMBINE_MAX_USES; | ||
1015 | } | ||
1016 | } | ||
1017 | @@ -1443,7 +1035,7 @@ | ||
1018 | *XP is the pattern of INSN, or a part of it. | ||
1019 | Called from reload_combine, and recursively by itself. */ | ||
1020 | static void | ||
1021 | -reload_combine_note_use (rtx *xp, rtx insn, int ruid, rtx containing_mem) | ||
1022 | +reload_combine_note_use (rtx *xp, rtx insn) | ||
1023 | { | ||
1024 | rtx x = *xp; | ||
1025 | enum rtx_code code = x->code; | ||
1026 | @@ -1456,7 +1048,7 @@ | ||
1027 | case SET: | ||
1028 | if (REG_P (SET_DEST (x))) | ||
1029 | { | ||
1030 | - reload_combine_note_use (&SET_SRC (x), insn, ruid, NULL_RTX); | ||
1031 | + reload_combine_note_use (&SET_SRC (x), insn); | ||
1032 | return; | ||
1033 | } | ||
1034 | break; | ||
1035 | @@ -1512,11 +1104,6 @@ | ||
1036 | return; | ||
1037 | } | ||
1038 | |||
1039 | - /* We may be called to update uses in previously seen insns. | ||
1040 | - Don't add uses beyond the last store we saw. */ | ||
1041 | - if (ruid < reg_state[regno].store_ruid) | ||
1042 | - return; | ||
1043 | - | ||
1044 | /* If this register is already used in some unknown fashion, we | ||
1045 | can't do anything. | ||
1046 | If we decrement the index from zero to -1, we can't store more | ||
1047 | @@ -1525,34 +1112,29 @@ | ||
1048 | if (use_index < 0) | ||
1049 | return; | ||
1050 | |||
1051 | - if (use_index == RELOAD_COMBINE_MAX_USES - 1) | ||
1052 | + if (use_index != RELOAD_COMBINE_MAX_USES - 1) | ||
1053 | + { | ||
1054 | + /* We have found another use for a register that is already | ||
1055 | + used later. Check if the offsets match; if not, mark the | ||
1056 | + register as used in an unknown fashion. */ | ||
1057 | + if (! rtx_equal_p (offset, reg_state[regno].offset)) | ||
1058 | + { | ||
1059 | + reg_state[regno].use_index = -1; | ||
1060 | + return; | ||
1061 | + } | ||
1062 | + } | ||
1063 | + else | ||
1064 | { | ||
1065 | /* This is the first use of this register we have seen since we | ||
1066 | marked it as dead. */ | ||
1067 | reg_state[regno].offset = offset; | ||
1068 | - reg_state[regno].all_offsets_match = true; | ||
1069 | - reg_state[regno].use_ruid = ruid; | ||
1070 | - } | ||
1071 | - else | ||
1072 | - { | ||
1073 | - if (reg_state[regno].use_ruid > ruid) | ||
1074 | - reg_state[regno].use_ruid = ruid; | ||
1075 | - | ||
1076 | - if (! rtx_equal_p (offset, reg_state[regno].offset)) | ||
1077 | - reg_state[regno].all_offsets_match = false; | ||
1078 | - } | ||
1079 | - | ||
1080 | + reg_state[regno].use_ruid = reload_combine_ruid; | ||
1081 | + } | ||
1082 | reg_state[regno].reg_use[use_index].insn = insn; | ||
1083 | - reg_state[regno].reg_use[use_index].ruid = ruid; | ||
1084 | - reg_state[regno].reg_use[use_index].containing_mem = containing_mem; | ||
1085 | reg_state[regno].reg_use[use_index].usep = xp; | ||
1086 | return; | ||
1087 | } | ||
1088 | |||
1089 | - case MEM: | ||
1090 | - containing_mem = x; | ||
1091 | - break; | ||
1092 | - | ||
1093 | default: | ||
1094 | break; | ||
1095 | } | ||
1096 | @@ -1562,12 +1144,11 @@ | ||
1097 | for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | ||
1098 | { | ||
1099 | if (fmt[i] == 'e') | ||
1100 | - reload_combine_note_use (&XEXP (x, i), insn, ruid, containing_mem); | ||
1101 | + reload_combine_note_use (&XEXP (x, i), insn); | ||
1102 | else if (fmt[i] == 'E') | ||
1103 | { | ||
1104 | for (j = XVECLEN (x, i) - 1; j >= 0; j--) | ||
1105 | - reload_combine_note_use (&XVECEXP (x, i, j), insn, ruid, | ||
1106 | - containing_mem); | ||
1107 | + reload_combine_note_use (&XVECEXP (x, i, j), insn); | ||
1108 | } | ||
1109 | } | ||
1110 | } | ||
1111 | @@ -1615,10 +1196,9 @@ | ||
1112 | while REG is known to already have value (SYM + offset). | ||
1113 | This function tries to change INSN into an add instruction | ||
1114 | (set (REG) (plus (REG) (OFF - offset))) using the known value. | ||
1115 | - It also updates the information about REG's known value. | ||
1116 | - Return true if we made a change. */ | ||
1117 | + It also updates the information about REG's known value. */ | ||
1118 | |||
1119 | -static bool | ||
1120 | +static void | ||
1121 | move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx insn) | ||
1122 | { | ||
1123 | rtx pat = PATTERN (insn); | ||
1124 | @@ -1627,7 +1207,6 @@ | ||
1125 | rtx new_src = gen_int_mode (INTVAL (off) - reg_offset[regno], | ||
1126 | GET_MODE (reg)); | ||
1127 | bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); | ||
1128 | - bool changed = false; | ||
1129 | |||
1130 | /* (set (reg) (plus (reg) (const_int 0))) is not canonical; | ||
1131 | use (set (reg) (reg)) instead. | ||
1132 | @@ -1642,13 +1221,13 @@ | ||
1133 | (reg)), would be discarded. Maybe we should | ||
1134 | try a truncMN pattern? */ | ||
1135 | if (INTVAL (off) == reg_offset [regno]) | ||
1136 | - changed = validate_change (insn, &SET_SRC (pat), reg, 0); | ||
1137 | + validate_change (insn, &SET_SRC (pat), reg, 0); | ||
1138 | } | ||
1139 | else if (rtx_cost (new_src, PLUS, speed) < rtx_cost (src, SET, speed) | ||
1140 | && have_add2_insn (reg, new_src)) | ||
1141 | { | ||
1142 | rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src); | ||
1143 | - changed = validate_change (insn, &SET_SRC (pat), tem, 0); | ||
1144 | + validate_change (insn, &SET_SRC (pat), tem, 0); | ||
1145 | } | ||
1146 | else if (sym == NULL_RTX && GET_MODE (reg) != BImode) | ||
1147 | { | ||
1148 | @@ -1673,9 +1252,8 @@ | ||
1149 | gen_rtx_STRICT_LOW_PART (VOIDmode, | ||
1150 | narrow_reg), | ||
1151 | narrow_src); | ||
1152 | - changed = validate_change (insn, &PATTERN (insn), | ||
1153 | - new_set, 0); | ||
1154 | - if (changed) | ||
1155 | + if (validate_change (insn, &PATTERN (insn), | ||
1156 | + new_set, 0)) | ||
1157 | break; | ||
1158 | } | ||
1159 | } | ||
1160 | @@ -1685,7 +1263,6 @@ | ||
1161 | reg_mode[regno] = GET_MODE (reg); | ||
1162 | reg_symbol_ref[regno] = sym; | ||
1163 | reg_offset[regno] = INTVAL (off); | ||
1164 | - return changed; | ||
1165 | } | ||
1166 | |||
1167 | |||
1168 | @@ -1695,10 +1272,9 @@ | ||
1169 | value (SYM + offset) and change INSN into an add instruction | ||
1170 | (set (REG) (plus (the found register) (OFF - offset))) if such | ||
1171 | a register is found. It also updates the information about | ||
1172 | - REG's known value. | ||
1173 | - Return true iff we made a change. */ | ||
1174 | + REG's known value. */ | ||
1175 | |||
1176 | -static bool | ||
1177 | +static void | ||
1178 | move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx insn) | ||
1179 | { | ||
1180 | rtx pat = PATTERN (insn); | ||
1181 | @@ -1708,7 +1284,6 @@ | ||
1182 | int min_regno; | ||
1183 | bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); | ||
1184 | int i; | ||
1185 | - bool changed = false; | ||
1186 | |||
1187 | for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | ||
1188 | if (reg_set_luid[i] > move2add_last_label_luid | ||
1189 | @@ -1753,25 +1328,20 @@ | ||
1190 | GET_MODE (reg)); | ||
1191 | tem = gen_rtx_PLUS (GET_MODE (reg), tem, new_src); | ||
1192 | } | ||
1193 | - if (validate_change (insn, &SET_SRC (pat), tem, 0)) | ||
1194 | - changed = true; | ||
1195 | + validate_change (insn, &SET_SRC (pat), tem, 0); | ||
1196 | } | ||
1197 | reg_set_luid[regno] = move2add_luid; | ||
1198 | reg_base_reg[regno] = -1; | ||
1199 | reg_mode[regno] = GET_MODE (reg); | ||
1200 | reg_symbol_ref[regno] = sym; | ||
1201 | reg_offset[regno] = INTVAL (off); | ||
1202 | - return changed; | ||
1203 | } | ||
1204 | |||
1205 | -/* Convert move insns with constant inputs to additions if they are cheaper. | ||
1206 | - Return true if any changes were made. */ | ||
1207 | -static bool | ||
1208 | +static void | ||
1209 | reload_cse_move2add (rtx first) | ||
1210 | { | ||
1211 | int i; | ||
1212 | rtx insn; | ||
1213 | - bool changed = false; | ||
1214 | |||
1215 | for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--) | ||
1216 | { | ||
1217 | @@ -1832,7 +1402,7 @@ | ||
1218 | && reg_base_reg[regno] < 0 | ||
1219 | && reg_symbol_ref[regno] == NULL_RTX) | ||
1220 | { | ||
1221 | - changed |= move2add_use_add2_insn (reg, NULL_RTX, src, insn); | ||
1222 | + move2add_use_add2_insn (reg, NULL_RTX, src, insn); | ||
1223 | continue; | ||
1224 | } | ||
1225 | |||
1226 | @@ -1893,7 +1463,6 @@ | ||
1227 | } | ||
1228 | if (success) | ||
1229 | delete_insn (insn); | ||
1230 | - changed |= success; | ||
1231 | insn = next; | ||
1232 | reg_mode[regno] = GET_MODE (reg); | ||
1233 | reg_offset[regno] = | ||
1234 | @@ -1939,12 +1508,12 @@ | ||
1235 | && reg_base_reg[regno] < 0 | ||
1236 | && reg_symbol_ref[regno] != NULL_RTX | ||
1237 | && rtx_equal_p (sym, reg_symbol_ref[regno])) | ||
1238 | - changed |= move2add_use_add2_insn (reg, sym, off, insn); | ||
1239 | + move2add_use_add2_insn (reg, sym, off, insn); | ||
1240 | |||
1241 | /* Otherwise, we have to find a register whose value is sum | ||
1242 | of sym and some constant value. */ | ||
1243 | else | ||
1244 | - changed |= move2add_use_add3_insn (reg, sym, off, insn); | ||
1245 | + move2add_use_add3_insn (reg, sym, off, insn); | ||
1246 | |||
1247 | continue; | ||
1248 | } | ||
1249 | @@ -1999,7 +1568,6 @@ | ||
1250 | } | ||
1251 | } | ||
1252 | } | ||
1253 | - return changed; | ||
1254 | } | ||
1255 | |||
1256 | /* SET is a SET or CLOBBER that sets DST. DATA is the insn which | ||
1257 | |||