Richard Henderson schrieb:
> On 10/13/2011 11:31 PM, Georg-Johann Lay wrote:
>> Richard Henderson schrieb:
>>> On 10/13/2011 12:00 PM, Georg-Johann Lay wrote:
>>>
>>>> What do you propose?
>>>>
>>>> o A command line option that is on per default like
>>>> -mnoreturn-tail-calls or -mjmp-noreturn
>>> The command-line-option. I think I prefer -mjump-noreturn,
>>> as the inverse -mno-noreturn-tail-calls is too awkward.
>> What about flag_optimize_sibling_calls?
>> What wa are seeing here is actually a tail call.
>
> Because we explicitly don't tail call noreturn for the
> reason previously explained.
Thanks for the explanation.
Here is the new patch for review with the new option -mjump-to-noreturn
Ok for trunk?
Johann
* doc/invoke.texi (AVR Options): Document -mjump-to-noreturn.
* config/avr/avr-protos.h (avr_out_call): New prototype.
* config/avr/avr.md (adjust_len): Add alternative "call".
(call_insn, call_calue_insn): Use it. Use avr_out_call to print
assembler.
* config/avr/avr.c (avr_out_call): New function.
(adjust_insn_length): Handle ADJUST_LEN_CALL.
* common/config/avr/avr-common.c (-mjump-to-noreturn): Turn on for
-O and higher.
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi (revision 179993)
+++ doc/invoke.texi (working copy)
@@ -487,7 +487,7 @@ Objective-C and Objective-C++ Dialects}.
@emph{AVR Options}
@gccoptlist{-mmcu=@var{mcu} -mno-interrupts @gol
--mcall-prologues -mtiny-stack -mint8 -mstrict-X}
+-mcall-prologues -mtiny-stack -mint8 -mstrict-X -mjump-to-noreturn}
@emph{Blackfin Options}
@gccoptlist{-mcpu=@var{cpu}@r{[}-@var{sirevision}@r{]} @gol
@@ -10690,6 +10690,13 @@ and long long will be 4 bytes. Please n
comply to the C standards, but it will provide you with smaller code
size.
+@item -mjump-to-noreturn
+@opindex mjump-to-noreturn
+Use a jump instruction instead of a call instruction when calling a
+no-return functions. This option is active if optimization is turned
+on and just affects the way a call instruction is printed out.
+Besides that, it has no effect on code generation or debug information.
+
@item -mstrict-X
@opindex mstrict-X
Use register @code{X} in a way proposed by the hardware. This means
Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md (revision 179992)
+++ config/avr/avr.md (working copy)
@@ -133,11 +133,10 @@ (define_attr "length" ""
;; Following insn attribute tells if and how the adjustment has to be
;; done:
;; no No adjustment needed; attribute "length" is fine.
-;; yes Analyse pattern in adjust_insn_length by hand.
;; Otherwise do special processing depending on the attribute.
(define_attr "adjust_len"
- "out_bitop, out_plus, addto_sp, tsthi, tstsi, compare,
+ "out_bitop, out_plus, addto_sp, tsthi, tstsi, compare, call,
mov8, mov16, mov32, reload_in16, reload_in32,
ashlqi, ashrqi, lshrqi,
ashlhi, ashrhi, lshrhi,
@@ -3634,21 +3633,12 @@ (define_insn "call_insn"
;; Operand 1 not used on the AVR.
;; Operand 2 is 1 for tail-call, 0 otherwise.
""
- "@
- %!icall
- %~call %x0
- %!ijmp
- %~jmp %x0"
+ {
+ return avr_out_call (insn, operands[0], 0 != INTVAL (operands[2]));
+ }
[(set_attr "cc" "clobber")
- (set_attr_alternative "length"
- [(const_int 1)
- (if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 2)
- (const_int 1))
- (const_int 1)
- (if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 2)
- (const_int 1))])])
+ (set_attr "length" "1,*,1,*")
+ (set_attr "adjust_len" "*,call,*,call")])
(define_insn "call_value_insn"
[(parallel[(set (match_operand 0 "register_operand" "=r,r,r,r")
@@ -3658,21 +3648,12 @@ (define_insn "call_value_insn"
;; Operand 2 not used on the AVR.
;; Operand 3 is 1 for tail-call, 0 otherwise.
""
- "@
- %!icall
- %~call %x1
- %!ijmp
- %~jmp %x1"
+ {
+ return avr_out_call (insn, operands[1], 0 != INTVAL (operands[3]));
+ }
[(set_attr "cc" "clobber")
- (set_attr_alternative "length"
- [(const_int 1)
- (if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 2)
- (const_int 1))
- (const_int 1)
- (if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 2)
- (const_int 1))])])
+ (set_attr "length" "1,*,1,*")
+ (set_attr "adjust_len" "*,call,*,call")])
(define_insn "nop"
[(const_int 0)]
Index: config/avr/avr.opt
===================================================================
--- config/avr/avr.opt (revision 179993)
+++ config/avr/avr.opt (working copy)
@@ -65,3 +65,7 @@ Make the linker relaxation machine assum
mstrict-X
Target Report Var(avr_strict_X) Init(0)
When accessing RAM, use X as imposed by the hardware, i.e. just use pre-decrement, post-increment and indirect addressing with the X register. Without this option, the compiler may assume that there is an addressing mode X+const similar to Y+const and Z+const and emit instructions to emulate such an addressing mode for X.
+
+mjump-to-noreturn
+Target Report Var(avr_jump_to_noreturn) Init(0)
+Jump to no-return functions instead of calling them.
Index: config/avr/avr-protos.h
===================================================================
--- config/avr/avr-protos.h (revision 179992)
+++ config/avr/avr-protos.h (working copy)
@@ -84,6 +84,7 @@ extern const char *avr_out_sbxx_branch (
extern const char* avr_out_bitop (rtx, rtx*, int*);
extern const char* avr_out_plus (rtx*, int*, int*);
extern const char* avr_out_addto_sp (rtx*, int*);
+extern const char* avr_out_call (rtx, rtx, bool);
extern bool avr_popcount_each_byte (rtx, int, int);
extern int extra_constraint_Q (rtx x);
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c (revision 179993)
+++ config/avr/avr.c (working copy)
@@ -4928,6 +4928,28 @@ avr_out_plus (rtx *xop, int *plen, int *
}
+/* Print call insn INSN to the assembler file and return "".
+ ADDRESS is the target address.
+ If SIBCALL_P then INSN is a tail-call. */
+
+const char*
+avr_out_call (rtx insn, rtx address, bool sibcall_p)
+{
+ /* No need to waste stack or time for no-return calls. */
+
+ if (avr_jump_to_noreturn
+ && find_reg_note (insn, REG_NORETURN, NULL))
+ sibcall_p = true;
+
+ if (REG_P (address))
+ output_asm_insn (sibcall_p ? "%!ijmp" : "%!icall", &address);
+ else
+ output_asm_insn (sibcall_p ? "%~jmp %x0" : "%~call %x0", &address);
+
+ return "";
+}
+
+
/* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
time constant XOP[2]:
@@ -5334,6 +5356,8 @@ adjust_insn_length (rtx insn, int len)
case ADJUST_LEN_ASHLQI: ashlqi3_out (insn, op, &len); break;
case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
+
+ case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
default:
gcc_unreachable();
Index: common/config/avr/avr-common.c
===================================================================
--- common/config/avr/avr-common.c (revision 179765)
+++ common/config/avr/avr-common.c (working copy)
@@ -29,6 +29,7 @@
static const struct default_options avr_option_optimization_table[] =
{
{ OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_mjump_to_noreturn, NULL, 1 },
{ OPT_LEVELS_NONE, 0, NULL, 0 }
};