From 9782290288e383a2d9c55a24f508f0934ff96ef3 Mon Sep 17 00:00:00 2001 From: Anatoly Sokolov Date: Thu, 22 May 2008 22:59:15 +0400 Subject: [PATCH] avr.c (get_sequence_length): Add new function. * config/avr/avr.c (get_sequence_length): Add new function. (expand_prologue, expand_epilogue): Remove duplicate code. From-SVN: r135775 --- gcc/ChangeLog | 5 ++ gcc/config/avr/avr.c | 174 +++++++++++++++++++++++++------------------ 2 files changed, 107 insertions(+), 72 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8e6029bf1a9..968d0eac5a0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2008-05-22 Anatoly Sokolov + + * config/avr/avr.c (get_sequence_length): Add new function. + (expand_prologue, expand_epilogue): Remove duplicate code. + 2008-05-22 Rafael Espindola * see.c (see_pre_insert_extensions): Use copy_rtx to avoid invalid rtx diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 1293a4b3463..012a7e4fd1b 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -54,6 +54,7 @@ static int signal_function_p (tree); static int avr_OS_task_function_p (tree); static int avr_OS_main_function_p (tree); static int avr_regs_to_save (HARD_REG_SET *); +static int get_sequence_length (rtx insns); static int sequent_regs_live (void); static const char *ptrreg_to_str (int); static const char *cond_string (enum rtx_code); @@ -585,6 +586,20 @@ sequent_regs_live (void) return (cur_seq == live_seq) ? live_seq : 0; } +/* Obtain the length sequence of insns. */ + +int +get_sequence_length (rtx insns) +{ + rtx insn; + int length; + + for (insn = insns, length = 0; insn; insn = NEXT_INSN (insn)) + length += get_attr_length (insn); + + return length; +} + /* Output function prologue. */ void @@ -718,12 +733,11 @@ expand_prologue (void) To avoid a complex logic, both methods are tested and shortest is selected. */ rtx myfp; - /* First method. */ + rtx fp_plus_insns; + rtx sp_plus_insns = NULL_RTX; + if (TARGET_TINY_STACK) { - if (size < -63 || size > 63) - warning (0, "large frame pointer change (%d) with -mtiny-stack", size); - /* The high byte (r29) doesn't change - prefer 'subi' (1 cycle) over 'sbiw' (2 cycles, same size). */ myfp = gen_rtx_REG (QImode, REGNO (frame_pointer_rtx)); @@ -733,51 +747,53 @@ expand_prologue (void) /* Normal sized addition. */ myfp = frame_pointer_rtx; } - /* Calculate length. */ - int method1_length; - method1_length = - get_attr_length (gen_move_insn (frame_pointer_rtx, stack_pointer_rtx)); - method1_length += - get_attr_length (gen_move_insn (myfp, - gen_rtx_PLUS (GET_MODE(myfp), myfp, - gen_int_mode (-size, - GET_MODE(myfp))))); - method1_length += - get_attr_length (gen_move_insn (stack_pointer_rtx, frame_pointer_rtx)); - + + /* Method 1-Adjust frame pointer. */ + start_sequence (); + + insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); + RTX_FRAME_RELATED_P (insn) = 1; + + insn = + emit_move_insn (myfp, + gen_rtx_PLUS (GET_MODE(myfp), myfp, + gen_int_mode (-size, + GET_MODE(myfp)))); + RTX_FRAME_RELATED_P (insn) = 1; + + insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); + RTX_FRAME_RELATED_P (insn) = 1; + + fp_plus_insns = get_insns (); + end_sequence (); + /* Method 2-Adjust Stack pointer. */ - int sp_plus_length = 0; if (size <= 6) { - sp_plus_length = - get_attr_length (gen_move_insn (stack_pointer_rtx, - gen_rtx_PLUS (HImode, stack_pointer_rtx, - gen_int_mode (-size, - HImode)))); - sp_plus_length += - get_attr_length (gen_move_insn (frame_pointer_rtx, stack_pointer_rtx)); + start_sequence (); + + insn = + emit_move_insn (stack_pointer_rtx, + gen_rtx_PLUS (HImode, + stack_pointer_rtx, + gen_int_mode (-size, + HImode))); + RTX_FRAME_RELATED_P (insn) = 1; + + insn = + emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); + RTX_FRAME_RELATED_P (insn) = 1; + + sp_plus_insns = get_insns (); + end_sequence (); } + /* Use shortest method. */ - if (size <= 6 && (sp_plus_length < method1_length)) - { - insn = emit_move_insn (stack_pointer_rtx, - gen_rtx_PLUS (HImode, stack_pointer_rtx, - gen_int_mode (-size, HImode))); - RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); - RTX_FRAME_RELATED_P (insn) = 1; - } + if (size <= 6 && (get_sequence_length (sp_plus_insns) + < get_sequence_length (fp_plus_insns))) + emit_insn (sp_plus_insns); else - { - insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); - RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_move_insn (myfp, - gen_rtx_PLUS (GET_MODE(myfp), myfp, - gen_int_mode (-size, GET_MODE(myfp)))); - RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_move_insn ( stack_pointer_rtx, frame_pointer_rtx); - RTX_FRAME_RELATED_P (insn) = 1; - } + emit_insn (fp_plus_insns); } } } @@ -872,42 +888,56 @@ expand_epilogue (void) if (size) { /* Try two methods to adjust stack and select shortest. */ - int fp_plus_length; + rtx myfp; + rtx fp_plus_insns; + rtx sp_plus_insns = NULL_RTX; + + if (TARGET_TINY_STACK) + { + /* The high byte (r29) doesn't change - prefer 'subi' + (1 cycle) over 'sbiw' (2 cycles, same size). */ + myfp = gen_rtx_REG (QImode, REGNO (frame_pointer_rtx)); + } + else + { + /* Normal sized addition. */ + myfp = frame_pointer_rtx; + } + /* Method 1-Adjust frame pointer. */ - fp_plus_length = - get_attr_length (gen_move_insn (frame_pointer_rtx, - gen_rtx_PLUS (HImode, frame_pointer_rtx, - gen_int_mode (size, - HImode)))); - /* Copy to stack pointer. */ - fp_plus_length += - get_attr_length (gen_move_insn (stack_pointer_rtx, frame_pointer_rtx)); - + start_sequence (); + + emit_move_insn (myfp, + gen_rtx_PLUS (HImode, myfp, + gen_int_mode (size, + GET_MODE(myfp)))); + + /* Copy to stack pointer. */ + emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); + + fp_plus_insns = get_insns (); + end_sequence (); + /* Method 2-Adjust Stack pointer. */ - int sp_plus_length = 0; if (size <= 5) { - sp_plus_length = - get_attr_length (gen_move_insn (stack_pointer_rtx, - gen_rtx_PLUS (HImode, stack_pointer_rtx, - gen_int_mode (size, - HImode)))); + start_sequence (); + + emit_move_insn (stack_pointer_rtx, + gen_rtx_PLUS (HImode, stack_pointer_rtx, + gen_int_mode (size, + HImode))); + + sp_plus_insns = get_insns (); + end_sequence (); } + /* Use shortest method. */ - if (size <= 5 && (sp_plus_length < fp_plus_length)) - { - emit_move_insn (stack_pointer_rtx, - gen_rtx_PLUS (HImode, stack_pointer_rtx, - gen_int_mode (size, HImode))); - } + if (size <= 5 && (get_sequence_length (sp_plus_insns) + < get_sequence_length (fp_plus_insns))) + emit_insn (sp_plus_insns); else - { - emit_move_insn (frame_pointer_rtx, - gen_rtx_PLUS (HImode, frame_pointer_rtx, - gen_int_mode (size, HImode))); - /* Copy to stack pointer. */ - emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); - } + emit_insn (fp_plus_insns); } if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)) { -- 2.30.2