]>
Commit | Line | Data |
---|---|---|
1 | --- gcc/gcc/Makefile.in 12 Oct 2005 12:38:00 -0000 1.1547 | |
2 | +++ gcc/gcc/Makefile.in 21 Oct 2005 11:22:39 -0000 | |
3 | @@ -2375,7 +2376,7 @@ postreload.o : postreload.c $(CONFIG_H) | |
4 | $(RTL_H) real.h $(FLAGS_H) $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) \ | |
5 | hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) output.h \ | |
6 | function.h toplev.h cselib.h $(TM_P_H) except.h $(TREE_H) $(MACHMODE_H) \ | |
7 | - $(OBSTACK_H) timevar.h tree-pass.h | |
8 | + $(TARGET_H) $(OBSTACK_H) timevar.h tree-pass.h | |
9 | postreload-gcse.o : postreload-gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ | |
10 | $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) real.h insn-config.h \ | |
11 | $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) function.h output.h toplev.h \ | |
12 | --- gcc/gcc/passes.c 11 Oct 2005 19:18:24 -0000 2.117 | |
13 | +++ gcc/gcc/passes.c 21 Oct 2005 11:22:40 -0000 | |
14 | @@ -650,6 +650,7 @@ init_optimization_passes (void) | |
15 | NEXT_PASS (pass_postreload_cse); | |
16 | NEXT_PASS (pass_gcse2); | |
17 | NEXT_PASS (pass_flow2); | |
18 | + NEXT_PASS (pass_machine_postreload); | |
19 | NEXT_PASS (pass_stack_adjustments); | |
20 | NEXT_PASS (pass_peephole2); | |
21 | NEXT_PASS (pass_if_after_reload); | |
22 | --- gcc/gcc/postreload.c 5 Jul 2005 16:20:09 -0000 2.33 | |
23 | +++ gcc/gcc/postreload.c 21 Oct 2005 11:22:40 -0000 | |
24 | @@ -41,6 +41,7 @@ Software Foundation, 51 Franklin Street, | |
25 | #include "output.h" | |
26 | #include "cselib.h" | |
27 | #include "real.h" | |
28 | +#include "target.h" | |
29 | #include "toplev.h" | |
30 | #include "except.h" | |
31 | #include "tree.h" | |
32 | @@ -1599,3 +1600,33 @@ struct tree_opt_pass pass_postreload_cse | |
33 | 'o' /* letter */ | |
34 | }; | |
35 | ||
36 | +/* Machine dependent postreload pass. */ | |
37 | +static bool | |
38 | +gate_handle_machine_postreload (void) | |
39 | +{ | |
40 | + return targetm.machine_dependent_postreload != 0; | |
41 | +} | |
42 | + | |
43 | + | |
44 | +static void | |
45 | +rest_of_handle_machine_postreload (void) | |
46 | +{ | |
47 | + targetm.machine_dependent_postreload (); | |
48 | +} | |
49 | + | |
50 | +struct tree_opt_pass pass_machine_postreload = | |
51 | +{ | |
52 | + "mach-postreload", /* name */ | |
53 | + gate_handle_machine_postreload, /* gate */ | |
54 | + rest_of_handle_machine_postreload, /* execute */ | |
55 | + NULL, /* sub */ | |
56 | + NULL, /* next */ | |
57 | + 0, /* static_pass_number */ | |
58 | + TV_MACH_DEP_AFTER_RELOAD, /* tv_id */ | |
59 | + 0, /* properties_required */ | |
60 | + 0, /* properties_provided */ | |
61 | + 0, /* properties_destroyed */ | |
62 | + 0, /* todo_flags_start */ | |
63 | + TODO_dump_func, /* todo_flags_finish */ | |
64 | + 0 /* letter */ | |
65 | +}; | |
66 | --- gcc/gcc/target-def.h 12 Oct 2005 20:54:48 -0000 1.134 | |
67 | +++ gcc/gcc/target-def.h 21 Oct 2005 11:22:40 -0000 | |
68 | @@ -395,6 +395,7 @@ Foundation, 51 Franklin Street, Fifth Fl | |
69 | ||
70 | #define TARGET_CC_MODES_COMPATIBLE default_cc_modes_compatible | |
71 | ||
72 | +#define TARGET_MACHINE_DEPENDENT_AFTER_RELOAD 0 | |
73 | #define TARGET_MACHINE_DEPENDENT_REORG 0 | |
74 | ||
75 | #define TARGET_BUILD_BUILTIN_VA_LIST std_build_builtin_va_list | |
76 | @@ -587,6 +588,7 @@ Foundation, 51 Franklin Street, Fifth Fl | |
77 | TARGET_DWARF_REGISTER_SPAN, \ | |
78 | TARGET_FIXED_CONDITION_CODE_REGS, \ | |
79 | TARGET_CC_MODES_COMPATIBLE, \ | |
80 | + TARGET_MACHINE_DEPENDENT_AFTER_RELOAD, \ | |
81 | TARGET_MACHINE_DEPENDENT_REORG, \ | |
82 | TARGET_BUILD_BUILTIN_VA_LIST, \ | |
83 | TARGET_GIMPLIFY_VA_ARG_EXPR, \ | |
84 | --- gcc/gcc/target.h 12 Oct 2005 20:54:48 -0000 1.145 | |
85 | +++ gcc/gcc/target.h 21 Oct 2005 11:22:40 -0000 | |
86 | @@ -478,6 +478,10 @@ struct gcc_target | |
87 | enum machine_mode (* cc_modes_compatible) (enum machine_mode, | |
88 | enum machine_mode); | |
89 | ||
90 | + /* Do machine-dependent post-reload pass. Called after | |
91 | + flow2 pass. */ | |
92 | + void (* machine_dependent_postreload) (void); | |
93 | + | |
94 | /* Do machine-dependent code transformations. Called just before | |
95 | delayed-branch scheduling. */ | |
96 | void (* machine_dependent_reorg) (void); | |
97 | --- gcc/gcc/timevar.def 1 Aug 2005 07:47:23 -0000 1.54 | |
98 | +++ gcc/gcc/timevar.def 21 Oct 2005 11:22:40 -0000 | |
99 | @@ -148,8 +148,9 @@ DEFTIMEVAR (TV_SCHED , " | |
100 | DEFTIMEVAR (TV_LOCAL_ALLOC , "local alloc") | |
101 | DEFTIMEVAR (TV_GLOBAL_ALLOC , "global alloc") | |
102 | DEFTIMEVAR (TV_RELOAD_CSE_REGS , "reload CSE regs") | |
103 | -DEFTIMEVAR (TV_GCSE_AFTER_RELOAD , "load CSE after reload") | |
104 | +DEFTIMEVAR (TV_GCSE_AFTER_RELOAD , "load CSE after reload") | |
105 | DEFTIMEVAR (TV_FLOW2 , "flow 2") | |
106 | +DEFTIMEVAR (TV_MACH_DEP_AFTER_RELOAD , "mach-dep after reload") | |
107 | DEFTIMEVAR (TV_IFCVT2 , "if-conversion 2") | |
108 | DEFTIMEVAR (TV_PEEPHOLE2 , "peephole 2") | |
109 | DEFTIMEVAR (TV_RENAME_REGISTERS , "rename registers") | |
110 | --- gcc/gcc/tree-pass.h 11 Oct 2005 19:18:24 -0000 2.59 | |
111 | +++ gcc/gcc/tree-pass.h 21 Oct 2005 11:22:40 -0000 | |
112 | @@ -352,6 +352,7 @@ extern struct tree_opt_pass pass_remove_ | |
113 | extern struct tree_opt_pass pass_postreload_cse; | |
114 | extern struct tree_opt_pass pass_gcse2; | |
115 | extern struct tree_opt_pass pass_flow2; | |
116 | +extern struct tree_opt_pass pass_machine_postreload; | |
117 | extern struct tree_opt_pass pass_stack_adjustments; | |
118 | extern struct tree_opt_pass pass_peephole2; | |
119 | extern struct tree_opt_pass pass_if_after_reload; | |
120 | --- gcc/gcc/config/i386/i386.c 19 Oct 2005 02:13:37 -0000 1.864 | |
121 | +++ gcc/gcc/config/i386/i386.c 21 Oct 2005 11:22:43 -0000 | |
122 | @@ -860,6 +860,7 @@ static void x86_output_mi_thunk (FILE *, | |
123 | HOST_WIDE_INT, tree); | |
124 | static bool x86_can_output_mi_thunk (tree, HOST_WIDE_INT, HOST_WIDE_INT, tree); | |
125 | static void x86_file_start (void); | |
126 | +static void ix86_postreload (void); | |
127 | static void ix86_reorg (void); | |
128 | static bool ix86_expand_carry_flag_compare (enum rtx_code, rtx, rtx, rtx*); | |
129 | static tree ix86_build_builtin_va_list (void); | |
130 | @@ -1062,6 +1063,9 @@ static void x86_64_elf_select_section (t | |
131 | #undef TARGET_CC_MODES_COMPATIBLE | |
132 | #define TARGET_CC_MODES_COMPATIBLE ix86_cc_modes_compatible | |
133 | ||
134 | +#undef TARGET_MACHINE_DEPENDENT_AFTER_RELOAD | |
135 | +#define TARGET_MACHINE_DEPENDENT_AFTER_RELOAD ix86_postreload | |
136 | + | |
137 | #undef TARGET_MACHINE_DEPENDENT_REORG | |
138 | #define TARGET_MACHINE_DEPENDENT_REORG ix86_reorg | |
139 | ||
140 | @@ -16908,6 +16912,236 @@ min_insn_size (rtx insn) | |
141 | return 2; | |
142 | } | |
143 | ||
144 | +/* Non-fcomi 387 FP compare sequences can not be CSE'd during cse1 pass. | |
145 | + This function implements elimination of redundant 387 FP compare | |
146 | + sequences. We look for a sequence of: | |
147 | + | |
148 | + fucom(p), fcom(p), ficom(p), fcompp, ftst | |
149 | + fnstsw %ax | |
150 | + sahf or test %ax | |
151 | + j<cc> | |
152 | + | |
153 | + After the FP compare sequence has been found, redundant instructions in | |
154 | + successor blocks are deleted: | |
155 | + | |
156 | + a) fcom/fnstsw combination iff compare arguments | |
157 | + and AX reg were not modified. | |
158 | + b) sahf (test %ax) and fcom/fnstsw iff compare arguments up to compare | |
159 | + insn and CC reg were not modified. | |
160 | + | |
161 | + This code is partially based on code from cse_condition_code_reg () and | |
162 | + cse_cc_succs () functions, as found in cse.c source file. */ | |
163 | + | |
164 | +static void | |
165 | +ix86_cse_i387_compares (void) | |
166 | +{ | |
167 | + rtx cc_reg = gen_rtx_REG (CCmode, FLAGS_REG); | |
168 | + rtx ax_reg; | |
169 | + basic_block bb; | |
170 | + | |
171 | + FOR_EACH_BB (bb) | |
172 | + { | |
173 | + rtx last_insn; | |
174 | + rtx insn; | |
175 | + rtx cc_src_insn; | |
176 | + rtx cc_src; | |
177 | + rtx ax_src_insn; | |
178 | + rtx ax_src; | |
179 | + | |
180 | + bool cc_src_clobbered_pred; | |
181 | + | |
182 | + edge e; | |
183 | + edge_iterator ei; | |
184 | + | |
185 | + last_insn = BB_END (bb); | |
186 | + if (!JUMP_P (last_insn)) | |
187 | + continue; | |
188 | + | |
189 | + /* Find CC setting insn. */ | |
190 | + if (! reg_referenced_p (cc_reg, PATTERN (last_insn))) | |
191 | + continue; | |
192 | + | |
193 | + cc_src_insn = NULL_RTX; | |
194 | + cc_src = NULL_RTX; | |
195 | + for (insn = PREV_INSN (last_insn); | |
196 | + insn && insn != PREV_INSN (BB_HEAD (bb)); | |
197 | + insn = PREV_INSN (insn)) | |
198 | + { | |
199 | + rtx set; | |
200 | + | |
201 | + if (! INSN_P (insn)) | |
202 | + continue; | |
203 | + | |
204 | + set = single_set (insn); | |
205 | + if (set | |
206 | + && REG_P (SET_DEST (set)) | |
207 | + && REGNO (SET_DEST (set)) == REGNO (cc_reg)) | |
208 | + { | |
209 | + cc_src_insn = insn; | |
210 | + cc_src = SET_SRC (set); | |
211 | + break; | |
212 | + } | |
213 | + else if (reg_set_p (cc_reg, insn)) | |
214 | + break; | |
215 | + } | |
216 | + | |
217 | + if (! cc_src_insn) | |
218 | + continue; | |
219 | + | |
220 | + /* Check if argument to CC setting insn (AX reg) has been | |
221 | + modified between CC setting insn and jump insn. */ | |
222 | + cc_src_clobbered_pred | |
223 | + = modified_between_p (cc_src, cc_src_insn, NEXT_INSN (last_insn)) | |
224 | + ? true : false; | |
225 | + | |
226 | + /* Find AX setting insn. */ | |
227 | + ax_reg = gen_rtx_REG (HImode, 0); | |
228 | + | |
229 | + if (! reg_referenced_p (ax_reg, PATTERN (cc_src_insn))) | |
230 | + continue; | |
231 | + | |
232 | + ax_src_insn = NULL_RTX; | |
233 | + ax_src = NULL_RTX; | |
234 | + for (insn = PREV_INSN (cc_src_insn); | |
235 | + insn && insn != PREV_INSN (BB_HEAD (bb)); | |
236 | + insn = PREV_INSN (insn)) | |
237 | + { | |
238 | + rtx set; | |
239 | + | |
240 | + if (! INSN_P (insn)) | |
241 | + continue; | |
242 | + | |
243 | + set = single_set (insn); | |
244 | + if (set | |
245 | + && REG_P (SET_DEST (set)) | |
246 | + && REGNO (SET_DEST (set)) == REGNO (ax_reg)) | |
247 | + { | |
248 | + ax_src_insn = insn; | |
249 | + ax_src = SET_SRC (set); | |
250 | + break; | |
251 | + } | |
252 | + else if (reg_set_p (ax_reg, insn)) | |
253 | + break; | |
254 | + } | |
255 | + | |
256 | + if (! ax_src_insn) | |
257 | + continue; | |
258 | + | |
259 | + if (! (GET_CODE (ax_src) == UNSPEC | |
260 | + && XINT (ax_src, 1) == UNSPEC_FNSTSW)) | |
261 | + continue; | |
262 | + | |
263 | + /* Leave this BB if input arguments to AX setting insn (compare) | |
264 | + have been modified between compare and jump insn. */ | |
265 | + if (modified_between_p (ax_src, ax_src_insn, NEXT_INSN (last_insn))) | |
266 | + continue; | |
267 | + | |
268 | + /* FP compare sequence has been found. Check successor blocks | |
269 | + for redundant insns. */ | |
270 | + FOR_EACH_EDGE (e, ei, bb->succs) | |
271 | + { | |
272 | + rtx insn; | |
273 | + rtx end; | |
274 | + | |
275 | + rtx delete_cc_src_insn = NULL_RTX; | |
276 | + rtx delete_ax_src_insn = NULL_RTX; | |
277 | + rtx maybe_delete_ax_src_insn = NULL_RTX; | |
278 | + | |
279 | + bool cc_src_clobbered; | |
280 | + bool cc_reg_clobbered; | |
281 | + | |
282 | + if (e->flags & EDGE_COMPLEX) | |
283 | + continue; | |
284 | + | |
285 | + if (EDGE_COUNT (e->dest->preds) != 1 | |
286 | + || e->dest == EXIT_BLOCK_PTR) | |
287 | + continue; | |
288 | + | |
289 | + end = NEXT_INSN (BB_END (e->dest)); | |
290 | + | |
291 | + cc_src_clobbered = cc_src_clobbered_pred; | |
292 | + cc_reg_clobbered = false; | |
293 | + | |
294 | + for (insn = BB_HEAD (e->dest); insn != end; insn = NEXT_INSN (insn)) | |
295 | + { | |
296 | + rtx set; | |
297 | + | |
298 | + if (! INSN_P (insn)) | |
299 | + continue; | |
300 | + | |
301 | + /* If compare arguments are modified, we have to | |
302 | + stop looking for a compare which uses it. */ | |
303 | + if (modified_in_p (ax_src, insn) | |
304 | + && maybe_delete_ax_src_insn == NULL_RTX) | |
305 | + break; | |
306 | + | |
307 | + set = single_set (insn); | |
308 | + | |
309 | + /* A compare insn can be deleted if it sets AX_REG | |
310 | + from AX_SRC and where CC_SRC is not clobbered yet. */ | |
311 | + if (set | |
312 | + && REG_P (SET_DEST (set)) | |
313 | + && REGNO (SET_DEST (set)) == REGNO (ax_reg) | |
314 | + && rtx_equal_p (ax_src, SET_SRC (set))) | |
315 | + { | |
316 | + maybe_delete_ax_src_insn = insn; | |
317 | + if (!cc_src_clobbered) | |
318 | + { | |
319 | + delete_ax_src_insn = insn; | |
320 | + continue; | |
321 | + } | |
322 | + } | |
323 | + | |
324 | + /* A CC setting insn can be deleted if it sets | |
325 | + CC_REG from CC_SRC, and CC is not clobbered yet. | |
326 | + In this case, compare insn should also be deleted. */ | |
327 | + if (set | |
328 | + && REG_P (SET_DEST (set)) | |
329 | + && REGNO (SET_DEST (set)) == REGNO (cc_reg) | |
330 | + && rtx_equal_p (cc_src, SET_SRC (set)) | |
331 | + && !cc_reg_clobbered | |
332 | + /* There should be a compare insn present in front. */ | |
333 | + && maybe_delete_ax_src_insn != NULL_RTX) | |
334 | + { | |
335 | + delete_ax_src_insn = maybe_delete_ax_src_insn; | |
336 | + delete_cc_src_insn = insn; | |
337 | + break; | |
338 | + } | |
339 | + | |
340 | + if (modified_in_p (cc_src, insn)) | |
341 | + cc_src_clobbered = true; | |
342 | + | |
343 | + if (modified_in_p (cc_reg, insn)) | |
344 | + cc_reg_clobbered = true; | |
345 | + | |
346 | + /* No usable register remains unclobbered. */ | |
347 | + if (cc_src_clobbered && cc_reg_clobbered) | |
348 | + break; | |
349 | + } | |
350 | + | |
351 | + /* Delete comparison. */ | |
352 | + if (delete_ax_src_insn) | |
353 | + { | |
354 | + gcc_assert (maybe_delete_ax_src_insn != NULL_RTX); | |
355 | + delete_insn (delete_ax_src_insn); | |
356 | + } | |
357 | + | |
358 | + /* Delete CC setting instruction. */ | |
359 | + if (delete_cc_src_insn) | |
360 | + delete_insn (delete_cc_src_insn); | |
361 | + } | |
362 | + } | |
363 | +} | |
364 | + | |
365 | +/* Implement machine specific post-reload optimizations. */ | |
366 | +static void | |
367 | +ix86_postreload (void) | |
368 | +{ | |
369 | + if (TARGET_80387 && !TARGET_CMOVE && | |
370 | + !flag_trapping_math && flag_expensive_optimizations) | |
371 | + ix86_cse_i387_compares (); | |
372 | +} | |
373 | + | |
374 | /* AMD K8 core mispredicts jumps when there are more than 3 jumps in 16 byte | |
375 | window. */ | |
376 | ||
377 | --- gcc/gcc/doc/tm.texi 12 Oct 2005 20:54:49 -0000 1.447 | |
378 | +++ gcc/gcc/doc/tm.texi 21 Oct 2005 11:29:35 -0000 | |
379 | @@ -9300,6 +9300,15 @@ added to the @code{struct ce_if_block} s | |
380 | by the @code{IFCVT_INIT_EXTRA_FIELDS} macro. | |
381 | @end defmac | |
382 | ||
383 | +@deftypefn {Target Hook} void TARGET_MACHINE_DEPENDENT_AFTER_RELOAD () | |
384 | +If non-null, this hook performs a target-specific pass over the | |
385 | +instruction stream. The compiler will run it at all optimization levels, | |
386 | +after instructions have been split in flow2 pass. | |
387 | + | |
388 | +You need not implement the hook if it has nothing to do. The default | |
389 | +definition is null. | |
390 | +@end deftypefn | |
391 | + | |
392 | @deftypefn {Target Hook} void TARGET_MACHINE_DEPENDENT_REORG () | |
393 | If non-null, this hook performs a target-specific pass over the | |
394 | instruction stream. The compiler will run it at all optimization levels, |