Add a new parameter to the function output_return_instruction to handle
simple cases of return when no epilogue needs to be printed out.
ChangeLog:
gcc
2012-05-31 Ian Bolton ian.bol...@arm.com
Sameera Deshpande sameera.deshpa...@arm.com
Greta Yorsh greta.yo...@arm.com
* config/arm/arm-protos.h (output_return_instruction): New
parameter.
* config/arm/arm.c (output_return_instruction): New parameter.
* config/arm/arm.md (arm_simple_return): New pattern.
(arm_return, cond_return, cond_return_inverted): Add new arguments.
* config/arm/thumb2.md (thumb2_return): Update condition and code.
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index f61feef..01cd794 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -148,7 +148,7 @@ extern int arm_address_offset_is_imm (rtx);
extern const char *output_add_immediate (rtx *);
extern const char *arithmetic_instr (rtx, int);
extern void output_ascii_pseudo_op (FILE *, const unsigned char *, int);
-extern const char *output_return_instruction (rtx, int, int);
+extern const char *output_return_instruction (rtx, int, int, int);
extern void arm_poke_function_name (FILE *, const char *);
extern void arm_final_prescan_insn (rtx);
extern int arm_debugger_arg_offset (int, rtx);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index c8642e2..e7a74e0 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -15592,9 +15592,11 @@ arm_get_vfp_saved_size (void)
/* Generate a function exit sequence. If REALLY_RETURN is false, then do
- everything bar the final return instruction. */
+ everything bar the final return instruction. If simple_return is true,
+ then do not output epilogue, because it has already been emitted in RTL. */
const char *
-output_return_instruction (rtx operand, int really_return, int reverse)
+output_return_instruction (rtx operand, int really_return, int reverse,
+ int simple_return)
{
char conditional[10];
char instr[100];
@@ -15637,7 +15639,7 @@ output_return_instruction (rtx operand, int
really_return, int reverse)
offsets = arm_get_frame_offsets ();
live_regs_mask = offsets-saved_regs_mask;
- if (live_regs_mask)
+ if (!simple_return live_regs_mask)
{
const char * return_reg;
@@ -15765,7 +15767,7 @@ output_return_instruction (rtx operand, int
really_return, int reverse)
{
/* The return has already been handled
by loading the LR into the PC. */
- really_return = 0;
+ return ;
}
}
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index d1c1894..867dcbe 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -8597,7 +8597,7 @@
arm_ccfsm_state += 2;
return \\;
}
-return output_return_instruction (const_true_rtx, TRUE, FALSE);
+return output_return_instruction (const_true_rtx, TRUE, FALSE, FALSE);
}
[(set_attr type load1)
(set_attr length 12)
@@ -8618,7 +8618,7 @@
arm_ccfsm_state += 2;
return \\;
}
-return output_return_instruction (operands[0], TRUE, FALSE);
+return output_return_instruction (operands[0], TRUE, FALSE, FALSE);
}
[(set_attr conds use)
(set_attr length 12)
@@ -8639,13 +8639,30 @@
arm_ccfsm_state += 2;
return \\;
}
-return output_return_instruction (operands[0], TRUE, TRUE);
+return output_return_instruction (operands[0], TRUE, TRUE, FALSE);
}
[(set_attr conds use)
(set_attr length 12)
(set_attr type load1)]
)
+(define_insn *arm_simple_return
+ [(simple_return)]
+ TARGET_ARM
+ *
+ {
+if (arm_ccfsm_state == 2)
+ {
+arm_ccfsm_state += 2;
+return \\;
+ }
+return output_return_instruction (const_true_rtx, TRUE, FALSE, TRUE);
+ }
+ [(set_attr type branch)
+ (set_attr length 4)
+ (set_attr predicable yes)]
+)
+
;; Generate a sequence of instructions to determine if the processor is
;; in 26-bit or 32-bit mode, and return the appropriate return address
;; mask.
diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
index 39a2138..b7a8423 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -635,17 +635,12 @@
(set_attr length 20)]
)
-;; Note: this is not predicable, to avoid issues with linker-generated
-;; interworking stubs.
(define_insn *thumb2_return
- [(return)]
- TARGET_THUMB2 USE_RETURN_INSN (FALSE)
- *
- {
-return output_return_instruction (const_true_rtx, TRUE, FALSE);
- }
- [(set_attr type load1)
- (set_attr length 12)]
+ [(simple_return)]
+ TARGET_THUMB2
+ * return output_return_instruction (const_true_rtx, TRUE, FALSE, TRUE);
+ [(set_attr type branch)
+ (set_attr length 4)]
)
(define_insn_and_split thumb2_eh_return