summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authoraesok <aesok@138bc75d-0d04-0410-961f-82ee72b054a4>2008-05-22 18:59:15 +0000
committeraesok <aesok@138bc75d-0d04-0410-961f-82ee72b054a4>2008-05-22 18:59:15 +0000
commit58f62c921d82803c9bb35c7f00cf2d5885eef463 (patch)
treeac2ff1bd4030cb4628a4cb3a1339518c2b32072a /gcc/config
parent38fecea44e0d352440294c1c3337bcce542ad5e3 (diff)
downloadgcc-58f62c921d82803c9bb35c7f00cf2d5885eef463.tar.gz
* config/avr/avr.c (get_sequence_length): Add new function.
(expand_prologue, expand_epilogue): Remove duplicate code. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@135775 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/avr/avr.c174
1 files changed, 102 insertions, 72 deletions
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))
{