summaryrefslogtreecommitdiffstats
path: root/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99474.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99474.patch')
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99474.patch3346
1 files changed, 3346 insertions, 0 deletions
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99474.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99474.patch
new file mode 100644
index 0000000000..9b0fb0b488
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99474.patch
@@ -0,0 +1,3346 @@
12011-01-14 Bernd Schmidt <bernds@codesourcery.com>
2
3 gcc/
4 * function.c (thread_prologue_and_epilogue_insns): Avoid uninitialized
5 variable.
6
72011-01-12 Bernd Schmidt <bernds@codesourcery.com>
8
9 gcc/
10 * config/s390/s390.c (s390_emit_epilogue): Don't use gen_rtx_RETURN.
11 * config/rx/rx.c (gen_rx_rtsd_vector): Likewise.
12 * config/m68hc11/m68hc11.md (return): Likewise.
13 * config/cris/cris.c (cris_expand_return): Likewise.
14 * config/m68k/m68k.c (m68k_expand_epilogue): Likewise.
15 * config/picochip/picochip.c (picochip_expand_epilogue): Likewise.
16 * config/h8300/h8300.c (h8300_push_pop, h8300_expand_epilogue):
17 Likewise.
18 * config/v850/v850.c (expand_epilogue): Likewise.
19 * config/bfin/bfin.c (bfin_expand_call): Likewise.
20
212011-01-04 Catherine Moore <clm@codesourcery.com>
22
23 gcc/
24 * config/rs6000/rs6000.c (rs6000_make_savres_rtx): Change
25 gen_rtx_RETURN to ret_rtx.
26 (rs6000_emit_epilogue): Likewise.
27 (rs6000_output_mi_thunk): Likewise.
28
292011-01-03 Bernd Schmidt <bernds@codesourcery.com>
30
31 gcc/
32 * doc/tm.texi (RETURN_ADDR_REGNUM): Document.
33 * doc/md.texi (simple_return): Document pattern.
34 (return): Add a sentence to clarify.
35 * doc/rtl.texi (simple_return): Document.
36 * doc/invoke.texi (Optimize Options): Document -fshrink-wrap.
37 * common.opt (fshrink-wrap): New.
38 * opts.c (decode_options): Set it for -O2 and above.
39 * gengenrtl.c (special_rtx): PC, CC0, RETURN and SIMPLE_RETURN
40 are special.
41 * rtl.h (ANY_RETURN_P): New macro.
42 (global_rtl_index): Add GR_RETURN and GR_SIMPLE_RETURN.
43 (ret_rtx, simple_return_rtx): New macros.
44 * genemit.c (gen_exp): RETURN and SIMPLE_RETURN have unique rtxs.
45 (gen_expand, gen_split): Use ANY_RETURN_P.
46 * rtl.c (copy_rtx): RETURN and SIMPLE_RETURN are shared.
47 * emit-rtl.c (verify_rtx_sharing): Likewise.
48 (skip_consecutive_labels): Return the argument if it is a return rtx.
49 (classify_insn): Handle both kinds of return.
50 (init_emit_regs): Create global rtl for ret_rtx and simple_return_rtx.
51 * df-scan.c (df_uses_record): Handle SIMPLE_RETURN.
52 * rtl.def (SIMPLE_RETURN): New.
53 * rtlanal.c (tablejump_p): Check JUMP_LABEL for returns.
54 * final.c (final_scan_insn): Recognize both kinds of return.
55 * reorg.c (function_return_label, function_simple_return_label): New
56 static variables.
57 (end_of_function_label): Remove.
58 (simplejump_or_return_p): New static function.
59 (find_end_label): Add a new arg, KIND. All callers changed.
60 Depending on KIND, look for a label suitable for return or
61 simple_return.
62 (make_return_insns): Make corresponding changes.
63 (get_jump_flags): Check JUMP_LABELs for returns.
64 (follow_jumps): Likewise.
65 (get_branch_condition): Check target for return patterns rather
66 than NULL.
67 (own_thread_p): Likewise for thread.
68 (steal_delay_list_from_target): Check JUMP_LABELs for returns.
69 Use simplejump_or_return_p.
70 (fill_simple_delay_slots): Likewise.
71 (optimize_skip): Likewise.
72 (fill_slots_from_thread): Likewise.
73 (relax_delay_slots): Likewise.
74 (dbr_schedule): Adjust handling of end_of_function_label for the
75 two new variables.
76 * ifcvt.c (find_if_case_1): Take care when redirecting jumps to the
77 exit block.
78 (dead_or_predicable): Change NEW_DEST arg to DEST_EDGE. All callers
79 changed. Ensure that the right label is passed to redirect_jump.
80 * jump.c (condjump_p, condjump_in_parallel_p, any_condjump_p,
81 returnjump_p): Handle SIMPLE_RETURNs.
82 (delete_related_insns): Check JUMP_LABEL for returns.
83 (redirect_target): New static function.
84 (redirect_exp_1): Use it. Handle any kind of return rtx as a label
85 rather than interpreting NULL as a return.
86 (redirect_jump_1): Assert that nlabel is not NULL.
87 (redirect_jump): Likewise.
88 (redirect_jump_2): Handle any kind of return rtx as a label rather
89 than interpreting NULL as a return.
90 * dwarf2out.c (compute_barrier_args_size_1): Check JUMP_LABEL for
91 returns.
92 * function.c (emit_return_into_block): Remove useless declaration.
93 (record_hard_reg_sets, frame_required_for_rtx, gen_return_pattern,
94 requires_stack_frame_p): New static functions.
95 (emit_return_into_block): New arg SIMPLE_P. All callers changed.
96 Generate either kind of return pattern and update the JUMP_LABEL.
97 (thread_prologue_and_epilogue_insns): Implement a form of
98 shrink-wrapping. Ensure JUMP_LABELs for return insns are set.
99 * print-rtl.c (print_rtx): Handle returns in JUMP_LABELs.
100 * cfglayout.c (fixup_reorder_chain): Ensure JUMP_LABELs for returns
101 remain correct.
102 * resource.c (find_dead_or_set_registers): Check JUMP_LABELs for
103 returns.
104 (mark_target_live_regs): Don't pass a return rtx to next_active_insn.
105 * basic-block.h (force_nonfallthru_and_redirect): Declare.
106 * sched-vis.c (print_pattern): Add case for SIMPLE_RETURN.
107 * cfgrtl.c (force_nonfallthru_and_redirect): No longer static. New arg
108 JUMP_LABEL. All callers changed. Use the label when generating
109 return insns.
110
111 * config/i386/i386.md (returns, return_str, return_cond): New
112 code_iterator and corresponding code_attrs.
113 (<return_str>return): Renamed from return and adapted.
114 (<return_str>return_internal): Likewise for return_internal.
115 (<return_str>return_internal_long): Likewise for return_internal_long.
116 (<return_str>return_pop_internal): Likewise for return_pop_internal.
117 (<return_str>return_indirect_internal): Likewise for
118 return_indirect_internal.
119 * config/i386/i386.c (ix86_expand_epilogue): Expand a simple_return as
120 the last insn.
121 (ix86_pad_returns): Handle both kinds of return rtx.
122 * config/arm/arm.c (use_simple_return_p): new function.
123 (is_jump_table): Handle returns in JUMP_LABELs.
124 (output_return_instruction): New arg SIMPLE. All callers changed.
125 Use it to determine which kind of return to generate.
126 (arm_final_prescan_insn): Handle both kinds of return.
127 * config/arm/arm.md (returns, return_str, return_simple_p,
128 return_cond): New code_iterator and corresponding code_attrs.
129 (<return_str>return): Renamed from return and adapted.
130 (arm_<return_str>return): Renamed from arm_return and adapted.
131 (cond_<return_str>return): Renamed from cond_return and adapted.
132 (cond_<return_str>return_inverted): Renamed from cond_return_inverted
133 and adapted.
134 (epilogue): Use ret_rtx instead of gen_rtx_RETURN.
135 * config/arm/thumb2.md (thumb2_<return_str>return): Renamed from
136 thumb2_return and adapted.
137 * config/arm/arm.h (RETURN_ADDR_REGNUM): Define.
138 * config/arm/arm-protos.h (use_simple_return_p): Declare.
139 (output_return_instruction): Adjust declaration.
140 * config/mips/mips.c (mips_expand_epilogue): Generate a simple_return
141 as final insn.
142 * config/mips/mips.md (simple_return): New expander.
143 (*simple_return, simple_return_internal): New patterns.
144 * config/sh/sh.c (barrier_align): Handle return in a JUMP_LABEL.
145 (split_branches): Don't pass a null label to redirect_jump.
146
147 From mainline:
148 * vec.h (FOR_EACH_VEC_ELT, FOR_EACH_VEC_ELT_REVERSE): New macros.
149 * haifa-sched.c (find_fallthru_edge_from): Rename from
150 find_fallthru_edge. All callers changed.
151 * sched-int.h (find_fallthru_edge_from): Rename declaration as well.
152 * basic-block.h (find_fallthru_edge): New inline function.
153
154=== modified file 'gcc/basic-block.h'
155Index: gcc-4_5-branch/gcc/basic-block.h
156===================================================================
157--- gcc-4_5-branch.orig/gcc/basic-block.h
158+++ gcc-4_5-branch/gcc/basic-block.h
159@@ -884,6 +884,7 @@ extern void flow_edge_list_print (const
160
161 /* In cfgrtl.c */
162 extern basic_block force_nonfallthru (edge);
163+extern basic_block force_nonfallthru_and_redirect (edge, basic_block, rtx);
164 extern rtx block_label (basic_block);
165 extern bool purge_all_dead_edges (void);
166 extern bool purge_dead_edges (basic_block);
167@@ -1004,6 +1005,20 @@ bb_has_abnormal_pred (basic_block bb)
168 return false;
169 }
170
171+/* Return the fallthru edge in EDGES if it exists, NULL otherwise. */
172+static inline edge
173+find_fallthru_edge (VEC(edge,gc) *edges)
174+{
175+ edge e;
176+ edge_iterator ei;
177+
178+ FOR_EACH_EDGE (e, ei, edges)
179+ if (e->flags & EDGE_FALLTHRU)
180+ break;
181+
182+ return e;
183+}
184+
185 /* In cfgloopmanip.c. */
186 extern edge mfb_kj_edge;
187 extern bool mfb_keep_just (edge);
188Index: gcc-4_5-branch/gcc/cfganal.c
189===================================================================
190--- gcc-4_5-branch.orig/gcc/cfganal.c
191+++ gcc-4_5-branch/gcc/cfganal.c
192@@ -271,6 +271,37 @@ set_edge_can_fallthru_flag (void)
193 EDGE_SUCC (bb, 0)->flags |= EDGE_CAN_FALLTHRU;
194 EDGE_SUCC (bb, 1)->flags |= EDGE_CAN_FALLTHRU;
195 }
196+ /* dwarf2out expects that a NOTE_INSN_EPILOGUE_BEGIN is always paired
197+ with a return or a sibcall. Ensure that this remains the case if
198+ they are in different basic blocks. */
199+ FOR_EACH_BB (bb)
200+ {
201+ edge e;
202+ edge_iterator ei;
203+ rtx insn, end;
204+
205+ end = BB_END (bb);
206+ FOR_BB_INSNS (bb, insn)
207+ if (GET_CODE (insn) == NOTE
208+ && NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG
209+ && !(CALL_P (end) && SIBLING_CALL_P (end))
210+ && !returnjump_p (end))
211+ {
212+ basic_block other_bb = NULL;
213+ FOR_EACH_EDGE (e, ei, bb->succs)
214+ {
215+ if (e->flags & EDGE_FALLTHRU)
216+ other_bb = e->dest;
217+ else
218+ e->flags &= ~EDGE_CAN_FALLTHRU;
219+ }
220+ FOR_EACH_EDGE (e, ei, other_bb->preds)
221+ {
222+ if (!(e->flags & EDGE_FALLTHRU))
223+ e->flags &= ~EDGE_CAN_FALLTHRU;
224+ }
225+ }
226+ }
227 }
228
229 /* Find unreachable blocks. An unreachable block will have 0 in
230Index: gcc-4_5-branch/gcc/cfglayout.c
231===================================================================
232--- gcc-4_5-branch.orig/gcc/cfglayout.c
233+++ gcc-4_5-branch/gcc/cfglayout.c
234@@ -766,6 +766,7 @@ fixup_reorder_chain (void)
235 {
236 edge e_fall, e_taken, e;
237 rtx bb_end_insn;
238+ rtx ret_label = NULL_RTX;
239 basic_block nb;
240 edge_iterator ei;
241
242@@ -785,6 +786,7 @@ fixup_reorder_chain (void)
243 bb_end_insn = BB_END (bb);
244 if (JUMP_P (bb_end_insn))
245 {
246+ ret_label = JUMP_LABEL (bb_end_insn);
247 if (any_condjump_p (bb_end_insn))
248 {
249 /* This might happen if the conditional jump has side
250@@ -899,7 +901,7 @@ fixup_reorder_chain (void)
251 }
252
253 /* We got here if we need to add a new jump insn. */
254- nb = force_nonfallthru (e_fall);
255+ nb = force_nonfallthru_and_redirect (e_fall, e_fall->dest, ret_label);
256 if (nb)
257 {
258 nb->il.rtl->visited = 1;
259@@ -1118,24 +1120,30 @@ extern bool cfg_layout_can_duplicate_bb_
260 bool
261 cfg_layout_can_duplicate_bb_p (const_basic_block bb)
262 {
263+ rtx insn;
264+
265 /* Do not attempt to duplicate tablejumps, as we need to unshare
266 the dispatch table. This is difficult to do, as the instructions
267 computing jump destination may be hoisted outside the basic block. */
268 if (tablejump_p (BB_END (bb), NULL, NULL))
269 return false;
270
271- /* Do not duplicate blocks containing insns that can't be copied. */
272- if (targetm.cannot_copy_insn_p)
273+ insn = BB_HEAD (bb);
274+ while (1)
275 {
276- rtx insn = BB_HEAD (bb);
277- while (1)
278- {
279- if (INSN_P (insn) && targetm.cannot_copy_insn_p (insn))
280- return false;
281- if (insn == BB_END (bb))
282- break;
283- insn = NEXT_INSN (insn);
284- }
285+ /* Do not duplicate blocks containing insns that can't be copied. */
286+ if (INSN_P (insn) && targetm.cannot_copy_insn_p
287+ && targetm.cannot_copy_insn_p (insn))
288+ return false;
289+ /* dwarf2out expects that these notes are always paired with a
290+ returnjump or sibling call. */
291+ if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG
292+ && !returnjump_p (BB_END (bb))
293+ && (!CALL_P (BB_END (bb)) || !SIBLING_CALL_P (BB_END (bb))))
294+ return false;
295+ if (insn == BB_END (bb))
296+ break;
297+ insn = NEXT_INSN (insn);
298 }
299
300 return true;
301@@ -1180,6 +1188,9 @@ duplicate_insn_chain (rtx from, rtx to)
302 break;
303 }
304 copy = emit_copy_of_insn_after (insn, get_last_insn ());
305+ if (JUMP_P (insn) && JUMP_LABEL (insn) != NULL_RTX
306+ && ANY_RETURN_P (JUMP_LABEL (insn)))
307+ JUMP_LABEL (copy) = JUMP_LABEL (insn);
308 maybe_copy_epilogue_insn (insn, copy);
309 break;
310
311Index: gcc-4_5-branch/gcc/cfgrtl.c
312===================================================================
313--- gcc-4_5-branch.orig/gcc/cfgrtl.c
314+++ gcc-4_5-branch/gcc/cfgrtl.c
315@@ -1107,10 +1107,13 @@ rtl_redirect_edge_and_branch (edge e, ba
316 }
317
318 /* Like force_nonfallthru below, but additionally performs redirection
319- Used by redirect_edge_and_branch_force. */
320+ Used by redirect_edge_and_branch_force. JUMP_LABEL is used only
321+ when redirecting to the EXIT_BLOCK, it is either a return or a
322+ simple_return rtx indicating which kind of returnjump to create.
323+ It should be NULL otherwise. */
324
325-static basic_block
326-force_nonfallthru_and_redirect (edge e, basic_block target)
327+basic_block
328+force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
329 {
330 basic_block jump_block, new_bb = NULL, src = e->src;
331 rtx note;
332@@ -1242,11 +1245,25 @@ force_nonfallthru_and_redirect (edge e,
333 e->flags &= ~EDGE_FALLTHRU;
334 if (target == EXIT_BLOCK_PTR)
335 {
336+ if (jump_label == ret_rtx)
337+ {
338 #ifdef HAVE_return
339- emit_jump_insn_after_setloc (gen_return (), BB_END (jump_block), loc);
340+ emit_jump_insn_after_setloc (gen_return (), BB_END (jump_block),
341+ loc);
342 #else
343- gcc_unreachable ();
344+ gcc_unreachable ();
345 #endif
346+ }
347+ else
348+ {
349+ gcc_assert (jump_label == simple_return_rtx);
350+#ifdef HAVE_simple_return
351+ emit_jump_insn_after_setloc (gen_simple_return (),
352+ BB_END (jump_block), loc);
353+#else
354+ gcc_unreachable ();
355+#endif
356+ }
357 }
358 else
359 {
360@@ -1273,7 +1290,7 @@ force_nonfallthru_and_redirect (edge e,
361 basic_block
362 force_nonfallthru (edge e)
363 {
364- return force_nonfallthru_and_redirect (e, e->dest);
365+ return force_nonfallthru_and_redirect (e, e->dest, NULL_RTX);
366 }
367
368 /* Redirect edge even at the expense of creating new jump insn or
369@@ -1290,7 +1307,7 @@ rtl_redirect_edge_and_branch_force (edge
370 /* In case the edge redirection failed, try to force it to be non-fallthru
371 and redirect newly created simplejump. */
372 df_set_bb_dirty (e->src);
373- return force_nonfallthru_and_redirect (e, target);
374+ return force_nonfallthru_and_redirect (e, target, NULL_RTX);
375 }
376
377 /* The given edge should potentially be a fallthru edge. If that is in
378Index: gcc-4_5-branch/gcc/common.opt
379===================================================================
380--- gcc-4_5-branch.orig/gcc/common.opt
381+++ gcc-4_5-branch/gcc/common.opt
382@@ -1147,6 +1147,11 @@ fshow-column
383 Common C ObjC C++ ObjC++ Report Var(flag_show_column) Init(1)
384 Show column numbers in diagnostics, when available. Default on
385
386+fshrink-wrap
387+Common Report Var(flag_shrink_wrap) Optimization
388+Emit function prologues only before parts of the function that need it,
389+rather than at the top of the function.
390+
391 fsignaling-nans
392 Common Report Var(flag_signaling_nans) Optimization
393 Disable optimizations observable by IEEE signaling NaNs
394Index: gcc-4_5-branch/gcc/config/arm/arm-protos.h
395===================================================================
396--- gcc-4_5-branch.orig/gcc/config/arm/arm-protos.h
397+++ gcc-4_5-branch/gcc/config/arm/arm-protos.h
398@@ -26,6 +26,7 @@
399 extern void arm_override_options (void);
400 extern void arm_optimization_options (int, int);
401 extern int use_return_insn (int, rtx);
402+extern bool use_simple_return_p (void);
403 extern enum reg_class arm_regno_class (int);
404 extern void arm_load_pic_register (unsigned long);
405 extern int arm_volatile_func (void);
406@@ -137,7 +138,7 @@ extern int arm_address_offset_is_imm (rt
407 extern const char *output_add_immediate (rtx *);
408 extern const char *arithmetic_instr (rtx, int);
409 extern void output_ascii_pseudo_op (FILE *, const unsigned char *, int);
410-extern const char *output_return_instruction (rtx, int, int);
411+extern const char *output_return_instruction (rtx, bool, bool, bool);
412 extern void arm_poke_function_name (FILE *, const char *);
413 extern void arm_print_operand (FILE *, rtx, int);
414 extern void arm_print_operand_address (FILE *, rtx);
415Index: gcc-4_5-branch/gcc/config/arm/arm.c
416===================================================================
417--- gcc-4_5-branch.orig/gcc/config/arm/arm.c
418+++ gcc-4_5-branch/gcc/config/arm/arm.c
419@@ -2163,6 +2163,18 @@ arm_trampoline_adjust_address (rtx addr)
420 return addr;
421 }
422
423+/* Return true if we should try to use a simple_return insn, i.e. perform
424+ shrink-wrapping if possible. This is the case if we need to emit a
425+ prologue, which we can test by looking at the offsets. */
426+bool
427+use_simple_return_p (void)
428+{
429+ arm_stack_offsets *offsets;
430+
431+ offsets = arm_get_frame_offsets ();
432+ return offsets->outgoing_args != 0;
433+}
434+
435 /* Return 1 if it is possible to return using a single instruction.
436 If SIBLING is non-null, this is a test for a return before a sibling
437 call. SIBLING is the call insn, so we can examine its register usage. */
438@@ -11284,6 +11296,7 @@ is_jump_table (rtx insn)
439
440 if (GET_CODE (insn) == JUMP_INSN
441 && JUMP_LABEL (insn) != NULL
442+ && !ANY_RETURN_P (JUMP_LABEL (insn))
443 && ((table = next_real_insn (JUMP_LABEL (insn)))
444 == next_real_insn (insn))
445 && table != NULL
446@@ -14168,7 +14181,7 @@ arm_get_vfp_saved_size (void)
447 /* Generate a function exit sequence. If REALLY_RETURN is false, then do
448 everything bar the final return instruction. */
449 const char *
450-output_return_instruction (rtx operand, int really_return, int reverse)
451+output_return_instruction (rtx operand, bool really_return, bool reverse, bool simple)
452 {
453 char conditional[10];
454 char instr[100];
455@@ -14206,10 +14219,15 @@ output_return_instruction (rtx operand,
456
457 sprintf (conditional, "%%?%%%c0", reverse ? 'D' : 'd');
458
459- cfun->machine->return_used_this_function = 1;
460+ if (simple)
461+ live_regs_mask = 0;
462+ else
463+ {
464+ cfun->machine->return_used_this_function = 1;
465
466- offsets = arm_get_frame_offsets ();
467- live_regs_mask = offsets->saved_regs_mask;
468+ offsets = arm_get_frame_offsets ();
469+ live_regs_mask = offsets->saved_regs_mask;
470+ }
471
472 if (live_regs_mask)
473 {
474@@ -17108,6 +17126,7 @@ arm_final_prescan_insn (rtx insn)
475
476 /* If we start with a return insn, we only succeed if we find another one. */
477 int seeking_return = 0;
478+ enum rtx_code return_code = UNKNOWN;
479
480 /* START_INSN will hold the insn from where we start looking. This is the
481 first insn after the following code_label if REVERSE is true. */
482@@ -17146,7 +17165,7 @@ arm_final_prescan_insn (rtx insn)
483 else
484 return;
485 }
486- else if (GET_CODE (body) == RETURN)
487+ else if (ANY_RETURN_P (body))
488 {
489 start_insn = next_nonnote_insn (start_insn);
490 if (GET_CODE (start_insn) == BARRIER)
491@@ -17157,6 +17176,7 @@ arm_final_prescan_insn (rtx insn)
492 {
493 reverse = TRUE;
494 seeking_return = 1;
495+ return_code = GET_CODE (body);
496 }
497 else
498 return;
499@@ -17197,11 +17217,15 @@ arm_final_prescan_insn (rtx insn)
500 label = XEXP (XEXP (SET_SRC (body), 2), 0);
501 then_not_else = FALSE;
502 }
503- else if (GET_CODE (XEXP (SET_SRC (body), 1)) == RETURN)
504- seeking_return = 1;
505- else if (GET_CODE (XEXP (SET_SRC (body), 2)) == RETURN)
506+ else if (ANY_RETURN_P (XEXP (SET_SRC (body), 1)))
507+ {
508+ seeking_return = 1;
509+ return_code = GET_CODE (XEXP (SET_SRC (body), 1));
510+ }
511+ else if (ANY_RETURN_P (XEXP (SET_SRC (body), 2)))
512 {
513 seeking_return = 1;
514+ return_code = GET_CODE (XEXP (SET_SRC (body), 2));
515 then_not_else = FALSE;
516 }
517 else
518@@ -17302,8 +17326,7 @@ arm_final_prescan_insn (rtx insn)
519 && !use_return_insn (TRUE, NULL)
520 && !optimize_size)
521 fail = TRUE;
522- else if (GET_CODE (scanbody) == RETURN
523- && seeking_return)
524+ else if (GET_CODE (scanbody) == return_code)
525 {
526 arm_ccfsm_state = 2;
527 succeed = TRUE;
528Index: gcc-4_5-branch/gcc/config/arm/arm.h
529===================================================================
530--- gcc-4_5-branch.orig/gcc/config/arm/arm.h
531+++ gcc-4_5-branch/gcc/config/arm/arm.h
532@@ -2622,6 +2622,8 @@ extern int making_const_table;
533 #define RETURN_ADDR_RTX(COUNT, FRAME) \
534 arm_return_addr (COUNT, FRAME)
535
536+#define RETURN_ADDR_REGNUM LR_REGNUM
537+
538 /* Mask of the bits in the PC that contain the real return address
539 when running in 26-bit mode. */
540 #define RETURN_ADDR_MASK26 (0x03fffffc)
541Index: gcc-4_5-branch/gcc/config/arm/arm.md
542===================================================================
543--- gcc-4_5-branch.orig/gcc/config/arm/arm.md
544+++ gcc-4_5-branch/gcc/config/arm/arm.md
545@@ -8882,66 +8882,72 @@
546 [(set_attr "type" "call")]
547 )
548
549-(define_expand "return"
550- [(return)]
551- "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
552+;; Both kinds of return insn.
553+(define_code_iterator returns [return simple_return])
554+(define_code_attr return_str [(return "") (simple_return "simple_")])
555+(define_code_attr return_simple_p [(return "false") (simple_return "true")])
556+(define_code_attr return_cond [(return " && USE_RETURN_INSN (FALSE)")
557+ (simple_return " && use_simple_return_p ()")])
558+
559+(define_expand "<return_str>return"
560+ [(returns)]
561+ "TARGET_32BIT<return_cond>"
562 "")
563
564-;; Often the return insn will be the same as loading from memory, so set attr
565-(define_insn "*arm_return"
566- [(return)]
567- "TARGET_ARM && USE_RETURN_INSN (FALSE)"
568- "*
569- {
570- if (arm_ccfsm_state == 2)
571- {
572- arm_ccfsm_state += 2;
573- return \"\";
574- }
575- return output_return_instruction (const_true_rtx, TRUE, FALSE);
576- }"
577+(define_insn "*arm_<return_str>return"
578+ [(returns)]
579+ "TARGET_ARM<return_cond>"
580+{
581+ if (arm_ccfsm_state == 2)
582+ {
583+ arm_ccfsm_state += 2;
584+ return "";
585+ }
586+ return output_return_instruction (const_true_rtx, true, false,
587+ <return_simple_p>);
588+}
589 [(set_attr "type" "load1")
590 (set_attr "length" "12")
591 (set_attr "predicable" "yes")]
592 )
593
594-(define_insn "*cond_return"
595+(define_insn "*cond_<return_str>return"
596 [(set (pc)
597 (if_then_else (match_operator 0 "arm_comparison_operator"
598 [(match_operand 1 "cc_register" "") (const_int 0)])
599- (return)
600+ (returns)
601 (pc)))]
602- "TARGET_ARM && USE_RETURN_INSN (TRUE)"
603- "*
604- {
605- if (arm_ccfsm_state == 2)
606- {
607- arm_ccfsm_state += 2;
608- return \"\";
609- }
610- return output_return_instruction (operands[0], TRUE, FALSE);
611- }"
612+ "TARGET_ARM<return_cond>"
613+{
614+ if (arm_ccfsm_state == 2)
615+ {
616+ arm_ccfsm_state += 2;
617+ return "";
618+ }
619+ return output_return_instruction (operands[0], true, false,
620+ <return_simple_p>);
621+}
622 [(set_attr "conds" "use")
623 (set_attr "length" "12")
624 (set_attr "type" "load1")]
625 )
626
627-(define_insn "*cond_return_inverted"
628+(define_insn "*cond_<return_str>return_inverted"
629 [(set (pc)
630 (if_then_else (match_operator 0 "arm_comparison_operator"
631 [(match_operand 1 "cc_register" "") (const_int 0)])
632 (pc)
633- (return)))]
634- "TARGET_ARM && USE_RETURN_INSN (TRUE)"
635- "*
636- {
637- if (arm_ccfsm_state == 2)
638- {
639- arm_ccfsm_state += 2;
640- return \"\";
641- }
642- return output_return_instruction (operands[0], TRUE, TRUE);
643- }"
644+ (returns)))]
645+ "TARGET_ARM<return_cond>"
646+{
647+ if (arm_ccfsm_state == 2)
648+ {
649+ arm_ccfsm_state += 2;
650+ return "";
651+ }
652+ return output_return_instruction (operands[0], true, true,
653+ <return_simple_p>);
654+}
655 [(set_attr "conds" "use")
656 (set_attr "length" "12")
657 (set_attr "type" "load1")]
658@@ -10809,8 +10815,7 @@
659 DONE;
660 }
661 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
662- gen_rtvec (1,
663- gen_rtx_RETURN (VOIDmode)),
664+ gen_rtvec (1, ret_rtx),
665 VUNSPEC_EPILOGUE));
666 DONE;
667 "
668@@ -10827,7 +10832,7 @@
669 "TARGET_32BIT"
670 "*
671 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
672- return output_return_instruction (const_true_rtx, FALSE, FALSE);
673+ return output_return_instruction (const_true_rtx, false, false, false);
674 return arm_output_epilogue (next_nonnote_insn (insn));
675 "
676 ;; Length is absolute worst case
677Index: gcc-4_5-branch/gcc/config/arm/thumb2.md
678===================================================================
679--- gcc-4_5-branch.orig/gcc/config/arm/thumb2.md
680+++ gcc-4_5-branch/gcc/config/arm/thumb2.md
681@@ -1020,16 +1020,15 @@
682
683 ;; Note: this is not predicable, to avoid issues with linker-generated
684 ;; interworking stubs.
685-(define_insn "*thumb2_return"
686- [(return)]
687- "TARGET_THUMB2 && USE_RETURN_INSN (FALSE)"
688- "*
689- {
690- return output_return_instruction (const_true_rtx, TRUE, FALSE);
691- }"
692+(define_insn "*thumb2_<return_str>return"
693+ [(returns)]
694+ "TARGET_THUMB2<return_cond>"
695+{
696+ return output_return_instruction (const_true_rtx, true, false,
697+ <return_simple_p>);
698+}
699 [(set_attr "type" "load1")
700- (set_attr "length" "12")]
701-)
702+ (set_attr "length" "12")])
703
704 (define_insn_and_split "thumb2_eh_return"
705 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
706Index: gcc-4_5-branch/gcc/config/bfin/bfin.c
707===================================================================
708--- gcc-4_5-branch.orig/gcc/config/bfin/bfin.c
709+++ gcc-4_5-branch/gcc/config/bfin/bfin.c
710@@ -2359,7 +2359,7 @@ bfin_expand_call (rtx retval, rtx fnaddr
711 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
712 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
713 if (sibcall)
714- XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
715+ XVECEXP (pat, 0, n++) = ret_rtx;
716 else
717 XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg);
718 call = emit_call_insn (pat);
719Index: gcc-4_5-branch/gcc/config/cris/cris.c
720===================================================================
721--- gcc-4_5-branch.orig/gcc/config/cris/cris.c
722+++ gcc-4_5-branch/gcc/config/cris/cris.c
723@@ -1771,7 +1771,7 @@ cris_expand_return (bool on_stack)
724 we do that until they're fixed. Currently, all return insns in a
725 function must be the same (not really a limiting factor) so we need
726 to check that it doesn't change half-way through. */
727- emit_jump_insn (gen_rtx_RETURN (VOIDmode));
728+ emit_jump_insn (ret_rtx);
729
730 CRIS_ASSERT (cfun->machine->return_type != CRIS_RETINSN_RET || !on_stack);
731 CRIS_ASSERT (cfun->machine->return_type != CRIS_RETINSN_JUMP || on_stack);
732Index: gcc-4_5-branch/gcc/config/h8300/h8300.c
733===================================================================
734--- gcc-4_5-branch.orig/gcc/config/h8300/h8300.c
735+++ gcc-4_5-branch/gcc/config/h8300/h8300.c
736@@ -691,7 +691,7 @@ h8300_push_pop (int regno, int nregs, bo
737 /* Add the return instruction. */
738 if (return_p)
739 {
740- RTVEC_ELT (vec, i) = gen_rtx_RETURN (VOIDmode);
741+ RTVEC_ELT (vec, i) = ret_rtx;
742 i++;
743 }
744
745@@ -975,7 +975,7 @@ h8300_expand_epilogue (void)
746 }
747
748 if (!returned_p)
749- emit_jump_insn (gen_rtx_RETURN (VOIDmode));
750+ emit_jump_insn (ret_rtx);
751 }
752
753 /* Return nonzero if the current function is an interrupt
754Index: gcc-4_5-branch/gcc/config/i386/i386.c
755===================================================================
756--- gcc-4_5-branch.orig/gcc/config/i386/i386.c
757+++ gcc-4_5-branch/gcc/config/i386/i386.c
758@@ -9308,13 +9308,13 @@ ix86_expand_epilogue (int style)
759
760 pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
761 popc, -1, true);
762- emit_jump_insn (gen_return_indirect_internal (ecx));
763+ emit_jump_insn (gen_simple_return_indirect_internal (ecx));
764 }
765 else
766- emit_jump_insn (gen_return_pop_internal (popc));
767+ emit_jump_insn (gen_simple_return_pop_internal (popc));
768 }
769 else
770- emit_jump_insn (gen_return_internal ());
771+ emit_jump_insn (gen_simple_return_internal ());
772
773 /* Restore the state back to the state from the prologue,
774 so that it's correct for the next epilogue. */
775@@ -26615,7 +26615,7 @@ ix86_pad_returns (void)
776 rtx prev;
777 bool replace = false;
778
779- if (!JUMP_P (ret) || GET_CODE (PATTERN (ret)) != RETURN
780+ if (!JUMP_P (ret) || !ANY_RETURN_P (PATTERN (ret))
781 || optimize_bb_for_size_p (bb))
782 continue;
783 for (prev = PREV_INSN (ret); prev; prev = PREV_INSN (prev))
784@@ -26645,7 +26645,10 @@ ix86_pad_returns (void)
785 }
786 if (replace)
787 {
788- emit_jump_insn_before (gen_return_internal_long (), ret);
789+ if (PATTERN (ret) == ret_rtx)
790+ emit_jump_insn_before (gen_return_internal_long (), ret);
791+ else
792+ emit_jump_insn_before (gen_simple_return_internal_long (), ret);
793 delete_insn (ret);
794 }
795 }
796Index: gcc-4_5-branch/gcc/config/i386/i386.md
797===================================================================
798--- gcc-4_5-branch.orig/gcc/config/i386/i386.md
799+++ gcc-4_5-branch/gcc/config/i386/i386.md
800@@ -13798,24 +13798,29 @@
801 ""
802 [(set_attr "length" "0")])
803
804+(define_code_iterator returns [return simple_return])
805+(define_code_attr return_str [(return "") (simple_return "simple_")])
806+(define_code_attr return_cond [(return "ix86_can_use_return_insn_p ()")
807+ (simple_return "")])
808+
809 ;; Insn emitted into the body of a function to return from a function.
810 ;; This is only done if the function's epilogue is known to be simple.
811 ;; See comments for ix86_can_use_return_insn_p in i386.c.
812
813-(define_expand "return"
814- [(return)]
815- "ix86_can_use_return_insn_p ()"
816+(define_expand "<return_str>return"
817+ [(returns)]
818+ "<return_cond>"
819 {
820 if (crtl->args.pops_args)
821 {
822 rtx popc = GEN_INT (crtl->args.pops_args);
823- emit_jump_insn (gen_return_pop_internal (popc));
824+ emit_jump_insn (gen_<return_str>return_pop_internal (popc));
825 DONE;
826 }
827 })
828
829-(define_insn "return_internal"
830- [(return)]
831+(define_insn "<return_str>return_internal"
832+ [(returns)]
833 "reload_completed"
834 "ret"
835 [(set_attr "length" "1")
836@@ -13826,8 +13831,8 @@
837 ;; Used by x86_machine_dependent_reorg to avoid penalty on single byte RET
838 ;; instruction Athlon and K8 have.
839
840-(define_insn "return_internal_long"
841- [(return)
842+(define_insn "<return_str>return_internal_long"
843+ [(returns)
844 (unspec [(const_int 0)] UNSPEC_REP)]
845 "reload_completed"
846 "rep\;ret"
847@@ -13837,8 +13842,8 @@
848 (set_attr "prefix_rep" "1")
849 (set_attr "modrm" "0")])
850
851-(define_insn "return_pop_internal"
852- [(return)
853+(define_insn "<return_str>return_pop_internal"
854+ [(returns)
855 (use (match_operand:SI 0 "const_int_operand" ""))]
856 "reload_completed"
857 "ret\t%0"
858@@ -13847,8 +13852,8 @@
859 (set_attr "length_immediate" "2")
860 (set_attr "modrm" "0")])
861
862-(define_insn "return_indirect_internal"
863- [(return)
864+(define_insn "<return_str>return_indirect_internal"
865+ [(returns)
866 (use (match_operand:SI 0 "register_operand" "r"))]
867 "reload_completed"
868 "jmp\t%A0"
869Index: gcc-4_5-branch/gcc/config/m68hc11/m68hc11.md
870===================================================================
871--- gcc-4_5-branch.orig/gcc/config/m68hc11/m68hc11.md
872+++ gcc-4_5-branch/gcc/config/m68hc11/m68hc11.md
873@@ -6576,7 +6576,7 @@
874 if (ret_size && ret_size <= 2)
875 {
876 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
877- gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
878+ gen_rtvec (2, ret_rtx,
879 gen_rtx_USE (VOIDmode,
880 gen_rtx_REG (HImode, 1)))));
881 DONE;
882@@ -6584,7 +6584,7 @@
883 if (ret_size)
884 {
885 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
886- gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
887+ gen_rtvec (2, ret_rtx,
888 gen_rtx_USE (VOIDmode,
889 gen_rtx_REG (SImode, 0)))));
890 DONE;
891Index: gcc-4_5-branch/gcc/config/m68k/m68k.c
892===================================================================
893--- gcc-4_5-branch.orig/gcc/config/m68k/m68k.c
894+++ gcc-4_5-branch/gcc/config/m68k/m68k.c
895@@ -1366,7 +1366,7 @@ m68k_expand_epilogue (bool sibcall_p)
896 EH_RETURN_STACKADJ_RTX));
897
898 if (!sibcall_p)
899- emit_jump_insn (gen_rtx_RETURN (VOIDmode));
900+ emit_jump_insn (ret_rtx);
901 }
902
903 /* Return true if X is a valid comparison operator for the dbcc
904Index: gcc-4_5-branch/gcc/config/mips/mips.c
905===================================================================
906--- gcc-4_5-branch.orig/gcc/config/mips/mips.c
907+++ gcc-4_5-branch/gcc/config/mips/mips.c
908@@ -10497,7 +10497,8 @@ mips_expand_epilogue (bool sibcall_p)
909 regno = GP_REG_FIRST + 7;
910 else
911 regno = RETURN_ADDR_REGNUM;
912- emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, regno)));
913+ emit_jump_insn (gen_simple_return_internal (gen_rtx_REG (Pmode,
914+ regno)));
915 }
916 }
917
918Index: gcc-4_5-branch/gcc/config/mips/mips.md
919===================================================================
920--- gcc-4_5-branch.orig/gcc/config/mips/mips.md
921+++ gcc-4_5-branch/gcc/config/mips/mips.md
922@@ -5815,6 +5815,18 @@
923 [(set_attr "type" "jump")
924 (set_attr "mode" "none")])
925
926+(define_expand "simple_return"
927+ [(simple_return)]
928+ "!mips_can_use_return_insn ()"
929+ { mips_expand_before_return (); })
930+
931+(define_insn "*simple_return"
932+ [(simple_return)]
933+ "!mips_can_use_return_insn ()"
934+ "%*j\t$31%/"
935+ [(set_attr "type" "jump")
936+ (set_attr "mode" "none")])
937+
938 ;; Normal return.
939
940 (define_insn "return_internal"
941@@ -5825,6 +5837,14 @@
942 [(set_attr "type" "jump")
943 (set_attr "mode" "none")])
944
945+(define_insn "simple_return_internal"
946+ [(simple_return)
947+ (use (match_operand 0 "pmode_register_operand" ""))]
948+ ""
949+ "%*j\t%0%/"
950+ [(set_attr "type" "jump")
951+ (set_attr "mode" "none")])
952+
953 ;; Exception return.
954 (define_insn "mips_eret"
955 [(return)
956Index: gcc-4_5-branch/gcc/config/picochip/picochip.c
957===================================================================
958--- gcc-4_5-branch.orig/gcc/config/picochip/picochip.c
959+++ gcc-4_5-branch/gcc/config/picochip/picochip.c
960@@ -1996,7 +1996,7 @@ picochip_expand_epilogue (int is_sibling
961 rtvec p;
962 p = rtvec_alloc (2);
963
964- RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
965+ RTVEC_ELT (p, 0) = ret_rtx;
966 RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode,
967 gen_rtx_REG (Pmode, LINK_REGNUM));
968 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
969Index: gcc-4_5-branch/gcc/config/rs6000/rs6000.c
970===================================================================
971--- gcc-4_5-branch.orig/gcc/config/rs6000/rs6000.c
972+++ gcc-4_5-branch/gcc/config/rs6000/rs6000.c
973@@ -18563,7 +18563,7 @@ rs6000_make_savres_rtx (rs6000_stack_t *
974 p = rtvec_alloc ((lr ? 4 : 3) + n_regs);
975
976 if (!savep && lr)
977- RTVEC_ELT (p, offset++) = gen_rtx_RETURN (VOIDmode);
978+ RTVEC_ELT (p, offset++) = ret_rtx;
979
980 RTVEC_ELT (p, offset++)
981 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 65));
982@@ -19638,7 +19638,7 @@ rs6000_emit_epilogue (int sibcall)
983 alloc_rname = ggc_strdup (rname);
984
985 j = 0;
986- RTVEC_ELT (p, j++) = gen_rtx_RETURN (VOIDmode);
987+ RTVEC_ELT (p, j++) = ret_rtx;
988 RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
989 gen_rtx_REG (Pmode,
990 LR_REGNO));
991@@ -20254,7 +20254,7 @@ rs6000_emit_epilogue (int sibcall)
992 else
993 p = rtvec_alloc (2);
994
995- RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
996+ RTVEC_ELT (p, 0) = ret_rtx;
997 RTVEC_ELT (p, 1) = ((restoring_FPRs_inline || !lr)
998 ? gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 65))
999 : gen_rtx_CLOBBER (VOIDmode,
1000@@ -20695,7 +20695,7 @@ rs6000_output_mi_thunk (FILE *file, tree
1001 gen_rtx_USE (VOIDmode,
1002 gen_rtx_REG (SImode,
1003 LR_REGNO)),
1004- gen_rtx_RETURN (VOIDmode))));
1005+ ret_rtx)));
1006 SIBLING_CALL_P (insn) = 1;
1007 emit_barrier ();
1008
1009Index: gcc-4_5-branch/gcc/config/rx/rx.c
1010===================================================================
1011--- gcc-4_5-branch.orig/gcc/config/rx/rx.c
1012+++ gcc-4_5-branch/gcc/config/rx/rx.c
1013@@ -1562,7 +1562,7 @@ gen_rx_rtsd_vector (unsigned int adjust,
1014 : plus_constant (stack_pointer_rtx,
1015 i * UNITS_PER_WORD)));
1016
1017- XVECEXP (vector, 0, count - 1) = gen_rtx_RETURN (VOIDmode);
1018+ XVECEXP (vector, 0, count - 1) = ret_rtx;
1019
1020 return vector;
1021 }
1022Index: gcc-4_5-branch/gcc/config/s390/s390.c
1023===================================================================
1024--- gcc-4_5-branch.orig/gcc/config/s390/s390.c
1025+++ gcc-4_5-branch/gcc/config/s390/s390.c
1026@@ -8170,7 +8170,7 @@ s390_emit_epilogue (bool sibcall)
1027
1028 p = rtvec_alloc (2);
1029
1030- RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
1031+ RTVEC_ELT (p, 0) = ret_rtx;
1032 RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, return_reg);
1033 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
1034 }
1035Index: gcc-4_5-branch/gcc/config/sh/sh.c
1036===================================================================
1037--- gcc-4_5-branch.orig/gcc/config/sh/sh.c
1038+++ gcc-4_5-branch/gcc/config/sh/sh.c
1039@@ -5252,7 +5252,8 @@ barrier_align (rtx barrier_or_label)
1040 }
1041 if (prev
1042 && JUMP_P (prev)
1043- && JUMP_LABEL (prev))
1044+ && JUMP_LABEL (prev)
1045+ && !ANY_RETURN_P (JUMP_LABEL (prev)))
1046 {
1047 rtx x;
1048 if (jump_to_next
1049@@ -5951,7 +5952,7 @@ split_branches (rtx first)
1050 JUMP_LABEL (insn) = far_label;
1051 LABEL_NUSES (far_label)++;
1052 }
1053- redirect_jump (insn, NULL_RTX, 1);
1054+ redirect_jump (insn, ret_rtx, 1);
1055 far_label = 0;
1056 }
1057 }
1058Index: gcc-4_5-branch/gcc/config/v850/v850.c
1059===================================================================
1060--- gcc-4_5-branch.orig/gcc/config/v850/v850.c
1061+++ gcc-4_5-branch/gcc/config/v850/v850.c
1062@@ -1832,7 +1832,7 @@ expand_epilogue (void)
1063 {
1064 restore_all = gen_rtx_PARALLEL (VOIDmode,
1065 rtvec_alloc (num_restore + 2));
1066- XVECEXP (restore_all, 0, 0) = gen_rtx_RETURN (VOIDmode);
1067+ XVECEXP (restore_all, 0, 0) = ret_rtx;
1068 XVECEXP (restore_all, 0, 1)
1069 = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1070 gen_rtx_PLUS (Pmode,
1071Index: gcc-4_5-branch/gcc/df-scan.c
1072===================================================================
1073--- gcc-4_5-branch.orig/gcc/df-scan.c
1074+++ gcc-4_5-branch/gcc/df-scan.c
1075@@ -3296,6 +3296,7 @@ df_uses_record (enum df_ref_class cl, st
1076 }
1077
1078 case RETURN:
1079+ case SIMPLE_RETURN:
1080 break;
1081
1082 case ASM_OPERANDS:
1083Index: gcc-4_5-branch/gcc/doc/invoke.texi
1084===================================================================
1085--- gcc-4_5-branch.orig/gcc/doc/invoke.texi
1086+++ gcc-4_5-branch/gcc/doc/invoke.texi
1087@@ -5751,6 +5751,7 @@ compilation time.
1088 -fipa-pure-const @gol
1089 -fipa-reference @gol
1090 -fmerge-constants
1091+-fshrink-wrap @gol
1092 -fsplit-wide-types @gol
1093 -ftree-builtin-call-dce @gol
1094 -ftree-ccp @gol
1095@@ -6506,6 +6507,12 @@ This option has no effect until one of @
1096 When pipelining loops during selective scheduling, also pipeline outer loops.
1097 This option has no effect until @option{-fsel-sched-pipelining} is turned on.
1098
1099+@item -fshrink-wrap
1100+@opindex fshrink-wrap
1101+Emit function prologues only before parts of the function that need it,
1102+rather than at the top of the function. This flag is enabled by default at
1103+@option{-O} and higher.
1104+
1105 @item -fcaller-saves
1106 @opindex fcaller-saves
1107 Enable values to be allocated in registers that will be clobbered by
1108Index: gcc-4_5-branch/gcc/doc/md.texi
1109===================================================================
1110--- gcc-4_5-branch.orig/gcc/doc/md.texi
1111+++ gcc-4_5-branch/gcc/doc/md.texi
1112@@ -4801,7 +4801,19 @@ RTL generation phase. In this case it i
1113 multiple instructions are usually needed to return from a function, but
1114 some class of functions only requires one instruction to implement a
1115 return. Normally, the applicable functions are those which do not need
1116-to save any registers or allocate stack space.
1117+to save any registers or allocate stack space, although some targets
1118+have instructions that can perform both the epilogue and function return
1119+in one instruction.
1120+
1121+@cindex @code{simple_return} instruction pattern
1122+@item @samp{simple_return}
1123+Subroutine return instruction. This instruction pattern name should be
1124+defined only if a single instruction can do all the work of returning
1125+from a function on a path where no epilogue is required. This pattern
1126+is very similar to the @code{return} instruction pattern, but it is emitted
1127+only by the shrink-wrapping optimization on paths where the function
1128+prologue has not been executed, and a function return should occur without
1129+any of the effects of the epilogue.
1130
1131 @findex reload_completed
1132 @findex leaf_function_p
1133Index: gcc-4_5-branch/gcc/doc/rtl.texi
1134===================================================================
1135--- gcc-4_5-branch.orig/gcc/doc/rtl.texi
1136+++ gcc-4_5-branch/gcc/doc/rtl.texi
1137@@ -2888,6 +2888,13 @@ placed in @code{pc} to return to the cal
1138 Note that an insn pattern of @code{(return)} is logically equivalent to
1139 @code{(set (pc) (return))}, but the latter form is never used.
1140
1141+@findex simple_return
1142+@item (simple_return)
1143+Like @code{(return)}, but truly represents only a function return, while
1144+@code{(return)} may represent an insn that also performs other functions
1145+of the function epilogue. Like @code{(return)}, this may also occur in
1146+conditional jumps.
1147+
1148 @findex call
1149 @item (call @var{function} @var{nargs})
1150 Represents a function call. @var{function} is a @code{mem} expression
1151@@ -3017,7 +3024,7 @@ Represents several side effects performe
1152 brackets stand for a vector; the operand of @code{parallel} is a
1153 vector of expressions. @var{x0}, @var{x1} and so on are individual
1154 side effect expressions---expressions of code @code{set}, @code{call},
1155-@code{return}, @code{clobber} or @code{use}.
1156+@code{return}, @code{simple_return}, @code{clobber} or @code{use}.
1157
1158 ``In parallel'' means that first all the values used in the individual
1159 side-effects are computed, and second all the actual side-effects are
1160@@ -3656,14 +3663,16 @@ and @code{call_insn} insns:
1161 @table @code
1162 @findex PATTERN
1163 @item PATTERN (@var{i})
1164-An expression for the side effect performed by this insn. This must be
1165-one of the following codes: @code{set}, @code{call}, @code{use},
1166-@code{clobber}, @code{return}, @code{asm_input}, @code{asm_output},
1167-@code{addr_vec}, @code{addr_diff_vec}, @code{trap_if}, @code{unspec},
1168-@code{unspec_volatile}, @code{parallel}, @code{cond_exec}, or @code{sequence}. If it is a @code{parallel},
1169-each element of the @code{parallel} must be one these codes, except that
1170-@code{parallel} expressions cannot be nested and @code{addr_vec} and
1171-@code{addr_diff_vec} are not permitted inside a @code{parallel} expression.
1172+An expression for the side effect performed by this insn. This must
1173+be one of the following codes: @code{set}, @code{call}, @code{use},
1174+@code{clobber}, @code{return}, @code{simple_return}, @code{asm_input},
1175+@code{asm_output}, @code{addr_vec}, @code{addr_diff_vec},
1176+@code{trap_if}, @code{unspec}, @code{unspec_volatile},
1177+@code{parallel}, @code{cond_exec}, or @code{sequence}. If it is a
1178+@code{parallel}, each element of the @code{parallel} must be one these
1179+codes, except that @code{parallel} expressions cannot be nested and
1180+@code{addr_vec} and @code{addr_diff_vec} are not permitted inside a
1181+@code{parallel} expression.
1182
1183 @findex INSN_CODE
1184 @item INSN_CODE (@var{i})
1185Index: gcc-4_5-branch/gcc/doc/tm.texi
1186===================================================================
1187--- gcc-4_5-branch.orig/gcc/doc/tm.texi
1188+++ gcc-4_5-branch/gcc/doc/tm.texi
1189@@ -3287,6 +3287,12 @@ Define this if the return address of a p
1190 from the frame pointer of the previous stack frame.
1191 @end defmac
1192
1193+@defmac RETURN_ADDR_REGNUM
1194+If defined, a C expression whose value is the register number of the return
1195+address for the current function. Targets that pass the return address on
1196+the stack should not define this macro.
1197+@end defmac
1198+
1199 @defmac INCOMING_RETURN_ADDR_RTX
1200 A C expression whose value is RTL representing the location of the
1201 incoming return address at the beginning of any function, before the
1202Index: gcc-4_5-branch/gcc/dwarf2out.c
1203===================================================================
1204--- gcc-4_5-branch.orig/gcc/dwarf2out.c
1205+++ gcc-4_5-branch/gcc/dwarf2out.c
1206@@ -1396,7 +1396,7 @@ compute_barrier_args_size_1 (rtx insn, H
1207 {
1208 rtx dest = JUMP_LABEL (insn);
1209
1210- if (dest)
1211+ if (dest && !ANY_RETURN_P (dest))
1212 {
1213 if (barrier_args_size [INSN_UID (dest)] < 0)
1214 {
1215Index: gcc-4_5-branch/gcc/emit-rtl.c
1216===================================================================
1217--- gcc-4_5-branch.orig/gcc/emit-rtl.c
1218+++ gcc-4_5-branch/gcc/emit-rtl.c
1219@@ -2432,6 +2432,8 @@ verify_rtx_sharing (rtx orig, rtx insn)
1220 case CODE_LABEL:
1221 case PC:
1222 case CC0:
1223+ case RETURN:
1224+ case SIMPLE_RETURN:
1225 case SCRATCH:
1226 return;
1227 /* SCRATCH must be shared because they represent distinct values. */
1228@@ -3323,14 +3325,17 @@ prev_label (rtx insn)
1229 return insn;
1230 }
1231
1232-/* Return the last label to mark the same position as LABEL. Return null
1233- if LABEL itself is null. */
1234+/* Return the last label to mark the same position as LABEL. Return LABEL
1235+ itself if it is null or any return rtx. */
1236
1237 rtx
1238 skip_consecutive_labels (rtx label)
1239 {
1240 rtx insn;
1241
1242+ if (label && ANY_RETURN_P (label))
1243+ return label;
1244+
1245 for (insn = label; insn != 0 && !INSN_P (insn); insn = NEXT_INSN (insn))
1246 if (LABEL_P (insn))
1247 label = insn;
1248@@ -5209,7 +5214,7 @@ classify_insn (rtx x)
1249 return CODE_LABEL;
1250 if (GET_CODE (x) == CALL)
1251 return CALL_INSN;
1252- if (GET_CODE (x) == RETURN)
1253+ if (GET_CODE (x) == RETURN || GET_CODE (x) == SIMPLE_RETURN)
1254 return JUMP_INSN;
1255 if (GET_CODE (x) == SET)
1256 {
1257@@ -5715,8 +5720,10 @@ init_emit_regs (void)
1258 init_reg_modes_target ();
1259
1260 /* Assign register numbers to the globally defined register rtx. */
1261- pc_rtx = gen_rtx_PC (VOIDmode);
1262- cc0_rtx = gen_rtx_CC0 (VOIDmode);
1263+ pc_rtx = gen_rtx_fmt_ (PC, VOIDmode);
1264+ ret_rtx = gen_rtx_fmt_ (RETURN, VOIDmode);
1265+ simple_return_rtx = gen_rtx_fmt_ (SIMPLE_RETURN, VOIDmode);
1266+ cc0_rtx = gen_rtx_fmt_ (CC0, VOIDmode);
1267 stack_pointer_rtx = gen_raw_REG (Pmode, STACK_POINTER_REGNUM);
1268 frame_pointer_rtx = gen_raw_REG (Pmode, FRAME_POINTER_REGNUM);
1269 hard_frame_pointer_rtx = gen_raw_REG (Pmode, HARD_FRAME_POINTER_REGNUM);
1270Index: gcc-4_5-branch/gcc/final.c
1271===================================================================
1272--- gcc-4_5-branch.orig/gcc/final.c
1273+++ gcc-4_5-branch/gcc/final.c
1274@@ -2428,7 +2428,7 @@ final_scan_insn (rtx insn, FILE *file, i
1275 delete_insn (insn);
1276 break;
1277 }
1278- else if (GET_CODE (SET_SRC (body)) == RETURN)
1279+ else if (ANY_RETURN_P (SET_SRC (body)))
1280 /* Replace (set (pc) (return)) with (return). */
1281 PATTERN (insn) = body = SET_SRC (body);
1282
1283Index: gcc-4_5-branch/gcc/function.c
1284===================================================================
1285--- gcc-4_5-branch.orig/gcc/function.c
1286+++ gcc-4_5-branch/gcc/function.c
1287@@ -147,9 +147,6 @@ extern tree debug_find_var_in_block_tree
1288 can always export `prologue_epilogue_contains'. */
1289 static void record_insns (rtx, rtx, htab_t *) ATTRIBUTE_UNUSED;
1290 static bool contains (const_rtx, htab_t);
1291-#ifdef HAVE_return
1292-static void emit_return_into_block (basic_block);
1293-#endif
1294 static void prepare_function_start (void);
1295 static void do_clobber_return_reg (rtx, void *);
1296 static void do_use_return_reg (rtx, void *);
1297@@ -4987,35 +4984,190 @@ prologue_epilogue_contains (const_rtx in
1298 return 0;
1299 }
1300
1301+#ifdef HAVE_simple_return
1302+/* This collects sets and clobbers of hard registers in a HARD_REG_SET,
1303+ which is pointed to by DATA. */
1304+static void
1305+record_hard_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
1306+{
1307+ HARD_REG_SET *pset = (HARD_REG_SET *)data;
1308+ if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
1309+ {
1310+ int nregs = hard_regno_nregs[REGNO (x)][GET_MODE (x)];
1311+ while (nregs-- > 0)
1312+ SET_HARD_REG_BIT (*pset, REGNO (x) + nregs);
1313+ }
1314+}
1315+
1316+/* A subroutine of requires_stack_frame_p, called via for_each_rtx.
1317+ If any change is made, set CHANGED
1318+ to true. */
1319+
1320+static int
1321+frame_required_for_rtx (rtx *loc, void *data ATTRIBUTE_UNUSED)
1322+{
1323+ rtx x = *loc;
1324+ if (x == stack_pointer_rtx || x == hard_frame_pointer_rtx
1325+ || x == arg_pointer_rtx || x == pic_offset_table_rtx
1326+#ifdef RETURN_ADDR_REGNUM
1327+ || (REG_P (x) && REGNO (x) == RETURN_ADDR_REGNUM)
1328+#endif
1329+ )
1330+ return 1;
1331+ return 0;
1332+}
1333+
1334+static bool
1335+requires_stack_frame_p (rtx insn)
1336+{
1337+ HARD_REG_SET hardregs;
1338+ unsigned regno;
1339+
1340+ if (!INSN_P (insn) || DEBUG_INSN_P (insn))
1341+ return false;
1342+ if (CALL_P (insn))
1343+ return !SIBLING_CALL_P (insn);
1344+ if (for_each_rtx (&PATTERN (insn), frame_required_for_rtx, NULL))
1345+ return true;
1346+ CLEAR_HARD_REG_SET (hardregs);
1347+ note_stores (PATTERN (insn), record_hard_reg_sets, &hardregs);
1348+ AND_COMPL_HARD_REG_SET (hardregs, call_used_reg_set);
1349+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1350+ if (TEST_HARD_REG_BIT (hardregs, regno)
1351+ && df_regs_ever_live_p (regno))
1352+ return true;
1353+ return false;
1354+}
1355+#endif
1356+
1357 #ifdef HAVE_return
1358-/* Insert gen_return at the end of block BB. This also means updating
1359- block_for_insn appropriately. */
1360+
1361+static rtx
1362+gen_return_pattern (bool simple_p)
1363+{
1364+#ifdef HAVE_simple_return
1365+ return simple_p ? gen_simple_return () : gen_return ();
1366+#else
1367+ gcc_assert (!simple_p);
1368+ return gen_return ();
1369+#endif
1370+}
1371+
1372+/* Insert an appropriate return pattern at the end of block BB. This
1373+ also means updating block_for_insn appropriately. */
1374
1375 static void
1376-emit_return_into_block (basic_block bb)
1377+emit_return_into_block (bool simple_p, basic_block bb)
1378 {
1379- emit_jump_insn_after (gen_return (), BB_END (bb));
1380+ rtx jump;
1381+ jump = emit_jump_insn_after (gen_return_pattern (simple_p), BB_END (bb));
1382+ JUMP_LABEL (jump) = simple_p ? simple_return_rtx : ret_rtx;
1383 }
1384-#endif /* HAVE_return */
1385+#endif
1386
1387 /* Generate the prologue and epilogue RTL if the machine supports it. Thread
1388 this into place with notes indicating where the prologue ends and where
1389- the epilogue begins. Update the basic block information when possible. */
1390+ the epilogue begins. Update the basic block information when possible.
1391+
1392+ Notes on epilogue placement:
1393+ There are several kinds of edges to the exit block:
1394+ * a single fallthru edge from LAST_BB
1395+ * possibly, edges from blocks containing sibcalls
1396+ * possibly, fake edges from infinite loops
1397+
1398+ The epilogue is always emitted on the fallthru edge from the last basic
1399+ block in the function, LAST_BB, into the exit block.
1400+
1401+ If LAST_BB is empty except for a label, it is the target of every
1402+ other basic block in the function that ends in a return. If a
1403+ target has a return or simple_return pattern (possibly with
1404+ conditional variants), these basic blocks can be changed so that a
1405+ return insn is emitted into them, and their target is adjusted to
1406+ the real exit block.
1407+
1408+ Notes on shrink wrapping: We implement a fairly conservative
1409+ version of shrink-wrapping rather than the textbook one. We only
1410+ generate a single prologue and a single epilogue. This is
1411+ sufficient to catch a number of interesting cases involving early
1412+ exits.
1413+
1414+ First, we identify the blocks that require the prologue to occur before
1415+ them. These are the ones that modify a call-saved register, or reference
1416+ any of the stack or frame pointer registers. To simplify things, we then
1417+ mark everything reachable from these blocks as also requiring a prologue.
1418+ This takes care of loops automatically, and avoids the need to examine
1419+ whether MEMs reference the frame, since it is sufficient to check for
1420+ occurrences of the stack or frame pointer.
1421+
1422+ We then compute the set of blocks for which the need for a prologue
1423+ is anticipatable (borrowing terminology from the shrink-wrapping
1424+ description in Muchnick's book). These are the blocks which either
1425+ require a prologue themselves, or those that have only successors
1426+ where the prologue is anticipatable. The prologue needs to be
1427+ inserted on all edges from BB1->BB2 where BB2 is in ANTIC and BB1
1428+ is not. For the moment, we ensure that only one such edge exists.
1429+
1430+ The epilogue is placed as described above, but we make a
1431+ distinction between inserting return and simple_return patterns
1432+ when modifying other blocks that end in a return. Blocks that end
1433+ in a sibcall omit the sibcall_epilogue if the block is not in
1434+ ANTIC. */
1435
1436 static void
1437 thread_prologue_and_epilogue_insns (void)
1438 {
1439 int inserted = 0;
1440+ basic_block last_bb;
1441+ bool last_bb_active;
1442+#ifdef HAVE_simple_return
1443+ bool unconverted_simple_returns = false;
1444+ basic_block simple_return_block = NULL;
1445+#endif
1446+ rtx returnjump ATTRIBUTE_UNUSED;
1447+ rtx seq ATTRIBUTE_UNUSED, epilogue_end ATTRIBUTE_UNUSED;
1448+ rtx prologue_seq ATTRIBUTE_UNUSED, split_prologue_seq ATTRIBUTE_UNUSED;
1449+ edge entry_edge, orig_entry_edge, exit_fallthru_edge;
1450 edge e;
1451-#if defined (HAVE_sibcall_epilogue) || defined (HAVE_epilogue) || defined (HAVE_return) || defined (HAVE_prologue)
1452- rtx seq;
1453-#endif
1454-#if defined (HAVE_epilogue) || defined(HAVE_return)
1455- rtx epilogue_end = NULL_RTX;
1456-#endif
1457 edge_iterator ei;
1458+ bitmap_head bb_flags;
1459+
1460+ df_analyze ();
1461
1462 rtl_profile_for_bb (ENTRY_BLOCK_PTR);
1463+
1464+ epilogue_end = NULL_RTX;
1465+ returnjump = NULL_RTX;
1466+
1467+ /* Can't deal with multiple successors of the entry block at the
1468+ moment. Function should always have at least one entry
1469+ point. */
1470+ gcc_assert (single_succ_p (ENTRY_BLOCK_PTR));
1471+ entry_edge = single_succ_edge (ENTRY_BLOCK_PTR);
1472+ orig_entry_edge = entry_edge;
1473+
1474+ exit_fallthru_edge = find_fallthru_edge (EXIT_BLOCK_PTR->preds);
1475+ if (exit_fallthru_edge != NULL)
1476+ {
1477+ rtx label;
1478+
1479+ last_bb = exit_fallthru_edge->src;
1480+ /* Test whether there are active instructions in the last block. */
1481+ label = BB_END (last_bb);
1482+ while (label && !LABEL_P (label))
1483+ {
1484+ if (active_insn_p (label))
1485+ break;
1486+ label = PREV_INSN (label);
1487+ }
1488+
1489+ last_bb_active = BB_HEAD (last_bb) != label || !LABEL_P (label);
1490+ }
1491+ else
1492+ {
1493+ last_bb = NULL;
1494+ last_bb_active = false;
1495+ }
1496+
1497 #ifdef HAVE_prologue
1498 if (HAVE_prologue)
1499 {
1500@@ -5040,20 +5192,169 @@ thread_prologue_and_epilogue_insns (void
1501 emit_insn (gen_blockage ());
1502 #endif
1503
1504- seq = get_insns ();
1505+ prologue_seq = get_insns ();
1506 end_sequence ();
1507 set_insn_locators (seq, prologue_locator);
1508+ }
1509+#endif
1510
1511- /* Can't deal with multiple successors of the entry block
1512- at the moment. Function should always have at least one
1513- entry point. */
1514- gcc_assert (single_succ_p (ENTRY_BLOCK_PTR));
1515+ bitmap_initialize (&bb_flags, &bitmap_default_obstack);
1516
1517- insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR));
1518- inserted = 1;
1519+#ifdef HAVE_simple_return
1520+ /* Try to perform a kind of shrink-wrapping, making sure the
1521+ prologue/epilogue is emitted only around those parts of the
1522+ function that require it. */
1523+
1524+ if (flag_shrink_wrap && HAVE_simple_return && !flag_non_call_exceptions
1525+ && HAVE_prologue && !crtl->calls_eh_return)
1526+ {
1527+ HARD_REG_SET prologue_clobbered, live_on_edge;
1528+ rtx p_insn;
1529+ VEC(basic_block, heap) *vec;
1530+ basic_block bb;
1531+ bitmap_head bb_antic_flags;
1532+ bitmap_head bb_on_list;
1533+
1534+ bitmap_initialize (&bb_antic_flags, &bitmap_default_obstack);
1535+ bitmap_initialize (&bb_on_list, &bitmap_default_obstack);
1536+
1537+ vec = VEC_alloc (basic_block, heap, n_basic_blocks);
1538+
1539+ FOR_EACH_BB (bb)
1540+ {
1541+ rtx insn;
1542+ FOR_BB_INSNS (bb, insn)
1543+ {
1544+ if (requires_stack_frame_p (insn))
1545+ {
1546+ bitmap_set_bit (&bb_flags, bb->index);
1547+ VEC_quick_push (basic_block, vec, bb);
1548+ break;
1549+ }
1550+ }
1551+ }
1552+
1553+ /* For every basic block that needs a prologue, mark all blocks
1554+ reachable from it, so as to ensure they are also seen as
1555+ requiring a prologue. */
1556+ while (!VEC_empty (basic_block, vec))
1557+ {
1558+ basic_block tmp_bb = VEC_pop (basic_block, vec);
1559+ edge e;
1560+ edge_iterator ei;
1561+ FOR_EACH_EDGE (e, ei, tmp_bb->succs)
1562+ {
1563+ if (e->dest == EXIT_BLOCK_PTR
1564+ || bitmap_bit_p (&bb_flags, e->dest->index))
1565+ continue;
1566+ bitmap_set_bit (&bb_flags, e->dest->index);
1567+ VEC_quick_push (basic_block, vec, e->dest);
1568+ }
1569+ }
1570+ /* If the last basic block contains only a label, we'll be able
1571+ to convert jumps to it to (potentially conditional) return
1572+ insns later. This means we don't necessarily need a prologue
1573+ for paths reaching it. */
1574+ if (last_bb)
1575+ {
1576+ if (!last_bb_active)
1577+ bitmap_clear_bit (&bb_flags, last_bb->index);
1578+ else if (!bitmap_bit_p (&bb_flags, last_bb->index))
1579+ goto fail_shrinkwrap;
1580+ }
1581+
1582+ /* Now walk backwards from every block that is marked as needing
1583+ a prologue to compute the bb_antic_flags bitmap. */
1584+ bitmap_copy (&bb_antic_flags, &bb_flags);
1585+ FOR_EACH_BB (bb)
1586+ {
1587+ edge e;
1588+ edge_iterator ei;
1589+ if (!bitmap_bit_p (&bb_flags, bb->index))
1590+ continue;
1591+ FOR_EACH_EDGE (e, ei, bb->preds)
1592+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index))
1593+ {
1594+ VEC_quick_push (basic_block, vec, e->src);
1595+ bitmap_set_bit (&bb_on_list, e->src->index);
1596+ }
1597+ }
1598+ while (!VEC_empty (basic_block, vec))
1599+ {
1600+ basic_block tmp_bb = VEC_pop (basic_block, vec);
1601+ edge e;
1602+ edge_iterator ei;
1603+ bool all_set = true;
1604+
1605+ bitmap_clear_bit (&bb_on_list, tmp_bb->index);
1606+ FOR_EACH_EDGE (e, ei, tmp_bb->succs)
1607+ {
1608+ if (!bitmap_bit_p (&bb_antic_flags, e->dest->index))
1609+ {
1610+ all_set = false;
1611+ break;
1612+ }
1613+ }
1614+ if (all_set)
1615+ {
1616+ bitmap_set_bit (&bb_antic_flags, tmp_bb->index);
1617+ FOR_EACH_EDGE (e, ei, tmp_bb->preds)
1618+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index))
1619+ {
1620+ VEC_quick_push (basic_block, vec, e->src);
1621+ bitmap_set_bit (&bb_on_list, e->src->index);
1622+ }
1623+ }
1624+ }
1625+ /* Find exactly one edge that leads to a block in ANTIC from
1626+ a block that isn't. */
1627+ if (!bitmap_bit_p (&bb_antic_flags, entry_edge->dest->index))
1628+ FOR_EACH_BB (bb)
1629+ {
1630+ if (!bitmap_bit_p (&bb_antic_flags, bb->index))
1631+ continue;
1632+ FOR_EACH_EDGE (e, ei, bb->preds)
1633+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index))
1634+ {
1635+ if (entry_edge != orig_entry_edge)
1636+ {
1637+ entry_edge = orig_entry_edge;
1638+ goto fail_shrinkwrap;
1639+ }
1640+ entry_edge = e;
1641+ }
1642+ }
1643+
1644+ /* Test whether the prologue is known to clobber any register
1645+ (other than FP or SP) which are live on the edge. */
1646+ CLEAR_HARD_REG_SET (prologue_clobbered);
1647+ for (p_insn = prologue_seq; p_insn; p_insn = NEXT_INSN (p_insn))
1648+ if (NONDEBUG_INSN_P (p_insn))
1649+ note_stores (PATTERN (p_insn), record_hard_reg_sets,
1650+ &prologue_clobbered);
1651+ CLEAR_HARD_REG_BIT (prologue_clobbered, STACK_POINTER_REGNUM);
1652+ if (frame_pointer_needed)
1653+ CLEAR_HARD_REG_BIT (prologue_clobbered, HARD_FRAME_POINTER_REGNUM);
1654+
1655+ CLEAR_HARD_REG_SET (live_on_edge);
1656+ reg_set_to_hard_reg_set (&live_on_edge,
1657+ df_get_live_in (entry_edge->dest));
1658+ if (hard_reg_set_intersect_p (live_on_edge, prologue_clobbered))
1659+ entry_edge = orig_entry_edge;
1660+
1661+ fail_shrinkwrap:
1662+ bitmap_clear (&bb_antic_flags);
1663+ bitmap_clear (&bb_on_list);
1664+ VEC_free (basic_block, heap, vec);
1665 }
1666 #endif
1667
1668+ if (prologue_seq != NULL_RTX)
1669+ {
1670+ insert_insn_on_edge (prologue_seq, entry_edge);
1671+ inserted = true;
1672+ }
1673+
1674 /* If the exit block has no non-fake predecessors, we don't need
1675 an epilogue. */
1676 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
1677@@ -5063,100 +5364,130 @@ thread_prologue_and_epilogue_insns (void
1678 goto epilogue_done;
1679
1680 rtl_profile_for_bb (EXIT_BLOCK_PTR);
1681+
1682 #ifdef HAVE_return
1683- if (optimize && HAVE_return)
1684+ /* If we're allowed to generate a simple return instruction, then by
1685+ definition we don't need a full epilogue. If the last basic
1686+ block before the exit block does not contain active instructions,
1687+ examine its predecessors and try to emit (conditional) return
1688+ instructions. */
1689+ if (optimize && !last_bb_active
1690+ && (HAVE_return || entry_edge != orig_entry_edge))
1691 {
1692- /* If we're allowed to generate a simple return instruction,
1693- then by definition we don't need a full epilogue. Examine
1694- the block that falls through to EXIT. If it does not
1695- contain any code, examine its predecessors and try to
1696- emit (conditional) return instructions. */
1697-
1698- basic_block last;
1699+ edge_iterator ei2;
1700+ int i;
1701+ basic_block bb;
1702 rtx label;
1703+ VEC(basic_block,heap) *src_bbs;
1704
1705- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
1706- if (e->flags & EDGE_FALLTHRU)
1707- break;
1708- if (e == NULL)
1709+ if (exit_fallthru_edge == NULL)
1710 goto epilogue_done;
1711- last = e->src;
1712+ label = BB_HEAD (last_bb);
1713
1714- /* Verify that there are no active instructions in the last block. */
1715- label = BB_END (last);
1716- while (label && !LABEL_P (label))
1717- {
1718- if (active_insn_p (label))
1719- break;
1720- label = PREV_INSN (label);
1721- }
1722+ src_bbs = VEC_alloc (basic_block, heap, EDGE_COUNT (last_bb->preds));
1723+ FOR_EACH_EDGE (e, ei2, last_bb->preds)
1724+ if (e->src != ENTRY_BLOCK_PTR)
1725+ VEC_quick_push (basic_block, src_bbs, e->src);
1726
1727- if (BB_HEAD (last) == label && LABEL_P (label))
1728+ FOR_EACH_VEC_ELT (basic_block, src_bbs, i, bb)
1729 {
1730- edge_iterator ei2;
1731+ bool simple_p;
1732+ rtx jump;
1733+ e = find_edge (bb, last_bb);
1734
1735- for (ei2 = ei_start (last->preds); (e = ei_safe_edge (ei2)); )
1736- {
1737- basic_block bb = e->src;
1738- rtx jump;
1739+ jump = BB_END (bb);
1740
1741- if (bb == ENTRY_BLOCK_PTR)
1742- {
1743- ei_next (&ei2);
1744- continue;
1745- }
1746+#ifdef HAVE_simple_return
1747+ simple_p = (entry_edge != orig_entry_edge
1748+ ? !bitmap_bit_p (&bb_flags, bb->index) : false);
1749+#else
1750+ simple_p = false;
1751+#endif
1752
1753- jump = BB_END (bb);
1754- if (!JUMP_P (jump) || JUMP_LABEL (jump) != label)
1755- {
1756- ei_next (&ei2);
1757- continue;
1758- }
1759+ if (!simple_p
1760+ && (!HAVE_return || !JUMP_P (jump)
1761+ || JUMP_LABEL (jump) != label))
1762+ continue;
1763
1764- /* If we have an unconditional jump, we can replace that
1765- with a simple return instruction. */
1766- if (simplejump_p (jump))
1767- {
1768- emit_return_into_block (bb);
1769- delete_insn (jump);
1770- }
1771+ /* If we have an unconditional jump, we can replace that
1772+ with a simple return instruction. */
1773+ if (!JUMP_P (jump))
1774+ {
1775+ emit_barrier_after (BB_END (bb));
1776+ emit_return_into_block (simple_p, bb);
1777+ }
1778+ else if (simplejump_p (jump))
1779+ {
1780+ emit_return_into_block (simple_p, bb);
1781+ delete_insn (jump);
1782+ }
1783+ else if (condjump_p (jump) && JUMP_LABEL (jump) != label)
1784+ {
1785+ basic_block new_bb;
1786+ edge new_e;
1787
1788- /* If we have a conditional jump, we can try to replace
1789- that with a conditional return instruction. */
1790- else if (condjump_p (jump))
1791- {
1792- if (! redirect_jump (jump, 0, 0))
1793- {
1794- ei_next (&ei2);
1795- continue;
1796- }
1797+ gcc_assert (simple_p);
1798+ new_bb = split_edge (e);
1799+ emit_barrier_after (BB_END (new_bb));
1800+ emit_return_into_block (simple_p, new_bb);
1801+#ifdef HAVE_simple_return
1802+ simple_return_block = new_bb;
1803+#endif
1804+ new_e = single_succ_edge (new_bb);
1805+ redirect_edge_succ (new_e, EXIT_BLOCK_PTR);
1806
1807- /* If this block has only one successor, it both jumps
1808- and falls through to the fallthru block, so we can't
1809- delete the edge. */
1810- if (single_succ_p (bb))
1811- {
1812- ei_next (&ei2);
1813- continue;
1814- }
1815- }
1816+ continue;
1817+ }
1818+ /* If we have a conditional jump branching to the last
1819+ block, we can try to replace that with a conditional
1820+ return instruction. */
1821+ else if (condjump_p (jump))
1822+ {
1823+ rtx dest;
1824+ if (simple_p)
1825+ dest = simple_return_rtx;
1826 else
1827+ dest = ret_rtx;
1828+ if (! redirect_jump (jump, dest, 0))
1829 {
1830- ei_next (&ei2);
1831+#ifdef HAVE_simple_return
1832+ if (simple_p)
1833+ unconverted_simple_returns = true;
1834+#endif
1835 continue;
1836 }
1837
1838- /* Fix up the CFG for the successful change we just made. */
1839- redirect_edge_succ (e, EXIT_BLOCK_PTR);
1840+ /* If this block has only one successor, it both jumps
1841+ and falls through to the fallthru block, so we can't
1842+ delete the edge. */
1843+ if (single_succ_p (bb))
1844+ continue;
1845+ }
1846+ else
1847+ {
1848+#ifdef HAVE_simple_return
1849+ if (simple_p)
1850+ unconverted_simple_returns = true;
1851+#endif
1852+ continue;
1853 }
1854
1855+ /* Fix up the CFG for the successful change we just made. */
1856+ redirect_edge_succ (e, EXIT_BLOCK_PTR);
1857+ }
1858+ VEC_free (basic_block, heap, src_bbs);
1859+
1860+ if (HAVE_return)
1861+ {
1862 /* Emit a return insn for the exit fallthru block. Whether
1863 this is still reachable will be determined later. */
1864
1865- emit_barrier_after (BB_END (last));
1866- emit_return_into_block (last);
1867- epilogue_end = BB_END (last);
1868- single_succ_edge (last)->flags &= ~EDGE_FALLTHRU;
1869+ emit_barrier_after (BB_END (last_bb));
1870+ emit_return_into_block (false, last_bb);
1871+ epilogue_end = BB_END (last_bb);
1872+ if (JUMP_P (epilogue_end))
1873+ JUMP_LABEL (epilogue_end) = ret_rtx;
1874+ single_succ_edge (last_bb)->flags &= ~EDGE_FALLTHRU;
1875 goto epilogue_done;
1876 }
1877 }
1878@@ -5193,15 +5524,10 @@ thread_prologue_and_epilogue_insns (void
1879 }
1880 #endif
1881
1882- /* Find the edge that falls through to EXIT. Other edges may exist
1883- due to RETURN instructions, but those don't need epilogues.
1884- There really shouldn't be a mixture -- either all should have
1885- been converted or none, however... */
1886+ /* If nothing falls through into the exit block, we don't need an
1887+ epilogue. */
1888
1889- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
1890- if (e->flags & EDGE_FALLTHRU)
1891- break;
1892- if (e == NULL)
1893+ if (exit_fallthru_edge == NULL)
1894 goto epilogue_done;
1895
1896 #ifdef HAVE_epilogue
1897@@ -5217,25 +5543,36 @@ thread_prologue_and_epilogue_insns (void
1898 set_insn_locators (seq, epilogue_locator);
1899
1900 seq = get_insns ();
1901+ returnjump = get_last_insn ();
1902 end_sequence ();
1903
1904- insert_insn_on_edge (seq, e);
1905+ insert_insn_on_edge (seq, exit_fallthru_edge);
1906 inserted = 1;
1907+ if (JUMP_P (returnjump))
1908+ {
1909+ rtx pat = PATTERN (returnjump);
1910+ if (GET_CODE (pat) == PARALLEL)
1911+ pat = XVECEXP (pat, 0, 0);
1912+ if (ANY_RETURN_P (pat))
1913+ JUMP_LABEL (returnjump) = pat;
1914+ else
1915+ JUMP_LABEL (returnjump) = ret_rtx;
1916+ }
1917 }
1918 else
1919 #endif
1920 {
1921 basic_block cur_bb;
1922
1923- if (! next_active_insn (BB_END (e->src)))
1924+ if (! next_active_insn (BB_END (exit_fallthru_edge->src)))
1925 goto epilogue_done;
1926 /* We have a fall-through edge to the exit block, the source is not
1927- at the end of the function, and there will be an assembler epilogue
1928- at the end of the function.
1929- We can't use force_nonfallthru here, because that would try to
1930- use return. Inserting a jump 'by hand' is extremely messy, so
1931+ at the end of the function, and there will be an assembler epilogue
1932+ at the end of the function.
1933+ We can't use force_nonfallthru here, because that would try to
1934+ use return. Inserting a jump 'by hand' is extremely messy, so
1935 we take advantage of cfg_layout_finalize using
1936- fixup_fallthru_exit_predecessor. */
1937+ fixup_fallthru_exit_predecessor. */
1938 cfg_layout_initialize (0);
1939 FOR_EACH_BB (cur_bb)
1940 if (cur_bb->index >= NUM_FIXED_BLOCKS
1941@@ -5244,6 +5581,7 @@ thread_prologue_and_epilogue_insns (void
1942 cfg_layout_finalize ();
1943 }
1944 epilogue_done:
1945+
1946 default_rtl_profile ();
1947
1948 if (inserted)
1949@@ -5260,33 +5598,93 @@ epilogue_done:
1950 }
1951 }
1952
1953+#ifdef HAVE_simple_return
1954+ /* If there were branches to an empty LAST_BB which we tried to
1955+ convert to conditional simple_returns, but couldn't for some
1956+ reason, create a block to hold a simple_return insn and redirect
1957+ those remaining edges. */
1958+ if (unconverted_simple_returns)
1959+ {
1960+ edge_iterator ei2;
1961+ basic_block exit_pred = EXIT_BLOCK_PTR->prev_bb;
1962+
1963+ gcc_assert (entry_edge != orig_entry_edge);
1964+
1965+#ifdef HAVE_epilogue
1966+ if (simple_return_block == NULL && returnjump != NULL_RTX
1967+ && JUMP_LABEL (returnjump) == simple_return_rtx)
1968+ {
1969+ edge e = split_block (exit_fallthru_edge->src,
1970+ PREV_INSN (returnjump));
1971+ simple_return_block = e->dest;
1972+ }
1973+#endif
1974+ if (simple_return_block == NULL)
1975+ {
1976+ basic_block bb;
1977+ rtx start;
1978+
1979+ bb = create_basic_block (NULL, NULL, exit_pred);
1980+ start = emit_jump_insn_after (gen_simple_return (),
1981+ BB_END (bb));
1982+ JUMP_LABEL (start) = simple_return_rtx;
1983+ emit_barrier_after (start);
1984+
1985+ simple_return_block = bb;
1986+ make_edge (bb, EXIT_BLOCK_PTR, 0);
1987+ }
1988+
1989+ restart_scan:
1990+ for (ei2 = ei_start (last_bb->preds); (e = ei_safe_edge (ei2)); )
1991+ {
1992+ basic_block bb = e->src;
1993+
1994+ if (bb != ENTRY_BLOCK_PTR
1995+ && !bitmap_bit_p (&bb_flags, bb->index))
1996+ {
1997+ redirect_edge_and_branch_force (e, simple_return_block);
1998+ goto restart_scan;
1999+ }
2000+ ei_next (&ei2);
2001+
2002+ }
2003+ }
2004+#endif
2005+
2006 #ifdef HAVE_sibcall_epilogue
2007 /* Emit sibling epilogues before any sibling call sites. */
2008 for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
2009 {
2010 basic_block bb = e->src;
2011 rtx insn = BB_END (bb);
2012+ rtx ep_seq;
2013
2014 if (!CALL_P (insn)
2015- || ! SIBLING_CALL_P (insn))
2016+ || ! SIBLING_CALL_P (insn)
2017+ || (entry_edge != orig_entry_edge
2018+ && !bitmap_bit_p (&bb_flags, bb->index)))
2019 {
2020 ei_next (&ei);
2021 continue;
2022 }
2023
2024- start_sequence ();
2025- emit_note (NOTE_INSN_EPILOGUE_BEG);
2026- emit_insn (gen_sibcall_epilogue ());
2027- seq = get_insns ();
2028- end_sequence ();
2029+ ep_seq = gen_sibcall_epilogue ();
2030+ if (ep_seq)
2031+ {
2032+ start_sequence ();
2033+ emit_note (NOTE_INSN_EPILOGUE_BEG);
2034+ emit_insn (ep_seq);
2035+ seq = get_insns ();
2036+ end_sequence ();
2037
2038- /* Retain a map of the epilogue insns. Used in life analysis to
2039- avoid getting rid of sibcall epilogue insns. Do this before we
2040- actually emit the sequence. */
2041- record_insns (seq, NULL, &epilogue_insn_hash);
2042- set_insn_locators (seq, epilogue_locator);
2043+ /* Retain a map of the epilogue insns. Used in life analysis to
2044+ avoid getting rid of sibcall epilogue insns. Do this before we
2045+ actually emit the sequence. */
2046+ record_insns (seq, NULL, &epilogue_insn_hash);
2047+ set_insn_locators (seq, epilogue_locator);
2048
2049- emit_insn_before (seq, insn);
2050+ emit_insn_before (seq, insn);
2051+ }
2052 ei_next (&ei);
2053 }
2054 #endif
2055@@ -5311,6 +5709,8 @@ epilogue_done:
2056 }
2057 #endif
2058
2059+ bitmap_clear (&bb_flags);
2060+
2061 /* Threading the prologue and epilogue changes the artificial refs
2062 in the entry and exit blocks. */
2063 epilogue_completed = 1;
2064Index: gcc-4_5-branch/gcc/genemit.c
2065===================================================================
2066--- gcc-4_5-branch.orig/gcc/genemit.c
2067+++ gcc-4_5-branch/gcc/genemit.c
2068@@ -222,6 +222,12 @@ gen_exp (rtx x, enum rtx_code subroutine
2069 case PC:
2070 printf ("pc_rtx");
2071 return;
2072+ case RETURN:
2073+ printf ("ret_rtx");
2074+ return;
2075+ case SIMPLE_RETURN:
2076+ printf ("simple_return_rtx");
2077+ return;
2078 case CLOBBER:
2079 if (REG_P (XEXP (x, 0)))
2080 {
2081@@ -544,8 +550,8 @@ gen_expand (rtx expand)
2082 || (GET_CODE (next) == PARALLEL
2083 && ((GET_CODE (XVECEXP (next, 0, 0)) == SET
2084 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
2085- || GET_CODE (XVECEXP (next, 0, 0)) == RETURN))
2086- || GET_CODE (next) == RETURN)
2087+ || ANY_RETURN_P (XVECEXP (next, 0, 0))))
2088+ || ANY_RETURN_P (next))
2089 printf (" emit_jump_insn (");
2090 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
2091 || GET_CODE (next) == CALL
2092@@ -660,7 +666,7 @@ gen_split (rtx split)
2093 || (GET_CODE (next) == PARALLEL
2094 && GET_CODE (XVECEXP (next, 0, 0)) == SET
2095 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
2096- || GET_CODE (next) == RETURN)
2097+ || ANY_RETURN_P (next))
2098 printf (" emit_jump_insn (");
2099 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
2100 || GET_CODE (next) == CALL
2101Index: gcc-4_5-branch/gcc/gengenrtl.c
2102===================================================================
2103--- gcc-4_5-branch.orig/gcc/gengenrtl.c
2104+++ gcc-4_5-branch/gcc/gengenrtl.c
2105@@ -146,6 +146,10 @@ special_rtx (int idx)
2106 || strcmp (defs[idx].enumname, "REG") == 0
2107 || strcmp (defs[idx].enumname, "SUBREG") == 0
2108 || strcmp (defs[idx].enumname, "MEM") == 0
2109+ || strcmp (defs[idx].enumname, "PC") == 0
2110+ || strcmp (defs[idx].enumname, "CC0") == 0
2111+ || strcmp (defs[idx].enumname, "RETURN") == 0
2112+ || strcmp (defs[idx].enumname, "SIMPLE_RETURN") == 0
2113 || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
2114 }
2115
2116Index: gcc-4_5-branch/gcc/haifa-sched.c
2117===================================================================
2118--- gcc-4_5-branch.orig/gcc/haifa-sched.c
2119+++ gcc-4_5-branch/gcc/haifa-sched.c
2120@@ -4231,7 +4231,7 @@ xrecalloc (void *p, size_t new_nmemb, si
2121 /* Helper function.
2122 Find fallthru edge from PRED. */
2123 edge
2124-find_fallthru_edge (basic_block pred)
2125+find_fallthru_edge_from (basic_block pred)
2126 {
2127 edge e;
2128 edge_iterator ei;
2129@@ -4298,7 +4298,7 @@ init_before_recovery (basic_block *befor
2130 edge e;
2131
2132 last = EXIT_BLOCK_PTR->prev_bb;
2133- e = find_fallthru_edge (last);
2134+ e = find_fallthru_edge_from (last);
2135
2136 if (e)
2137 {
2138@@ -5234,6 +5234,11 @@ check_cfg (rtx head, rtx tail)
2139 gcc_assert (/* Usual case. */
2140 (EDGE_COUNT (bb->succs) > 1
2141 && !BARRIER_P (NEXT_INSN (head)))
2142+ /* Special cases, see cfglayout.c:
2143+ fixup_reorder_chain. */
2144+ || (EDGE_COUNT (bb->succs) == 1
2145+ && (!onlyjump_p (head)
2146+ || returnjump_p (head)))
2147 /* Or jump to the next instruction. */
2148 || (EDGE_COUNT (bb->succs) == 1
2149 && (BB_HEAD (EDGE_I (bb->succs, 0)->dest)
2150Index: gcc-4_5-branch/gcc/ifcvt.c
2151===================================================================
2152--- gcc-4_5-branch.orig/gcc/ifcvt.c
2153+++ gcc-4_5-branch/gcc/ifcvt.c
2154@@ -105,7 +105,7 @@ static int find_if_case_1 (basic_block,
2155 static int find_if_case_2 (basic_block, edge, edge);
2156 static int find_memory (rtx *, void *);
2157 static int dead_or_predicable (basic_block, basic_block, basic_block,
2158- basic_block, int);
2159+ edge, int);
2160 static void noce_emit_move_insn (rtx, rtx);
2161 static rtx block_has_only_trap (basic_block);
2162
2163@@ -3791,6 +3791,7 @@ find_if_case_1 (basic_block test_bb, edg
2164 basic_block then_bb = then_edge->dest;
2165 basic_block else_bb = else_edge->dest;
2166 basic_block new_bb;
2167+ rtx else_target = NULL_RTX;
2168 int then_bb_index;
2169
2170 /* If we are partitioning hot/cold basic blocks, we don't want to
2171@@ -3840,9 +3841,16 @@ find_if_case_1 (basic_block test_bb, edg
2172 predictable_edge_p (then_edge)))))
2173 return FALSE;
2174
2175+ if (else_bb == EXIT_BLOCK_PTR)
2176+ {
2177+ rtx jump = BB_END (else_edge->src);
2178+ gcc_assert (JUMP_P (jump));
2179+ else_target = JUMP_LABEL (jump);
2180+ }
2181+
2182 /* Registers set are dead, or are predicable. */
2183 if (! dead_or_predicable (test_bb, then_bb, else_bb,
2184- single_succ (then_bb), 1))
2185+ single_succ_edge (then_bb), 1))
2186 return FALSE;
2187
2188 /* Conversion went ok, including moving the insns and fixing up the
2189@@ -3859,6 +3867,9 @@ find_if_case_1 (basic_block test_bb, edg
2190 redirect_edge_succ (FALLTHRU_EDGE (test_bb), else_bb);
2191 new_bb = 0;
2192 }
2193+ else if (else_bb == EXIT_BLOCK_PTR)
2194+ new_bb = force_nonfallthru_and_redirect (FALLTHRU_EDGE (test_bb),
2195+ else_bb, else_target);
2196 else
2197 new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb),
2198 else_bb);
2199@@ -3957,7 +3968,7 @@ find_if_case_2 (basic_block test_bb, edg
2200 return FALSE;
2201
2202 /* Registers set are dead, or are predicable. */
2203- if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ->dest, 0))
2204+ if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ, 0))
2205 return FALSE;
2206
2207 /* Conversion went ok, including moving the insns and fixing up the
2208@@ -3995,12 +4006,34 @@ find_memory (rtx *px, void *data ATTRIBU
2209
2210 static int
2211 dead_or_predicable (basic_block test_bb, basic_block merge_bb,
2212- basic_block other_bb, basic_block new_dest, int reversep)
2213+ basic_block other_bb, edge dest_edge, int reversep)
2214 {
2215- rtx head, end, jump, earliest = NULL_RTX, old_dest, new_label = NULL_RTX;
2216+ basic_block new_dest = dest_edge->dest;
2217+ rtx head, end, jump, earliest = NULL_RTX, old_dest;
2218 bitmap merge_set = NULL;
2219 /* Number of pending changes. */
2220 int n_validated_changes = 0;
2221+ rtx new_dest_label;
2222+
2223+ jump = BB_END (dest_edge->src);
2224+ if (JUMP_P (jump))
2225+ {
2226+ new_dest_label = JUMP_LABEL (jump);
2227+ if (new_dest_label == NULL_RTX)
2228+ {
2229+ new_dest_label = PATTERN (jump);
2230+ gcc_assert (ANY_RETURN_P (new_dest_label));
2231+ }
2232+ }
2233+ else if (other_bb != new_dest)
2234+ {
2235+ if (new_dest == EXIT_BLOCK_PTR)
2236+ new_dest_label = ret_rtx;
2237+ else
2238+ new_dest_label = block_label (new_dest);
2239+ }
2240+ else
2241+ new_dest_label = NULL_RTX;
2242
2243 jump = BB_END (test_bb);
2244
2245@@ -4220,10 +4253,9 @@ dead_or_predicable (basic_block test_bb,
2246 old_dest = JUMP_LABEL (jump);
2247 if (other_bb != new_dest)
2248 {
2249- new_label = block_label (new_dest);
2250 if (reversep
2251- ? ! invert_jump_1 (jump, new_label)
2252- : ! redirect_jump_1 (jump, new_label))
2253+ ? ! invert_jump_1 (jump, new_dest_label)
2254+ : ! redirect_jump_1 (jump, new_dest_label))
2255 goto cancel;
2256 }
2257
2258@@ -4234,7 +4266,7 @@ dead_or_predicable (basic_block test_bb,
2259
2260 if (other_bb != new_dest)
2261 {
2262- redirect_jump_2 (jump, old_dest, new_label, 0, reversep);
2263+ redirect_jump_2 (jump, old_dest, new_dest_label, 0, reversep);
2264
2265 redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
2266 if (reversep)
2267Index: gcc-4_5-branch/gcc/jump.c
2268===================================================================
2269--- gcc-4_5-branch.orig/gcc/jump.c
2270+++ gcc-4_5-branch/gcc/jump.c
2271@@ -29,7 +29,8 @@ along with GCC; see the file COPYING3.
2272 JUMP_LABEL internal field. With this we can detect labels that
2273 become unused because of the deletion of all the jumps that
2274 formerly used them. The JUMP_LABEL info is sometimes looked
2275- at by later passes.
2276+ at by later passes. For return insns, it contains either a
2277+ RETURN or a SIMPLE_RETURN rtx.
2278
2279 The subroutines redirect_jump and invert_jump are used
2280 from other passes as well. */
2281@@ -742,10 +743,10 @@ condjump_p (const_rtx insn)
2282 return (GET_CODE (x) == IF_THEN_ELSE
2283 && ((GET_CODE (XEXP (x, 2)) == PC
2284 && (GET_CODE (XEXP (x, 1)) == LABEL_REF
2285- || GET_CODE (XEXP (x, 1)) == RETURN))
2286+ || ANY_RETURN_P (XEXP (x, 1))))
2287 || (GET_CODE (XEXP (x, 1)) == PC
2288 && (GET_CODE (XEXP (x, 2)) == LABEL_REF
2289- || GET_CODE (XEXP (x, 2)) == RETURN))));
2290+ || ANY_RETURN_P (XEXP (x, 2))))));
2291 }
2292
2293 /* Return nonzero if INSN is a (possibly) conditional jump inside a
2294@@ -774,11 +775,11 @@ condjump_in_parallel_p (const_rtx insn)
2295 return 0;
2296 if (XEXP (SET_SRC (x), 2) == pc_rtx
2297 && (GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF
2298- || GET_CODE (XEXP (SET_SRC (x), 1)) == RETURN))
2299+ || ANY_RETURN_P (XEXP (SET_SRC (x), 1)) == RETURN))
2300 return 1;
2301 if (XEXP (SET_SRC (x), 1) == pc_rtx
2302 && (GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF
2303- || GET_CODE (XEXP (SET_SRC (x), 2)) == RETURN))
2304+ || ANY_RETURN_P (XEXP (SET_SRC (x), 2))))
2305 return 1;
2306 return 0;
2307 }
2308@@ -840,8 +841,9 @@ any_condjump_p (const_rtx insn)
2309 a = GET_CODE (XEXP (SET_SRC (x), 1));
2310 b = GET_CODE (XEXP (SET_SRC (x), 2));
2311
2312- return ((b == PC && (a == LABEL_REF || a == RETURN))
2313- || (a == PC && (b == LABEL_REF || b == RETURN)));
2314+ return ((b == PC && (a == LABEL_REF || a == RETURN || a == SIMPLE_RETURN))
2315+ || (a == PC
2316+ && (b == LABEL_REF || b == RETURN || b == SIMPLE_RETURN)));
2317 }
2318
2319 /* Return the label of a conditional jump. */
2320@@ -878,6 +880,7 @@ returnjump_p_1 (rtx *loc, void *data ATT
2321 switch (GET_CODE (x))
2322 {
2323 case RETURN:
2324+ case SIMPLE_RETURN:
2325 case EH_RETURN:
2326 return true;
2327
2328@@ -1200,7 +1203,7 @@ delete_related_insns (rtx insn)
2329 /* If deleting a jump, decrement the count of the label,
2330 and delete the label if it is now unused. */
2331
2332- if (JUMP_P (insn) && JUMP_LABEL (insn))
2333+ if (JUMP_P (insn) && JUMP_LABEL (insn) && !ANY_RETURN_P (JUMP_LABEL (insn)))
2334 {
2335 rtx lab = JUMP_LABEL (insn), lab_next;
2336
2337@@ -1331,6 +1334,18 @@ delete_for_peephole (rtx from, rtx to)
2338 is also an unconditional jump in that case. */
2339 }
2340
2341+/* A helper function for redirect_exp_1; examines its input X and returns
2342+ either a LABEL_REF around a label, or a RETURN if X was NULL. */
2343+static rtx
2344+redirect_target (rtx x)
2345+{
2346+ if (x == NULL_RTX)
2347+ return ret_rtx;
2348+ if (!ANY_RETURN_P (x))
2349+ return gen_rtx_LABEL_REF (Pmode, x);
2350+ return x;
2351+}
2352+
2353 /* Throughout LOC, redirect OLABEL to NLABEL. Treat null OLABEL or
2354 NLABEL as a return. Accrue modifications into the change group. */
2355
2356@@ -1342,37 +1357,19 @@ redirect_exp_1 (rtx *loc, rtx olabel, rt
2357 int i;
2358 const char *fmt;
2359
2360- if (code == LABEL_REF)
2361- {
2362- if (XEXP (x, 0) == olabel)
2363- {
2364- rtx n;
2365- if (nlabel)
2366- n = gen_rtx_LABEL_REF (Pmode, nlabel);
2367- else
2368- n = gen_rtx_RETURN (VOIDmode);
2369-
2370- validate_change (insn, loc, n, 1);
2371- return;
2372- }
2373- }
2374- else if (code == RETURN && olabel == 0)
2375+ if ((code == LABEL_REF && XEXP (x, 0) == olabel)
2376+ || x == olabel)
2377 {
2378- if (nlabel)
2379- x = gen_rtx_LABEL_REF (Pmode, nlabel);
2380- else
2381- x = gen_rtx_RETURN (VOIDmode);
2382- if (loc == &PATTERN (insn))
2383- x = gen_rtx_SET (VOIDmode, pc_rtx, x);
2384- validate_change (insn, loc, x, 1);
2385+ validate_change (insn, loc, redirect_target (nlabel), 1);
2386 return;
2387 }
2388
2389- if (code == SET && nlabel == 0 && SET_DEST (x) == pc_rtx
2390+ if (code == SET && SET_DEST (x) == pc_rtx
2391+ && ANY_RETURN_P (nlabel)
2392 && GET_CODE (SET_SRC (x)) == LABEL_REF
2393 && XEXP (SET_SRC (x), 0) == olabel)
2394 {
2395- validate_change (insn, loc, gen_rtx_RETURN (VOIDmode), 1);
2396+ validate_change (insn, loc, nlabel, 1);
2397 return;
2398 }
2399
2400@@ -1409,6 +1406,7 @@ redirect_jump_1 (rtx jump, rtx nlabel)
2401 int ochanges = num_validated_changes ();
2402 rtx *loc, asmop;
2403
2404+ gcc_assert (nlabel);
2405 asmop = extract_asm_operands (PATTERN (jump));
2406 if (asmop)
2407 {
2408@@ -1430,17 +1428,20 @@ redirect_jump_1 (rtx jump, rtx nlabel)
2409 jump target label is unused as a result, it and the code following
2410 it may be deleted.
2411
2412- If NLABEL is zero, we are to turn the jump into a (possibly conditional)
2413- RETURN insn.
2414+ Normally, NLABEL will be a label, but it may also be a RETURN or
2415+ SIMPLE_RETURN rtx; in that case we are to turn the jump into a
2416+ (possibly conditional) return insn.
2417
2418 The return value will be 1 if the change was made, 0 if it wasn't
2419- (this can only occur for NLABEL == 0). */
2420+ (this can only occur when trying to produce return insns). */
2421
2422 int
2423 redirect_jump (rtx jump, rtx nlabel, int delete_unused)
2424 {
2425 rtx olabel = JUMP_LABEL (jump);
2426
2427+ gcc_assert (nlabel != NULL_RTX);
2428+
2429 if (nlabel == olabel)
2430 return 1;
2431
2432@@ -1452,7 +1453,7 @@ redirect_jump (rtx jump, rtx nlabel, int
2433 }
2434
2435 /* Fix up JUMP_LABEL and label ref counts after OLABEL has been replaced with
2436- NLABEL in JUMP.
2437+ NEW_DEST in JUMP.
2438 If DELETE_UNUSED is positive, delete related insn to OLABEL if its ref
2439 count has dropped to zero. */
2440 void
2441@@ -1468,13 +1469,14 @@ redirect_jump_2 (rtx jump, rtx olabel, r
2442 about this. */
2443 gcc_assert (delete_unused >= 0);
2444 JUMP_LABEL (jump) = nlabel;
2445- if (nlabel)
2446+ if (nlabel && !ANY_RETURN_P (nlabel))
2447 ++LABEL_NUSES (nlabel);
2448
2449 /* Update labels in any REG_EQUAL note. */
2450 if ((note = find_reg_note (jump, REG_EQUAL, NULL_RTX)) != NULL_RTX)
2451 {
2452- if (!nlabel || (invert && !invert_exp_1 (XEXP (note, 0), jump)))
2453+ if (ANY_RETURN_P (nlabel)
2454+ || (invert && !invert_exp_1 (XEXP (note, 0), jump)))
2455 remove_note (jump, note);
2456 else
2457 {
2458@@ -1483,7 +1485,8 @@ redirect_jump_2 (rtx jump, rtx olabel, r
2459 }
2460 }
2461
2462- if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
2463+ if (olabel && !ANY_RETURN_P (olabel)
2464+ && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
2465 /* Undefined labels will remain outside the insn stream. */
2466 && INSN_UID (olabel))
2467 delete_related_insns (olabel);
2468Index: gcc-4_5-branch/gcc/opts.c
2469===================================================================
2470--- gcc-4_5-branch.orig/gcc/opts.c
2471+++ gcc-4_5-branch/gcc/opts.c
2472@@ -909,6 +909,7 @@ decode_options (unsigned int argc, const
2473 flag_ipa_cp = opt2;
2474 flag_ipa_sra = opt2;
2475 flag_ee = opt2;
2476+ flag_shrink_wrap = opt2;
2477
2478 /* Track fields in field-sensitive alias analysis. */
2479 set_param_value ("max-fields-for-field-sensitive",
2480Index: gcc-4_5-branch/gcc/print-rtl.c
2481===================================================================
2482--- gcc-4_5-branch.orig/gcc/print-rtl.c
2483+++ gcc-4_5-branch/gcc/print-rtl.c
2484@@ -308,9 +308,16 @@ print_rtx (const_rtx in_rtx)
2485 }
2486 }
2487 else if (i == 8 && JUMP_P (in_rtx) && JUMP_LABEL (in_rtx) != NULL)
2488- /* Output the JUMP_LABEL reference. */
2489- fprintf (outfile, "\n%s%*s -> %d", print_rtx_head, indent * 2, "",
2490- INSN_UID (JUMP_LABEL (in_rtx)));
2491+ {
2492+ /* Output the JUMP_LABEL reference. */
2493+ fprintf (outfile, "\n%s%*s -> ", print_rtx_head, indent * 2, "");
2494+ if (GET_CODE (JUMP_LABEL (in_rtx)) == RETURN)
2495+ fprintf (outfile, "return");
2496+ else if (GET_CODE (JUMP_LABEL (in_rtx)) == SIMPLE_RETURN)
2497+ fprintf (outfile, "simple_return");
2498+ else
2499+ fprintf (outfile, "%d", INSN_UID (JUMP_LABEL (in_rtx)));
2500+ }
2501 else if (i == 0 && GET_CODE (in_rtx) == VALUE)
2502 {
2503 #ifndef GENERATOR_FILE
2504Index: gcc-4_5-branch/gcc/reorg.c
2505===================================================================
2506--- gcc-4_5-branch.orig/gcc/reorg.c
2507+++ gcc-4_5-branch/gcc/reorg.c
2508@@ -161,8 +161,11 @@ static rtx *unfilled_firstobj;
2509 #define unfilled_slots_next \
2510 ((rtx *) obstack_next_free (&unfilled_slots_obstack))
2511
2512-/* Points to the label before the end of the function. */
2513-static rtx end_of_function_label;
2514+/* Points to the label before the end of the function, or before a
2515+ return insn. */
2516+static rtx function_return_label;
2517+/* Likewise for a simple_return. */
2518+static rtx function_simple_return_label;
2519
2520 /* Mapping between INSN_UID's and position in the code since INSN_UID's do
2521 not always monotonically increase. */
2522@@ -175,7 +178,7 @@ static int stop_search_p (rtx, int);
2523 static int resource_conflicts_p (struct resources *, struct resources *);
2524 static int insn_references_resource_p (rtx, struct resources *, bool);
2525 static int insn_sets_resource_p (rtx, struct resources *, bool);
2526-static rtx find_end_label (void);
2527+static rtx find_end_label (rtx);
2528 static rtx emit_delay_sequence (rtx, rtx, int);
2529 static rtx add_to_delay_list (rtx, rtx);
2530 static rtx delete_from_delay_slot (rtx);
2531@@ -220,6 +223,15 @@ static void relax_delay_slots (rtx);
2532 static void make_return_insns (rtx);
2533 #endif
2534
2535+/* Return true iff INSN is a simplejump, or any kind of return insn. */
2536+
2537+static bool
2538+simplejump_or_return_p (rtx insn)
2539+{
2540+ return (JUMP_P (insn)
2541+ && (simplejump_p (insn) || ANY_RETURN_P (PATTERN (insn))));
2542+}
2543+
2544 /* Return TRUE if this insn should stop the search for insn to fill delay
2545 slots. LABELS_P indicates that labels should terminate the search.
2546 In all cases, jumps terminate the search. */
2547@@ -335,23 +347,29 @@ insn_sets_resource_p (rtx insn, struct r
2548
2549 ??? There may be a problem with the current implementation. Suppose
2550 we start with a bare RETURN insn and call find_end_label. It may set
2551- end_of_function_label just before the RETURN. Suppose the machinery
2552+ function_return_label just before the RETURN. Suppose the machinery
2553 is able to fill the delay slot of the RETURN insn afterwards. Then
2554- end_of_function_label is no longer valid according to the property
2555+ function_return_label is no longer valid according to the property
2556 described above and find_end_label will still return it unmodified.
2557 Note that this is probably mitigated by the following observation:
2558- once end_of_function_label is made, it is very likely the target of
2559+ once function_return_label is made, it is very likely the target of
2560 a jump, so filling the delay slot of the RETURN will be much more
2561 difficult. */
2562
2563 static rtx
2564-find_end_label (void)
2565+find_end_label (rtx kind)
2566 {
2567 rtx insn;
2568+ rtx *plabel;
2569+
2570+ if (kind == ret_rtx)
2571+ plabel = &function_return_label;
2572+ else
2573+ plabel = &function_simple_return_label;
2574
2575 /* If we found one previously, return it. */
2576- if (end_of_function_label)
2577- return end_of_function_label;
2578+ if (*plabel)
2579+ return *plabel;
2580
2581 /* Otherwise, see if there is a label at the end of the function. If there
2582 is, it must be that RETURN insns aren't needed, so that is our return
2583@@ -366,44 +384,44 @@ find_end_label (void)
2584
2585 /* When a target threads its epilogue we might already have a
2586 suitable return insn. If so put a label before it for the
2587- end_of_function_label. */
2588+ function_return_label. */
2589 if (BARRIER_P (insn)
2590 && JUMP_P (PREV_INSN (insn))
2591- && GET_CODE (PATTERN (PREV_INSN (insn))) == RETURN)
2592+ && PATTERN (PREV_INSN (insn)) == kind)
2593 {
2594 rtx temp = PREV_INSN (PREV_INSN (insn));
2595- end_of_function_label = gen_label_rtx ();
2596- LABEL_NUSES (end_of_function_label) = 0;
2597+ rtx label = gen_label_rtx ();
2598+ LABEL_NUSES (label) = 0;
2599
2600 /* Put the label before an USE insns that may precede the RETURN insn. */
2601 while (GET_CODE (temp) == USE)
2602 temp = PREV_INSN (temp);
2603
2604- emit_label_after (end_of_function_label, temp);
2605+ emit_label_after (label, temp);
2606+ *plabel = label;
2607 }
2608
2609 else if (LABEL_P (insn))
2610- end_of_function_label = insn;
2611+ *plabel = insn;
2612 else
2613 {
2614- end_of_function_label = gen_label_rtx ();
2615- LABEL_NUSES (end_of_function_label) = 0;
2616+ rtx label = gen_label_rtx ();
2617+ LABEL_NUSES (label) = 0;
2618 /* If the basic block reorder pass moves the return insn to
2619 some other place try to locate it again and put our
2620- end_of_function_label there. */
2621- while (insn && ! (JUMP_P (insn)
2622- && (GET_CODE (PATTERN (insn)) == RETURN)))
2623+ function_return_label there. */
2624+ while (insn && ! (JUMP_P (insn) && (PATTERN (insn) == kind)))
2625 insn = PREV_INSN (insn);
2626 if (insn)
2627 {
2628 insn = PREV_INSN (insn);
2629
2630- /* Put the label before an USE insns that may proceed the
2631+ /* Put the label before an USE insns that may precede the
2632 RETURN insn. */
2633 while (GET_CODE (insn) == USE)
2634 insn = PREV_INSN (insn);
2635
2636- emit_label_after (end_of_function_label, insn);
2637+ emit_label_after (label, insn);
2638 }
2639 else
2640 {
2641@@ -413,19 +431,16 @@ find_end_label (void)
2642 && ! HAVE_return
2643 #endif
2644 )
2645- {
2646- /* The RETURN insn has its delay slot filled so we cannot
2647- emit the label just before it. Since we already have
2648- an epilogue and cannot emit a new RETURN, we cannot
2649- emit the label at all. */
2650- end_of_function_label = NULL_RTX;
2651- return end_of_function_label;
2652- }
2653+ /* The RETURN insn has its delay slot filled so we cannot
2654+ emit the label just before it. Since we already have
2655+ an epilogue and cannot emit a new RETURN, we cannot
2656+ emit the label at all. */
2657+ return NULL_RTX;
2658 #endif /* HAVE_epilogue */
2659
2660 /* Otherwise, make a new label and emit a RETURN and BARRIER,
2661 if needed. */
2662- emit_label (end_of_function_label);
2663+ emit_label (label);
2664 #ifdef HAVE_return
2665 /* We don't bother trying to create a return insn if the
2666 epilogue has filled delay-slots; we would have to try and
2667@@ -437,19 +452,21 @@ find_end_label (void)
2668 /* The return we make may have delay slots too. */
2669 rtx insn = gen_return ();
2670 insn = emit_jump_insn (insn);
2671+ JUMP_LABEL (insn) = ret_rtx;
2672 emit_barrier ();
2673 if (num_delay_slots (insn) > 0)
2674 obstack_ptr_grow (&unfilled_slots_obstack, insn);
2675 }
2676 #endif
2677 }
2678+ *plabel = label;
2679 }
2680
2681 /* Show one additional use for this label so it won't go away until
2682 we are done. */
2683- ++LABEL_NUSES (end_of_function_label);
2684+ ++LABEL_NUSES (*plabel);
2685
2686- return end_of_function_label;
2687+ return *plabel;
2688 }
2689
2690 /* Put INSN and LIST together in a SEQUENCE rtx of LENGTH, and replace
2691@@ -797,10 +814,8 @@ optimize_skip (rtx insn)
2692 if ((next_trial == next_active_insn (JUMP_LABEL (insn))
2693 && ! (next_trial == 0 && crtl->epilogue_delay_list != 0))
2694 || (next_trial != 0
2695- && JUMP_P (next_trial)
2696- && JUMP_LABEL (insn) == JUMP_LABEL (next_trial)
2697- && (simplejump_p (next_trial)
2698- || GET_CODE (PATTERN (next_trial)) == RETURN)))
2699+ && simplejump_or_return_p (next_trial)
2700+ && JUMP_LABEL (insn) == JUMP_LABEL (next_trial)))
2701 {
2702 if (eligible_for_annul_false (insn, 0, trial, flags))
2703 {
2704@@ -819,13 +834,11 @@ optimize_skip (rtx insn)
2705 branch, thread our jump to the target of that branch. Don't
2706 change this into a RETURN here, because it may not accept what
2707 we have in the delay slot. We'll fix this up later. */
2708- if (next_trial && JUMP_P (next_trial)
2709- && (simplejump_p (next_trial)
2710- || GET_CODE (PATTERN (next_trial)) == RETURN))
2711+ if (next_trial && simplejump_or_return_p (next_trial))
2712 {
2713 rtx target_label = JUMP_LABEL (next_trial);
2714- if (target_label == 0)
2715- target_label = find_end_label ();
2716+ if (ANY_RETURN_P (target_label))
2717+ target_label = find_end_label (target_label);
2718
2719 if (target_label)
2720 {
2721@@ -866,7 +879,7 @@ get_jump_flags (rtx insn, rtx label)
2722 if (JUMP_P (insn)
2723 && (condjump_p (insn) || condjump_in_parallel_p (insn))
2724 && INSN_UID (insn) <= max_uid
2725- && label != 0
2726+ && label != 0 && !ANY_RETURN_P (label)
2727 && INSN_UID (label) <= max_uid)
2728 flags
2729 = (uid_to_ruid[INSN_UID (label)] > uid_to_ruid[INSN_UID (insn)])
2730@@ -1038,7 +1051,7 @@ get_branch_condition (rtx insn, rtx targ
2731 pat = XVECEXP (pat, 0, 0);
2732
2733 if (GET_CODE (pat) == RETURN)
2734- return target == 0 ? const_true_rtx : 0;
2735+ return ANY_RETURN_P (target) ? const_true_rtx : 0;
2736
2737 else if (GET_CODE (pat) != SET || SET_DEST (pat) != pc_rtx)
2738 return 0;
2739@@ -1318,7 +1331,11 @@ steal_delay_list_from_target (rtx insn,
2740 }
2741
2742 /* Show the place to which we will be branching. */
2743- *pnew_thread = next_active_insn (JUMP_LABEL (XVECEXP (seq, 0, 0)));
2744+ temp = JUMP_LABEL (XVECEXP (seq, 0, 0));
2745+ if (ANY_RETURN_P (temp))
2746+ *pnew_thread = temp;
2747+ else
2748+ *pnew_thread = next_active_insn (temp);
2749
2750 /* Add any new insns to the delay list and update the count of the
2751 number of slots filled. */
2752@@ -1358,8 +1375,7 @@ steal_delay_list_from_fallthrough (rtx i
2753 /* We can't do anything if SEQ's delay insn isn't an
2754 unconditional branch. */
2755
2756- if (! simplejump_p (XVECEXP (seq, 0, 0))
2757- && GET_CODE (PATTERN (XVECEXP (seq, 0, 0))) != RETURN)
2758+ if (! simplejump_or_return_p (XVECEXP (seq, 0, 0)))
2759 return delay_list;
2760
2761 for (i = 1; i < XVECLEN (seq, 0); i++)
2762@@ -1827,7 +1843,7 @@ own_thread_p (rtx thread, rtx label, int
2763 rtx insn;
2764
2765 /* We don't own the function end. */
2766- if (thread == 0)
2767+ if (ANY_RETURN_P (thread))
2768 return 0;
2769
2770 /* Get the first active insn, or THREAD, if it is an active insn. */
2771@@ -2245,7 +2261,8 @@ fill_simple_delay_slots (int non_jumps_p
2772 && (!JUMP_P (insn)
2773 || ((condjump_p (insn) || condjump_in_parallel_p (insn))
2774 && ! simplejump_p (insn)
2775- && JUMP_LABEL (insn) != 0)))
2776+ && JUMP_LABEL (insn) != 0
2777+ && !ANY_RETURN_P (JUMP_LABEL (insn)))))
2778 {
2779 /* Invariant: If insn is a JUMP_INSN, the insn's jump
2780 label. Otherwise, zero. */
2781@@ -2270,7 +2287,7 @@ fill_simple_delay_slots (int non_jumps_p
2782 target = JUMP_LABEL (insn);
2783 }
2784
2785- if (target == 0)
2786+ if (target == 0 || ANY_RETURN_P (target))
2787 for (trial = next_nonnote_insn (insn); trial; trial = next_trial)
2788 {
2789 next_trial = next_nonnote_insn (trial);
2790@@ -2349,6 +2366,7 @@ fill_simple_delay_slots (int non_jumps_p
2791 && JUMP_P (trial)
2792 && simplejump_p (trial)
2793 && (target == 0 || JUMP_LABEL (trial) == target)
2794+ && !ANY_RETURN_P (JUMP_LABEL (trial))
2795 && (next_trial = next_active_insn (JUMP_LABEL (trial))) != 0
2796 && ! (NONJUMP_INSN_P (next_trial)
2797 && GET_CODE (PATTERN (next_trial)) == SEQUENCE)
2798@@ -2371,7 +2389,7 @@ fill_simple_delay_slots (int non_jumps_p
2799 if (new_label != 0)
2800 new_label = get_label_before (new_label);
2801 else
2802- new_label = find_end_label ();
2803+ new_label = find_end_label (simple_return_rtx);
2804
2805 if (new_label)
2806 {
2807@@ -2503,7 +2521,8 @@ fill_simple_delay_slots (int non_jumps_p
2808
2809 /* Follow any unconditional jump at LABEL;
2810 return the ultimate label reached by any such chain of jumps.
2811- Return null if the chain ultimately leads to a return instruction.
2812+ Return a suitable return rtx if the chain ultimately leads to a
2813+ return instruction.
2814 If LABEL is not followed by a jump, return LABEL.
2815 If the chain loops or we can't find end, return LABEL,
2816 since that tells caller to avoid changing the insn. */
2817@@ -2518,6 +2537,7 @@ follow_jumps (rtx label)
2818
2819 for (depth = 0;
2820 (depth < 10
2821+ && !ANY_RETURN_P (value)
2822 && (insn = next_active_insn (value)) != 0
2823 && JUMP_P (insn)
2824 && ((JUMP_LABEL (insn) != 0 && any_uncondjump_p (insn)
2825@@ -2527,18 +2547,22 @@ follow_jumps (rtx label)
2826 && BARRIER_P (next));
2827 depth++)
2828 {
2829- rtx tem;
2830+ rtx this_label = JUMP_LABEL (insn);
2831
2832 /* If we have found a cycle, make the insn jump to itself. */
2833- if (JUMP_LABEL (insn) == label)
2834+ if (this_label == label)
2835 return label;
2836
2837- tem = next_active_insn (JUMP_LABEL (insn));
2838- if (tem && (GET_CODE (PATTERN (tem)) == ADDR_VEC
2839+ if (!ANY_RETURN_P (this_label))
2840+ {
2841+ rtx tem = next_active_insn (this_label);
2842+ if (tem
2843+ && (GET_CODE (PATTERN (tem)) == ADDR_VEC
2844 || GET_CODE (PATTERN (tem)) == ADDR_DIFF_VEC))
2845- break;
2846+ break;
2847+ }
2848
2849- value = JUMP_LABEL (insn);
2850+ value = this_label;
2851 }
2852 if (depth == 10)
2853 return label;
2854@@ -2901,6 +2925,7 @@ fill_slots_from_thread (rtx insn, rtx co
2855 arithmetic insn after the jump insn and put the arithmetic insn in the
2856 delay slot. If we can't do this, return. */
2857 if (delay_list == 0 && likely && new_thread
2858+ && !ANY_RETURN_P (new_thread)
2859 && NONJUMP_INSN_P (new_thread)
2860 && GET_CODE (PATTERN (new_thread)) != ASM_INPUT
2861 && asm_noperands (PATTERN (new_thread)) < 0)
2862@@ -2985,16 +3010,14 @@ fill_slots_from_thread (rtx insn, rtx co
2863
2864 gcc_assert (thread_if_true);
2865
2866- if (new_thread && JUMP_P (new_thread)
2867- && (simplejump_p (new_thread)
2868- || GET_CODE (PATTERN (new_thread)) == RETURN)
2869+ if (new_thread && simplejump_or_return_p (new_thread)
2870 && redirect_with_delay_list_safe_p (insn,
2871 JUMP_LABEL (new_thread),
2872 delay_list))
2873 new_thread = follow_jumps (JUMP_LABEL (new_thread));
2874
2875- if (new_thread == 0)
2876- label = find_end_label ();
2877+ if (ANY_RETURN_P (new_thread))
2878+ label = find_end_label (new_thread);
2879 else if (LABEL_P (new_thread))
2880 label = new_thread;
2881 else
2882@@ -3340,11 +3363,12 @@ relax_delay_slots (rtx first)
2883 group of consecutive labels. */
2884 if (JUMP_P (insn)
2885 && (condjump_p (insn) || condjump_in_parallel_p (insn))
2886- && (target_label = JUMP_LABEL (insn)) != 0)
2887+ && (target_label = JUMP_LABEL (insn)) != 0
2888+ && !ANY_RETURN_P (target_label))
2889 {
2890 target_label = skip_consecutive_labels (follow_jumps (target_label));
2891- if (target_label == 0)
2892- target_label = find_end_label ();
2893+ if (ANY_RETURN_P (target_label))
2894+ target_label = find_end_label (target_label);
2895
2896 if (target_label && next_active_insn (target_label) == next
2897 && ! condjump_in_parallel_p (insn))
2898@@ -3359,9 +3383,8 @@ relax_delay_slots (rtx first)
2899 /* See if this jump conditionally branches around an unconditional
2900 jump. If so, invert this jump and point it to the target of the
2901 second jump. */
2902- if (next && JUMP_P (next)
2903+ if (next && simplejump_or_return_p (next)
2904 && any_condjump_p (insn)
2905- && (simplejump_p (next) || GET_CODE (PATTERN (next)) == RETURN)
2906 && target_label
2907 && next_active_insn (target_label) == next_active_insn (next)
2908 && no_labels_between_p (insn, next))
2909@@ -3403,8 +3426,7 @@ relax_delay_slots (rtx first)
2910 Don't do this if we expect the conditional branch to be true, because
2911 we would then be making the more common case longer. */
2912
2913- if (JUMP_P (insn)
2914- && (simplejump_p (insn) || GET_CODE (PATTERN (insn)) == RETURN)
2915+ if (simplejump_or_return_p (insn)
2916 && (other = prev_active_insn (insn)) != 0
2917 && any_condjump_p (other)
2918 && no_labels_between_p (other, insn)
2919@@ -3445,10 +3467,10 @@ relax_delay_slots (rtx first)
2920 Only do so if optimizing for size since this results in slower, but
2921 smaller code. */
2922 if (optimize_function_for_size_p (cfun)
2923- && GET_CODE (PATTERN (delay_insn)) == RETURN
2924+ && ANY_RETURN_P (PATTERN (delay_insn))
2925 && next
2926 && JUMP_P (next)
2927- && GET_CODE (PATTERN (next)) == RETURN)
2928+ && PATTERN (next) == PATTERN (delay_insn))
2929 {
2930 rtx after;
2931 int i;
2932@@ -3487,14 +3509,16 @@ relax_delay_slots (rtx first)
2933 continue;
2934
2935 target_label = JUMP_LABEL (delay_insn);
2936+ if (target_label && ANY_RETURN_P (target_label))
2937+ continue;
2938
2939 if (target_label)
2940 {
2941 /* If this jump goes to another unconditional jump, thread it, but
2942 don't convert a jump into a RETURN here. */
2943 trial = skip_consecutive_labels (follow_jumps (target_label));
2944- if (trial == 0)
2945- trial = find_end_label ();
2946+ if (ANY_RETURN_P (trial))
2947+ trial = find_end_label (trial);
2948
2949 if (trial && trial != target_label
2950 && redirect_with_delay_slots_safe_p (delay_insn, trial, insn))
2951@@ -3517,7 +3541,7 @@ relax_delay_slots (rtx first)
2952 later incorrectly compute register live/death info. */
2953 rtx tmp = next_active_insn (trial);
2954 if (tmp == 0)
2955- tmp = find_end_label ();
2956+ tmp = find_end_label (simple_return_rtx);
2957
2958 if (tmp)
2959 {
2960@@ -3537,14 +3561,12 @@ relax_delay_slots (rtx first)
2961 delay list and that insn is redundant, thread the jump. */
2962 if (trial && GET_CODE (PATTERN (trial)) == SEQUENCE
2963 && XVECLEN (PATTERN (trial), 0) == 2
2964- && JUMP_P (XVECEXP (PATTERN (trial), 0, 0))
2965- && (simplejump_p (XVECEXP (PATTERN (trial), 0, 0))
2966- || GET_CODE (PATTERN (XVECEXP (PATTERN (trial), 0, 0))) == RETURN)
2967+ && simplejump_or_return_p (XVECEXP (PATTERN (trial), 0, 0))
2968 && redundant_insn (XVECEXP (PATTERN (trial), 0, 1), insn, 0))
2969 {
2970 target_label = JUMP_LABEL (XVECEXP (PATTERN (trial), 0, 0));
2971- if (target_label == 0)
2972- target_label = find_end_label ();
2973+ if (ANY_RETURN_P (target_label))
2974+ target_label = find_end_label (target_label);
2975
2976 if (target_label
2977 && redirect_with_delay_slots_safe_p (delay_insn, target_label,
2978@@ -3622,16 +3644,15 @@ relax_delay_slots (rtx first)
2979 a RETURN here. */
2980 if (! INSN_ANNULLED_BRANCH_P (delay_insn)
2981 && any_condjump_p (delay_insn)
2982- && next && JUMP_P (next)
2983- && (simplejump_p (next) || GET_CODE (PATTERN (next)) == RETURN)
2984+ && next && simplejump_or_return_p (next)
2985 && next_active_insn (target_label) == next_active_insn (next)
2986 && no_labels_between_p (insn, next))
2987 {
2988 rtx label = JUMP_LABEL (next);
2989 rtx old_label = JUMP_LABEL (delay_insn);
2990
2991- if (label == 0)
2992- label = find_end_label ();
2993+ if (ANY_RETURN_P (label))
2994+ label = find_end_label (label);
2995
2996 /* find_end_label can generate a new label. Check this first. */
2997 if (label
2998@@ -3692,7 +3713,8 @@ static void
2999 make_return_insns (rtx first)
3000 {
3001 rtx insn, jump_insn, pat;
3002- rtx real_return_label = end_of_function_label;
3003+ rtx real_return_label = function_return_label;
3004+ rtx real_simple_return_label = function_simple_return_label;
3005 int slots, i;
3006
3007 #ifdef DELAY_SLOTS_FOR_EPILOGUE
3008@@ -3707,18 +3729,25 @@ make_return_insns (rtx first)
3009 #endif
3010
3011 /* See if there is a RETURN insn in the function other than the one we
3012- made for END_OF_FUNCTION_LABEL. If so, set up anything we can't change
3013+ made for FUNCTION_RETURN_LABEL. If so, set up anything we can't change
3014 into a RETURN to jump to it. */
3015 for (insn = first; insn; insn = NEXT_INSN (insn))
3016- if (JUMP_P (insn) && GET_CODE (PATTERN (insn)) == RETURN)
3017+ if (JUMP_P (insn) && ANY_RETURN_P (PATTERN (insn)))
3018 {
3019- real_return_label = get_label_before (insn);
3020+ rtx t = get_label_before (insn);
3021+ if (PATTERN (insn) == ret_rtx)
3022+ real_return_label = t;
3023+ else
3024+ real_simple_return_label = t;
3025 break;
3026 }
3027
3028 /* Show an extra usage of REAL_RETURN_LABEL so it won't go away if it
3029- was equal to END_OF_FUNCTION_LABEL. */
3030- LABEL_NUSES (real_return_label)++;
3031+ was equal to FUNCTION_RETURN_LABEL. */
3032+ if (real_return_label)
3033+ LABEL_NUSES (real_return_label)++;
3034+ if (real_simple_return_label)
3035+ LABEL_NUSES (real_simple_return_label)++;
3036
3037 /* Clear the list of insns to fill so we can use it. */
3038 obstack_free (&unfilled_slots_obstack, unfilled_firstobj);
3039@@ -3726,13 +3755,27 @@ make_return_insns (rtx first)
3040 for (insn = first; insn; insn = NEXT_INSN (insn))
3041 {
3042 int flags;
3043+ rtx kind, real_label;
3044
3045 /* Only look at filled JUMP_INSNs that go to the end of function
3046 label. */
3047 if (!NONJUMP_INSN_P (insn)
3048 || GET_CODE (PATTERN (insn)) != SEQUENCE
3049- || !JUMP_P (XVECEXP (PATTERN (insn), 0, 0))
3050- || JUMP_LABEL (XVECEXP (PATTERN (insn), 0, 0)) != end_of_function_label)
3051+ || !JUMP_P (XVECEXP (PATTERN (insn), 0, 0)))
3052+ continue;
3053+
3054+ if (JUMP_LABEL (XVECEXP (PATTERN (insn), 0, 0)) == function_return_label)
3055+ {
3056+ kind = ret_rtx;
3057+ real_label = real_return_label;
3058+ }
3059+ else if (JUMP_LABEL (XVECEXP (PATTERN (insn), 0, 0))
3060+ == function_simple_return_label)
3061+ {
3062+ kind = simple_return_rtx;
3063+ real_label = real_simple_return_label;
3064+ }
3065+ else
3066 continue;
3067
3068 pat = PATTERN (insn);
3069@@ -3740,14 +3783,12 @@ make_return_insns (rtx first)
3070
3071 /* If we can't make the jump into a RETURN, try to redirect it to the best
3072 RETURN and go on to the next insn. */
3073- if (! reorg_redirect_jump (jump_insn, NULL_RTX))
3074+ if (! reorg_redirect_jump (jump_insn, kind))
3075 {
3076 /* Make sure redirecting the jump will not invalidate the delay
3077 slot insns. */
3078- if (redirect_with_delay_slots_safe_p (jump_insn,
3079- real_return_label,
3080- insn))
3081- reorg_redirect_jump (jump_insn, real_return_label);
3082+ if (redirect_with_delay_slots_safe_p (jump_insn, real_label, insn))
3083+ reorg_redirect_jump (jump_insn, real_label);
3084 continue;
3085 }
3086
3087@@ -3787,7 +3828,7 @@ make_return_insns (rtx first)
3088 RETURN, delete the SEQUENCE and output the individual insns,
3089 followed by the RETURN. Then set things up so we try to find
3090 insns for its delay slots, if it needs some. */
3091- if (GET_CODE (PATTERN (jump_insn)) == RETURN)
3092+ if (ANY_RETURN_P (PATTERN (jump_insn)))
3093 {
3094 rtx prev = PREV_INSN (insn);
3095
3096@@ -3804,13 +3845,16 @@ make_return_insns (rtx first)
3097 else
3098 /* It is probably more efficient to keep this with its current
3099 delay slot as a branch to a RETURN. */
3100- reorg_redirect_jump (jump_insn, real_return_label);
3101+ reorg_redirect_jump (jump_insn, real_label);
3102 }
3103
3104 /* Now delete REAL_RETURN_LABEL if we never used it. Then try to fill any
3105 new delay slots we have created. */
3106- if (--LABEL_NUSES (real_return_label) == 0)
3107+ if (real_return_label != NULL_RTX && --LABEL_NUSES (real_return_label) == 0)
3108 delete_related_insns (real_return_label);
3109+ if (real_simple_return_label != NULL_RTX
3110+ && --LABEL_NUSES (real_simple_return_label) == 0)
3111+ delete_related_insns (real_simple_return_label);
3112
3113 fill_simple_delay_slots (1);
3114 fill_simple_delay_slots (0);
3115@@ -3878,7 +3922,7 @@ dbr_schedule (rtx first)
3116 init_resource_info (epilogue_insn);
3117
3118 /* Show we haven't computed an end-of-function label yet. */
3119- end_of_function_label = 0;
3120+ function_return_label = function_simple_return_label = NULL_RTX;
3121
3122 /* Initialize the statistics for this function. */
3123 memset (num_insns_needing_delays, 0, sizeof num_insns_needing_delays);
3124@@ -3900,11 +3944,23 @@ dbr_schedule (rtx first)
3125 /* If we made an end of function label, indicate that it is now
3126 safe to delete it by undoing our prior adjustment to LABEL_NUSES.
3127 If it is now unused, delete it. */
3128- if (end_of_function_label && --LABEL_NUSES (end_of_function_label) == 0)
3129- delete_related_insns (end_of_function_label);
3130+ if (function_return_label && --LABEL_NUSES (function_return_label) == 0)
3131+ delete_related_insns (function_return_label);
3132+ if (function_simple_return_label
3133+ && --LABEL_NUSES (function_simple_return_label) == 0)
3134+ delete_related_insns (function_simple_return_label);
3135
3136+#if defined HAVE_return || defined HAVE_simple_return
3137+ if (
3138 #ifdef HAVE_return
3139- if (HAVE_return && end_of_function_label != 0)
3140+ (HAVE_return && function_return_label != 0)
3141+#else
3142+ 0
3143+#endif
3144+#ifdef HAVE_simple_return
3145+ || (HAVE_simple_return && function_simple_return_label != 0)
3146+#endif
3147+ )
3148 make_return_insns (first);
3149 #endif
3150
3151Index: gcc-4_5-branch/gcc/resource.c
3152===================================================================
3153--- gcc-4_5-branch.orig/gcc/resource.c
3154+++ gcc-4_5-branch/gcc/resource.c
3155@@ -495,6 +495,8 @@ find_dead_or_set_registers (rtx target,
3156 || GET_CODE (PATTERN (this_jump_insn)) == RETURN)
3157 {
3158 next = JUMP_LABEL (this_jump_insn);
3159+ if (next && ANY_RETURN_P (next))
3160+ next = NULL_RTX;
3161 if (jump_insn == 0)
3162 {
3163 jump_insn = insn;
3164@@ -562,9 +564,10 @@ find_dead_or_set_registers (rtx target,
3165 AND_COMPL_HARD_REG_SET (scratch, needed.regs);
3166 AND_COMPL_HARD_REG_SET (fallthrough_res.regs, scratch);
3167
3168- find_dead_or_set_registers (JUMP_LABEL (this_jump_insn),
3169- &target_res, 0, jump_count,
3170- target_set, needed);
3171+ if (!ANY_RETURN_P (JUMP_LABEL (this_jump_insn)))
3172+ find_dead_or_set_registers (JUMP_LABEL (this_jump_insn),
3173+ &target_res, 0, jump_count,
3174+ target_set, needed);
3175 find_dead_or_set_registers (next,
3176 &fallthrough_res, 0, jump_count,
3177 set, needed);
3178@@ -1097,6 +1100,8 @@ mark_target_live_regs (rtx insns, rtx ta
3179 struct resources new_resources;
3180 rtx stop_insn = next_active_insn (jump_insn);
3181
3182+ if (jump_target && ANY_RETURN_P (jump_target))
3183+ jump_target = NULL_RTX;
3184 mark_target_live_regs (insns, next_active_insn (jump_target),
3185 &new_resources);
3186 CLEAR_RESOURCE (&set);
3187Index: gcc-4_5-branch/gcc/rtl.c
3188===================================================================
3189--- gcc-4_5-branch.orig/gcc/rtl.c
3190+++ gcc-4_5-branch/gcc/rtl.c
3191@@ -256,6 +256,8 @@ copy_rtx (rtx orig)
3192 case CODE_LABEL:
3193 case PC:
3194 case CC0:
3195+ case RETURN:
3196+ case SIMPLE_RETURN:
3197 case SCRATCH:
3198 /* SCRATCH must be shared because they represent distinct values. */
3199 return orig;
3200Index: gcc-4_5-branch/gcc/rtl.def
3201===================================================================
3202--- gcc-4_5-branch.orig/gcc/rtl.def
3203+++ gcc-4_5-branch/gcc/rtl.def
3204@@ -296,6 +296,10 @@ DEF_RTL_EXPR(CALL, "call", "ee", RTX_EXT
3205
3206 DEF_RTL_EXPR(RETURN, "return", "", RTX_EXTRA)
3207
3208+/* A plain return, to be used on paths that are reached without going
3209+ through the function prologue. */
3210+DEF_RTL_EXPR(SIMPLE_RETURN, "simple_return", "", RTX_EXTRA)
3211+
3212 /* Special for EH return from subroutine. */
3213
3214 DEF_RTL_EXPR(EH_RETURN, "eh_return", "", RTX_EXTRA)
3215Index: gcc-4_5-branch/gcc/rtl.h
3216===================================================================
3217--- gcc-4_5-branch.orig/gcc/rtl.h
3218+++ gcc-4_5-branch/gcc/rtl.h
3219@@ -411,6 +411,10 @@ struct GTY(()) rtvec_def {
3220 (JUMP_P (INSN) && (GET_CODE (PATTERN (INSN)) == ADDR_VEC || \
3221 GET_CODE (PATTERN (INSN)) == ADDR_DIFF_VEC))
3222
3223+/* Predicate yielding nonzero iff X is a return or simple_preturn. */
3224+#define ANY_RETURN_P(X) \
3225+ (GET_CODE (X) == RETURN || GET_CODE (X) == SIMPLE_RETURN)
3226+
3227 /* 1 if X is a unary operator. */
3228
3229 #define UNARY_P(X) \
3230@@ -1998,6 +2002,8 @@ enum global_rtl_index
3231 {
3232 GR_PC,
3233 GR_CC0,
3234+ GR_RETURN,
3235+ GR_SIMPLE_RETURN,
3236 GR_STACK_POINTER,
3237 GR_FRAME_POINTER,
3238 /* For register elimination to work properly these hard_frame_pointer_rtx,
3239@@ -2032,6 +2038,8 @@ extern GTY(()) rtx global_rtl[GR_MAX];
3240
3241 /* Standard pieces of rtx, to be substituted directly into things. */
3242 #define pc_rtx (global_rtl[GR_PC])
3243+#define ret_rtx (global_rtl[GR_RETURN])
3244+#define simple_return_rtx (global_rtl[GR_SIMPLE_RETURN])
3245 #define cc0_rtx (global_rtl[GR_CC0])
3246
3247 /* All references to certain hard regs, except those created
3248Index: gcc-4_5-branch/gcc/rtlanal.c
3249===================================================================
3250--- gcc-4_5-branch.orig/gcc/rtlanal.c
3251+++ gcc-4_5-branch/gcc/rtlanal.c
3252@@ -2673,6 +2673,7 @@ tablejump_p (const_rtx insn, rtx *labelp
3253
3254 if (JUMP_P (insn)
3255 && (label = JUMP_LABEL (insn)) != NULL_RTX
3256+ && !ANY_RETURN_P (label)
3257 && (table = next_active_insn (label)) != NULL_RTX
3258 && JUMP_TABLE_DATA_P (table))
3259 {
3260Index: gcc-4_5-branch/gcc/sched-int.h
3261===================================================================
3262--- gcc-4_5-branch.orig/gcc/sched-int.h
3263+++ gcc-4_5-branch/gcc/sched-int.h
3264@@ -199,7 +199,7 @@ extern int max_issue (struct ready_list
3265
3266 extern void ebb_compute_jump_reg_dependencies (rtx, regset, regset, regset);
3267
3268-extern edge find_fallthru_edge (basic_block);
3269+extern edge find_fallthru_edge_from (basic_block);
3270
3271 extern void (* sched_init_only_bb) (basic_block, basic_block);
3272 extern basic_block (* sched_split_block) (basic_block, rtx);
3273Index: gcc-4_5-branch/gcc/sched-vis.c
3274===================================================================
3275--- gcc-4_5-branch.orig/gcc/sched-vis.c
3276+++ gcc-4_5-branch/gcc/sched-vis.c
3277@@ -549,6 +549,9 @@ print_pattern (char *buf, const_rtx x, i
3278 case RETURN:
3279 sprintf (buf, "return");
3280 break;
3281+ case SIMPLE_RETURN:
3282+ sprintf (buf, "simple_return");
3283+ break;
3284 case CALL:
3285 print_exp (buf, x, verbose);
3286 break;
3287Index: gcc-4_5-branch/gcc/sel-sched-ir.c
3288===================================================================
3289--- gcc-4_5-branch.orig/gcc/sel-sched-ir.c
3290+++ gcc-4_5-branch/gcc/sel-sched-ir.c
3291@@ -686,7 +686,7 @@ merge_fences (fence_t f, insn_t insn,
3292
3293 /* Find fallthrough edge. */
3294 gcc_assert (BLOCK_FOR_INSN (insn)->prev_bb);
3295- candidate = find_fallthru_edge (BLOCK_FOR_INSN (insn)->prev_bb);
3296+ candidate = find_fallthru_edge_from (BLOCK_FOR_INSN (insn)->prev_bb);
3297
3298 if (!candidate
3299 || (candidate->src != BLOCK_FOR_INSN (last_scheduled_insn)
3300Index: gcc-4_5-branch/gcc/sel-sched.c
3301===================================================================
3302--- gcc-4_5-branch.orig/gcc/sel-sched.c
3303+++ gcc-4_5-branch/gcc/sel-sched.c
3304@@ -617,8 +617,8 @@ in_fallthru_bb_p (rtx insn, rtx succ)
3305 if (bb == BLOCK_FOR_INSN (succ))
3306 return true;
3307
3308- if (find_fallthru_edge (bb))
3309- bb = find_fallthru_edge (bb)->dest;
3310+ if (find_fallthru_edge_from (bb))
3311+ bb = find_fallthru_edge_from (bb)->dest;
3312 else
3313 return false;
3314
3315@@ -4911,7 +4911,7 @@ move_cond_jump (rtx insn, bnd_t bnd)
3316 next = PREV_INSN (insn);
3317 BND_TO (bnd) = insn;
3318
3319- ft_edge = find_fallthru_edge (block_from);
3320+ ft_edge = find_fallthru_edge_from (block_from);
3321 block_next = ft_edge->dest;
3322 /* There must be a fallthrough block (or where should go
3323 control flow in case of false jump predicate otherwise?). */
3324Index: gcc-4_5-branch/gcc/vec.h
3325===================================================================
3326--- gcc-4_5-branch.orig/gcc/vec.h
3327+++ gcc-4_5-branch/gcc/vec.h
3328@@ -188,6 +188,18 @@ along with GCC; see the file COPYING3.
3329
3330 #define VEC_iterate(T,V,I,P) (VEC_OP(T,base,iterate)(VEC_BASE(V),I,&(P)))
3331
3332+/* Convenience macro for forward iteration. */
3333+
3334+#define FOR_EACH_VEC_ELT(T, V, I, P) \
3335+ for (I = 0; VEC_iterate (T, (V), (I), (P)); ++(I))
3336+
3337+/* Convenience macro for reverse iteration. */
3338+
3339+#define FOR_EACH_VEC_ELT_REVERSE(T,V,I,P) \
3340+ for (I = VEC_length (T, (V)) - 1; \
3341+ VEC_iterate (T, (V), (I), (P)); \
3342+ (I)--)
3343+
3344 /* Allocate new vector.
3345 VEC(T,A) *VEC_T_A_alloc(int reserve);
3346