diff options
author | Koen Kooi <koen@dominion.thruhere.net> | 2010-11-02 22:03:58 +0100 |
---|---|---|
committer | Koen Kooi <koen@dominion.thruhere.net> | 2010-11-02 22:12:02 +0100 |
commit | be10a6b1321f250b1034c7d9d0a8ef18b296eef1 (patch) | |
tree | 9249025cbfbfbee4cc430d62b27f75301dd4dfde /recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99380.patch | |
parent | 93b28937ac67ba46d65f55637e42552e224aa7e2 (diff) | |
download | meta-openembedded-be10a6b1321f250b1034c7d9d0a8ef18b296eef1.tar.gz |
angstrom-layers: meta-openembedded: replace poky gcc 4.5 sources with OE ones
This needs further investigation, but for now we can get the tested sources into the poky gcc harness
Signed-off-by: Koen Kooi <k-kooi@ti.com>
Diffstat (limited to 'recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99380.patch')
-rw-r--r-- | recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99380.patch | 2997 |
1 files changed, 2997 insertions, 0 deletions
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99380.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99380.patch new file mode 100644 index 0000000000..c66c11f82c --- /dev/null +++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99380.patch | |||
@@ -0,0 +1,2997 @@ | |||
1 | 2010-08-31 Chung-Lin Tang <cltang@codesourcery.com> | ||
2 | |||
3 | Backport from mainline: | ||
4 | |||
5 | 2010-04-14 Bernd Schmidt <bernds@codesourcery.com> | ||
6 | |||
7 | PR target/21803 | ||
8 | gcc/ | ||
9 | * ifcvt.c (cond_exec_process_if_block): Look for identical sequences | ||
10 | at the start and end of the then/else blocks, and omit them from the | ||
11 | conversion. | ||
12 | * cfgcleanup.c (flow_find_cross_jump): No longer static. Remove MODE | ||
13 | argument; all callers changed. Pass zero to old_insns_match_p instead. | ||
14 | (flow_find_head_matching_sequence): New function. | ||
15 | (old_insns_match_p): Check REG_EH_REGION notes for calls. | ||
16 | * basic-block.h (flow_find_cross_jump, | ||
17 | flow_find_head_matching_sequence): Declare functions. | ||
18 | |||
19 | gcc/testsuite/ | ||
20 | * gcc.target/arm/pr42496.c: New test. | ||
21 | |||
22 | 2010-04-22 Bernd Schmidt <bernds@codesourcery.com> | ||
23 | |||
24 | PR middle-end/29274 | ||
25 | gcc/ | ||
26 | * tree-pass.h (pass_optimize_widening_mul): Declare. | ||
27 | * tree-ssa-math-opts.c (execute_optimize_widening_mul, | ||
28 | gate_optimize_widening_mul): New static functions. | ||
29 | (pass_optimize_widening_mul): New. | ||
30 | * expr.c (expand_expr_real_2) <case WIDEN_MULT_EXPR>: New case. | ||
31 | <case MULT_EXPR>: Remove support for widening multiplies. | ||
32 | * tree.def (WIDEN_MULT_EXPR): Tweak comment. | ||
33 | * cfgexpand.c (expand_debug_expr) <case WIDEN_MULT_EXPR>: Use | ||
34 | simplify_gen_unary rather than directly building extensions. | ||
35 | * tree-cfg.c (verify_gimple_assign_binary): Add tests for | ||
36 | WIDEN_MULT_EXPR. | ||
37 | * expmed.c (expand_widening_mult): New function. | ||
38 | * passes.c (init_optimization_passes): Add pass_optimize_widening_mul. | ||
39 | * optabs.h (expand_widening_mult): Declare. | ||
40 | |||
41 | gcc/testsuite/ | ||
42 | * gcc.target/i386/wmul-1.c: New test. | ||
43 | * gcc.target/i386/wmul-2.c: New test. | ||
44 | * gcc.target/bfin/wmul-1.c: New test. | ||
45 | * gcc.target/bfin/wmul-2.c: New test. | ||
46 | * gcc.target/arm/wmul-1.c: New test. | ||
47 | * gcc.target/arm/wmul-2.c: New test. | ||
48 | |||
49 | 2010-04-24 Bernd Schmidt <bernds@codesourcery.com> | ||
50 | |||
51 | PR tree-optimization/41442 | ||
52 | gcc/ | ||
53 | * fold-const.c (merge_truthop_with_opposite_arm): New function. | ||
54 | (fold_binary_loc): Call it. | ||
55 | |||
56 | gcc/testsuite/ | ||
57 | * gcc.target/i386/pr41442.c: New test. | ||
58 | |||
59 | 2010-04-29 Bernd Schmidt <bernds@codesourcery.com> | ||
60 | |||
61 | PR target/42895 | ||
62 | gcc/ | ||
63 | * doc/tm.texi (ADJUST_REG_ALLOC_ORDER): Renamed from | ||
64 | ORDER_REGS_FOR_LOCAL_ALLOC. All instances of this macro changed. | ||
65 | (HONOR_REG_ALLOC_ORDER): Describe new macro. | ||
66 | * ira.c (setup_alloc_regs): Use ADJUST_REG_ALLOC_ORDER if defined. | ||
67 | * ira-color.c (assign_hard_reg): Take prologue/epilogue costs into | ||
68 | account only if HONOR_REG_ALLOC_ORDER is not defined. | ||
69 | * config/arm/arm.h (HONOR_REG_ALLOC_ORDER): Define. | ||
70 | * system.h (ORDER_REGS_FOR_LOCAL_ALLOC): Poison. | ||
71 | |||
72 | 2010-05-04 Mikael Pettersson <mikpe@it.uu.se> | ||
73 | |||
74 | PR bootstrap/43964 | ||
75 | gcc/ | ||
76 | * ira-color.c (assign_hard_reg): Declare rclass and add_cost | ||
77 | only if HONOR_REG_ALLOC_ORDER is not defined. | ||
78 | |||
79 | 2010-06-04 Bernd Schmidt <bernds@codesourcery.com> | ||
80 | |||
81 | PR rtl-optimization/39871 | ||
82 | PR rtl-optimization/40615 | ||
83 | PR rtl-optimization/42500 | ||
84 | PR rtl-optimization/42502 | ||
85 | gcc/ | ||
86 | * ira.c (init_reg_equiv_memory_loc: New function. | ||
87 | (ira): Call it twice. | ||
88 | * reload.h (calculate_elim_costs_all_insns): Declare. | ||
89 | * ira-costs.c: Include "reload.h". | ||
90 | (regno_equiv_gains): New static variable. | ||
91 | (init_costs): Allocate it. | ||
92 | (finish_costs): Free it. | ||
93 | (ira_costs): Call calculate_elim_costs_all_insns. | ||
94 | (find_costs_and_classes): Take estimated elimination costs | ||
95 | into account. | ||
96 | (ira_adjust_equiv_reg_cost): New function. | ||
97 | * ira.h (ira_adjust_equiv_reg_cost): Declare it. | ||
98 | * reload1.c (init_eliminable_invariants, free_reg_equiv, | ||
99 | elimination_costs_in_insn, note_reg_elim_costly): New static functions. | ||
100 | (elim_bb): New static variable. | ||
101 | (reload): Move code out of here into init_eliminable_invariants and | ||
102 | free_reg_equiv. Call them. | ||
103 | (calculate_elim_costs_all_insns): New function. | ||
104 | (eliminate_regs_1): Declare. Add extra arg FOR_COSTS; | ||
105 | all callers changed. If FOR_COSTS is true, don't call alter_reg, | ||
106 | but call note_reg_elim_costly if we turned a valid memory address | ||
107 | into an invalid one. | ||
108 | * Makefile.in (ira-costs.o): Depend on reload.h. | ||
109 | |||
110 | gcc/testsuite/ | ||
111 | * gcc.target/arm/eliminate.c: New test. | ||
112 | |||
113 | 2010-06-09 Bernd Schmidt <bernds@codesourcery.com> | ||
114 | |||
115 | gcc/ | ||
116 | * config/arm/arm.c (thumb2_reorg): New function. | ||
117 | (arm_reorg): Call it. | ||
118 | * config/arm/thumb2.md (define_peephole2 for flag clobbering | ||
119 | arithmetic operations): Delete. | ||
120 | |||
121 | 2010-06-12 Bernd Schmidt <bernds@codesourcery.com> | ||
122 | |||
123 | gcc/ | ||
124 | * config/arm/arm.c (thumb2_reorg): Fix errors in previous change. | ||
125 | |||
126 | 2010-06-17 Bernd Schmidt <bernds@codesourcery.com> | ||
127 | |||
128 | PR rtl-optimization/39871 | ||
129 | gcc/ | ||
130 | * reload1.c (init_eliminable_invariants): For flag_pic, disable | ||
131 | equivalences only for constants that aren't LEGITIMATE_PIC_OPERAND_P. | ||
132 | (function_invariant_p): Rule out a plus of frame or arg pointer with | ||
133 | a SYMBOL_REF. | ||
134 | * ira.c (find_reg_equiv_invariant_const): Likewise. | ||
135 | |||
136 | 2010-06-18 Eric Botcazou <ebotcazou@adacore.com> | ||
137 | |||
138 | PR rtl-optimization/40900 | ||
139 | gcc/ | ||
140 | * expr.c (expand_expr_real_1) <SSA_NAME>: Fix long line. Save the | ||
141 | original expression for later reuse. | ||
142 | <expand_decl_rtl>: Use promote_function_mode to compute the signedness | ||
143 | of the promoted RTL for a SSA_NAME on the LHS of a call statement. | ||
144 | |||
145 | 2010-06-18 Bernd Schmidt <bernds@codesourcery.com> | ||
146 | gcc/testsuite/ | ||
147 | * gcc.target/arm/pr40900.c: New test. | ||
148 | |||
149 | 2010-06-30 Bernd Schmidt <bernds@codesourcery.com> | ||
150 | |||
151 | PR tree-optimization/39799 | ||
152 | gcc/ | ||
153 | * tree-inline.c (remap_ssa_name): Initialize variable only if | ||
154 | SSA_NAME_OCCURS_IN_ABNORMAL_PHI. | ||
155 | * tree-ssa.c (warn_uninit): Avoid emitting an unnecessary message. | ||
156 | |||
157 | gcc/testsuite/ | ||
158 | * c-c++-common/uninit-17.c: New test. | ||
159 | |||
160 | 2010-07-25 Eric Botcazou <ebotcazou@adacore.com> | ||
161 | |||
162 | PR target/44484 | ||
163 | gcc/ | ||
164 | * config/sparc/predicates.md (memory_reg_operand): Delete. | ||
165 | * config/sparc/sync.md (sync_compare_and_swap): Minor tweaks. | ||
166 | (*sync_compare_and_swap): Encode the address form in the pattern. | ||
167 | (*sync_compare_and_swapdi_v8plus): Likewise. | ||
168 | |||
169 | 2010-08-29 Chung-Lin Tang <cltang@codesourcery.com> | ||
170 | |||
171 | Backport from mainline: | ||
172 | |||
173 | === modified file 'gcc/Makefile.in' | ||
174 | --- old/gcc/Makefile.in 2010-08-10 13:31:21 +0000 | ||
175 | +++ new/gcc/Makefile.in 2010-09-01 13:29:58 +0000 | ||
176 | @@ -3193,7 +3193,7 @@ | ||
177 | ira-costs.o: ira-costs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ | ||
178 | hard-reg-set.h $(RTL_H) $(EXPR_H) $(TM_P_H) $(FLAGS_H) $(BASIC_BLOCK_H) \ | ||
179 | $(REGS_H) addresses.h insn-config.h $(RECOG_H) $(TOPLEV_H) $(TARGET_H) \ | ||
180 | - $(PARAMS_H) $(IRA_INT_H) | ||
181 | + $(PARAMS_H) $(IRA_INT_H) reload.h | ||
182 | ira-conflicts.o: ira-conflicts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ | ||
183 | $(TARGET_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) \ | ||
184 | insn-config.h $(RECOG_H) $(BASIC_BLOCK_H) $(TOPLEV_H) $(TM_P_H) $(PARAMS_H) \ | ||
185 | |||
186 | === modified file 'gcc/basic-block.h' | ||
187 | --- old/gcc/basic-block.h 2010-08-16 09:41:58 +0000 | ||
188 | +++ new/gcc/basic-block.h 2010-09-01 13:29:58 +0000 | ||
189 | @@ -894,6 +894,10 @@ | ||
190 | |||
191 | /* In cfgcleanup.c. */ | ||
192 | extern bool cleanup_cfg (int); | ||
193 | +extern int flow_find_cross_jump (basic_block, basic_block, rtx *, rtx *); | ||
194 | +extern int flow_find_head_matching_sequence (basic_block, basic_block, | ||
195 | + rtx *, rtx *, int); | ||
196 | + | ||
197 | extern bool delete_unreachable_blocks (void); | ||
198 | |||
199 | extern bool mark_dfs_back_edges (void); | ||
200 | |||
201 | === modified file 'gcc/cfgcleanup.c' | ||
202 | --- old/gcc/cfgcleanup.c 2010-05-17 16:26:22 +0000 | ||
203 | +++ new/gcc/cfgcleanup.c 2010-09-01 13:29:58 +0000 | ||
204 | @@ -68,7 +68,6 @@ | ||
205 | static bool try_crossjump_to_edge (int, edge, edge); | ||
206 | static bool try_crossjump_bb (int, basic_block); | ||
207 | static bool outgoing_edges_match (int, basic_block, basic_block); | ||
208 | -static int flow_find_cross_jump (int, basic_block, basic_block, rtx *, rtx *); | ||
209 | static bool old_insns_match_p (int, rtx, rtx); | ||
210 | |||
211 | static void merge_blocks_move_predecessor_nojumps (basic_block, basic_block); | ||
212 | @@ -972,13 +971,27 @@ | ||
213 | be filled that clobbers a parameter expected by the subroutine. | ||
214 | |||
215 | ??? We take the simple route for now and assume that if they're | ||
216 | - equal, they were constructed identically. */ | ||
217 | - | ||
218 | - if (CALL_P (i1) | ||
219 | - && (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1), | ||
220 | + equal, they were constructed identically. | ||
221 | + | ||
222 | + Also check for identical exception regions. */ | ||
223 | + | ||
224 | + if (CALL_P (i1)) | ||
225 | + { | ||
226 | + /* Ensure the same EH region. */ | ||
227 | + rtx n1 = find_reg_note (i1, REG_EH_REGION, 0); | ||
228 | + rtx n2 = find_reg_note (i2, REG_EH_REGION, 0); | ||
229 | + | ||
230 | + if (!n1 && n2) | ||
231 | + return false; | ||
232 | + | ||
233 | + if (n1 && (!n2 || XEXP (n1, 0) != XEXP (n2, 0))) | ||
234 | + return false; | ||
235 | + | ||
236 | + if (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1), | ||
237 | CALL_INSN_FUNCTION_USAGE (i2)) | ||
238 | - || SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2))) | ||
239 | - return false; | ||
240 | + || SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2)) | ||
241 | + return false; | ||
242 | + } | ||
243 | |||
244 | #ifdef STACK_REGS | ||
245 | /* If cross_jump_death_matters is not 0, the insn's mode | ||
246 | @@ -1017,6 +1030,29 @@ | ||
247 | return false; | ||
248 | } | ||
249 | |||
250 | +/* When comparing insns I1 and I2 in flow_find_cross_jump or | ||
251 | + flow_find_head_matching_sequence, ensure the notes match. */ | ||
252 | + | ||
253 | +static void | ||
254 | +merge_notes (rtx i1, rtx i2) | ||
255 | +{ | ||
256 | + /* If the merged insns have different REG_EQUAL notes, then | ||
257 | + remove them. */ | ||
258 | + rtx equiv1 = find_reg_equal_equiv_note (i1); | ||
259 | + rtx equiv2 = find_reg_equal_equiv_note (i2); | ||
260 | + | ||
261 | + if (equiv1 && !equiv2) | ||
262 | + remove_note (i1, equiv1); | ||
263 | + else if (!equiv1 && equiv2) | ||
264 | + remove_note (i2, equiv2); | ||
265 | + else if (equiv1 && equiv2 | ||
266 | + && !rtx_equal_p (XEXP (equiv1, 0), XEXP (equiv2, 0))) | ||
267 | + { | ||
268 | + remove_note (i1, equiv1); | ||
269 | + remove_note (i2, equiv2); | ||
270 | + } | ||
271 | +} | ||
272 | + | ||
273 | /* Look through the insns at the end of BB1 and BB2 and find the longest | ||
274 | sequence that are equivalent. Store the first insns for that sequence | ||
275 | in *F1 and *F2 and return the sequence length. | ||
276 | @@ -1024,9 +1060,8 @@ | ||
277 | To simplify callers of this function, if the blocks match exactly, | ||
278 | store the head of the blocks in *F1 and *F2. */ | ||
279 | |||
280 | -static int | ||
281 | -flow_find_cross_jump (int mode ATTRIBUTE_UNUSED, basic_block bb1, | ||
282 | - basic_block bb2, rtx *f1, rtx *f2) | ||
283 | +int | ||
284 | +flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx *f1, rtx *f2) | ||
285 | { | ||
286 | rtx i1, i2, last1, last2, afterlast1, afterlast2; | ||
287 | int ninsns = 0; | ||
288 | @@ -1066,7 +1101,7 @@ | ||
289 | if (i1 == BB_HEAD (bb1) || i2 == BB_HEAD (bb2)) | ||
290 | break; | ||
291 | |||
292 | - if (!old_insns_match_p (mode, i1, i2)) | ||
293 | + if (!old_insns_match_p (0, i1, i2)) | ||
294 | break; | ||
295 | |||
296 | merge_memattrs (i1, i2); | ||
297 | @@ -1074,21 +1109,7 @@ | ||
298 | /* Don't begin a cross-jump with a NOTE insn. */ | ||
299 | if (INSN_P (i1)) | ||
300 | { | ||
301 | - /* If the merged insns have different REG_EQUAL notes, then | ||
302 | - remove them. */ | ||
303 | - rtx equiv1 = find_reg_equal_equiv_note (i1); | ||
304 | - rtx equiv2 = find_reg_equal_equiv_note (i2); | ||
305 | - | ||
306 | - if (equiv1 && !equiv2) | ||
307 | - remove_note (i1, equiv1); | ||
308 | - else if (!equiv1 && equiv2) | ||
309 | - remove_note (i2, equiv2); | ||
310 | - else if (equiv1 && equiv2 | ||
311 | - && !rtx_equal_p (XEXP (equiv1, 0), XEXP (equiv2, 0))) | ||
312 | - { | ||
313 | - remove_note (i1, equiv1); | ||
314 | - remove_note (i2, equiv2); | ||
315 | - } | ||
316 | + merge_notes (i1, i2); | ||
317 | |||
318 | afterlast1 = last1, afterlast2 = last2; | ||
319 | last1 = i1, last2 = i2; | ||
320 | @@ -1130,6 +1151,97 @@ | ||
321 | return ninsns; | ||
322 | } | ||
323 | |||
324 | +/* Like flow_find_cross_jump, except start looking for a matching sequence from | ||
325 | + the head of the two blocks. Do not include jumps at the end. | ||
326 | + If STOP_AFTER is nonzero, stop after finding that many matching | ||
327 | + instructions. */ | ||
328 | + | ||
329 | +int | ||
330 | +flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx *f1, | ||
331 | + rtx *f2, int stop_after) | ||
332 | +{ | ||
333 | + rtx i1, i2, last1, last2, beforelast1, beforelast2; | ||
334 | + int ninsns = 0; | ||
335 | + edge e; | ||
336 | + edge_iterator ei; | ||
337 | + int nehedges1 = 0, nehedges2 = 0; | ||
338 | + | ||
339 | + FOR_EACH_EDGE (e, ei, bb1->succs) | ||
340 | + if (e->flags & EDGE_EH) | ||
341 | + nehedges1++; | ||
342 | + FOR_EACH_EDGE (e, ei, bb2->succs) | ||
343 | + if (e->flags & EDGE_EH) | ||
344 | + nehedges2++; | ||
345 | + | ||
346 | + i1 = BB_HEAD (bb1); | ||
347 | + i2 = BB_HEAD (bb2); | ||
348 | + last1 = beforelast1 = last2 = beforelast2 = NULL_RTX; | ||
349 | + | ||
350 | + while (true) | ||
351 | + { | ||
352 | + | ||
353 | + /* Ignore notes. */ | ||
354 | + while (!NONDEBUG_INSN_P (i1) && i1 != BB_END (bb1)) | ||
355 | + i1 = NEXT_INSN (i1); | ||
356 | + | ||
357 | + while (!NONDEBUG_INSN_P (i2) && i2 != BB_END (bb2)) | ||
358 | + i2 = NEXT_INSN (i2); | ||
359 | + | ||
360 | + if (NOTE_P (i1) || NOTE_P (i2) | ||
361 | + || JUMP_P (i1) || JUMP_P (i2)) | ||
362 | + break; | ||
363 | + | ||
364 | + /* A sanity check to make sure we're not merging insns with different | ||
365 | + effects on EH. If only one of them ends a basic block, it shouldn't | ||
366 | + have an EH edge; if both end a basic block, there should be the same | ||
367 | + number of EH edges. */ | ||
368 | + if ((i1 == BB_END (bb1) && i2 != BB_END (bb2) | ||
369 | + && nehedges1 > 0) | ||
370 | + || (i2 == BB_END (bb2) && i1 != BB_END (bb1) | ||
371 | + && nehedges2 > 0) | ||
372 | + || (i1 == BB_END (bb1) && i2 == BB_END (bb2) | ||
373 | + && nehedges1 != nehedges2)) | ||
374 | + break; | ||
375 | + | ||
376 | + if (!old_insns_match_p (0, i1, i2)) | ||
377 | + break; | ||
378 | + | ||
379 | + merge_memattrs (i1, i2); | ||
380 | + | ||
381 | + /* Don't begin a cross-jump with a NOTE insn. */ | ||
382 | + if (INSN_P (i1)) | ||
383 | + { | ||
384 | + merge_notes (i1, i2); | ||
385 | + | ||
386 | + beforelast1 = last1, beforelast2 = last2; | ||
387 | + last1 = i1, last2 = i2; | ||
388 | + ninsns++; | ||
389 | + } | ||
390 | + | ||
391 | + if (i1 == BB_END (bb1) || i2 == BB_END (bb2) | ||
392 | + || (stop_after > 0 && ninsns == stop_after)) | ||
393 | + break; | ||
394 | + | ||
395 | + i1 = NEXT_INSN (i1); | ||
396 | + i2 = NEXT_INSN (i2); | ||
397 | + } | ||
398 | + | ||
399 | +#ifdef HAVE_cc0 | ||
400 | + /* Don't allow a compare to be shared by cross-jumping unless the insn | ||
401 | + after the compare is also shared. */ | ||
402 | + if (ninsns && reg_mentioned_p (cc0_rtx, last1) && sets_cc0_p (last1)) | ||
403 | + last1 = beforelast1, last2 = beforelast2, ninsns--; | ||
404 | +#endif | ||
405 | + | ||
406 | + if (ninsns) | ||
407 | + { | ||
408 | + *f1 = last1; | ||
409 | + *f2 = last2; | ||
410 | + } | ||
411 | + | ||
412 | + return ninsns; | ||
413 | +} | ||
414 | + | ||
415 | /* Return true iff outgoing edges of BB1 and BB2 match, together with | ||
416 | the branch instruction. This means that if we commonize the control | ||
417 | flow before end of the basic block, the semantic remains unchanged. | ||
418 | @@ -1498,7 +1610,7 @@ | ||
419 | return false; | ||
420 | |||
421 | /* ... and part the second. */ | ||
422 | - nmatch = flow_find_cross_jump (mode, src1, src2, &newpos1, &newpos2); | ||
423 | + nmatch = flow_find_cross_jump (src1, src2, &newpos1, &newpos2); | ||
424 | |||
425 | /* Don't proceed with the crossjump unless we found a sufficient number | ||
426 | of matching instructions or the 'from' block was totally matched | ||
427 | |||
428 | === modified file 'gcc/cfgexpand.c' | ||
429 | --- old/gcc/cfgexpand.c 2010-05-14 17:11:03 +0000 | ||
430 | +++ new/gcc/cfgexpand.c 2010-09-01 13:29:58 +0000 | ||
431 | @@ -3026,14 +3026,15 @@ | ||
432 | if (SCALAR_INT_MODE_P (GET_MODE (op0)) | ||
433 | && SCALAR_INT_MODE_P (mode)) | ||
434 | { | ||
435 | + enum machine_mode inner_mode = GET_MODE (op0); | ||
436 | if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))) | ||
437 | - op0 = gen_rtx_ZERO_EXTEND (mode, op0); | ||
438 | + op0 = simplify_gen_unary (ZERO_EXTEND, mode, op0, inner_mode); | ||
439 | else | ||
440 | - op0 = gen_rtx_SIGN_EXTEND (mode, op0); | ||
441 | + op0 = simplify_gen_unary (SIGN_EXTEND, mode, op0, inner_mode); | ||
442 | if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)))) | ||
443 | - op1 = gen_rtx_ZERO_EXTEND (mode, op1); | ||
444 | + op1 = simplify_gen_unary (ZERO_EXTEND, mode, op1, inner_mode); | ||
445 | else | ||
446 | - op1 = gen_rtx_SIGN_EXTEND (mode, op1); | ||
447 | + op1 = simplify_gen_unary (SIGN_EXTEND, mode, op1, inner_mode); | ||
448 | return gen_rtx_MULT (mode, op0, op1); | ||
449 | } | ||
450 | return NULL; | ||
451 | |||
452 | === modified file 'gcc/config/arm/arm.c' | ||
453 | --- old/gcc/config/arm/arm.c 2010-08-31 10:00:27 +0000 | ||
454 | +++ new/gcc/config/arm/arm.c 2010-09-01 13:29:58 +0000 | ||
455 | @@ -8116,8 +8116,6 @@ | ||
456 | static bool | ||
457 | xscale_sched_adjust_cost (rtx insn, rtx link, rtx dep, int * cost) | ||
458 | { | ||
459 | - rtx i_pat, d_pat; | ||
460 | - | ||
461 | /* Some true dependencies can have a higher cost depending | ||
462 | on precisely how certain input operands are used. */ | ||
463 | if (REG_NOTE_KIND (link) == 0 | ||
464 | @@ -12166,6 +12164,60 @@ | ||
465 | return result; | ||
466 | } | ||
467 | |||
468 | +/* Convert instructions to their cc-clobbering variant if possible, since | ||
469 | + that allows us to use smaller encodings. */ | ||
470 | + | ||
471 | +static void | ||
472 | +thumb2_reorg (void) | ||
473 | +{ | ||
474 | + basic_block bb; | ||
475 | + regset_head live; | ||
476 | + | ||
477 | + INIT_REG_SET (&live); | ||
478 | + | ||
479 | + /* We are freeing block_for_insn in the toplev to keep compatibility | ||
480 | + with old MDEP_REORGS that are not CFG based. Recompute it now. */ | ||
481 | + compute_bb_for_insn (); | ||
482 | + df_analyze (); | ||
483 | + | ||
484 | + FOR_EACH_BB (bb) | ||
485 | + { | ||
486 | + rtx insn; | ||
487 | + COPY_REG_SET (&live, DF_LR_OUT (bb)); | ||
488 | + df_simulate_initialize_backwards (bb, &live); | ||
489 | + FOR_BB_INSNS_REVERSE (bb, insn) | ||
490 | + { | ||
491 | + if (NONJUMP_INSN_P (insn) | ||
492 | + && !REGNO_REG_SET_P (&live, CC_REGNUM)) | ||
493 | + { | ||
494 | + rtx pat = PATTERN (insn); | ||
495 | + if (GET_CODE (pat) == SET | ||
496 | + && low_register_operand (XEXP (pat, 0), SImode) | ||
497 | + && thumb_16bit_operator (XEXP (pat, 1), SImode) | ||
498 | + && low_register_operand (XEXP (XEXP (pat, 1), 0), SImode) | ||
499 | + && low_register_operand (XEXP (XEXP (pat, 1), 1), SImode)) | ||
500 | + { | ||
501 | + rtx dst = XEXP (pat, 0); | ||
502 | + rtx src = XEXP (pat, 1); | ||
503 | + rtx op0 = XEXP (src, 0); | ||
504 | + if (rtx_equal_p (dst, op0) | ||
505 | + || GET_CODE (src) == PLUS || GET_CODE (src) == MINUS) | ||
506 | + { | ||
507 | + rtx ccreg = gen_rtx_REG (CCmode, CC_REGNUM); | ||
508 | + rtx clobber = gen_rtx_CLOBBER (VOIDmode, ccreg); | ||
509 | + rtvec vec = gen_rtvec (2, pat, clobber); | ||
510 | + PATTERN (insn) = gen_rtx_PARALLEL (VOIDmode, vec); | ||
511 | + INSN_CODE (insn) = -1; | ||
512 | + } | ||
513 | + } | ||
514 | + } | ||
515 | + if (NONDEBUG_INSN_P (insn)) | ||
516 | + df_simulate_one_insn_backwards (bb, insn, &live); | ||
517 | + } | ||
518 | + } | ||
519 | + CLEAR_REG_SET (&live); | ||
520 | +} | ||
521 | + | ||
522 | /* Gcc puts the pool in the wrong place for ARM, since we can only | ||
523 | load addresses a limited distance around the pc. We do some | ||
524 | special munging to move the constant pool values to the correct | ||
525 | @@ -12177,6 +12229,9 @@ | ||
526 | HOST_WIDE_INT address = 0; | ||
527 | Mfix * fix; | ||
528 | |||
529 | + if (TARGET_THUMB2) | ||
530 | + thumb2_reorg (); | ||
531 | + | ||
532 | minipool_fix_head = minipool_fix_tail = NULL; | ||
533 | |||
534 | /* The first insn must always be a note, or the code below won't | ||
535 | |||
536 | === modified file 'gcc/config/arm/arm.h' | ||
537 | --- old/gcc/config/arm/arm.h 2010-08-13 11:11:15 +0000 | ||
538 | +++ new/gcc/config/arm/arm.h 2010-09-01 13:29:58 +0000 | ||
539 | @@ -1133,7 +1133,11 @@ | ||
540 | } | ||
541 | |||
542 | /* Use different register alloc ordering for Thumb. */ | ||
543 | -#define ORDER_REGS_FOR_LOCAL_ALLOC arm_order_regs_for_local_alloc () | ||
544 | +#define ADJUST_REG_ALLOC_ORDER arm_order_regs_for_local_alloc () | ||
545 | + | ||
546 | +/* Tell IRA to use the order we define rather than messing it up with its | ||
547 | + own cost calculations. */ | ||
548 | +#define HONOR_REG_ALLOC_ORDER | ||
549 | |||
550 | /* Interrupt functions can only use registers that have already been | ||
551 | saved by the prologue, even if they would normally be | ||
552 | |||
553 | === modified file 'gcc/config/arm/arm.md' | ||
554 | --- old/gcc/config/arm/arm.md 2010-08-31 10:00:27 +0000 | ||
555 | +++ new/gcc/config/arm/arm.md 2010-09-01 13:29:58 +0000 | ||
556 | @@ -4074,7 +4074,7 @@ | ||
557 | |||
558 | (define_split | ||
559 | [(set (match_operand:SI 0 "register_operand" "") | ||
560 | - (zero_extend:SI (match_operand:HI 1 "register_operand" "l,m")))] | ||
561 | + (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] | ||
562 | "!TARGET_THUMB2 && !arm_arch6" | ||
563 | [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) | ||
564 | (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))] | ||
565 | |||
566 | === modified file 'gcc/config/arm/thumb2.md' | ||
567 | --- old/gcc/config/arm/thumb2.md 2010-08-31 10:00:27 +0000 | ||
568 | +++ new/gcc/config/arm/thumb2.md 2010-09-01 13:29:58 +0000 | ||
569 | @@ -1046,29 +1046,6 @@ | ||
570 | }" | ||
571 | ) | ||
572 | |||
573 | -;; Peepholes and insns for 16-bit flag clobbering instructions. | ||
574 | -;; The conditional forms of these instructions do not clobber CC. | ||
575 | -;; However by the time peepholes are run it is probably too late to do | ||
576 | -;; anything useful with this information. | ||
577 | -(define_peephole2 | ||
578 | - [(set (match_operand:SI 0 "low_register_operand" "") | ||
579 | - (match_operator:SI 3 "thumb_16bit_operator" | ||
580 | - [(match_operand:SI 1 "low_register_operand" "") | ||
581 | - (match_operand:SI 2 "low_register_operand" "")]))] | ||
582 | - "TARGET_THUMB2 | ||
583 | - && (rtx_equal_p(operands[0], operands[1]) | ||
584 | - || GET_CODE(operands[3]) == PLUS | ||
585 | - || GET_CODE(operands[3]) == MINUS) | ||
586 | - && peep2_regno_dead_p(0, CC_REGNUM)" | ||
587 | - [(parallel | ||
588 | - [(set (match_dup 0) | ||
589 | - (match_op_dup 3 | ||
590 | - [(match_dup 1) | ||
591 | - (match_dup 2)])) | ||
592 | - (clobber (reg:CC CC_REGNUM))])] | ||
593 | - "" | ||
594 | -) | ||
595 | - | ||
596 | (define_insn "*thumb2_alusi3_short" | ||
597 | [(set (match_operand:SI 0 "s_register_operand" "=l") | ||
598 | (match_operator:SI 3 "thumb_16bit_operator" | ||
599 | |||
600 | === modified file 'gcc/config/avr/avr.h' | ||
601 | --- old/gcc/config/avr/avr.h 2010-01-11 23:12:14 +0000 | ||
602 | +++ new/gcc/config/avr/avr.h 2010-09-01 13:29:58 +0000 | ||
603 | @@ -232,7 +232,7 @@ | ||
604 | 32,33,34,35 \ | ||
605 | } | ||
606 | |||
607 | -#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc () | ||
608 | +#define ADJUST_REG_ALLOC_ORDER order_regs_for_local_alloc () | ||
609 | |||
610 | |||
611 | #define HARD_REGNO_NREGS(REGNO, MODE) ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) | ||
612 | |||
613 | === modified file 'gcc/config/i386/i386.h' | ||
614 | --- old/gcc/config/i386/i386.h 2010-04-27 19:14:19 +0000 | ||
615 | +++ new/gcc/config/i386/i386.h 2010-09-01 13:29:58 +0000 | ||
616 | @@ -955,7 +955,7 @@ | ||
617 | registers listed in CALL_USED_REGISTERS, keeping the others | ||
618 | available for storage of persistent values. | ||
619 | |||
620 | - The ORDER_REGS_FOR_LOCAL_ALLOC actually overwrite the order, | ||
621 | + The ADJUST_REG_ALLOC_ORDER actually overwrite the order, | ||
622 | so this is just empty initializer for array. */ | ||
623 | |||
624 | #define REG_ALLOC_ORDER \ | ||
625 | @@ -964,11 +964,11 @@ | ||
626 | 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \ | ||
627 | 48, 49, 50, 51, 52 } | ||
628 | |||
629 | -/* ORDER_REGS_FOR_LOCAL_ALLOC is a macro which permits reg_alloc_order | ||
630 | +/* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order | ||
631 | to be rearranged based on a particular function. When using sse math, | ||
632 | we want to allocate SSE before x87 registers and vice versa. */ | ||
633 | |||
634 | -#define ORDER_REGS_FOR_LOCAL_ALLOC x86_order_regs_for_local_alloc () | ||
635 | +#define ADJUST_REG_ALLOC_ORDER x86_order_regs_for_local_alloc () | ||
636 | |||
637 | |||
638 | #define OVERRIDE_ABI_FORMAT(FNDECL) ix86_call_abi_override (FNDECL) | ||
639 | |||
640 | === modified file 'gcc/config/mips/mips.h' | ||
641 | --- old/gcc/config/mips/mips.h 2009-10-29 17:39:52 +0000 | ||
642 | +++ new/gcc/config/mips/mips.h 2010-09-01 13:29:58 +0000 | ||
643 | @@ -2059,12 +2059,12 @@ | ||
644 | 182,183,184,185,186,187 \ | ||
645 | } | ||
646 | |||
647 | -/* ORDER_REGS_FOR_LOCAL_ALLOC is a macro which permits reg_alloc_order | ||
648 | +/* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order | ||
649 | to be rearranged based on a particular function. On the mips16, we | ||
650 | want to allocate $24 (T_REG) before other registers for | ||
651 | instructions for which it is possible. */ | ||
652 | |||
653 | -#define ORDER_REGS_FOR_LOCAL_ALLOC mips_order_regs_for_local_alloc () | ||
654 | +#define ADJUST_REG_ALLOC_ORDER mips_order_regs_for_local_alloc () | ||
655 | |||
656 | /* True if VALUE is an unsigned 6-bit number. */ | ||
657 | |||
658 | |||
659 | === modified file 'gcc/config/picochip/picochip.h' | ||
660 | --- old/gcc/config/picochip/picochip.h 2009-11-04 11:06:36 +0000 | ||
661 | +++ new/gcc/config/picochip/picochip.h 2010-09-01 13:29:58 +0000 | ||
662 | @@ -261,7 +261,7 @@ | ||
663 | /* We can dynamically change the REG_ALLOC_ORDER using the following hook. | ||
664 | It would be desirable to change it for leaf functions so we can put | ||
665 | r12 at the end of this list.*/ | ||
666 | -#define ORDER_REGS_FOR_LOCAL_ALLOC picochip_order_regs_for_local_alloc () | ||
667 | +#define ADJUST_REG_ALLOC_ORDER picochip_order_regs_for_local_alloc () | ||
668 | |||
669 | /* How Values Fit in Registers */ | ||
670 | |||
671 | |||
672 | === modified file 'gcc/config/sparc/predicates.md' | ||
673 | --- old/gcc/config/sparc/predicates.md 2009-02-20 15:20:38 +0000 | ||
674 | +++ new/gcc/config/sparc/predicates.md 2010-09-01 13:29:58 +0000 | ||
675 | @@ -1,5 +1,5 @@ | ||
676 | ;; Predicate definitions for SPARC. | ||
677 | -;; Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. | ||
678 | +;; Copyright (C) 2005, 2007, 2008, 2010 Free Software Foundation, Inc. | ||
679 | ;; | ||
680 | ;; This file is part of GCC. | ||
681 | ;; | ||
682 | @@ -473,9 +473,3 @@ | ||
683 | ;; and (xor ... (not ...)) to (not (xor ...)). */ | ||
684 | (define_predicate "cc_arith_not_operator" | ||
685 | (match_code "and,ior")) | ||
686 | - | ||
687 | -;; Return true if OP is memory operand with just [%reg] addressing mode. | ||
688 | -(define_predicate "memory_reg_operand" | ||
689 | - (and (match_code "mem") | ||
690 | - (and (match_operand 0 "memory_operand") | ||
691 | - (match_test "REG_P (XEXP (op, 0))")))) | ||
692 | |||
693 | === modified file 'gcc/config/sparc/sparc.h' | ||
694 | --- old/gcc/config/sparc/sparc.h 2010-04-02 18:54:46 +0000 | ||
695 | +++ new/gcc/config/sparc/sparc.h 2010-09-01 13:29:58 +0000 | ||
696 | @@ -1181,7 +1181,7 @@ | ||
697 | 96, 97, 98, 99, /* %fcc0-3 */ \ | ||
698 | 100, 0, 14, 30, 31, 101} /* %icc, %g0, %o6, %i6, %i7, %sfp */ | ||
699 | |||
700 | -#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc () | ||
701 | +#define ADJUST_REG_ALLOC_ORDER order_regs_for_local_alloc () | ||
702 | |||
703 | extern char sparc_leaf_regs[]; | ||
704 | #define LEAF_REGISTERS sparc_leaf_regs | ||
705 | |||
706 | === modified file 'gcc/config/sparc/sync.md' | ||
707 | --- old/gcc/config/sparc/sync.md 2009-02-20 15:20:38 +0000 | ||
708 | +++ new/gcc/config/sparc/sync.md 2010-09-01 13:29:58 +0000 | ||
709 | @@ -1,5 +1,5 @@ | ||
710 | ;; GCC machine description for SPARC synchronization instructions. | ||
711 | -;; Copyright (C) 2005, 2007, 2009 | ||
712 | +;; Copyright (C) 2005, 2007, 2009, 2010 | ||
713 | ;; Free Software Foundation, Inc. | ||
714 | ;; | ||
715 | ;; This file is part of GCC. | ||
716 | @@ -62,7 +62,7 @@ | ||
717 | |||
718 | (define_expand "sync_compare_and_swap<mode>" | ||
719 | [(parallel | ||
720 | - [(set (match_operand:I48MODE 0 "register_operand" "=r") | ||
721 | + [(set (match_operand:I48MODE 0 "register_operand" "") | ||
722 | (match_operand:I48MODE 1 "memory_operand" "")) | ||
723 | (set (match_dup 1) | ||
724 | (unspec_volatile:I48MODE | ||
725 | @@ -71,7 +71,7 @@ | ||
726 | UNSPECV_CAS))])] | ||
727 | "TARGET_V9" | ||
728 | { | ||
729 | - if (! REG_P (XEXP (operands[1], 0))) | ||
730 | + if (!REG_P (XEXP (operands[1], 0))) | ||
731 | { | ||
732 | rtx addr = force_reg (Pmode, XEXP (operands[1], 0)); | ||
733 | operands[1] = replace_equiv_address (operands[1], addr); | ||
734 | @@ -81,20 +81,20 @@ | ||
735 | |||
736 | (define_insn "*sync_compare_and_swap<mode>" | ||
737 | [(set (match_operand:I48MODE 0 "register_operand" "=r") | ||
738 | - (match_operand:I48MODE 1 "memory_reg_operand" "+m")) | ||
739 | - (set (match_dup 1) | ||
740 | + (mem:I48MODE (match_operand 1 "register_operand" "r"))) | ||
741 | + (set (mem:I48MODE (match_dup 1)) | ||
742 | (unspec_volatile:I48MODE | ||
743 | [(match_operand:I48MODE 2 "register_operand" "r") | ||
744 | (match_operand:I48MODE 3 "register_operand" "0")] | ||
745 | UNSPECV_CAS))] | ||
746 | "TARGET_V9 && (<MODE>mode == SImode || TARGET_ARCH64)" | ||
747 | - "cas<modesuffix>\t%1, %2, %0" | ||
748 | + "cas<modesuffix>\t[%1], %2, %0" | ||
749 | [(set_attr "type" "multi")]) | ||
750 | |||
751 | (define_insn "*sync_compare_and_swapdi_v8plus" | ||
752 | [(set (match_operand:DI 0 "register_operand" "=h") | ||
753 | - (match_operand:DI 1 "memory_reg_operand" "+m")) | ||
754 | - (set (match_dup 1) | ||
755 | + (mem:DI (match_operand 1 "register_operand" "r"))) | ||
756 | + (set (mem:DI (match_dup 1)) | ||
757 | (unspec_volatile:DI | ||
758 | [(match_operand:DI 2 "register_operand" "h") | ||
759 | (match_operand:DI 3 "register_operand" "0")] | ||
760 | @@ -109,7 +109,7 @@ | ||
761 | output_asm_insn ("srl\t%L2, 0, %L2", operands); | ||
762 | output_asm_insn ("sllx\t%H2, 32, %H3", operands); | ||
763 | output_asm_insn ("or\t%L2, %H3, %H3", operands); | ||
764 | - output_asm_insn ("casx\t%1, %H3, %L3", operands); | ||
765 | + output_asm_insn ("casx\t[%1], %H3, %L3", operands); | ||
766 | return "srlx\t%L3, 32, %H3"; | ||
767 | } | ||
768 | [(set_attr "type" "multi") | ||
769 | |||
770 | === modified file 'gcc/config/xtensa/xtensa.h' | ||
771 | --- old/gcc/config/xtensa/xtensa.h 2009-09-23 21:24:42 +0000 | ||
772 | +++ new/gcc/config/xtensa/xtensa.h 2010-09-01 13:29:58 +0000 | ||
773 | @@ -286,7 +286,7 @@ | ||
774 | incoming argument in a2 is live throughout the function and | ||
775 | local-alloc decides to use a2, then the incoming argument must | ||
776 | either be spilled or copied to another register. To get around | ||
777 | - this, we define ORDER_REGS_FOR_LOCAL_ALLOC to redefine | ||
778 | + this, we define ADJUST_REG_ALLOC_ORDER to redefine | ||
779 | reg_alloc_order for leaf functions such that lowest numbered | ||
780 | registers are used first with the exception that the incoming | ||
781 | argument registers are not used until after other register choices | ||
782 | @@ -300,7 +300,7 @@ | ||
783 | 35, \ | ||
784 | } | ||
785 | |||
786 | -#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc () | ||
787 | +#define ADJUST_REG_ALLOC_ORDER order_regs_for_local_alloc () | ||
788 | |||
789 | /* For Xtensa, the only point of this is to prevent GCC from otherwise | ||
790 | giving preference to call-used registers. To minimize window | ||
791 | |||
792 | === modified file 'gcc/doc/tm.texi' | ||
793 | --- old/gcc/doc/tm.texi 2010-08-13 11:53:46 +0000 | ||
794 | +++ new/gcc/doc/tm.texi 2010-09-01 13:29:58 +0000 | ||
795 | @@ -2093,7 +2093,7 @@ | ||
796 | the highest numbered allocable register first. | ||
797 | @end defmac | ||
798 | |||
799 | -@defmac ORDER_REGS_FOR_LOCAL_ALLOC | ||
800 | +@defmac ADJUST_REG_ALLOC_ORDER | ||
801 | A C statement (sans semicolon) to choose the order in which to allocate | ||
802 | hard registers for pseudo-registers local to a basic block. | ||
803 | |||
804 | @@ -2107,6 +2107,15 @@ | ||
805 | On most machines, it is not necessary to define this macro. | ||
806 | @end defmac | ||
807 | |||
808 | +@defmac HONOR_REG_ALLOC_ORDER | ||
809 | +Normally, IRA tries to estimate the costs for saving a register in the | ||
810 | +prologue and restoring it in the epilogue. This discourages it from | ||
811 | +using call-saved registers. If a machine wants to ensure that IRA | ||
812 | +allocates registers in the order given by REG_ALLOC_ORDER even if some | ||
813 | +call-saved registers appear earlier than call-used ones, this macro | ||
814 | +should be defined. | ||
815 | +@end defmac | ||
816 | + | ||
817 | @defmac IRA_HARD_REGNO_ADD_COST_MULTIPLIER (@var{regno}) | ||
818 | In some case register allocation order is not enough for the | ||
819 | Integrated Register Allocator (@acronym{IRA}) to generate a good code. | ||
820 | |||
821 | === modified file 'gcc/expmed.c' | ||
822 | --- old/gcc/expmed.c 2010-03-03 22:10:17 +0000 | ||
823 | +++ new/gcc/expmed.c 2010-09-01 13:29:58 +0000 | ||
824 | @@ -3253,6 +3253,55 @@ | ||
825 | gcc_assert (op0); | ||
826 | return op0; | ||
827 | } | ||
828 | + | ||
829 | +/* Perform a widening multiplication and return an rtx for the result. | ||
830 | + MODE is mode of value; OP0 and OP1 are what to multiply (rtx's); | ||
831 | + TARGET is a suggestion for where to store the result (an rtx). | ||
832 | + THIS_OPTAB is the optab we should use, it must be either umul_widen_optab | ||
833 | + or smul_widen_optab. | ||
834 | + | ||
835 | + We check specially for a constant integer as OP1, comparing the | ||
836 | + cost of a widening multiply against the cost of a sequence of shifts | ||
837 | + and adds. */ | ||
838 | + | ||
839 | +rtx | ||
840 | +expand_widening_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, | ||
841 | + int unsignedp, optab this_optab) | ||
842 | +{ | ||
843 | + bool speed = optimize_insn_for_speed_p (); | ||
844 | + | ||
845 | + if (CONST_INT_P (op1) | ||
846 | + && (INTVAL (op1) >= 0 | ||
847 | + || GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)) | ||
848 | + { | ||
849 | + HOST_WIDE_INT coeff = INTVAL (op1); | ||
850 | + int max_cost; | ||
851 | + enum mult_variant variant; | ||
852 | + struct algorithm algorithm; | ||
853 | + | ||
854 | + /* Special case powers of two. */ | ||
855 | + if (EXACT_POWER_OF_2_OR_ZERO_P (coeff)) | ||
856 | + { | ||
857 | + op0 = convert_to_mode (mode, op0, this_optab == umul_widen_optab); | ||
858 | + return expand_shift (LSHIFT_EXPR, mode, op0, | ||
859 | + build_int_cst (NULL_TREE, floor_log2 (coeff)), | ||
860 | + target, unsignedp); | ||
861 | + } | ||
862 | + | ||
863 | + /* Exclude cost of op0 from max_cost to match the cost | ||
864 | + calculation of the synth_mult. */ | ||
865 | + max_cost = mul_widen_cost[speed][mode]; | ||
866 | + if (choose_mult_variant (mode, coeff, &algorithm, &variant, | ||
867 | + max_cost)) | ||
868 | + { | ||
869 | + op0 = convert_to_mode (mode, op0, this_optab == umul_widen_optab); | ||
870 | + return expand_mult_const (mode, op0, coeff, target, | ||
871 | + &algorithm, variant); | ||
872 | + } | ||
873 | + } | ||
874 | + return expand_binop (mode, this_optab, op0, op1, target, | ||
875 | + unsignedp, OPTAB_LIB_WIDEN); | ||
876 | +} | ||
877 | |||
878 | /* Return the smallest n such that 2**n >= X. */ | ||
879 | |||
880 | |||
881 | === modified file 'gcc/expr.c' | ||
882 | --- old/gcc/expr.c 2010-08-20 16:21:01 +0000 | ||
883 | +++ new/gcc/expr.c 2010-09-01 13:29:58 +0000 | ||
884 | @@ -7224,7 +7224,6 @@ | ||
885 | optab this_optab; | ||
886 | rtx subtarget, original_target; | ||
887 | int ignore; | ||
888 | - tree subexp0, subexp1; | ||
889 | bool reduce_bit_field; | ||
890 | gimple subexp0_def, subexp1_def; | ||
891 | tree top0, top1; | ||
892 | @@ -7679,13 +7678,7 @@ | ||
893 | |||
894 | goto binop2; | ||
895 | |||
896 | - case MULT_EXPR: | ||
897 | - /* If this is a fixed-point operation, then we cannot use the code | ||
898 | - below because "expand_mult" doesn't support sat/no-sat fixed-point | ||
899 | - multiplications. */ | ||
900 | - if (ALL_FIXED_POINT_MODE_P (mode)) | ||
901 | - goto binop; | ||
902 | - | ||
903 | + case WIDEN_MULT_EXPR: | ||
904 | /* If first operand is constant, swap them. | ||
905 | Thus the following special case checks need only | ||
906 | check the second operand. */ | ||
907 | @@ -7696,96 +7689,35 @@ | ||
908 | treeop1 = t1; | ||
909 | } | ||
910 | |||
911 | - /* Attempt to return something suitable for generating an | ||
912 | - indexed address, for machines that support that. */ | ||
913 | - | ||
914 | - if (modifier == EXPAND_SUM && mode == ptr_mode | ||
915 | - && host_integerp (treeop1, 0)) | ||
916 | - { | ||
917 | - tree exp1 = treeop1; | ||
918 | - | ||
919 | - op0 = expand_expr (treeop0, subtarget, VOIDmode, | ||
920 | - EXPAND_SUM); | ||
921 | - | ||
922 | - if (!REG_P (op0)) | ||
923 | - op0 = force_operand (op0, NULL_RTX); | ||
924 | - if (!REG_P (op0)) | ||
925 | - op0 = copy_to_mode_reg (mode, op0); | ||
926 | - | ||
927 | - return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0, | ||
928 | - gen_int_mode (tree_low_cst (exp1, 0), | ||
929 | - TYPE_MODE (TREE_TYPE (exp1))))); | ||
930 | - } | ||
931 | - | ||
932 | - if (modifier == EXPAND_STACK_PARM) | ||
933 | - target = 0; | ||
934 | - | ||
935 | - /* Check for multiplying things that have been extended | ||
936 | - from a narrower type. If this machine supports multiplying | ||
937 | - in that narrower type with a result in the desired type, | ||
938 | - do it that way, and avoid the explicit type-conversion. */ | ||
939 | - | ||
940 | - subexp0 = treeop0; | ||
941 | - subexp1 = treeop1; | ||
942 | - subexp0_def = get_def_for_expr (subexp0, NOP_EXPR); | ||
943 | - subexp1_def = get_def_for_expr (subexp1, NOP_EXPR); | ||
944 | - top0 = top1 = NULL_TREE; | ||
945 | - | ||
946 | /* First, check if we have a multiplication of one signed and one | ||
947 | unsigned operand. */ | ||
948 | - if (subexp0_def | ||
949 | - && (top0 = gimple_assign_rhs1 (subexp0_def)) | ||
950 | - && subexp1_def | ||
951 | - && (top1 = gimple_assign_rhs1 (subexp1_def)) | ||
952 | - && TREE_CODE (type) == INTEGER_TYPE | ||
953 | - && (TYPE_PRECISION (TREE_TYPE (top0)) | ||
954 | - < TYPE_PRECISION (TREE_TYPE (subexp0))) | ||
955 | - && (TYPE_PRECISION (TREE_TYPE (top0)) | ||
956 | - == TYPE_PRECISION (TREE_TYPE (top1))) | ||
957 | - && (TYPE_UNSIGNED (TREE_TYPE (top0)) | ||
958 | - != TYPE_UNSIGNED (TREE_TYPE (top1)))) | ||
959 | + if (TREE_CODE (treeop1) != INTEGER_CST | ||
960 | + && (TYPE_UNSIGNED (TREE_TYPE (treeop0)) | ||
961 | + != TYPE_UNSIGNED (TREE_TYPE (treeop1)))) | ||
962 | { | ||
963 | - enum machine_mode innermode | ||
964 | - = TYPE_MODE (TREE_TYPE (top0)); | ||
965 | + enum machine_mode innermode = TYPE_MODE (TREE_TYPE (treeop0)); | ||
966 | this_optab = usmul_widen_optab; | ||
967 | - if (mode == GET_MODE_WIDER_MODE (innermode)) | ||
968 | + if (mode == GET_MODE_2XWIDER_MODE (innermode)) | ||
969 | { | ||
970 | if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing) | ||
971 | { | ||
972 | - if (TYPE_UNSIGNED (TREE_TYPE (top0))) | ||
973 | - expand_operands (top0, top1, NULL_RTX, &op0, &op1, | ||
974 | + if (TYPE_UNSIGNED (TREE_TYPE (treeop0))) | ||
975 | + expand_operands (treeop0, treeop1, subtarget, &op0, &op1, | ||
976 | EXPAND_NORMAL); | ||
977 | else | ||
978 | - expand_operands (top0, top1, NULL_RTX, &op1, &op0, | ||
979 | + expand_operands (treeop0, treeop1, subtarget, &op1, &op0, | ||
980 | EXPAND_NORMAL); | ||
981 | - | ||
982 | goto binop3; | ||
983 | } | ||
984 | } | ||
985 | } | ||
986 | - /* Check for a multiplication with matching signedness. If | ||
987 | - valid, TOP0 and TOP1 were set in the previous if | ||
988 | - condition. */ | ||
989 | - else if (top0 | ||
990 | - && TREE_CODE (type) == INTEGER_TYPE | ||
991 | - && (TYPE_PRECISION (TREE_TYPE (top0)) | ||
992 | - < TYPE_PRECISION (TREE_TYPE (subexp0))) | ||
993 | - && ((TREE_CODE (subexp1) == INTEGER_CST | ||
994 | - && int_fits_type_p (subexp1, TREE_TYPE (top0)) | ||
995 | - /* Don't use a widening multiply if a shift will do. */ | ||
996 | - && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (subexp1))) | ||
997 | - > HOST_BITS_PER_WIDE_INT) | ||
998 | - || exact_log2 (TREE_INT_CST_LOW (subexp1)) < 0)) | ||
999 | - || | ||
1000 | - (top1 | ||
1001 | - && (TYPE_PRECISION (TREE_TYPE (top1)) | ||
1002 | - == TYPE_PRECISION (TREE_TYPE (top0)) | ||
1003 | - /* If both operands are extended, they must either both | ||
1004 | - be zero-extended or both be sign-extended. */ | ||
1005 | - && (TYPE_UNSIGNED (TREE_TYPE (top1)) | ||
1006 | - == TYPE_UNSIGNED (TREE_TYPE (top0))))))) | ||
1007 | + /* Check for a multiplication with matching signedness. */ | ||
1008 | + else if ((TREE_CODE (treeop1) == INTEGER_CST | ||
1009 | + && int_fits_type_p (treeop1, TREE_TYPE (treeop0))) | ||
1010 | + || (TYPE_UNSIGNED (TREE_TYPE (treeop1)) | ||
1011 | + == TYPE_UNSIGNED (TREE_TYPE (treeop0)))) | ||
1012 | { | ||
1013 | - tree op0type = TREE_TYPE (top0); | ||
1014 | + tree op0type = TREE_TYPE (treeop0); | ||
1015 | enum machine_mode innermode = TYPE_MODE (op0type); | ||
1016 | bool zextend_p = TYPE_UNSIGNED (op0type); | ||
1017 | optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab; | ||
1018 | @@ -7795,24 +7727,22 @@ | ||
1019 | { | ||
1020 | if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing) | ||
1021 | { | ||
1022 | - if (TREE_CODE (subexp1) == INTEGER_CST) | ||
1023 | - expand_operands (top0, subexp1, NULL_RTX, &op0, &op1, | ||
1024 | - EXPAND_NORMAL); | ||
1025 | - else | ||
1026 | - expand_operands (top0, top1, NULL_RTX, &op0, &op1, | ||
1027 | - EXPAND_NORMAL); | ||
1028 | - goto binop3; | ||
1029 | + expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, | ||
1030 | + EXPAND_NORMAL); | ||
1031 | + temp = expand_widening_mult (mode, op0, op1, target, | ||
1032 | + unsignedp, this_optab); | ||
1033 | + return REDUCE_BIT_FIELD (temp); | ||
1034 | } | ||
1035 | - else if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing | ||
1036 | - && innermode == word_mode) | ||
1037 | + if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing | ||
1038 | + && innermode == word_mode) | ||
1039 | { | ||
1040 | rtx htem, hipart; | ||
1041 | - op0 = expand_normal (top0); | ||
1042 | - if (TREE_CODE (subexp1) == INTEGER_CST) | ||
1043 | + op0 = expand_normal (treeop0); | ||
1044 | + if (TREE_CODE (treeop1) == INTEGER_CST) | ||
1045 | op1 = convert_modes (innermode, mode, | ||
1046 | - expand_normal (subexp1), unsignedp); | ||
1047 | + expand_normal (treeop1), unsignedp); | ||
1048 | else | ||
1049 | - op1 = expand_normal (top1); | ||
1050 | + op1 = expand_normal (treeop1); | ||
1051 | temp = expand_binop (mode, other_optab, op0, op1, target, | ||
1052 | unsignedp, OPTAB_LIB_WIDEN); | ||
1053 | hipart = gen_highpart (innermode, temp); | ||
1054 | @@ -7825,7 +7755,53 @@ | ||
1055 | } | ||
1056 | } | ||
1057 | } | ||
1058 | - expand_operands (subexp0, subexp1, subtarget, &op0, &op1, EXPAND_NORMAL); | ||
1059 | + treeop0 = fold_build1 (CONVERT_EXPR, type, treeop0); | ||
1060 | + treeop1 = fold_build1 (CONVERT_EXPR, type, treeop1); | ||
1061 | + expand_operands (treeop0, treeop1, subtarget, &op0, &op1, EXPAND_NORMAL); | ||
1062 | + return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp)); | ||
1063 | + | ||
1064 | + case MULT_EXPR: | ||
1065 | + /* If this is a fixed-point operation, then we cannot use the code | ||
1066 | + below because "expand_mult" doesn't support sat/no-sat fixed-point | ||
1067 | + multiplications. */ | ||
1068 | + if (ALL_FIXED_POINT_MODE_P (mode)) | ||
1069 | + goto binop; | ||
1070 | + | ||
1071 | + /* If first operand is constant, swap them. | ||
1072 | + Thus the following special case checks need only | ||
1073 | + check the second operand. */ | ||
1074 | + if (TREE_CODE (treeop0) == INTEGER_CST) | ||
1075 | + { | ||
1076 | + tree t1 = treeop0; | ||
1077 | + treeop0 = treeop1; | ||
1078 | + treeop1 = t1; | ||
1079 | + } | ||
1080 | + | ||
1081 | + /* Attempt to return something suitable for generating an | ||
1082 | + indexed address, for machines that support that. */ | ||
1083 | + | ||
1084 | + if (modifier == EXPAND_SUM && mode == ptr_mode | ||
1085 | + && host_integerp (treeop1, 0)) | ||
1086 | + { | ||
1087 | + tree exp1 = treeop1; | ||
1088 | + | ||
1089 | + op0 = expand_expr (treeop0, subtarget, VOIDmode, | ||
1090 | + EXPAND_SUM); | ||
1091 | + | ||
1092 | + if (!REG_P (op0)) | ||
1093 | + op0 = force_operand (op0, NULL_RTX); | ||
1094 | + if (!REG_P (op0)) | ||
1095 | + op0 = copy_to_mode_reg (mode, op0); | ||
1096 | + | ||
1097 | + return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0, | ||
1098 | + gen_int_mode (tree_low_cst (exp1, 0), | ||
1099 | + TYPE_MODE (TREE_TYPE (exp1))))); | ||
1100 | + } | ||
1101 | + | ||
1102 | + if (modifier == EXPAND_STACK_PARM) | ||
1103 | + target = 0; | ||
1104 | + | ||
1105 | + expand_operands (treeop0, treeop1, subtarget, &op0, &op1, EXPAND_NORMAL); | ||
1106 | return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp)); | ||
1107 | |||
1108 | case TRUNC_DIV_EXPR: | ||
1109 | @@ -8311,6 +8287,8 @@ | ||
1110 | location_t loc = EXPR_LOCATION (exp); | ||
1111 | struct separate_ops ops; | ||
1112 | tree treeop0, treeop1, treeop2; | ||
1113 | + tree ssa_name = NULL_TREE; | ||
1114 | + gimple g; | ||
1115 | |||
1116 | type = TREE_TYPE (exp); | ||
1117 | mode = TYPE_MODE (type); | ||
1118 | @@ -8423,15 +8401,17 @@ | ||
1119 | base variable. This unnecessarily allocates a pseudo, see how we can | ||
1120 | reuse it, if partition base vars have it set already. */ | ||
1121 | if (!currently_expanding_to_rtl) | ||
1122 | - return expand_expr_real_1 (SSA_NAME_VAR (exp), target, tmode, modifier, NULL); | ||
1123 | - { | ||
1124 | - gimple g = get_gimple_for_ssa_name (exp); | ||
1125 | - if (g) | ||
1126 | - return expand_expr_real (gimple_assign_rhs_to_tree (g), target, | ||
1127 | - tmode, modifier, NULL); | ||
1128 | - } | ||
1129 | - decl_rtl = get_rtx_for_ssa_name (exp); | ||
1130 | - exp = SSA_NAME_VAR (exp); | ||
1131 | + return expand_expr_real_1 (SSA_NAME_VAR (exp), target, tmode, modifier, | ||
1132 | + NULL); | ||
1133 | + | ||
1134 | + g = get_gimple_for_ssa_name (exp); | ||
1135 | + if (g) | ||
1136 | + return expand_expr_real (gimple_assign_rhs_to_tree (g), target, tmode, | ||
1137 | + modifier, NULL); | ||
1138 | + | ||
1139 | + ssa_name = exp; | ||
1140 | + decl_rtl = get_rtx_for_ssa_name (ssa_name); | ||
1141 | + exp = SSA_NAME_VAR (ssa_name); | ||
1142 | goto expand_decl_rtl; | ||
1143 | |||
1144 | case PARM_DECL: | ||
1145 | @@ -8533,15 +8513,21 @@ | ||
1146 | /* If the mode of DECL_RTL does not match that of the decl, it | ||
1147 | must be a promoted value. We return a SUBREG of the wanted mode, | ||
1148 | but mark it so that we know that it was already extended. */ | ||
1149 | - | ||
1150 | - if (REG_P (decl_rtl) | ||
1151 | - && GET_MODE (decl_rtl) != DECL_MODE (exp)) | ||
1152 | + if (REG_P (decl_rtl) && GET_MODE (decl_rtl) != DECL_MODE (exp)) | ||
1153 | { | ||
1154 | enum machine_mode pmode; | ||
1155 | |||
1156 | - /* Get the signedness used for this variable. Ensure we get the | ||
1157 | - same mode we got when the variable was declared. */ | ||
1158 | - pmode = promote_decl_mode (exp, &unsignedp); | ||
1159 | + /* Get the signedness to be used for this variable. Ensure we get | ||
1160 | + the same mode we got when the variable was declared. */ | ||
1161 | + if (code == SSA_NAME | ||
1162 | + && (g = SSA_NAME_DEF_STMT (ssa_name)) | ||
1163 | + && gimple_code (g) == GIMPLE_CALL) | ||
1164 | + pmode = promote_function_mode (type, mode, &unsignedp, | ||
1165 | + TREE_TYPE | ||
1166 | + (TREE_TYPE (gimple_call_fn (g))), | ||
1167 | + 2); | ||
1168 | + else | ||
1169 | + pmode = promote_decl_mode (exp, &unsignedp); | ||
1170 | gcc_assert (GET_MODE (decl_rtl) == pmode); | ||
1171 | |||
1172 | temp = gen_lowpart_SUBREG (mode, decl_rtl); | ||
1173 | |||
1174 | === modified file 'gcc/fold-const.c' | ||
1175 | --- old/gcc/fold-const.c 2010-04-06 09:36:57 +0000 | ||
1176 | +++ new/gcc/fold-const.c 2010-09-01 13:29:58 +0000 | ||
1177 | @@ -5741,6 +5741,76 @@ | ||
1178 | const_binop (BIT_XOR_EXPR, c, temp, 0)); | ||
1179 | } | ||
1180 | |||
1181 | +/* For an expression that has the form | ||
1182 | + (A && B) || ~B | ||
1183 | + or | ||
1184 | + (A || B) && ~B, | ||
1185 | + we can drop one of the inner expressions and simplify to | ||
1186 | + A || ~B | ||
1187 | + or | ||
1188 | + A && ~B | ||
1189 | + LOC is the location of the resulting expression. OP is the inner | ||
1190 | + logical operation; the left-hand side in the examples above, while CMPOP | ||
1191 | + is the right-hand side. RHS_ONLY is used to prevent us from accidentally | ||
1192 | + removing a condition that guards another, as in | ||
1193 | + (A != NULL && A->...) || A == NULL | ||
1194 | + which we must not transform. If RHS_ONLY is true, only eliminate the | ||
1195 | + right-most operand of the inner logical operation. */ | ||
1196 | + | ||
1197 | +static tree | ||
1198 | +merge_truthop_with_opposite_arm (location_t loc, tree op, tree cmpop, | ||
1199 | + bool rhs_only) | ||
1200 | +{ | ||
1201 | + tree type = TREE_TYPE (cmpop); | ||
1202 | + enum tree_code code = TREE_CODE (cmpop); | ||
1203 | + enum tree_code truthop_code = TREE_CODE (op); | ||
1204 | + tree lhs = TREE_OPERAND (op, 0); | ||
1205 | + tree rhs = TREE_OPERAND (op, 1); | ||
1206 | + tree orig_lhs = lhs, orig_rhs = rhs; | ||
1207 | + enum tree_code rhs_code = TREE_CODE (rhs); | ||
1208 | + enum tree_code lhs_code = TREE_CODE (lhs); | ||
1209 | + enum tree_code inv_code; | ||
1210 | + | ||
1211 | + if (TREE_SIDE_EFFECTS (op) || TREE_SIDE_EFFECTS (cmpop)) | ||
1212 | + return NULL_TREE; | ||
1213 | + | ||
1214 | + if (TREE_CODE_CLASS (code) != tcc_comparison) | ||
1215 | + return NULL_TREE; | ||
1216 | + | ||
1217 | + if (rhs_code == truthop_code) | ||
1218 | + { | ||
1219 | + tree newrhs = merge_truthop_with_opposite_arm (loc, rhs, cmpop, rhs_only); | ||
1220 | + if (newrhs != NULL_TREE) | ||
1221 | + { | ||
1222 | + rhs = newrhs; | ||
1223 | + rhs_code = TREE_CODE (rhs); | ||
1224 | + } | ||
1225 | + } | ||
1226 | + if (lhs_code == truthop_code && !rhs_only) | ||
1227 | + { | ||
1228 | + tree newlhs = merge_truthop_with_opposite_arm (loc, lhs, cmpop, false); | ||
1229 | + if (newlhs != NULL_TREE) | ||
1230 | + { | ||
1231 | + lhs = newlhs; | ||
1232 | + lhs_code = TREE_CODE (lhs); | ||
1233 | + } | ||
1234 | + } | ||
1235 | + | ||
1236 | + inv_code = invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (type))); | ||
1237 | + if (inv_code == rhs_code | ||
1238 | + && operand_equal_p (TREE_OPERAND (rhs, 0), TREE_OPERAND (cmpop, 0), 0) | ||
1239 | + && operand_equal_p (TREE_OPERAND (rhs, 1), TREE_OPERAND (cmpop, 1), 0)) | ||
1240 | + return lhs; | ||
1241 | + if (!rhs_only && inv_code == lhs_code | ||
1242 | + && operand_equal_p (TREE_OPERAND (lhs, 0), TREE_OPERAND (cmpop, 0), 0) | ||
1243 | + && operand_equal_p (TREE_OPERAND (lhs, 1), TREE_OPERAND (cmpop, 1), 0)) | ||
1244 | + return rhs; | ||
1245 | + if (rhs != orig_rhs || lhs != orig_lhs) | ||
1246 | + return fold_build2_loc (loc, truthop_code, TREE_TYPE (cmpop), | ||
1247 | + lhs, rhs); | ||
1248 | + return NULL_TREE; | ||
1249 | +} | ||
1250 | + | ||
1251 | /* Find ways of folding logical expressions of LHS and RHS: | ||
1252 | Try to merge two comparisons to the same innermost item. | ||
1253 | Look for range tests like "ch >= '0' && ch <= '9'". | ||
1254 | @@ -12539,6 +12609,22 @@ | ||
1255 | if (0 != (tem = fold_range_test (loc, code, type, op0, op1))) | ||
1256 | return tem; | ||
1257 | |||
1258 | + if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg0) == TRUTH_ORIF_EXPR) | ||
1259 | + || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg0) == TRUTH_ANDIF_EXPR)) | ||
1260 | + { | ||
1261 | + tem = merge_truthop_with_opposite_arm (loc, arg0, arg1, true); | ||
1262 | + if (tem) | ||
1263 | + return fold_build2_loc (loc, code, type, tem, arg1); | ||
1264 | + } | ||
1265 | + | ||
1266 | + if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg1) == TRUTH_ORIF_EXPR) | ||
1267 | + || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg1) == TRUTH_ANDIF_EXPR)) | ||
1268 | + { | ||
1269 | + tem = merge_truthop_with_opposite_arm (loc, arg1, arg0, false); | ||
1270 | + if (tem) | ||
1271 | + return fold_build2_loc (loc, code, type, arg0, tem); | ||
1272 | + } | ||
1273 | + | ||
1274 | /* Check for the possibility of merging component references. If our | ||
1275 | lhs is another similar operation, try to merge its rhs with our | ||
1276 | rhs. Then try to merge our lhs and rhs. */ | ||
1277 | |||
1278 | === modified file 'gcc/ifcvt.c' | ||
1279 | --- old/gcc/ifcvt.c 2010-04-02 18:54:46 +0000 | ||
1280 | +++ new/gcc/ifcvt.c 2010-09-01 13:29:58 +0000 | ||
1281 | @@ -385,7 +385,11 @@ | ||
1282 | rtx false_expr; /* test for then block insns */ | ||
1283 | rtx true_prob_val; /* probability of else block */ | ||
1284 | rtx false_prob_val; /* probability of then block */ | ||
1285 | - int n_insns; | ||
1286 | + rtx then_last_head = NULL_RTX; /* Last match at the head of THEN */ | ||
1287 | + rtx else_last_head = NULL_RTX; /* Last match at the head of ELSE */ | ||
1288 | + rtx then_first_tail = NULL_RTX; /* First match at the tail of THEN */ | ||
1289 | + rtx else_first_tail = NULL_RTX; /* First match at the tail of ELSE */ | ||
1290 | + int then_n_insns, else_n_insns, n_insns; | ||
1291 | enum rtx_code false_code; | ||
1292 | |||
1293 | /* If test is comprised of && or || elements, and we've failed at handling | ||
1294 | @@ -418,15 +422,78 @@ | ||
1295 | number of insns and see if it is small enough to convert. */ | ||
1296 | then_start = first_active_insn (then_bb); | ||
1297 | then_end = last_active_insn (then_bb, TRUE); | ||
1298 | - n_insns = ce_info->num_then_insns = count_bb_insns (then_bb); | ||
1299 | + then_n_insns = ce_info->num_then_insns = count_bb_insns (then_bb); | ||
1300 | + n_insns = then_n_insns; | ||
1301 | max = MAX_CONDITIONAL_EXECUTE; | ||
1302 | |||
1303 | if (else_bb) | ||
1304 | { | ||
1305 | + int n_matching; | ||
1306 | + | ||
1307 | max *= 2; | ||
1308 | else_start = first_active_insn (else_bb); | ||
1309 | else_end = last_active_insn (else_bb, TRUE); | ||
1310 | - n_insns += ce_info->num_else_insns = count_bb_insns (else_bb); | ||
1311 | + else_n_insns = ce_info->num_else_insns = count_bb_insns (else_bb); | ||
1312 | + n_insns += else_n_insns; | ||
1313 | + | ||
1314 | + /* Look for matching sequences at the head and tail of the two blocks, | ||
1315 | + and limit the range of insns to be converted if possible. */ | ||
1316 | + n_matching = flow_find_cross_jump (then_bb, else_bb, | ||
1317 | + &then_first_tail, &else_first_tail); | ||
1318 | + if (then_first_tail == BB_HEAD (then_bb)) | ||
1319 | + then_start = then_end = NULL_RTX; | ||
1320 | + if (else_first_tail == BB_HEAD (else_bb)) | ||
1321 | + else_start = else_end = NULL_RTX; | ||
1322 | + | ||
1323 | + if (n_matching > 0) | ||
1324 | + { | ||
1325 | + if (then_end) | ||
1326 | + then_end = prev_active_insn (then_first_tail); | ||
1327 | + if (else_end) | ||
1328 | + else_end = prev_active_insn (else_first_tail); | ||
1329 | + n_insns -= 2 * n_matching; | ||
1330 | + } | ||
1331 | + | ||
1332 | + if (then_start && else_start) | ||
1333 | + { | ||
1334 | + int longest_match = MIN (then_n_insns - n_matching, | ||
1335 | + else_n_insns - n_matching); | ||
1336 | + n_matching | ||
1337 | + = flow_find_head_matching_sequence (then_bb, else_bb, | ||
1338 | + &then_last_head, | ||
1339 | + &else_last_head, | ||
1340 | + longest_match); | ||
1341 | + | ||
1342 | + if (n_matching > 0) | ||
1343 | + { | ||
1344 | + rtx insn; | ||
1345 | + | ||
1346 | + /* We won't pass the insns in the head sequence to | ||
1347 | + cond_exec_process_insns, so we need to test them here | ||
1348 | + to make sure that they don't clobber the condition. */ | ||
1349 | + for (insn = BB_HEAD (then_bb); | ||
1350 | + insn != NEXT_INSN (then_last_head); | ||
1351 | + insn = NEXT_INSN (insn)) | ||
1352 | + if (!LABEL_P (insn) && !NOTE_P (insn) | ||
1353 | + && !DEBUG_INSN_P (insn) | ||
1354 | + && modified_in_p (test_expr, insn)) | ||
1355 | + return FALSE; | ||
1356 | + } | ||
1357 | + | ||
1358 | + if (then_last_head == then_end) | ||
1359 | + then_start = then_end = NULL_RTX; | ||
1360 | + if (else_last_head == else_end) | ||
1361 | + else_start = else_end = NULL_RTX; | ||
1362 | + | ||
1363 | + if (n_matching > 0) | ||
1364 | + { | ||
1365 | + if (then_start) | ||
1366 | + then_start = next_active_insn (then_last_head); | ||
1367 | + if (else_start) | ||
1368 | + else_start = next_active_insn (else_last_head); | ||
1369 | + n_insns -= 2 * n_matching; | ||
1370 | + } | ||
1371 | + } | ||
1372 | } | ||
1373 | |||
1374 | if (n_insns > max) | ||
1375 | @@ -570,7 +637,21 @@ | ||
1376 | fprintf (dump_file, "%d insn%s converted to conditional execution.\n", | ||
1377 | n_insns, (n_insns == 1) ? " was" : "s were"); | ||
1378 | |||
1379 | - /* Merge the blocks! */ | ||
1380 | + /* Merge the blocks! If we had matching sequences, make sure to delete one | ||
1381 | + copy at the appropriate location first: delete the copy in the THEN branch | ||
1382 | + for a tail sequence so that the remaining one is executed last for both | ||
1383 | + branches, and delete the copy in the ELSE branch for a head sequence so | ||
1384 | + that the remaining one is executed first for both branches. */ | ||
1385 | + if (then_first_tail) | ||
1386 | + { | ||
1387 | + rtx from = then_first_tail; | ||
1388 | + if (!INSN_P (from)) | ||
1389 | + from = next_active_insn (from); | ||
1390 | + delete_insn_chain (from, BB_END (then_bb), false); | ||
1391 | + } | ||
1392 | + if (else_last_head) | ||
1393 | + delete_insn_chain (first_active_insn (else_bb), else_last_head, false); | ||
1394 | + | ||
1395 | merge_if_block (ce_info); | ||
1396 | cond_exec_changed_p = TRUE; | ||
1397 | return TRUE; | ||
1398 | |||
1399 | === modified file 'gcc/ira-color.c' | ||
1400 | --- old/gcc/ira-color.c 2010-04-02 18:54:46 +0000 | ||
1401 | +++ new/gcc/ira-color.c 2010-09-01 13:29:58 +0000 | ||
1402 | @@ -441,14 +441,18 @@ | ||
1403 | { | ||
1404 | HARD_REG_SET conflicting_regs; | ||
1405 | int i, j, k, hard_regno, best_hard_regno, class_size; | ||
1406 | - int cost, mem_cost, min_cost, full_cost, min_full_cost, add_cost; | ||
1407 | + int cost, mem_cost, min_cost, full_cost, min_full_cost; | ||
1408 | int *a_costs; | ||
1409 | int *conflict_costs; | ||
1410 | - enum reg_class cover_class, rclass, conflict_cover_class; | ||
1411 | + enum reg_class cover_class, conflict_cover_class; | ||
1412 | enum machine_mode mode; | ||
1413 | ira_allocno_t a, conflict_allocno; | ||
1414 | ira_allocno_conflict_iterator aci; | ||
1415 | static int costs[FIRST_PSEUDO_REGISTER], full_costs[FIRST_PSEUDO_REGISTER]; | ||
1416 | +#ifndef HONOR_REG_ALLOC_ORDER | ||
1417 | + enum reg_class rclass; | ||
1418 | + int add_cost; | ||
1419 | +#endif | ||
1420 | #ifdef STACK_REGS | ||
1421 | bool no_stack_reg_p; | ||
1422 | #endif | ||
1423 | @@ -586,6 +590,7 @@ | ||
1424 | continue; | ||
1425 | cost = costs[i]; | ||
1426 | full_cost = full_costs[i]; | ||
1427 | +#ifndef HONOR_REG_ALLOC_ORDER | ||
1428 | if (! allocated_hardreg_p[hard_regno] | ||
1429 | && ira_hard_reg_not_in_set_p (hard_regno, mode, call_used_reg_set)) | ||
1430 | /* We need to save/restore the hard register in | ||
1431 | @@ -598,6 +603,7 @@ | ||
1432 | cost += add_cost; | ||
1433 | full_cost += add_cost; | ||
1434 | } | ||
1435 | +#endif | ||
1436 | if (min_cost > cost) | ||
1437 | min_cost = cost; | ||
1438 | if (min_full_cost > full_cost) | ||
1439 | |||
1440 | === modified file 'gcc/ira-costs.c' | ||
1441 | --- old/gcc/ira-costs.c 2010-08-13 11:40:17 +0000 | ||
1442 | +++ new/gcc/ira-costs.c 2010-09-01 13:29:58 +0000 | ||
1443 | @@ -33,6 +33,7 @@ | ||
1444 | #include "addresses.h" | ||
1445 | #include "insn-config.h" | ||
1446 | #include "recog.h" | ||
1447 | +#include "reload.h" | ||
1448 | #include "toplev.h" | ||
1449 | #include "target.h" | ||
1450 | #include "params.h" | ||
1451 | @@ -123,6 +124,10 @@ | ||
1452 | /* Record cover register class of each allocno with the same regno. */ | ||
1453 | static enum reg_class *regno_cover_class; | ||
1454 | |||
1455 | +/* Record cost gains for not allocating a register with an invariant | ||
1456 | + equivalence. */ | ||
1457 | +static int *regno_equiv_gains; | ||
1458 | + | ||
1459 | /* Execution frequency of the current insn. */ | ||
1460 | static int frequency; | ||
1461 | |||
1462 | @@ -1263,6 +1268,7 @@ | ||
1463 | #ifdef FORBIDDEN_INC_DEC_CLASSES | ||
1464 | int inc_dec_p = false; | ||
1465 | #endif | ||
1466 | + int equiv_savings = regno_equiv_gains[i]; | ||
1467 | |||
1468 | if (! allocno_p) | ||
1469 | { | ||
1470 | @@ -1311,6 +1317,15 @@ | ||
1471 | #endif | ||
1472 | } | ||
1473 | } | ||
1474 | + if (equiv_savings < 0) | ||
1475 | + temp_costs->mem_cost = -equiv_savings; | ||
1476 | + else if (equiv_savings > 0) | ||
1477 | + { | ||
1478 | + temp_costs->mem_cost = 0; | ||
1479 | + for (k = 0; k < cost_classes_num; k++) | ||
1480 | + temp_costs->cost[k] += equiv_savings; | ||
1481 | + } | ||
1482 | + | ||
1483 | best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1; | ||
1484 | best = ALL_REGS; | ||
1485 | alt_class = NO_REGS; | ||
1486 | @@ -1680,6 +1695,8 @@ | ||
1487 | regno_cover_class | ||
1488 | = (enum reg_class *) ira_allocate (sizeof (enum reg_class) | ||
1489 | * max_reg_num ()); | ||
1490 | + regno_equiv_gains = (int *) ira_allocate (sizeof (int) * max_reg_num ()); | ||
1491 | + memset (regno_equiv_gains, 0, sizeof (int) * max_reg_num ()); | ||
1492 | } | ||
1493 | |||
1494 | /* Common finalization function for ira_costs and | ||
1495 | @@ -1687,6 +1704,7 @@ | ||
1496 | static void | ||
1497 | finish_costs (void) | ||
1498 | { | ||
1499 | + ira_free (regno_equiv_gains); | ||
1500 | ira_free (regno_cover_class); | ||
1501 | ira_free (pref_buffer); | ||
1502 | ira_free (costs); | ||
1503 | @@ -1702,6 +1720,7 @@ | ||
1504 | init_costs (); | ||
1505 | total_allocno_costs = (struct costs *) ira_allocate (max_struct_costs_size | ||
1506 | * ira_allocnos_num); | ||
1507 | + calculate_elim_costs_all_insns (); | ||
1508 | find_costs_and_classes (ira_dump_file); | ||
1509 | setup_allocno_cover_class_and_costs (); | ||
1510 | finish_costs (); | ||
1511 | @@ -1775,3 +1794,16 @@ | ||
1512 | ALLOCNO_COVER_CLASS_COST (a) = min_cost; | ||
1513 | } | ||
1514 | } | ||
1515 | + | ||
1516 | +/* Add COST to the estimated gain for eliminating REGNO with its | ||
1517 | + equivalence. If COST is zero, record that no such elimination is | ||
1518 | + possible. */ | ||
1519 | + | ||
1520 | +void | ||
1521 | +ira_adjust_equiv_reg_cost (unsigned regno, int cost) | ||
1522 | +{ | ||
1523 | + if (cost == 0) | ||
1524 | + regno_equiv_gains[regno] = 0; | ||
1525 | + else | ||
1526 | + regno_equiv_gains[regno] += cost; | ||
1527 | +} | ||
1528 | |||
1529 | === modified file 'gcc/ira.c' | ||
1530 | --- old/gcc/ira.c 2010-08-12 13:51:16 +0000 | ||
1531 | +++ new/gcc/ira.c 2010-09-01 13:29:58 +0000 | ||
1532 | @@ -431,9 +431,6 @@ | ||
1533 | HARD_REG_SET processed_hard_reg_set; | ||
1534 | |||
1535 | ira_assert (SHRT_MAX >= FIRST_PSEUDO_REGISTER); | ||
1536 | - /* We could call ORDER_REGS_FOR_LOCAL_ALLOC here (it is usually | ||
1537 | - putting hard callee-used hard registers first). But our | ||
1538 | - heuristics work better. */ | ||
1539 | for (cl = (int) N_REG_CLASSES - 1; cl >= 0; cl--) | ||
1540 | { | ||
1541 | COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); | ||
1542 | @@ -490,6 +487,9 @@ | ||
1543 | static void | ||
1544 | setup_alloc_regs (bool use_hard_frame_p) | ||
1545 | { | ||
1546 | +#ifdef ADJUST_REG_ALLOC_ORDER | ||
1547 | + ADJUST_REG_ALLOC_ORDER; | ||
1548 | +#endif | ||
1549 | COPY_HARD_REG_SET (no_unit_alloc_regs, fixed_reg_set); | ||
1550 | if (! use_hard_frame_p) | ||
1551 | SET_HARD_REG_BIT (no_unit_alloc_regs, HARD_FRAME_POINTER_REGNUM); | ||
1552 | @@ -1533,12 +1533,8 @@ | ||
1553 | |||
1554 | x = XEXP (note, 0); | ||
1555 | |||
1556 | - if (! function_invariant_p (x) | ||
1557 | - || ! flag_pic | ||
1558 | - /* A function invariant is often CONSTANT_P but may | ||
1559 | - include a register. We promise to only pass CONSTANT_P | ||
1560 | - objects to LEGITIMATE_PIC_OPERAND_P. */ | ||
1561 | - || (CONSTANT_P (x) && LEGITIMATE_PIC_OPERAND_P (x))) | ||
1562 | + if (! CONSTANT_P (x) | ||
1563 | + || ! flag_pic || LEGITIMATE_PIC_OPERAND_P (x)) | ||
1564 | { | ||
1565 | /* It can happen that a REG_EQUIV note contains a MEM | ||
1566 | that is not a legitimate memory operand. As later | ||
1567 | @@ -3097,8 +3093,19 @@ | ||
1568 | if (dump_file) | ||
1569 | print_insn_chains (dump_file); | ||
1570 | } | ||
1571 | - | ||
1572 | |||
1573 | +/* Allocate memory for reg_equiv_memory_loc. */ | ||
1574 | +static void | ||
1575 | +init_reg_equiv_memory_loc (void) | ||
1576 | +{ | ||
1577 | + max_regno = max_reg_num (); | ||
1578 | + | ||
1579 | + /* And the reg_equiv_memory_loc array. */ | ||
1580 | + VEC_safe_grow (rtx, gc, reg_equiv_memory_loc_vec, max_regno); | ||
1581 | + memset (VEC_address (rtx, reg_equiv_memory_loc_vec), 0, | ||
1582 | + sizeof (rtx) * max_regno); | ||
1583 | + reg_equiv_memory_loc = VEC_address (rtx, reg_equiv_memory_loc_vec); | ||
1584 | +} | ||
1585 | |||
1586 | /* All natural loops. */ | ||
1587 | struct loops ira_loops; | ||
1588 | @@ -3203,6 +3210,8 @@ | ||
1589 | record_loop_exits (); | ||
1590 | current_loops = &ira_loops; | ||
1591 | |||
1592 | + init_reg_equiv_memory_loc (); | ||
1593 | + | ||
1594 | if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL) | ||
1595 | fprintf (ira_dump_file, "Building IRA IR\n"); | ||
1596 | loops_p = ira_build (optimize | ||
1597 | @@ -3263,13 +3272,8 @@ | ||
1598 | #endif | ||
1599 | |||
1600 | delete_trivially_dead_insns (get_insns (), max_reg_num ()); | ||
1601 | - max_regno = max_reg_num (); | ||
1602 | |||
1603 | - /* And the reg_equiv_memory_loc array. */ | ||
1604 | - VEC_safe_grow (rtx, gc, reg_equiv_memory_loc_vec, max_regno); | ||
1605 | - memset (VEC_address (rtx, reg_equiv_memory_loc_vec), 0, | ||
1606 | - sizeof (rtx) * max_regno); | ||
1607 | - reg_equiv_memory_loc = VEC_address (rtx, reg_equiv_memory_loc_vec); | ||
1608 | + init_reg_equiv_memory_loc (); | ||
1609 | |||
1610 | if (max_regno != max_regno_before_ira) | ||
1611 | { | ||
1612 | |||
1613 | === modified file 'gcc/ira.h' | ||
1614 | --- old/gcc/ira.h 2009-09-02 17:54:25 +0000 | ||
1615 | +++ new/gcc/ira.h 2010-09-01 13:29:58 +0000 | ||
1616 | @@ -87,3 +87,4 @@ | ||
1617 | extern void ira_mark_new_stack_slot (rtx, int, unsigned int); | ||
1618 | extern bool ira_better_spill_reload_regno_p (int *, int *, rtx, rtx, rtx); | ||
1619 | |||
1620 | +extern void ira_adjust_equiv_reg_cost (unsigned, int); | ||
1621 | |||
1622 | === modified file 'gcc/optabs.h' | ||
1623 | --- old/gcc/optabs.h 2009-11-25 10:55:54 +0000 | ||
1624 | +++ new/gcc/optabs.h 2010-09-01 13:29:58 +0000 | ||
1625 | @@ -771,6 +771,9 @@ | ||
1626 | /* Generate code for float to integral conversion. */ | ||
1627 | extern bool expand_sfix_optab (rtx, rtx, convert_optab); | ||
1628 | |||
1629 | +/* Generate code for a widening multiply. */ | ||
1630 | +extern rtx expand_widening_mult (enum machine_mode, rtx, rtx, rtx, int, optab); | ||
1631 | + | ||
1632 | /* Return tree if target supports vector operations for COND_EXPR. */ | ||
1633 | bool expand_vec_cond_expr_p (tree, enum machine_mode); | ||
1634 | |||
1635 | |||
1636 | === modified file 'gcc/passes.c' | ||
1637 | --- old/gcc/passes.c 2010-05-19 12:14:37 +0000 | ||
1638 | +++ new/gcc/passes.c 2010-09-01 13:29:58 +0000 | ||
1639 | @@ -944,6 +944,7 @@ | ||
1640 | NEXT_PASS (pass_forwprop); | ||
1641 | NEXT_PASS (pass_phiopt); | ||
1642 | NEXT_PASS (pass_fold_builtins); | ||
1643 | + NEXT_PASS (pass_optimize_widening_mul); | ||
1644 | NEXT_PASS (pass_tail_calls); | ||
1645 | NEXT_PASS (pass_rename_ssa_copies); | ||
1646 | NEXT_PASS (pass_uncprop); | ||
1647 | |||
1648 | === modified file 'gcc/reload.h' | ||
1649 | --- old/gcc/reload.h 2010-04-02 18:54:46 +0000 | ||
1650 | +++ new/gcc/reload.h 2010-09-01 13:29:58 +0000 | ||
1651 | @@ -347,6 +347,10 @@ | ||
1652 | extern rtx eliminate_regs (rtx, enum machine_mode, rtx); | ||
1653 | extern bool elimination_target_reg_p (rtx); | ||
1654 | |||
1655 | +/* Called from the register allocator to estimate costs of eliminating | ||
1656 | + invariant registers. */ | ||
1657 | +extern void calculate_elim_costs_all_insns (void); | ||
1658 | + | ||
1659 | /* Deallocate the reload register used by reload number R. */ | ||
1660 | extern void deallocate_reload_reg (int r); | ||
1661 | |||
1662 | |||
1663 | === modified file 'gcc/reload1.c' | ||
1664 | --- old/gcc/reload1.c 2010-03-02 18:56:50 +0000 | ||
1665 | +++ new/gcc/reload1.c 2010-09-01 13:29:58 +0000 | ||
1666 | @@ -413,6 +413,7 @@ | ||
1667 | static void set_label_offsets (rtx, rtx, int); | ||
1668 | static void check_eliminable_occurrences (rtx); | ||
1669 | static void elimination_effects (rtx, enum machine_mode); | ||
1670 | +static rtx eliminate_regs_1 (rtx, enum machine_mode, rtx, bool, bool); | ||
1671 | static int eliminate_regs_in_insn (rtx, int); | ||
1672 | static void update_eliminable_offsets (void); | ||
1673 | static void mark_not_eliminable (rtx, const_rtx, void *); | ||
1674 | @@ -420,8 +421,11 @@ | ||
1675 | static bool verify_initial_elim_offsets (void); | ||
1676 | static void set_initial_label_offsets (void); | ||
1677 | static void set_offsets_for_label (rtx); | ||
1678 | +static void init_eliminable_invariants (rtx, bool); | ||
1679 | static void init_elim_table (void); | ||
1680 | +static void free_reg_equiv (void); | ||
1681 | static void update_eliminables (HARD_REG_SET *); | ||
1682 | +static void elimination_costs_in_insn (rtx); | ||
1683 | static void spill_hard_reg (unsigned int, int); | ||
1684 | static int finish_spills (int); | ||
1685 | static void scan_paradoxical_subregs (rtx); | ||
1686 | @@ -698,6 +702,9 @@ | ||
1687 | |||
1688 | /* Global variables used by reload and its subroutines. */ | ||
1689 | |||
1690 | +/* The current basic block while in calculate_elim_costs_all_insns. */ | ||
1691 | +static basic_block elim_bb; | ||
1692 | + | ||
1693 | /* Set during calculate_needs if an insn needs register elimination. */ | ||
1694 | static int something_needs_elimination; | ||
1695 | /* Set during calculate_needs if an insn needs an operand changed. */ | ||
1696 | @@ -776,22 +783,6 @@ | ||
1697 | if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i)) | ||
1698 | df_set_regs_ever_live (i, true); | ||
1699 | |||
1700 | - /* Find all the pseudo registers that didn't get hard regs | ||
1701 | - but do have known equivalent constants or memory slots. | ||
1702 | - These include parameters (known equivalent to parameter slots) | ||
1703 | - and cse'd or loop-moved constant memory addresses. | ||
1704 | - | ||
1705 | - Record constant equivalents in reg_equiv_constant | ||
1706 | - so they will be substituted by find_reloads. | ||
1707 | - Record memory equivalents in reg_mem_equiv so they can | ||
1708 | - be substituted eventually by altering the REG-rtx's. */ | ||
1709 | - | ||
1710 | - reg_equiv_constant = XCNEWVEC (rtx, max_regno); | ||
1711 | - reg_equiv_invariant = XCNEWVEC (rtx, max_regno); | ||
1712 | - reg_equiv_mem = XCNEWVEC (rtx, max_regno); | ||
1713 | - reg_equiv_alt_mem_list = XCNEWVEC (rtx, max_regno); | ||
1714 | - reg_equiv_address = XCNEWVEC (rtx, max_regno); | ||
1715 | - reg_max_ref_width = XCNEWVEC (unsigned int, max_regno); | ||
1716 | reg_old_renumber = XCNEWVEC (short, max_regno); | ||
1717 | memcpy (reg_old_renumber, reg_renumber, max_regno * sizeof (short)); | ||
1718 | pseudo_forbidden_regs = XNEWVEC (HARD_REG_SET, max_regno); | ||
1719 | @@ -799,115 +790,9 @@ | ||
1720 | |||
1721 | CLEAR_HARD_REG_SET (bad_spill_regs_global); | ||
1722 | |||
1723 | - /* Look for REG_EQUIV notes; record what each pseudo is equivalent | ||
1724 | - to. Also find all paradoxical subregs and find largest such for | ||
1725 | - each pseudo. */ | ||
1726 | - | ||
1727 | - num_eliminable_invariants = 0; | ||
1728 | - for (insn = first; insn; insn = NEXT_INSN (insn)) | ||
1729 | - { | ||
1730 | - rtx set = single_set (insn); | ||
1731 | - | ||
1732 | - /* We may introduce USEs that we want to remove at the end, so | ||
1733 | - we'll mark them with QImode. Make sure there are no | ||
1734 | - previously-marked insns left by say regmove. */ | ||
1735 | - if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE | ||
1736 | - && GET_MODE (insn) != VOIDmode) | ||
1737 | - PUT_MODE (insn, VOIDmode); | ||
1738 | - | ||
1739 | - if (NONDEBUG_INSN_P (insn)) | ||
1740 | - scan_paradoxical_subregs (PATTERN (insn)); | ||
1741 | - | ||
1742 | - if (set != 0 && REG_P (SET_DEST (set))) | ||
1743 | - { | ||
1744 | - rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX); | ||
1745 | - rtx x; | ||
1746 | - | ||
1747 | - if (! note) | ||
1748 | - continue; | ||
1749 | - | ||
1750 | - i = REGNO (SET_DEST (set)); | ||
1751 | - x = XEXP (note, 0); | ||
1752 | - | ||
1753 | - if (i <= LAST_VIRTUAL_REGISTER) | ||
1754 | - continue; | ||
1755 | - | ||
1756 | - if (! function_invariant_p (x) | ||
1757 | - || ! flag_pic | ||
1758 | - /* A function invariant is often CONSTANT_P but may | ||
1759 | - include a register. We promise to only pass | ||
1760 | - CONSTANT_P objects to LEGITIMATE_PIC_OPERAND_P. */ | ||
1761 | - || (CONSTANT_P (x) | ||
1762 | - && LEGITIMATE_PIC_OPERAND_P (x))) | ||
1763 | - { | ||
1764 | - /* It can happen that a REG_EQUIV note contains a MEM | ||
1765 | - that is not a legitimate memory operand. As later | ||
1766 | - stages of reload assume that all addresses found | ||
1767 | - in the reg_equiv_* arrays were originally legitimate, | ||
1768 | - we ignore such REG_EQUIV notes. */ | ||
1769 | - if (memory_operand (x, VOIDmode)) | ||
1770 | - { | ||
1771 | - /* Always unshare the equivalence, so we can | ||
1772 | - substitute into this insn without touching the | ||
1773 | - equivalence. */ | ||
1774 | - reg_equiv_memory_loc[i] = copy_rtx (x); | ||
1775 | - } | ||
1776 | - else if (function_invariant_p (x)) | ||
1777 | - { | ||
1778 | - if (GET_CODE (x) == PLUS) | ||
1779 | - { | ||
1780 | - /* This is PLUS of frame pointer and a constant, | ||
1781 | - and might be shared. Unshare it. */ | ||
1782 | - reg_equiv_invariant[i] = copy_rtx (x); | ||
1783 | - num_eliminable_invariants++; | ||
1784 | - } | ||
1785 | - else if (x == frame_pointer_rtx || x == arg_pointer_rtx) | ||
1786 | - { | ||
1787 | - reg_equiv_invariant[i] = x; | ||
1788 | - num_eliminable_invariants++; | ||
1789 | - } | ||
1790 | - else if (LEGITIMATE_CONSTANT_P (x)) | ||
1791 | - reg_equiv_constant[i] = x; | ||
1792 | - else | ||
1793 | - { | ||
1794 | - reg_equiv_memory_loc[i] | ||
1795 | - = force_const_mem (GET_MODE (SET_DEST (set)), x); | ||
1796 | - if (! reg_equiv_memory_loc[i]) | ||
1797 | - reg_equiv_init[i] = NULL_RTX; | ||
1798 | - } | ||
1799 | - } | ||
1800 | - else | ||
1801 | - { | ||
1802 | - reg_equiv_init[i] = NULL_RTX; | ||
1803 | - continue; | ||
1804 | - } | ||
1805 | - } | ||
1806 | - else | ||
1807 | - reg_equiv_init[i] = NULL_RTX; | ||
1808 | - } | ||
1809 | - } | ||
1810 | - | ||
1811 | - if (dump_file) | ||
1812 | - for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) | ||
1813 | - if (reg_equiv_init[i]) | ||
1814 | - { | ||
1815 | - fprintf (dump_file, "init_insns for %u: ", i); | ||
1816 | - print_inline_rtx (dump_file, reg_equiv_init[i], 20); | ||
1817 | - fprintf (dump_file, "\n"); | ||
1818 | - } | ||
1819 | - | ||
1820 | + init_eliminable_invariants (first, true); | ||
1821 | init_elim_table (); | ||
1822 | |||
1823 | - first_label_num = get_first_label_num (); | ||
1824 | - num_labels = max_label_num () - first_label_num; | ||
1825 | - | ||
1826 | - /* Allocate the tables used to store offset information at labels. */ | ||
1827 | - /* We used to use alloca here, but the size of what it would try to | ||
1828 | - allocate would occasionally cause it to exceed the stack limit and | ||
1829 | - cause a core dump. */ | ||
1830 | - offsets_known_at = XNEWVEC (char, num_labels); | ||
1831 | - offsets_at = (HOST_WIDE_INT (*)[NUM_ELIMINABLE_REGS]) xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (HOST_WIDE_INT)); | ||
1832 | - | ||
1833 | /* Alter each pseudo-reg rtx to contain its hard reg number. Assign | ||
1834 | stack slots to the pseudos that lack hard regs or equivalents. | ||
1835 | Do not touch virtual registers. */ | ||
1836 | @@ -1411,31 +1296,11 @@ | ||
1837 | } | ||
1838 | } | ||
1839 | |||
1840 | + free (temp_pseudo_reg_arr); | ||
1841 | + | ||
1842 | /* Indicate that we no longer have known memory locations or constants. */ | ||
1843 | - if (reg_equiv_constant) | ||
1844 | - free (reg_equiv_constant); | ||
1845 | - if (reg_equiv_invariant) | ||
1846 | - free (reg_equiv_invariant); | ||
1847 | - reg_equiv_constant = 0; | ||
1848 | - reg_equiv_invariant = 0; | ||
1849 | - VEC_free (rtx, gc, reg_equiv_memory_loc_vec); | ||
1850 | - reg_equiv_memory_loc = 0; | ||
1851 | - | ||
1852 | - free (temp_pseudo_reg_arr); | ||
1853 | - | ||
1854 | - if (offsets_known_at) | ||
1855 | - free (offsets_known_at); | ||
1856 | - if (offsets_at) | ||
1857 | - free (offsets_at); | ||
1858 | - | ||
1859 | - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | ||
1860 | - if (reg_equiv_alt_mem_list[i]) | ||
1861 | - free_EXPR_LIST_list (®_equiv_alt_mem_list[i]); | ||
1862 | - free (reg_equiv_alt_mem_list); | ||
1863 | - | ||
1864 | - free (reg_equiv_mem); | ||
1865 | + free_reg_equiv (); | ||
1866 | reg_equiv_init = 0; | ||
1867 | - free (reg_equiv_address); | ||
1868 | free (reg_max_ref_width); | ||
1869 | free (reg_old_renumber); | ||
1870 | free (pseudo_previous_regs); | ||
1871 | @@ -1728,6 +1593,100 @@ | ||
1872 | *pprev_reload = 0; | ||
1873 | } | ||
1874 | |||
1875 | +/* This function is called from the register allocator to set up estimates | ||
1876 | + for the cost of eliminating pseudos which have REG_EQUIV equivalences to | ||
1877 | + an invariant. The structure is similar to calculate_needs_all_insns. */ | ||
1878 | + | ||
1879 | +void | ||
1880 | +calculate_elim_costs_all_insns (void) | ||
1881 | +{ | ||
1882 | + int *reg_equiv_init_cost; | ||
1883 | + basic_block bb; | ||
1884 | + int i; | ||
1885 | + | ||
1886 | + reg_equiv_init_cost = XCNEWVEC (int, max_regno); | ||
1887 | + init_elim_table (); | ||
1888 | + init_eliminable_invariants (get_insns (), false); | ||
1889 | + | ||
1890 | + set_initial_elim_offsets (); | ||
1891 | + set_initial_label_offsets (); | ||
1892 | + | ||
1893 | + FOR_EACH_BB (bb) | ||
1894 | + { | ||
1895 | + rtx insn; | ||
1896 | + elim_bb = bb; | ||
1897 | + | ||
1898 | + FOR_BB_INSNS (bb, insn) | ||
1899 | + { | ||
1900 | + /* If this is a label, a JUMP_INSN, or has REG_NOTES (which might | ||
1901 | + include REG_LABEL_OPERAND and REG_LABEL_TARGET), we need to see | ||
1902 | + what effects this has on the known offsets at labels. */ | ||
1903 | + | ||
1904 | + if (LABEL_P (insn) || JUMP_P (insn) | ||
1905 | + || (INSN_P (insn) && REG_NOTES (insn) != 0)) | ||
1906 | + set_label_offsets (insn, insn, 0); | ||
1907 | + | ||
1908 | + if (INSN_P (insn)) | ||
1909 | + { | ||
1910 | + rtx set = single_set (insn); | ||
1911 | + | ||
1912 | + /* Skip insns that only set an equivalence. */ | ||
1913 | + if (set && REG_P (SET_DEST (set)) | ||
1914 | + && reg_renumber[REGNO (SET_DEST (set))] < 0 | ||
1915 | + && (reg_equiv_constant[REGNO (SET_DEST (set))] | ||
1916 | + || (reg_equiv_invariant[REGNO (SET_DEST (set))]))) | ||
1917 | + { | ||
1918 | + unsigned regno = REGNO (SET_DEST (set)); | ||
1919 | + rtx init = reg_equiv_init[regno]; | ||
1920 | + if (init) | ||
1921 | + { | ||
1922 | + rtx t = eliminate_regs_1 (SET_SRC (set), VOIDmode, insn, | ||
1923 | + false, true); | ||
1924 | + int cost = rtx_cost (t, SET, | ||
1925 | + optimize_bb_for_speed_p (bb)); | ||
1926 | + int freq = REG_FREQ_FROM_BB (bb); | ||
1927 | + | ||
1928 | + reg_equiv_init_cost[regno] = cost * freq; | ||
1929 | + continue; | ||
1930 | + } | ||
1931 | + } | ||
1932 | + /* If needed, eliminate any eliminable registers. */ | ||
1933 | + if (num_eliminable || num_eliminable_invariants) | ||
1934 | + elimination_costs_in_insn (insn); | ||
1935 | + | ||
1936 | + if (num_eliminable) | ||
1937 | + update_eliminable_offsets (); | ||
1938 | + } | ||
1939 | + } | ||
1940 | + } | ||
1941 | + for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) | ||
1942 | + { | ||
1943 | + if (reg_equiv_invariant[i]) | ||
1944 | + { | ||
1945 | + if (reg_equiv_init[i]) | ||
1946 | + { | ||
1947 | + int cost = reg_equiv_init_cost[i]; | ||
1948 | + if (dump_file) | ||
1949 | + fprintf (dump_file, | ||
1950 | + "Reg %d has equivalence, initial gains %d\n", i, cost); | ||
1951 | + if (cost != 0) | ||
1952 | + ira_adjust_equiv_reg_cost (i, cost); | ||
1953 | + } | ||
1954 | + else | ||
1955 | + { | ||
1956 | + if (dump_file) | ||
1957 | + fprintf (dump_file, | ||
1958 | + "Reg %d had equivalence, but can't be eliminated\n", | ||
1959 | + i); | ||
1960 | + ira_adjust_equiv_reg_cost (i, 0); | ||
1961 | + } | ||
1962 | + } | ||
1963 | + } | ||
1964 | + | ||
1965 | + free_reg_equiv (); | ||
1966 | + free (reg_equiv_init_cost); | ||
1967 | +} | ||
1968 | + | ||
1969 | /* Comparison function for qsort to decide which of two reloads | ||
1970 | should be handled first. *P1 and *P2 are the reload numbers. */ | ||
1971 | |||
1972 | @@ -2514,6 +2473,36 @@ | ||
1973 | } | ||
1974 | } | ||
1975 | |||
1976 | +/* Called through for_each_rtx, this function examines every reg that occurs | ||
1977 | + in PX and adjusts the costs for its elimination which are gathered by IRA. | ||
1978 | + DATA is the insn in which PX occurs. We do not recurse into MEM | ||
1979 | + expressions. */ | ||
1980 | + | ||
1981 | +static int | ||
1982 | +note_reg_elim_costly (rtx *px, void *data) | ||
1983 | +{ | ||
1984 | + rtx insn = (rtx)data; | ||
1985 | + rtx x = *px; | ||
1986 | + | ||
1987 | + if (MEM_P (x)) | ||
1988 | + return -1; | ||
1989 | + | ||
1990 | + if (REG_P (x) | ||
1991 | + && REGNO (x) >= FIRST_PSEUDO_REGISTER | ||
1992 | + && reg_equiv_init[REGNO (x)] | ||
1993 | + && reg_equiv_invariant[REGNO (x)]) | ||
1994 | + { | ||
1995 | + rtx t = reg_equiv_invariant[REGNO (x)]; | ||
1996 | + rtx new_rtx = eliminate_regs_1 (t, Pmode, insn, true, true); | ||
1997 | + int cost = rtx_cost (new_rtx, SET, optimize_bb_for_speed_p (elim_bb)); | ||
1998 | + int freq = REG_FREQ_FROM_BB (elim_bb); | ||
1999 | + | ||
2000 | + if (cost != 0) | ||
2001 | + ira_adjust_equiv_reg_cost (REGNO (x), -cost * freq); | ||
2002 | + } | ||
2003 | + return 0; | ||
2004 | +} | ||
2005 | + | ||
2006 | /* Scan X and replace any eliminable registers (such as fp) with a | ||
2007 | replacement (such as sp), plus an offset. | ||
2008 | |||
2009 | @@ -2533,6 +2522,9 @@ | ||
2010 | This means, do not set ref_outside_mem even if the reference | ||
2011 | is outside of MEMs. | ||
2012 | |||
2013 | + If FOR_COSTS is true, we are being called before reload in order to | ||
2014 | + estimate the costs of keeping registers with an equivalence unallocated. | ||
2015 | + | ||
2016 | REG_EQUIV_MEM and REG_EQUIV_ADDRESS contain address that have had | ||
2017 | replacements done assuming all offsets are at their initial values. If | ||
2018 | they are not, or if REG_EQUIV_ADDRESS is nonzero for a pseudo we | ||
2019 | @@ -2541,7 +2533,7 @@ | ||
2020 | |||
2021 | static rtx | ||
2022 | eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn, | ||
2023 | - bool may_use_invariant) | ||
2024 | + bool may_use_invariant, bool for_costs) | ||
2025 | { | ||
2026 | enum rtx_code code = GET_CODE (x); | ||
2027 | struct elim_table *ep; | ||
2028 | @@ -2589,11 +2581,12 @@ | ||
2029 | { | ||
2030 | if (may_use_invariant || (insn && DEBUG_INSN_P (insn))) | ||
2031 | return eliminate_regs_1 (copy_rtx (reg_equiv_invariant[regno]), | ||
2032 | - mem_mode, insn, true); | ||
2033 | + mem_mode, insn, true, for_costs); | ||
2034 | /* There exists at least one use of REGNO that cannot be | ||
2035 | eliminated. Prevent the defining insn from being deleted. */ | ||
2036 | reg_equiv_init[regno] = NULL_RTX; | ||
2037 | - alter_reg (regno, -1, true); | ||
2038 | + if (!for_costs) | ||
2039 | + alter_reg (regno, -1, true); | ||
2040 | } | ||
2041 | return x; | ||
2042 | |||
2043 | @@ -2654,8 +2647,10 @@ | ||
2044 | operand of a load-address insn. */ | ||
2045 | |||
2046 | { | ||
2047 | - rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true); | ||
2048 | - rtx new1 = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true); | ||
2049 | + rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true, | ||
2050 | + for_costs); | ||
2051 | + rtx new1 = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true, | ||
2052 | + for_costs); | ||
2053 | |||
2054 | if (reg_renumber && (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))) | ||
2055 | { | ||
2056 | @@ -2729,9 +2724,11 @@ | ||
2057 | case GE: case GT: case GEU: case GTU: | ||
2058 | case LE: case LT: case LEU: case LTU: | ||
2059 | { | ||
2060 | - rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false); | ||
2061 | + rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false, | ||
2062 | + for_costs); | ||
2063 | rtx new1 = XEXP (x, 1) | ||
2064 | - ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, false) : 0; | ||
2065 | + ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, false, | ||
2066 | + for_costs) : 0; | ||
2067 | |||
2068 | if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)) | ||
2069 | return gen_rtx_fmt_ee (code, GET_MODE (x), new0, new1); | ||
2070 | @@ -2742,7 +2739,8 @@ | ||
2071 | /* If we have something in XEXP (x, 0), the usual case, eliminate it. */ | ||
2072 | if (XEXP (x, 0)) | ||
2073 | { | ||
2074 | - new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true); | ||
2075 | + new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true, | ||
2076 | + for_costs); | ||
2077 | if (new_rtx != XEXP (x, 0)) | ||
2078 | { | ||
2079 | /* If this is a REG_DEAD note, it is not valid anymore. | ||
2080 | @@ -2750,7 +2748,8 @@ | ||
2081 | REG_DEAD note for the stack or frame pointer. */ | ||
2082 | if (REG_NOTE_KIND (x) == REG_DEAD) | ||
2083 | return (XEXP (x, 1) | ||
2084 | - ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true) | ||
2085 | + ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true, | ||
2086 | + for_costs) | ||
2087 | : NULL_RTX); | ||
2088 | |||
2089 | x = alloc_reg_note (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1)); | ||
2090 | @@ -2765,7 +2764,8 @@ | ||
2091 | strictly needed, but it simplifies the code. */ | ||
2092 | if (XEXP (x, 1)) | ||
2093 | { | ||
2094 | - new_rtx = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true); | ||
2095 | + new_rtx = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true, | ||
2096 | + for_costs); | ||
2097 | if (new_rtx != XEXP (x, 1)) | ||
2098 | return | ||
2099 | gen_rtx_fmt_ee (GET_CODE (x), GET_MODE (x), XEXP (x, 0), new_rtx); | ||
2100 | @@ -2791,7 +2791,7 @@ | ||
2101 | && XEXP (XEXP (x, 1), 0) == XEXP (x, 0)) | ||
2102 | { | ||
2103 | rtx new_rtx = eliminate_regs_1 (XEXP (XEXP (x, 1), 1), mem_mode, | ||
2104 | - insn, true); | ||
2105 | + insn, true, for_costs); | ||
2106 | |||
2107 | if (new_rtx != XEXP (XEXP (x, 1), 1)) | ||
2108 | return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x, 0), | ||
2109 | @@ -2814,7 +2814,8 @@ | ||
2110 | case POPCOUNT: | ||
2111 | case PARITY: | ||
2112 | case BSWAP: | ||
2113 | - new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false); | ||
2114 | + new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false, | ||
2115 | + for_costs); | ||
2116 | if (new_rtx != XEXP (x, 0)) | ||
2117 | return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx); | ||
2118 | return x; | ||
2119 | @@ -2835,7 +2836,8 @@ | ||
2120 | new_rtx = SUBREG_REG (x); | ||
2121 | } | ||
2122 | else | ||
2123 | - new_rtx = eliminate_regs_1 (SUBREG_REG (x), mem_mode, insn, false); | ||
2124 | + new_rtx = eliminate_regs_1 (SUBREG_REG (x), mem_mode, insn, false, | ||
2125 | + for_costs); | ||
2126 | |||
2127 | if (new_rtx != SUBREG_REG (x)) | ||
2128 | { | ||
2129 | @@ -2869,14 +2871,20 @@ | ||
2130 | /* Our only special processing is to pass the mode of the MEM to our | ||
2131 | recursive call and copy the flags. While we are here, handle this | ||
2132 | case more efficiently. */ | ||
2133 | - return | ||
2134 | - replace_equiv_address_nv (x, | ||
2135 | - eliminate_regs_1 (XEXP (x, 0), GET_MODE (x), | ||
2136 | - insn, true)); | ||
2137 | + | ||
2138 | + new_rtx = eliminate_regs_1 (XEXP (x, 0), GET_MODE (x), insn, true, | ||
2139 | + for_costs); | ||
2140 | + if (for_costs | ||
2141 | + && memory_address_p (GET_MODE (x), XEXP (x, 0)) | ||
2142 | + && !memory_address_p (GET_MODE (x), new_rtx)) | ||
2143 | + for_each_rtx (&XEXP (x, 0), note_reg_elim_costly, insn); | ||
2144 | + | ||
2145 | + return replace_equiv_address_nv (x, new_rtx); | ||
2146 | |||
2147 | case USE: | ||
2148 | /* Handle insn_list USE that a call to a pure function may generate. */ | ||
2149 | - new_rtx = eliminate_regs_1 (XEXP (x, 0), VOIDmode, insn, false); | ||
2150 | + new_rtx = eliminate_regs_1 (XEXP (x, 0), VOIDmode, insn, false, | ||
2151 | + for_costs); | ||
2152 | if (new_rtx != XEXP (x, 0)) | ||
2153 | return gen_rtx_USE (GET_MODE (x), new_rtx); | ||
2154 | return x; | ||
2155 | @@ -2900,7 +2908,8 @@ | ||
2156 | { | ||
2157 | if (*fmt == 'e') | ||
2158 | { | ||
2159 | - new_rtx = eliminate_regs_1 (XEXP (x, i), mem_mode, insn, false); | ||
2160 | + new_rtx = eliminate_regs_1 (XEXP (x, i), mem_mode, insn, false, | ||
2161 | + for_costs); | ||
2162 | if (new_rtx != XEXP (x, i) && ! copied) | ||
2163 | { | ||
2164 | x = shallow_copy_rtx (x); | ||
2165 | @@ -2913,7 +2922,8 @@ | ||
2166 | int copied_vec = 0; | ||
2167 | for (j = 0; j < XVECLEN (x, i); j++) | ||
2168 | { | ||
2169 | - new_rtx = eliminate_regs_1 (XVECEXP (x, i, j), mem_mode, insn, false); | ||
2170 | + new_rtx = eliminate_regs_1 (XVECEXP (x, i, j), mem_mode, insn, false, | ||
2171 | + for_costs); | ||
2172 | if (new_rtx != XVECEXP (x, i, j) && ! copied_vec) | ||
2173 | { | ||
2174 | rtvec new_v = gen_rtvec_v (XVECLEN (x, i), | ||
2175 | @@ -2937,7 +2947,7 @@ | ||
2176 | rtx | ||
2177 | eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn) | ||
2178 | { | ||
2179 | - return eliminate_regs_1 (x, mem_mode, insn, false); | ||
2180 | + return eliminate_regs_1 (x, mem_mode, insn, false, false); | ||
2181 | } | ||
2182 | |||
2183 | /* Scan rtx X for modifications of elimination target registers. Update | ||
2184 | @@ -3455,7 +3465,8 @@ | ||
2185 | /* Companion to the above plus substitution, we can allow | ||
2186 | invariants as the source of a plain move. */ | ||
2187 | is_set_src = false; | ||
2188 | - if (old_set && recog_data.operand_loc[i] == &SET_SRC (old_set)) | ||
2189 | + if (old_set | ||
2190 | + && recog_data.operand_loc[i] == &SET_SRC (old_set)) | ||
2191 | is_set_src = true; | ||
2192 | in_plus = false; | ||
2193 | if (plus_src | ||
2194 | @@ -3466,7 +3477,7 @@ | ||
2195 | substed_operand[i] | ||
2196 | = eliminate_regs_1 (recog_data.operand[i], VOIDmode, | ||
2197 | replace ? insn : NULL_RTX, | ||
2198 | - is_set_src || in_plus); | ||
2199 | + is_set_src || in_plus, false); | ||
2200 | if (substed_operand[i] != orig_operand[i]) | ||
2201 | val = 1; | ||
2202 | /* Terminate the search in check_eliminable_occurrences at | ||
2203 | @@ -3594,11 +3605,167 @@ | ||
2204 | the pre-passes. */ | ||
2205 | if (val && REG_NOTES (insn) != 0) | ||
2206 | REG_NOTES (insn) | ||
2207 | - = eliminate_regs_1 (REG_NOTES (insn), VOIDmode, REG_NOTES (insn), true); | ||
2208 | + = eliminate_regs_1 (REG_NOTES (insn), VOIDmode, REG_NOTES (insn), true, | ||
2209 | + false); | ||
2210 | |||
2211 | return val; | ||
2212 | } | ||
2213 | |||
2214 | +/* Like eliminate_regs_in_insn, but only estimate costs for the use of the | ||
2215 | + register allocator. INSN is the instruction we need to examine, we perform | ||
2216 | + eliminations in its operands and record cases where eliminating a reg with | ||
2217 | + an invariant equivalence would add extra cost. */ | ||
2218 | + | ||
2219 | +static void | ||
2220 | +elimination_costs_in_insn (rtx insn) | ||
2221 | +{ | ||
2222 | + int icode = recog_memoized (insn); | ||
2223 | + rtx old_body = PATTERN (insn); | ||
2224 | + int insn_is_asm = asm_noperands (old_body) >= 0; | ||
2225 | + rtx old_set = single_set (insn); | ||
2226 | + int i; | ||
2227 | + rtx orig_operand[MAX_RECOG_OPERANDS]; | ||
2228 | + rtx orig_dup[MAX_RECOG_OPERANDS]; | ||
2229 | + struct elim_table *ep; | ||
2230 | + rtx plus_src, plus_cst_src; | ||
2231 | + bool sets_reg_p; | ||
2232 | + | ||
2233 | + if (! insn_is_asm && icode < 0) | ||
2234 | + { | ||
2235 | + gcc_assert (GET_CODE (PATTERN (insn)) == USE | ||
2236 | + || GET_CODE (PATTERN (insn)) == CLOBBER | ||
2237 | + || GET_CODE (PATTERN (insn)) == ADDR_VEC | ||
2238 | + || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC | ||
2239 | + || GET_CODE (PATTERN (insn)) == ASM_INPUT | ||
2240 | + || DEBUG_INSN_P (insn)); | ||
2241 | + return; | ||
2242 | + } | ||
2243 | + | ||
2244 | + if (old_set != 0 && REG_P (SET_DEST (old_set)) | ||
2245 | + && REGNO (SET_DEST (old_set)) < FIRST_PSEUDO_REGISTER) | ||
2246 | + { | ||
2247 | + /* Check for setting an eliminable register. */ | ||
2248 | + for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) | ||
2249 | + if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate) | ||
2250 | + return; | ||
2251 | + } | ||
2252 | + | ||
2253 | + /* We allow one special case which happens to work on all machines we | ||
2254 | + currently support: a single set with the source or a REG_EQUAL | ||
2255 | + note being a PLUS of an eliminable register and a constant. */ | ||
2256 | + plus_src = plus_cst_src = 0; | ||
2257 | + sets_reg_p = false; | ||
2258 | + if (old_set && REG_P (SET_DEST (old_set))) | ||
2259 | + { | ||
2260 | + sets_reg_p = true; | ||
2261 | + if (GET_CODE (SET_SRC (old_set)) == PLUS) | ||
2262 | + plus_src = SET_SRC (old_set); | ||
2263 | + /* First see if the source is of the form (plus (...) CST). */ | ||
2264 | + if (plus_src | ||
2265 | + && CONST_INT_P (XEXP (plus_src, 1))) | ||
2266 | + plus_cst_src = plus_src; | ||
2267 | + else if (REG_P (SET_SRC (old_set)) | ||
2268 | + || plus_src) | ||
2269 | + { | ||
2270 | + /* Otherwise, see if we have a REG_EQUAL note of the form | ||
2271 | + (plus (...) CST). */ | ||
2272 | + rtx links; | ||
2273 | + for (links = REG_NOTES (insn); links; links = XEXP (links, 1)) | ||
2274 | + { | ||
2275 | + if ((REG_NOTE_KIND (links) == REG_EQUAL | ||
2276 | + || REG_NOTE_KIND (links) == REG_EQUIV) | ||
2277 | + && GET_CODE (XEXP (links, 0)) == PLUS | ||
2278 | + && CONST_INT_P (XEXP (XEXP (links, 0), 1))) | ||
2279 | + { | ||
2280 | + plus_cst_src = XEXP (links, 0); | ||
2281 | + break; | ||
2282 | + } | ||
2283 | + } | ||
2284 | + } | ||
2285 | + } | ||
2286 | + | ||
2287 | + /* Determine the effects of this insn on elimination offsets. */ | ||
2288 | + elimination_effects (old_body, VOIDmode); | ||
2289 | + | ||
2290 | + /* Eliminate all eliminable registers occurring in operands that | ||
2291 | + can be handled by reload. */ | ||
2292 | + extract_insn (insn); | ||
2293 | + for (i = 0; i < recog_data.n_dups; i++) | ||
2294 | + orig_dup[i] = *recog_data.dup_loc[i]; | ||
2295 | + | ||
2296 | + for (i = 0; i < recog_data.n_operands; i++) | ||
2297 | + { | ||
2298 | + orig_operand[i] = recog_data.operand[i]; | ||
2299 | + | ||
2300 | + /* For an asm statement, every operand is eliminable. */ | ||
2301 | + if (insn_is_asm || insn_data[icode].operand[i].eliminable) | ||
2302 | + { | ||
2303 | + bool is_set_src, in_plus; | ||
2304 | + | ||
2305 | + /* Check for setting a register that we know about. */ | ||
2306 | + if (recog_data.operand_type[i] != OP_IN | ||
2307 | + && REG_P (orig_operand[i])) | ||
2308 | + { | ||
2309 | + /* If we are assigning to a register that can be eliminated, it | ||
2310 | + must be as part of a PARALLEL, since the code above handles | ||
2311 | + single SETs. We must indicate that we can no longer | ||
2312 | + eliminate this reg. */ | ||
2313 | + for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; | ||
2314 | + ep++) | ||
2315 | + if (ep->from_rtx == orig_operand[i]) | ||
2316 | + ep->can_eliminate = 0; | ||
2317 | + } | ||
2318 | + | ||
2319 | + /* Companion to the above plus substitution, we can allow | ||
2320 | + invariants as the source of a plain move. */ | ||
2321 | + is_set_src = false; | ||
2322 | + if (old_set && recog_data.operand_loc[i] == &SET_SRC (old_set)) | ||
2323 | + is_set_src = true; | ||
2324 | + if (is_set_src && !sets_reg_p) | ||
2325 | + note_reg_elim_costly (&SET_SRC (old_set), insn); | ||
2326 | + in_plus = false; | ||
2327 | + if (plus_src && sets_reg_p | ||
2328 | + && (recog_data.operand_loc[i] == &XEXP (plus_src, 0) | ||
2329 | + || recog_data.operand_loc[i] == &XEXP (plus_src, 1))) | ||
2330 | + in_plus = true; | ||
2331 | + | ||
2332 | + eliminate_regs_1 (recog_data.operand[i], VOIDmode, | ||
2333 | + NULL_RTX, | ||
2334 | + is_set_src || in_plus, true); | ||
2335 | + /* Terminate the search in check_eliminable_occurrences at | ||
2336 | + this point. */ | ||
2337 | + *recog_data.operand_loc[i] = 0; | ||
2338 | + } | ||
2339 | + } | ||
2340 | + | ||
2341 | + for (i = 0; i < recog_data.n_dups; i++) | ||
2342 | + *recog_data.dup_loc[i] | ||
2343 | + = *recog_data.operand_loc[(int) recog_data.dup_num[i]]; | ||
2344 | + | ||
2345 | + /* If any eliminable remain, they aren't eliminable anymore. */ | ||
2346 | + check_eliminable_occurrences (old_body); | ||
2347 | + | ||
2348 | + /* Restore the old body. */ | ||
2349 | + for (i = 0; i < recog_data.n_operands; i++) | ||
2350 | + *recog_data.operand_loc[i] = orig_operand[i]; | ||
2351 | + for (i = 0; i < recog_data.n_dups; i++) | ||
2352 | + *recog_data.dup_loc[i] = orig_dup[i]; | ||
2353 | + | ||
2354 | + /* Update all elimination pairs to reflect the status after the current | ||
2355 | + insn. The changes we make were determined by the earlier call to | ||
2356 | + elimination_effects. */ | ||
2357 | + | ||
2358 | + for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) | ||
2359 | + { | ||
2360 | + if (ep->previous_offset != ep->offset && ep->ref_outside_mem) | ||
2361 | + ep->can_eliminate = 0; | ||
2362 | + | ||
2363 | + ep->ref_outside_mem = 0; | ||
2364 | + } | ||
2365 | + | ||
2366 | + return; | ||
2367 | +} | ||
2368 | + | ||
2369 | /* Loop through all elimination pairs. | ||
2370 | Recalculate the number not at initial offset. | ||
2371 | |||
2372 | @@ -3908,6 +4075,168 @@ | ||
2373 | ep->to_rtx = gen_rtx_REG (Pmode, ep->to); | ||
2374 | } | ||
2375 | } | ||
2376 | + | ||
2377 | +/* Find all the pseudo registers that didn't get hard regs | ||
2378 | + but do have known equivalent constants or memory slots. | ||
2379 | + These include parameters (known equivalent to parameter slots) | ||
2380 | + and cse'd or loop-moved constant memory addresses. | ||
2381 | + | ||
2382 | + Record constant equivalents in reg_equiv_constant | ||
2383 | + so they will be substituted by find_reloads. | ||
2384 | + Record memory equivalents in reg_mem_equiv so they can | ||
2385 | + be substituted eventually by altering the REG-rtx's. */ | ||
2386 | + | ||
2387 | +static void | ||
2388 | +init_eliminable_invariants (rtx first, bool do_subregs) | ||
2389 | +{ | ||
2390 | + int i; | ||
2391 | + rtx insn; | ||
2392 | + | ||
2393 | + reg_equiv_constant = XCNEWVEC (rtx, max_regno); | ||
2394 | + reg_equiv_invariant = XCNEWVEC (rtx, max_regno); | ||
2395 | + reg_equiv_mem = XCNEWVEC (rtx, max_regno); | ||
2396 | + reg_equiv_alt_mem_list = XCNEWVEC (rtx, max_regno); | ||
2397 | + reg_equiv_address = XCNEWVEC (rtx, max_regno); | ||
2398 | + if (do_subregs) | ||
2399 | + reg_max_ref_width = XCNEWVEC (unsigned int, max_regno); | ||
2400 | + else | ||
2401 | + reg_max_ref_width = NULL; | ||
2402 | + | ||
2403 | + num_eliminable_invariants = 0; | ||
2404 | + | ||
2405 | + first_label_num = get_first_label_num (); | ||
2406 | + num_labels = max_label_num () - first_label_num; | ||
2407 | + | ||
2408 | + /* Allocate the tables used to store offset information at labels. */ | ||
2409 | + offsets_known_at = XNEWVEC (char, num_labels); | ||
2410 | + offsets_at = (HOST_WIDE_INT (*)[NUM_ELIMINABLE_REGS]) xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (HOST_WIDE_INT)); | ||
2411 | + | ||
2412 | +/* Look for REG_EQUIV notes; record what each pseudo is equivalent | ||
2413 | + to. If DO_SUBREGS is true, also find all paradoxical subregs and | ||
2414 | + find largest such for each pseudo. FIRST is the head of the insn | ||
2415 | + list. */ | ||
2416 | + | ||
2417 | + for (insn = first; insn; insn = NEXT_INSN (insn)) | ||
2418 | + { | ||
2419 | + rtx set = single_set (insn); | ||
2420 | + | ||
2421 | + /* We may introduce USEs that we want to remove at the end, so | ||
2422 | + we'll mark them with QImode. Make sure there are no | ||
2423 | + previously-marked insns left by say regmove. */ | ||
2424 | + if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE | ||
2425 | + && GET_MODE (insn) != VOIDmode) | ||
2426 | + PUT_MODE (insn, VOIDmode); | ||
2427 | + | ||
2428 | + if (do_subregs && NONDEBUG_INSN_P (insn)) | ||
2429 | + scan_paradoxical_subregs (PATTERN (insn)); | ||
2430 | + | ||
2431 | + if (set != 0 && REG_P (SET_DEST (set))) | ||
2432 | + { | ||
2433 | + rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX); | ||
2434 | + rtx x; | ||
2435 | + | ||
2436 | + if (! note) | ||
2437 | + continue; | ||
2438 | + | ||
2439 | + i = REGNO (SET_DEST (set)); | ||
2440 | + x = XEXP (note, 0); | ||
2441 | + | ||
2442 | + if (i <= LAST_VIRTUAL_REGISTER) | ||
2443 | + continue; | ||
2444 | + | ||
2445 | + /* If flag_pic and we have constant, verify it's legitimate. */ | ||
2446 | + if (!CONSTANT_P (x) | ||
2447 | + || !flag_pic || LEGITIMATE_PIC_OPERAND_P (x)) | ||
2448 | + { | ||
2449 | + /* It can happen that a REG_EQUIV note contains a MEM | ||
2450 | + that is not a legitimate memory operand. As later | ||
2451 | + stages of reload assume that all addresses found | ||
2452 | + in the reg_equiv_* arrays were originally legitimate, | ||
2453 | + we ignore such REG_EQUIV notes. */ | ||
2454 | + if (memory_operand (x, VOIDmode)) | ||
2455 | + { | ||
2456 | + /* Always unshare the equivalence, so we can | ||
2457 | + substitute into this insn without touching the | ||
2458 | + equivalence. */ | ||
2459 | + reg_equiv_memory_loc[i] = copy_rtx (x); | ||
2460 | + } | ||
2461 | + else if (function_invariant_p (x)) | ||
2462 | + { | ||
2463 | + if (GET_CODE (x) == PLUS) | ||
2464 | + { | ||
2465 | + /* This is PLUS of frame pointer and a constant, | ||
2466 | + and might be shared. Unshare it. */ | ||
2467 | + reg_equiv_invariant[i] = copy_rtx (x); | ||
2468 | + num_eliminable_invariants++; | ||
2469 | + } | ||
2470 | + else if (x == frame_pointer_rtx || x == arg_pointer_rtx) | ||
2471 | + { | ||
2472 | + reg_equiv_invariant[i] = x; | ||
2473 | + num_eliminable_invariants++; | ||
2474 | + } | ||
2475 | + else if (LEGITIMATE_CONSTANT_P (x)) | ||
2476 | + reg_equiv_constant[i] = x; | ||
2477 | + else | ||
2478 | + { | ||
2479 | + reg_equiv_memory_loc[i] | ||
2480 | + = force_const_mem (GET_MODE (SET_DEST (set)), x); | ||
2481 | + if (! reg_equiv_memory_loc[i]) | ||
2482 | + reg_equiv_init[i] = NULL_RTX; | ||
2483 | + } | ||
2484 | + } | ||
2485 | + else | ||
2486 | + { | ||
2487 | + reg_equiv_init[i] = NULL_RTX; | ||
2488 | + continue; | ||
2489 | + } | ||
2490 | + } | ||
2491 | + else | ||
2492 | + reg_equiv_init[i] = NULL_RTX; | ||
2493 | + } | ||
2494 | + } | ||
2495 | + | ||
2496 | + if (dump_file) | ||
2497 | + for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) | ||
2498 | + if (reg_equiv_init[i]) | ||
2499 | + { | ||
2500 | + fprintf (dump_file, "init_insns for %u: ", i); | ||
2501 | + print_inline_rtx (dump_file, reg_equiv_init[i], 20); | ||
2502 | + fprintf (dump_file, "\n"); | ||
2503 | + } | ||
2504 | +} | ||
2505 | + | ||
2506 | +/* Indicate that we no longer have known memory locations or constants. | ||
2507 | + Free all data involved in tracking these. */ | ||
2508 | + | ||
2509 | +static void | ||
2510 | +free_reg_equiv (void) | ||
2511 | +{ | ||
2512 | + int i; | ||
2513 | + | ||
2514 | + if (reg_equiv_constant) | ||
2515 | + free (reg_equiv_constant); | ||
2516 | + if (reg_equiv_invariant) | ||
2517 | + free (reg_equiv_invariant); | ||
2518 | + reg_equiv_constant = 0; | ||
2519 | + reg_equiv_invariant = 0; | ||
2520 | + VEC_free (rtx, gc, reg_equiv_memory_loc_vec); | ||
2521 | + reg_equiv_memory_loc = 0; | ||
2522 | + | ||
2523 | + if (offsets_known_at) | ||
2524 | + free (offsets_known_at); | ||
2525 | + if (offsets_at) | ||
2526 | + free (offsets_at); | ||
2527 | + offsets_at = 0; | ||
2528 | + offsets_known_at = 0; | ||
2529 | + | ||
2530 | + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | ||
2531 | + if (reg_equiv_alt_mem_list[i]) | ||
2532 | + free_EXPR_LIST_list (®_equiv_alt_mem_list[i]); | ||
2533 | + free (reg_equiv_alt_mem_list); | ||
2534 | + | ||
2535 | + free (reg_equiv_mem); | ||
2536 | + free (reg_equiv_address); | ||
2537 | +} | ||
2538 | |||
2539 | /* Kick all pseudos out of hard register REGNO. | ||
2540 | |||
2541 | @@ -5664,7 +5993,7 @@ | ||
2542 | return 1; | ||
2543 | if (GET_CODE (x) == PLUS | ||
2544 | && (XEXP (x, 0) == frame_pointer_rtx || XEXP (x, 0) == arg_pointer_rtx) | ||
2545 | - && CONSTANT_P (XEXP (x, 1))) | ||
2546 | + && GET_CODE (XEXP (x, 1)) == CONST_INT) | ||
2547 | return 1; | ||
2548 | return 0; | ||
2549 | } | ||
2550 | |||
2551 | === modified file 'gcc/system.h' | ||
2552 | --- old/gcc/system.h 2009-12-13 23:00:53 +0000 | ||
2553 | +++ new/gcc/system.h 2010-09-01 13:29:58 +0000 | ||
2554 | @@ -761,7 +761,8 @@ | ||
2555 | TARGET_ASM_EXCEPTION_SECTION TARGET_ASM_EH_FRAME_SECTION \ | ||
2556 | SMALL_ARG_MAX ASM_OUTPUT_SHARED_BSS ASM_OUTPUT_SHARED_COMMON \ | ||
2557 | ASM_OUTPUT_SHARED_LOCAL ASM_MAKE_LABEL_LINKONCE \ | ||
2558 | - STACK_CHECK_PROBE_INTERVAL STACK_CHECK_PROBE_LOAD | ||
2559 | + STACK_CHECK_PROBE_INTERVAL STACK_CHECK_PROBE_LOAD \ | ||
2560 | + ORDER_REGS_FOR_LOCAL_ALLOC | ||
2561 | |||
2562 | /* Hooks that are no longer used. */ | ||
2563 | #pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE \ | ||
2564 | |||
2565 | === added file 'gcc/testsuite/c-c++-common/uninit-17.c' | ||
2566 | --- old/gcc/testsuite/c-c++-common/uninit-17.c 1970-01-01 00:00:00 +0000 | ||
2567 | +++ new/gcc/testsuite/c-c++-common/uninit-17.c 2010-09-01 13:29:58 +0000 | ||
2568 | @@ -0,0 +1,25 @@ | ||
2569 | +/* { dg-do compile } */ | ||
2570 | +/* { dg-options "-O2 -Wuninitialized" } */ | ||
2571 | + | ||
2572 | +inline int foo(int x) | ||
2573 | +{ | ||
2574 | + return x; | ||
2575 | +} | ||
2576 | +static void bar(int a, int *ptr) | ||
2577 | +{ | ||
2578 | + do | ||
2579 | + { | ||
2580 | + int b; /* { dg-warning "is used uninitialized" } */ | ||
2581 | + if (b < 40) { | ||
2582 | + ptr[0] = b; | ||
2583 | + } | ||
2584 | + b += 1; | ||
2585 | + ptr++; | ||
2586 | + } | ||
2587 | + while (--a != 0); | ||
2588 | +} | ||
2589 | +void foobar(int a, int *ptr) | ||
2590 | +{ | ||
2591 | + bar(foo(a), ptr); | ||
2592 | +} | ||
2593 | + | ||
2594 | |||
2595 | === added file 'gcc/testsuite/gcc.target/arm/eliminate.c' | ||
2596 | --- old/gcc/testsuite/gcc.target/arm/eliminate.c 1970-01-01 00:00:00 +0000 | ||
2597 | +++ new/gcc/testsuite/gcc.target/arm/eliminate.c 2010-09-01 13:29:58 +0000 | ||
2598 | @@ -0,0 +1,19 @@ | ||
2599 | +/* { dg-do compile } */ | ||
2600 | +/* { dg-options "-O2" } */ | ||
2601 | + | ||
2602 | +struct X | ||
2603 | +{ | ||
2604 | + int c; | ||
2605 | +}; | ||
2606 | + | ||
2607 | +extern void bar(struct X *); | ||
2608 | + | ||
2609 | +void foo () | ||
2610 | +{ | ||
2611 | + struct X x; | ||
2612 | + bar (&x); | ||
2613 | + bar (&x); | ||
2614 | + bar (&x); | ||
2615 | +} | ||
2616 | + | ||
2617 | +/* { dg-final { scan-assembler-times "r0,\[\\t \]*sp" 3 } } */ | ||
2618 | |||
2619 | === added file 'gcc/testsuite/gcc.target/arm/pr40900.c' | ||
2620 | --- old/gcc/testsuite/gcc.target/arm/pr40900.c 1970-01-01 00:00:00 +0000 | ||
2621 | +++ new/gcc/testsuite/gcc.target/arm/pr40900.c 2010-09-01 13:29:58 +0000 | ||
2622 | @@ -0,0 +1,12 @@ | ||
2623 | +/* { dg-do compile } */ | ||
2624 | +/* { dg-options "-O2 -fno-optimize-sibling-calls" } */ | ||
2625 | + | ||
2626 | +extern short shortv2(); | ||
2627 | +short shortv1() | ||
2628 | +{ | ||
2629 | + return shortv2(); | ||
2630 | +} | ||
2631 | + | ||
2632 | +/* { dg-final { scan-assembler-not "lsl" } } */ | ||
2633 | +/* { dg-final { scan-assembler-not "asr" } } */ | ||
2634 | +/* { dg-final { scan-assembler-not "sxth" } } */ | ||
2635 | |||
2636 | === added file 'gcc/testsuite/gcc.target/arm/pr42496.c' | ||
2637 | --- old/gcc/testsuite/gcc.target/arm/pr42496.c 1970-01-01 00:00:00 +0000 | ||
2638 | +++ new/gcc/testsuite/gcc.target/arm/pr42496.c 2010-09-01 13:29:58 +0000 | ||
2639 | @@ -0,0 +1,16 @@ | ||
2640 | +/* { dg-options "-O2" } */ | ||
2641 | + | ||
2642 | +void foo(int i) | ||
2643 | +{ | ||
2644 | + extern int j; | ||
2645 | + | ||
2646 | + if (i) { | ||
2647 | + j = 10; | ||
2648 | + } | ||
2649 | + else { | ||
2650 | + j = 20; | ||
2651 | + } | ||
2652 | +} | ||
2653 | + | ||
2654 | +/* { dg-final { scan-assembler-not "strne" } } */ | ||
2655 | +/* { dg-final { scan-assembler-not "streq" } } */ | ||
2656 | |||
2657 | === added file 'gcc/testsuite/gcc.target/arm/wmul-1.c' | ||
2658 | --- old/gcc/testsuite/gcc.target/arm/wmul-1.c 1970-01-01 00:00:00 +0000 | ||
2659 | +++ new/gcc/testsuite/gcc.target/arm/wmul-1.c 2010-09-01 13:29:58 +0000 | ||
2660 | @@ -0,0 +1,18 @@ | ||
2661 | +/* { dg-do compile } */ | ||
2662 | +/* { dg-options "-O2 -march=armv6t2 -fno-unroll-loops" } */ | ||
2663 | + | ||
2664 | +int mac(const short *a, const short *b, int sqr, int *sum) | ||
2665 | +{ | ||
2666 | + int i; | ||
2667 | + int dotp = *sum; | ||
2668 | + | ||
2669 | + for (i = 0; i < 150; i++) { | ||
2670 | + dotp += b[i] * a[i]; | ||
2671 | + sqr += b[i] * b[i]; | ||
2672 | + } | ||
2673 | + | ||
2674 | + *sum = dotp; | ||
2675 | + return sqr; | ||
2676 | +} | ||
2677 | + | ||
2678 | +/* { dg-final { scan-assembler-times "smulbb" 2 } } */ | ||
2679 | |||
2680 | === added file 'gcc/testsuite/gcc.target/arm/wmul-2.c' | ||
2681 | --- old/gcc/testsuite/gcc.target/arm/wmul-2.c 1970-01-01 00:00:00 +0000 | ||
2682 | +++ new/gcc/testsuite/gcc.target/arm/wmul-2.c 2010-09-01 13:29:58 +0000 | ||
2683 | @@ -0,0 +1,12 @@ | ||
2684 | +/* { dg-do compile } */ | ||
2685 | +/* { dg-options "-O2 -march=armv6t2 -fno-unroll-loops" } */ | ||
2686 | + | ||
2687 | +void vec_mpy(int y[], const short x[], short scaler) | ||
2688 | +{ | ||
2689 | + int i; | ||
2690 | + | ||
2691 | + for (i = 0; i < 150; i++) | ||
2692 | + y[i] += ((scaler * x[i]) >> 31); | ||
2693 | +} | ||
2694 | + | ||
2695 | +/* { dg-final { scan-assembler-times "smulbb" 1 } } */ | ||
2696 | |||
2697 | === added file 'gcc/testsuite/gcc.target/bfin/wmul-1.c' | ||
2698 | --- old/gcc/testsuite/gcc.target/bfin/wmul-1.c 1970-01-01 00:00:00 +0000 | ||
2699 | +++ new/gcc/testsuite/gcc.target/bfin/wmul-1.c 2010-09-01 13:29:58 +0000 | ||
2700 | @@ -0,0 +1,18 @@ | ||
2701 | +/* { dg-do compile } */ | ||
2702 | +/* { dg-options "-O2" } */ | ||
2703 | + | ||
2704 | +int mac(const short *a, const short *b, int sqr, int *sum) | ||
2705 | +{ | ||
2706 | + int i; | ||
2707 | + int dotp = *sum; | ||
2708 | + | ||
2709 | + for (i = 0; i < 150; i++) { | ||
2710 | + dotp += b[i] * a[i]; | ||
2711 | + sqr += b[i] * b[i]; | ||
2712 | + } | ||
2713 | + | ||
2714 | + *sum = dotp; | ||
2715 | + return sqr; | ||
2716 | +} | ||
2717 | + | ||
2718 | +/* { dg-final { scan-assembler-times "\\(IS\\)" 2 } } */ | ||
2719 | |||
2720 | === added file 'gcc/testsuite/gcc.target/bfin/wmul-2.c' | ||
2721 | --- old/gcc/testsuite/gcc.target/bfin/wmul-2.c 1970-01-01 00:00:00 +0000 | ||
2722 | +++ new/gcc/testsuite/gcc.target/bfin/wmul-2.c 2010-09-01 13:29:58 +0000 | ||
2723 | @@ -0,0 +1,12 @@ | ||
2724 | +/* { dg-do compile } */ | ||
2725 | +/* { dg-options "-O2" } */ | ||
2726 | + | ||
2727 | +void vec_mpy(int y[], const short x[], short scaler) | ||
2728 | +{ | ||
2729 | + int i; | ||
2730 | + | ||
2731 | + for (i = 0; i < 150; i++) | ||
2732 | + y[i] += ((scaler * x[i]) >> 31); | ||
2733 | +} | ||
2734 | + | ||
2735 | +/* { dg-final { scan-assembler-times "\\(IS\\)" 1 } } */ | ||
2736 | |||
2737 | === added file 'gcc/testsuite/gcc.target/i386/pr41442.c' | ||
2738 | --- old/gcc/testsuite/gcc.target/i386/pr41442.c 1970-01-01 00:00:00 +0000 | ||
2739 | +++ new/gcc/testsuite/gcc.target/i386/pr41442.c 2010-09-01 13:29:58 +0000 | ||
2740 | @@ -0,0 +1,18 @@ | ||
2741 | +/* { dg-do compile } */ | ||
2742 | +/* { dg-options "-O2" } */ | ||
2743 | + | ||
2744 | +typedef struct LINK link; | ||
2745 | +struct LINK | ||
2746 | +{ | ||
2747 | + link* next; | ||
2748 | +}; | ||
2749 | + | ||
2750 | +int haha(link* p1, link* p2) | ||
2751 | +{ | ||
2752 | + if ((p1->next && !p2->next) || p2->next) | ||
2753 | + return 0; | ||
2754 | + | ||
2755 | + return 1; | ||
2756 | +} | ||
2757 | + | ||
2758 | +/* { dg-final { scan-assembler-times "test|cmp" 2 } } */ | ||
2759 | |||
2760 | === added file 'gcc/testsuite/gcc.target/i386/wmul-1.c' | ||
2761 | --- old/gcc/testsuite/gcc.target/i386/wmul-1.c 1970-01-01 00:00:00 +0000 | ||
2762 | +++ new/gcc/testsuite/gcc.target/i386/wmul-1.c 2010-09-01 13:29:58 +0000 | ||
2763 | @@ -0,0 +1,18 @@ | ||
2764 | +/* { dg-do compile } */ | ||
2765 | +/* { dg-options "-O2" } */ | ||
2766 | + | ||
2767 | +long long mac(const int *a, const int *b, long long sqr, long long *sum) | ||
2768 | +{ | ||
2769 | + int i; | ||
2770 | + long long dotp = *sum; | ||
2771 | + | ||
2772 | + for (i = 0; i < 150; i++) { | ||
2773 | + dotp += (long long)b[i] * a[i]; | ||
2774 | + sqr += (long long)b[i] * b[i]; | ||
2775 | + } | ||
2776 | + | ||
2777 | + *sum = dotp; | ||
2778 | + return sqr; | ||
2779 | +} | ||
2780 | + | ||
2781 | +/* { dg-final { scan-assembler-times "imull" 2 } } */ | ||
2782 | |||
2783 | === added file 'gcc/testsuite/gcc.target/i386/wmul-2.c' | ||
2784 | --- old/gcc/testsuite/gcc.target/i386/wmul-2.c 1970-01-01 00:00:00 +0000 | ||
2785 | +++ new/gcc/testsuite/gcc.target/i386/wmul-2.c 2010-09-01 13:29:58 +0000 | ||
2786 | @@ -0,0 +1,12 @@ | ||
2787 | +/* { dg-do compile } */ | ||
2788 | +/* { dg-options "-O2" } */ | ||
2789 | + | ||
2790 | +void vec_mpy(int y[], const int x[], int scaler) | ||
2791 | +{ | ||
2792 | + int i; | ||
2793 | + | ||
2794 | + for (i = 0; i < 150; i++) | ||
2795 | + y[i] += (((long long)scaler * x[i]) >> 31); | ||
2796 | +} | ||
2797 | + | ||
2798 | +/* { dg-final { scan-assembler-times "imull" 1 } } */ | ||
2799 | |||
2800 | === modified file 'gcc/tree-cfg.c' | ||
2801 | --- old/gcc/tree-cfg.c 2010-08-10 13:31:21 +0000 | ||
2802 | +++ new/gcc/tree-cfg.c 2010-09-01 13:29:58 +0000 | ||
2803 | @@ -3428,8 +3428,13 @@ | ||
2804 | connected to the operand types. */ | ||
2805 | return verify_gimple_comparison (lhs_type, rhs1, rhs2); | ||
2806 | |||
2807 | + case WIDEN_MULT_EXPR: | ||
2808 | + if (TREE_CODE (lhs_type) != INTEGER_TYPE) | ||
2809 | + return true; | ||
2810 | + return ((2 * TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (lhs_type)) | ||
2811 | + || (TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type))); | ||
2812 | + | ||
2813 | case WIDEN_SUM_EXPR: | ||
2814 | - case WIDEN_MULT_EXPR: | ||
2815 | case VEC_WIDEN_MULT_HI_EXPR: | ||
2816 | case VEC_WIDEN_MULT_LO_EXPR: | ||
2817 | case VEC_PACK_TRUNC_EXPR: | ||
2818 | |||
2819 | === modified file 'gcc/tree-inline.c' | ||
2820 | --- old/gcc/tree-inline.c 2010-08-10 13:31:21 +0000 | ||
2821 | +++ new/gcc/tree-inline.c 2010-09-01 13:29:58 +0000 | ||
2822 | @@ -229,6 +229,7 @@ | ||
2823 | regions of the CFG, but this is expensive to test. */ | ||
2824 | if (id->entry_bb | ||
2825 | && is_gimple_reg (SSA_NAME_VAR (name)) | ||
2826 | + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name) | ||
2827 | && TREE_CODE (SSA_NAME_VAR (name)) != PARM_DECL | ||
2828 | && (id->entry_bb != EDGE_SUCC (ENTRY_BLOCK_PTR, 0)->dest | ||
2829 | || EDGE_COUNT (id->entry_bb->preds) != 1)) | ||
2830 | |||
2831 | === modified file 'gcc/tree-pass.h' | ||
2832 | --- old/gcc/tree-pass.h 2010-04-02 18:54:46 +0000 | ||
2833 | +++ new/gcc/tree-pass.h 2010-09-01 13:29:58 +0000 | ||
2834 | @@ -407,6 +407,7 @@ | ||
2835 | extern struct gimple_opt_pass pass_cse_reciprocals; | ||
2836 | extern struct gimple_opt_pass pass_cse_sincos; | ||
2837 | extern struct gimple_opt_pass pass_optimize_bswap; | ||
2838 | +extern struct gimple_opt_pass pass_optimize_widening_mul; | ||
2839 | extern struct gimple_opt_pass pass_warn_function_return; | ||
2840 | extern struct gimple_opt_pass pass_warn_function_noreturn; | ||
2841 | extern struct gimple_opt_pass pass_cselim; | ||
2842 | |||
2843 | === modified file 'gcc/tree-ssa-math-opts.c' | ||
2844 | --- old/gcc/tree-ssa-math-opts.c 2010-04-02 18:54:46 +0000 | ||
2845 | +++ new/gcc/tree-ssa-math-opts.c 2010-09-01 13:29:58 +0000 | ||
2846 | @@ -1260,3 +1260,137 @@ | ||
2847 | 0 /* todo_flags_finish */ | ||
2848 | } | ||
2849 | }; | ||
2850 | + | ||
2851 | +/* Find integer multiplications where the operands are extended from | ||
2852 | + smaller types, and replace the MULT_EXPR with a WIDEN_MULT_EXPR | ||
2853 | + where appropriate. */ | ||
2854 | + | ||
2855 | +static unsigned int | ||
2856 | +execute_optimize_widening_mul (void) | ||
2857 | +{ | ||
2858 | + bool changed = false; | ||
2859 | + basic_block bb; | ||
2860 | + | ||
2861 | + FOR_EACH_BB (bb) | ||
2862 | + { | ||
2863 | + gimple_stmt_iterator gsi; | ||
2864 | + | ||
2865 | + for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | ||
2866 | + { | ||
2867 | + gimple stmt = gsi_stmt (gsi); | ||
2868 | + gimple rhs1_stmt = NULL, rhs2_stmt = NULL; | ||
2869 | + tree type, type1 = NULL, type2 = NULL; | ||
2870 | + tree rhs1, rhs2, rhs1_convop = NULL, rhs2_convop = NULL; | ||
2871 | + enum tree_code rhs1_code, rhs2_code; | ||
2872 | + | ||
2873 | + if (!is_gimple_assign (stmt) | ||
2874 | + || gimple_assign_rhs_code (stmt) != MULT_EXPR) | ||
2875 | + continue; | ||
2876 | + | ||
2877 | + type = TREE_TYPE (gimple_assign_lhs (stmt)); | ||
2878 | + | ||
2879 | + if (TREE_CODE (type) != INTEGER_TYPE) | ||
2880 | + continue; | ||
2881 | + | ||
2882 | + rhs1 = gimple_assign_rhs1 (stmt); | ||
2883 | + rhs2 = gimple_assign_rhs2 (stmt); | ||
2884 | + | ||
2885 | + if (TREE_CODE (rhs1) == SSA_NAME) | ||
2886 | + { | ||
2887 | + rhs1_stmt = SSA_NAME_DEF_STMT (rhs1); | ||
2888 | + if (!is_gimple_assign (rhs1_stmt)) | ||
2889 | + continue; | ||
2890 | + rhs1_code = gimple_assign_rhs_code (rhs1_stmt); | ||
2891 | + if (!CONVERT_EXPR_CODE_P (rhs1_code)) | ||
2892 | + continue; | ||
2893 | + rhs1_convop = gimple_assign_rhs1 (rhs1_stmt); | ||
2894 | + type1 = TREE_TYPE (rhs1_convop); | ||
2895 | + if (TYPE_PRECISION (type1) * 2 != TYPE_PRECISION (type)) | ||
2896 | + continue; | ||
2897 | + } | ||
2898 | + else if (TREE_CODE (rhs1) != INTEGER_CST) | ||
2899 | + continue; | ||
2900 | + | ||
2901 | + if (TREE_CODE (rhs2) == SSA_NAME) | ||
2902 | + { | ||
2903 | + rhs2_stmt = SSA_NAME_DEF_STMT (rhs2); | ||
2904 | + if (!is_gimple_assign (rhs2_stmt)) | ||
2905 | + continue; | ||
2906 | + rhs2_code = gimple_assign_rhs_code (rhs2_stmt); | ||
2907 | + if (!CONVERT_EXPR_CODE_P (rhs2_code)) | ||
2908 | + continue; | ||
2909 | + rhs2_convop = gimple_assign_rhs1 (rhs2_stmt); | ||
2910 | + type2 = TREE_TYPE (rhs2_convop); | ||
2911 | + if (TYPE_PRECISION (type2) * 2 != TYPE_PRECISION (type)) | ||
2912 | + continue; | ||
2913 | + } | ||
2914 | + else if (TREE_CODE (rhs2) != INTEGER_CST) | ||
2915 | + continue; | ||
2916 | + | ||
2917 | + if (rhs1_stmt == NULL && rhs2_stmt == NULL) | ||
2918 | + continue; | ||
2919 | + | ||
2920 | + /* Verify that the machine can perform a widening multiply in this | ||
2921 | + mode/signedness combination, otherwise this transformation is | ||
2922 | + likely to pessimize code. */ | ||
2923 | + if ((rhs1_stmt == NULL || TYPE_UNSIGNED (type1)) | ||
2924 | + && (rhs2_stmt == NULL || TYPE_UNSIGNED (type2)) | ||
2925 | + && (optab_handler (umul_widen_optab, TYPE_MODE (type)) | ||
2926 | + ->insn_code == CODE_FOR_nothing)) | ||
2927 | + continue; | ||
2928 | + else if ((rhs1_stmt == NULL || !TYPE_UNSIGNED (type1)) | ||
2929 | + && (rhs2_stmt == NULL || !TYPE_UNSIGNED (type2)) | ||
2930 | + && (optab_handler (smul_widen_optab, TYPE_MODE (type)) | ||
2931 | + ->insn_code == CODE_FOR_nothing)) | ||
2932 | + continue; | ||
2933 | + else if (rhs1_stmt != NULL && rhs2_stmt != 0 | ||
2934 | + && (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2)) | ||
2935 | + && (optab_handler (usmul_widen_optab, TYPE_MODE (type)) | ||
2936 | + ->insn_code == CODE_FOR_nothing)) | ||
2937 | + continue; | ||
2938 | + | ||
2939 | + if ((rhs1_stmt == NULL && !int_fits_type_p (rhs1, type2)) | ||
2940 | + || (rhs2_stmt == NULL && !int_fits_type_p (rhs2, type1))) | ||
2941 | + continue; | ||
2942 | + | ||
2943 | + if (rhs1_stmt == NULL) | ||
2944 | + gimple_assign_set_rhs1 (stmt, fold_convert (type2, rhs1)); | ||
2945 | + else | ||
2946 | + gimple_assign_set_rhs1 (stmt, rhs1_convop); | ||
2947 | + if (rhs2_stmt == NULL) | ||
2948 | + gimple_assign_set_rhs2 (stmt, fold_convert (type1, rhs2)); | ||
2949 | + else | ||
2950 | + gimple_assign_set_rhs2 (stmt, rhs2_convop); | ||
2951 | + gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR); | ||
2952 | + update_stmt (stmt); | ||
2953 | + changed = true; | ||
2954 | + } | ||
2955 | + } | ||
2956 | + return (changed ? TODO_dump_func | TODO_update_ssa | TODO_verify_ssa | ||
2957 | + | TODO_verify_stmts : 0); | ||
2958 | +} | ||
2959 | + | ||
2960 | +static bool | ||
2961 | +gate_optimize_widening_mul (void) | ||
2962 | +{ | ||
2963 | + return flag_expensive_optimizations && optimize; | ||
2964 | +} | ||
2965 | + | ||
2966 | +struct gimple_opt_pass pass_optimize_widening_mul = | ||
2967 | +{ | ||
2968 | + { | ||
2969 | + GIMPLE_PASS, | ||
2970 | + "widening_mul", /* name */ | ||
2971 | + gate_optimize_widening_mul, /* gate */ | ||
2972 | + execute_optimize_widening_mul, /* execute */ | ||
2973 | + NULL, /* sub */ | ||
2974 | + NULL, /* next */ | ||
2975 | + 0, /* static_pass_number */ | ||
2976 | + TV_NONE, /* tv_id */ | ||
2977 | + PROP_ssa, /* properties_required */ | ||
2978 | + 0, /* properties_provided */ | ||
2979 | + 0, /* properties_destroyed */ | ||
2980 | + 0, /* todo_flags_start */ | ||
2981 | + 0 /* todo_flags_finish */ | ||
2982 | + } | ||
2983 | +}; | ||
2984 | |||
2985 | === modified file 'gcc/tree-ssa.c' | ||
2986 | --- old/gcc/tree-ssa.c 2009-12-07 22:42:10 +0000 | ||
2987 | +++ new/gcc/tree-ssa.c 2010-09-01 13:29:58 +0000 | ||
2988 | @@ -1671,6 +1671,8 @@ | ||
2989 | { | ||
2990 | TREE_NO_WARNING (var) = 1; | ||
2991 | |||
2992 | + if (location == DECL_SOURCE_LOCATION (var)) | ||
2993 | + return; | ||
2994 | if (xloc.file != floc.file | ||
2995 | || xloc.line < floc.line | ||
2996 | || xloc.line > LOCATION_LINE (cfun->function_end_locus)) | ||
2997 | |||