2 ===================================================================
3 --- gcc/gcc/doc/tm.texi (revision 109809)
4 +++ gcc/gcc/doc/tm.texi (working copy)
6 by the @code{IFCVT_INIT_EXTRA_FIELDS} macro.
9 +@deftypefn {Target Hook} void TARGET_MACHINE_DEPENDENT_AFTER_RELOAD ()
10 +If non-null, this hook performs a target-specific pass over the
11 +instruction stream. The compiler will run it at all optimization levels,
12 +after instructions have been split in flow2 pass.
14 +You need not implement the hook if it has nothing to do. The default
18 @deftypefn {Target Hook} void TARGET_MACHINE_DEPENDENT_REORG ()
19 If non-null, this hook performs a target-specific pass over the
20 instruction stream. The compiler will run it at all optimization levels,
22 ===================================================================
23 --- gcc/gcc/postreload.c (revision 109809)
24 +++ gcc/gcc/postreload.c (working copy)
33 @@ -1600,3 +1601,33 @@
37 +/* Machine dependent postreload pass. */
39 +gate_handle_machine_postreload (void)
41 + return targetm.machine_dependent_postreload != 0;
46 +rest_of_handle_machine_postreload (void)
48 + targetm.machine_dependent_postreload ();
51 +struct tree_opt_pass pass_machine_postreload =
53 + "mach-postreload", /* name */
54 + gate_handle_machine_postreload, /* gate */
55 + rest_of_handle_machine_postreload, /* execute */
58 + 0, /* static_pass_number */
59 + TV_MACH_DEP_AFTER_RELOAD, /* tv_id */
60 + 0, /* properties_required */
61 + 0, /* properties_provided */
62 + 0, /* properties_destroyed */
63 + 0, /* todo_flags_start */
64 + TODO_dump_func, /* todo_flags_finish */
68 ===================================================================
69 --- gcc/gcc/tree-pass.h (revision 109809)
70 +++ gcc/gcc/tree-pass.h (working copy)
72 extern struct tree_opt_pass pass_postreload_cse;
73 extern struct tree_opt_pass pass_gcse2;
74 extern struct tree_opt_pass pass_flow2;
75 +extern struct tree_opt_pass pass_machine_postreload;
76 extern struct tree_opt_pass pass_stack_adjustments;
77 extern struct tree_opt_pass pass_peephole2;
78 extern struct tree_opt_pass pass_if_after_reload;
80 ===================================================================
81 --- gcc/gcc/target.h (revision 109809)
82 +++ gcc/gcc/target.h (working copy)
84 enum machine_mode (* cc_modes_compatible) (enum machine_mode,
87 + /* Do machine-dependent post-reload pass. Called after
89 + void (* machine_dependent_postreload) (void);
91 /* Do machine-dependent code transformations. Called just before
92 delayed-branch scheduling. */
93 void (* machine_dependent_reorg) (void);
95 ===================================================================
96 --- gcc/gcc/timevar.def (revision 109809)
97 +++ gcc/gcc/timevar.def (working copy)
99 DEFTIMEVAR (TV_GLOBAL_ALLOC , "global alloc")
100 DEFTIMEVAR (TV_RELOAD_CSE_REGS , "reload CSE regs")
101 DEFTIMEVAR (TV_SEQABSTR , "sequence abstraction")
102 -DEFTIMEVAR (TV_GCSE_AFTER_RELOAD , "load CSE after reload")
103 +DEFTIMEVAR (TV_GCSE_AFTER_RELOAD , "load CSE after reload")
104 DEFTIMEVAR (TV_FLOW2 , "flow 2")
105 +DEFTIMEVAR (TV_MACH_DEP_AFTER_RELOAD , "mach-dep after reload")
106 DEFTIMEVAR (TV_IFCVT2 , "if-conversion 2")
107 DEFTIMEVAR (TV_PEEPHOLE2 , "peephole 2")
108 DEFTIMEVAR (TV_RENAME_REGISTERS , "rename registers")
110 ===================================================================
111 --- gcc/gcc/target-def.h (revision 109809)
112 +++ gcc/gcc/target-def.h (working copy)
115 #define TARGET_CC_MODES_COMPATIBLE default_cc_modes_compatible
117 +#define TARGET_MACHINE_DEPENDENT_AFTER_RELOAD 0
118 #define TARGET_MACHINE_DEPENDENT_REORG 0
120 #define TARGET_BUILD_BUILTIN_VA_LIST std_build_builtin_va_list
122 TARGET_DWARF_REGISTER_SPAN, \
123 TARGET_FIXED_CONDITION_CODE_REGS, \
124 TARGET_CC_MODES_COMPATIBLE, \
125 + TARGET_MACHINE_DEPENDENT_AFTER_RELOAD, \
126 TARGET_MACHINE_DEPENDENT_REORG, \
127 TARGET_BUILD_BUILTIN_VA_LIST, \
128 TARGET_GIMPLIFY_VA_ARG_EXPR, \
130 ===================================================================
131 --- gcc/gcc/Makefile.in (revision 109809)
132 +++ gcc/gcc/Makefile.in (working copy)
133 @@ -2448,7 +2448,7 @@
134 $(RTL_H) real.h $(FLAGS_H) $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) \
135 hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) output.h \
136 $(FUNCTION_H) toplev.h cselib.h $(TM_P_H) except.h $(TREE_H) $(MACHMODE_H) \
137 - $(OBSTACK_H) timevar.h tree-pass.h
138 + $(TARGET_H) $(OBSTACK_H) timevar.h tree-pass.h
139 postreload-gcse.o : postreload-gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
140 $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) real.h insn-config.h \
141 $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h toplev.h \
143 ===================================================================
144 --- gcc/gcc/passes.c (revision 109809)
145 +++ gcc/gcc/passes.c (working copy)
147 NEXT_PASS (pass_postreload_cse);
148 NEXT_PASS (pass_gcse2);
149 NEXT_PASS (pass_flow2);
150 + NEXT_PASS (pass_machine_postreload);
151 NEXT_PASS (pass_rtl_seqabstr);
152 NEXT_PASS (pass_stack_adjustments);
153 NEXT_PASS (pass_peephole2);
154 Index: config/i386/i386.c
155 ===================================================================
156 --- gcc/gcc/config/i386/i386.c (revision 109809)
157 +++ gcc/gcc/config/i386/i386.c (working copy)
159 HOST_WIDE_INT, tree);
160 static bool x86_can_output_mi_thunk (tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);
161 static void x86_file_start (void);
162 +static void ix86_postreload (void);
163 static void ix86_reorg (void);
164 static bool ix86_expand_carry_flag_compare (enum rtx_code, rtx, rtx, rtx*);
165 static tree ix86_build_builtin_va_list (void);
166 @@ -1147,6 +1148,9 @@
167 #undef TARGET_CC_MODES_COMPATIBLE
168 #define TARGET_CC_MODES_COMPATIBLE ix86_cc_modes_compatible
170 +#undef TARGET_MACHINE_DEPENDENT_AFTER_RELOAD
171 +#define TARGET_MACHINE_DEPENDENT_AFTER_RELOAD ix86_postreload
173 #undef TARGET_MACHINE_DEPENDENT_REORG
174 #define TARGET_MACHINE_DEPENDENT_REORG ix86_reorg
176 @@ -17149,6 +17153,236 @@
180 +/* Non-fcomi 387 FP compare sequences can not be CSE'd during cse1 pass.
181 + This function implements elimination of redundant 387 FP compare
182 + sequences. We look for a sequence of:
184 + fucom(p), fcom(p), ficom(p), fcompp, ftst
189 + After the FP compare sequence has been found, redundant instructions in
190 + successor blocks are deleted:
192 + a) fcom/fnstsw combination iff compare arguments
193 + and AX reg were not modified.
194 + b) sahf (test %ax) and fcom/fnstsw iff compare arguments up to compare
195 + insn and CC reg were not modified.
197 + This code is partially based on code from cse_condition_code_reg () and
198 + cse_cc_succs () functions, as found in cse.c source file. */
201 +ix86_cse_i387_compares (void)
203 + rtx cc_reg = gen_rtx_REG (CCmode, FLAGS_REG);
216 + bool cc_src_clobbered_pred;
221 + last_insn = BB_END (bb);
222 + if (!JUMP_P (last_insn))
225 + /* Find CC setting insn. */
226 + if (! reg_referenced_p (cc_reg, PATTERN (last_insn)))
229 + cc_src_insn = NULL_RTX;
231 + for (insn = PREV_INSN (last_insn);
232 + insn && insn != PREV_INSN (BB_HEAD (bb));
233 + insn = PREV_INSN (insn))
237 + if (! INSN_P (insn))
240 + set = single_set (insn);
242 + && REG_P (SET_DEST (set))
243 + && REGNO (SET_DEST (set)) == REGNO (cc_reg))
245 + cc_src_insn = insn;
246 + cc_src = SET_SRC (set);
249 + else if (reg_set_p (cc_reg, insn))
256 + /* Check if argument to CC setting insn (AX reg) has been
257 + modified between CC setting insn and jump insn. */
258 + cc_src_clobbered_pred
259 + = modified_between_p (cc_src, cc_src_insn, NEXT_INSN (last_insn))
262 + /* Find AX setting insn. */
263 + ax_reg = gen_rtx_REG (HImode, 0);
265 + if (! reg_referenced_p (ax_reg, PATTERN (cc_src_insn)))
268 + ax_src_insn = NULL_RTX;
270 + for (insn = PREV_INSN (cc_src_insn);
271 + insn && insn != PREV_INSN (BB_HEAD (bb));
272 + insn = PREV_INSN (insn))
276 + if (! INSN_P (insn))
279 + set = single_set (insn);
281 + && REG_P (SET_DEST (set))
282 + && REGNO (SET_DEST (set)) == REGNO (ax_reg))
284 + ax_src_insn = insn;
285 + ax_src = SET_SRC (set);
288 + else if (reg_set_p (ax_reg, insn))
295 + if (! (GET_CODE (ax_src) == UNSPEC
296 + && XINT (ax_src, 1) == UNSPEC_FNSTSW))
299 + /* Leave this BB if input arguments to AX setting insn (compare)
300 + have been modified between compare and jump insn. */
301 + if (modified_between_p (ax_src, ax_src_insn, NEXT_INSN (last_insn)))
304 + /* FP compare sequence has been found. Check successor blocks
305 + for redundant insns. */
306 + FOR_EACH_EDGE (e, ei, bb->succs)
311 + rtx delete_cc_src_insn = NULL_RTX;
312 + rtx delete_ax_src_insn = NULL_RTX;
313 + rtx maybe_delete_ax_src_insn = NULL_RTX;
315 + bool cc_src_clobbered;
316 + bool cc_reg_clobbered;
318 + if (e->flags & EDGE_COMPLEX)
321 + if (EDGE_COUNT (e->dest->preds) != 1
322 + || e->dest == EXIT_BLOCK_PTR)
325 + end = NEXT_INSN (BB_END (e->dest));
327 + cc_src_clobbered = cc_src_clobbered_pred;
328 + cc_reg_clobbered = false;
330 + for (insn = BB_HEAD (e->dest); insn != end; insn = NEXT_INSN (insn))
334 + if (! INSN_P (insn))
337 + /* If compare arguments are modified, we have to
338 + stop looking for a compare which uses it. */
339 + if (modified_in_p (ax_src, insn)
340 + && maybe_delete_ax_src_insn == NULL_RTX)
343 + set = single_set (insn);
345 + /* A compare insn can be deleted if it sets AX_REG
346 + from AX_SRC and where CC_SRC is not clobbered yet. */
348 + && REG_P (SET_DEST (set))
349 + && REGNO (SET_DEST (set)) == REGNO (ax_reg)
350 + && rtx_equal_p (ax_src, SET_SRC (set)))
352 + maybe_delete_ax_src_insn = insn;
353 + if (!cc_src_clobbered)
355 + delete_ax_src_insn = insn;
360 + /* A CC setting insn can be deleted if it sets
361 + CC_REG from CC_SRC, and CC is not clobbered yet.
362 + In this case, compare insn should also be deleted. */
364 + && REG_P (SET_DEST (set))
365 + && REGNO (SET_DEST (set)) == REGNO (cc_reg)
366 + && rtx_equal_p (cc_src, SET_SRC (set))
367 + && !cc_reg_clobbered
368 + /* There should be a compare insn present in front. */
369 + && maybe_delete_ax_src_insn != NULL_RTX)
371 + delete_ax_src_insn = maybe_delete_ax_src_insn;
372 + delete_cc_src_insn = insn;
376 + if (modified_in_p (cc_src, insn))
377 + cc_src_clobbered = true;
379 + if (modified_in_p (cc_reg, insn))
380 + cc_reg_clobbered = true;
382 + /* No usable register remains unclobbered. */
383 + if (cc_src_clobbered && cc_reg_clobbered)
387 + /* Delete comparison. */
388 + if (delete_ax_src_insn)
390 + gcc_assert (maybe_delete_ax_src_insn != NULL_RTX);
391 + delete_insn (delete_ax_src_insn);
394 + /* Delete CC setting instruction. */
395 + if (delete_cc_src_insn)
396 + delete_insn (delete_cc_src_insn);
401 +/* Implement machine specific post-reload optimizations. */
403 +ix86_postreload (void)
405 + if (TARGET_80387 && !TARGET_CMOVE &&
406 + !flag_trapping_math && flag_expensive_optimizations)
407 + ix86_cse_i387_compares ();
410 /* AMD K8 core mispredicts jumps when there are more than 3 jumps in 16 byte