aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2000-12-22 18:22:03 +0000
committerNick Clifton <nickc@gcc.gnu.org>2000-12-22 18:22:03 +0000
commit6f7ebcbb5043b17735e7d39b10132762154635b1 (patch)
treed5ec2ba16f6c16dbdb3da1dcf8a8c8a9d3448e92 /gcc
parentb53ef1a25fb257dac1b951f9f1c440a97ce39bbc (diff)
downloadgcc-6f7ebcbb5043b17735e7d39b10132762154635b1.zip
gcc-6f7ebcbb5043b17735e7d39b10132762154635b1.tar.gz
gcc-6f7ebcbb5043b17735e7d39b10132762154635b1.tar.bz2
Prevent LR from being used by 2nd cond exec pass.
From-SVN: r38467
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/arm/arm.c56
-rw-r--r--gcc/config/arm/arm.h2
3 files changed, 50 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 35823fa..eebb4aa 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,18 @@
2000-12-22 Nick Clifton <nickc@redhat.com>
+ * config/arm/arm.h (struct machine_function): Add new field
+ 'lr_save_eliminated'.
+ * config/arm/arm.c (arm_compute_save_reg_mask): Do not include the
+ link register if its save has been eliminated.
+ (output_arm_prologue): Mention if the save of the link register
+ has been eliminated.
+ (output_arm_epilogue): Rename 'live_regs_mask' to
+ 'saved_regs_mask'.
+ Test 'saved_regs_mask' for the link register, not regs_ever_live.
+ (arm_expand_prologue): If the link register has not been saved set
+ lr_save_eliminated and emit a USE to prevent later passes from
+ scavenging it.
+
* dwarf2out_frame_debug_expr: Allow the (scratch) frame
pointer to be initialised from the stack pointer plus a
constant.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index ee2757c..7e092c4 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -587,13 +587,13 @@ arm_override_options ()
arm_arch4 = (insn_flags & FL_ARCH4) != 0;
arm_arch5 = (insn_flags & FL_ARCH5) != 0;
arm_is_xscale = (insn_flags & FL_XSCALE) != 0;
-
+
arm_ld_sched = (tune_flags & FL_LDSCHED) != 0;
arm_is_strong = (tune_flags & FL_STRONG) != 0;
thumb_code = (TARGET_ARM == 0);
arm_is_6_or_7 = (((tune_flags & (FL_MODE26 | FL_MODE32))
&& !(tune_flags & FL_ARCH4))) != 0;
-
+
/* Default value for floating point code... if no co-processor
bus, then schedule for emulated floating point. Otherwise,
assume the user has an FPA.
@@ -1647,7 +1647,7 @@ arm_return_in_memory (type)
a register are not allowed. */
if (RETURN_IN_MEMORY (TREE_TYPE (field)))
return 1;
-
+
/* Now check the remaining fields, if any. Only bitfields are allowed,
since they are not addressable. */
for (field = TREE_CHAIN (field);
@@ -6906,6 +6906,9 @@ arm_compute_save_reg_mask ()
&& ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL)))
save_reg_mask |= 1 << LR_REGNUM;
+ if (cfun->machine->lr_save_eliminated)
+ save_reg_mask &= ~ (1 << LR_REGNUM);
+
return save_reg_mask;
}
@@ -7204,6 +7207,9 @@ output_arm_prologue (f, frame_size)
frame_pointer_needed,
current_function_anonymous_args);
+ if (cfun->machine->lr_save_eliminated)
+ asm_fprintf (f, "\t%@ link register save eliminated.\n");
+
#ifdef AOF_ASSEMBLER
if (flag_pic)
asm_fprintf (f, "\tmov\t%r, %r\n", IP_REGNUM, PIC_OFFSET_TABLE_REGNUM);
@@ -7217,7 +7223,7 @@ arm_output_epilogue (really_return)
int really_return;
{
int reg;
- unsigned long live_regs_mask;
+ unsigned long saved_regs_mask;
unsigned long func_type;
/* If we need this, then it will always be at least this much. */
int floats_offset = 12;
@@ -7255,11 +7261,11 @@ arm_output_epilogue (really_return)
be doing a return, so we can't tail-call. */
abort ();
- live_regs_mask = arm_compute_save_reg_mask ();
+ saved_regs_mask = arm_compute_save_reg_mask ();
/* Compute how far away the floats will be. */
for (reg = 0; reg <= LAST_ARM_REGNUM; reg ++)
- if (live_regs_mask & (1 << reg))
+ if (saved_regs_mask & (1 << reg))
floats_offset += 4;
if (frame_pointer_needed)
@@ -7309,27 +7315,27 @@ arm_output_epilogue (really_return)
FP_REGNUM, floats_offset);
}
- /* live_regs_mask should contain the IP, which at the time of stack
+ /* saved_regs_mask should contain the IP, which at the time of stack
frame generation actually contains the old stack pointer. So a
quick way to unwind the stack is just pop the IP register directly
into the stack pointer. */
- if ((live_regs_mask & (1 << IP_REGNUM)) == 0)
+ if ((saved_regs_mask & (1 << IP_REGNUM)) == 0)
abort ();
- live_regs_mask &= ~ (1 << IP_REGNUM);
- live_regs_mask |= (1 << SP_REGNUM);
+ saved_regs_mask &= ~ (1 << IP_REGNUM);
+ saved_regs_mask |= (1 << SP_REGNUM);
- /* There are two registers left in live_regs_mask - LR and PC. We
+ /* There are two registers left in saved_regs_mask - LR and PC. We
only need to restore the LR register (the return address), but to
save time we can load it directly into the PC, unless we need a
special function exit sequence, or we are not really returning. */
if (really_return && ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL)
/* Delete the LR from the register mask, so that the LR on
the stack is loaded into the PC in the register mask. */
- live_regs_mask &= ~ (1 << LR_REGNUM);
+ saved_regs_mask &= ~ (1 << LR_REGNUM);
else
- live_regs_mask &= ~ (1 << PC_REGNUM);
+ saved_regs_mask &= ~ (1 << PC_REGNUM);
- print_multi_reg (f, "ldmea\t%r", FP_REGNUM, live_regs_mask);
+ print_multi_reg (f, "ldmea\t%r", FP_REGNUM, saved_regs_mask);
}
else
{
@@ -7385,15 +7391,15 @@ arm_output_epilogue (really_return)
if (ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL
&& really_return
&& current_function_pretend_args_size == 0
- && regs_ever_live [LR_REGNUM])
+ && saved_regs_mask & (1 << LR_REGNUM))
{
- live_regs_mask &= ~ (1 << LR_REGNUM);
- live_regs_mask |= (1 << PC_REGNUM);
+ saved_regs_mask &= ~ (1 << LR_REGNUM);
+ saved_regs_mask |= (1 << PC_REGNUM);
}
/* Load the registers off the stack. If we only have one register
to load use the LDR instruction - it is faster. */
- if (live_regs_mask == (1 << LR_REGNUM))
+ if (saved_regs_mask == (1 << LR_REGNUM))
{
/* The excpetion handler ignores the LR, so we do
not really need to load it off the stack. */
@@ -7402,8 +7408,8 @@ arm_output_epilogue (really_return)
else
asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
}
- else if (live_regs_mask)
- print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, live_regs_mask);
+ else if (saved_regs_mask)
+ print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
if (current_function_pretend_args_size)
{
@@ -7452,7 +7458,7 @@ arm_output_epilogue (really_return)
here. */
;
else if (current_function_pretend_args_size == 0
- && regs_ever_live [LR_REGNUM])
+ && (saved_regs_mask & (1 << LR_REGNUM)))
/* Similarly we may have been able to load LR into the PC
even if we did not create a stack frame. */
;
@@ -7879,6 +7885,14 @@ arm_expand_prologue ()
scheduling in the prolog. */
if (profile_flag || profile_block_flag || TARGET_NO_SCHED_PRO)
emit_insn (gen_blockage ());
+
+ /* If the link register is being kept alive, with the return address in it,
+ then make sure that it does not get reused by the ce2 pass. */
+ if ((live_regs_mask & (1 << LR_REGNUM)) == 0)
+ {
+ emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, LR_REGNUM)));
+ cfun->machine->lr_save_eliminated = 1;
+ }
}
/* If CODE is 'd', then the X is a condition operand and the instruction
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 40287c8..68affb4 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -1444,6 +1444,8 @@ typedef struct machine_function
int far_jump_used;
/* Records if ARG_POINTER was ever live. */
int arg_pointer_live;
+ /* Records if the save of LR has been eliminated. */
+ int lr_save_eliminated;
/* Records the type of the current function. */
unsigned long func_type;
}