Prevent LR from being used by 2nd cond exec pass.
authorNick Clifton <nickc@redhat.com>
Fri, 22 Dec 2000 18:22:03 +0000 (18:22 +0000)
committerNick Clifton <nickc@gcc.gnu.org>
Fri, 22 Dec 2000 18:22:03 +0000 (18:22 +0000)
From-SVN: r38467

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.h

index 35823fab234e5d7c4049019d16266c9abfeb4c80..eebb4aae1d4449ba0b90aa068f294ec43df8114b 100644 (file)
@@ -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.
index ee2757c31b4e56cd0e633af991762724b6f8e41e..7e092c4f8524a9b869975f0a0e7e0a34bde94803 100644 (file)
@@ -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;
+    }
 }
 \f
 /* If CODE is 'd', then the X is a condition operand and the instruction
index 40287c8d99ecc0753975a58674156a6cb0c887ce..68affb42b5a7b645365c6ad9bb29c527b874c386 100644 (file)
@@ -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;
 }