* arm.c (output_call_mem): If the address references the link-register
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 13 Jun 2003 14:30:38 +0000 (14:30 +0000)
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 13 Jun 2003 14:30:38 +0000 (14:30 +0000)
use an instruction sequence that avoids early-clobbering IP.
(eliminate_lr2ip): Delete.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@67899 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 6e67d29..c86143d 100644 (file)
@@ -1,3 +1,9 @@
+2003-06-13  Richard Earnshaw  <rearnsha@arm.com>
+
+       * arm.c (output_call_mem): If the address references the link-register
+       use an instruction sequence that avoids early-clobbering IP.
+       (eliminate_lr2ip): Delete.
+
 2003-06-13  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * c-format.c (format_types_orig): Disallow '*' width/precision in
index 9123594..f9f5474 100644 (file)
@@ -73,7 +73,6 @@ static int arm_legitimate_index_p (enum machine_mode, rtx, int);
 static int thumb_base_register_rtx_p (rtx, enum machine_mode, int);
 inline static int thumb_index_register_rtx_p (rtx, int);
 static int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);
-static int eliminate_lr2ip (rtx *);
 static rtx emit_multi_reg_push (int);
 static rtx emit_sfm (int, int);
 #ifndef AOF_ASSEMBLER
@@ -6965,54 +6964,25 @@ output_call (rtx *operands)
   return "";
 }
 
-static int
-eliminate_lr2ip (rtx *x)
-{
-  int something_changed = 0;
-  rtx x0 = * x;
-  int code = GET_CODE (x0);
-  int i, j;
-  const char * fmt;
-  
-  switch (code)
-    {
-    case REG:
-      if (REGNO (x0) == LR_REGNUM)
-        {
-         *x = gen_rtx_REG (SImode, IP_REGNUM);
-         return 1;
-        }
-      return 0;
-    default:
-      /* Scan through the sub-elements and change any references there.  */
-      fmt = GET_RTX_FORMAT (code);
-      
-      for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-       if (fmt[i] == 'e')
-         something_changed |= eliminate_lr2ip (&XEXP (x0, i));
-       else if (fmt[i] == 'E')
-         for (j = 0; j < XVECLEN (x0, i); j++)
-           something_changed |= eliminate_lr2ip (&XVECEXP (x0, i, j));
-      
-      return something_changed;
-    }
-}
-  
 /* Output a 'call' insn that is a reference in memory.  */
 const char *
 output_call_mem (rtx *operands)
 {
-  operands[0] = copy_rtx (operands[0]); /* Be ultra careful.  */
-  /* Handle calls using lr by using ip (which may be clobbered in subr anyway).  */
-  if (eliminate_lr2ip (&operands[0]))
-    output_asm_insn ("mov%?\t%|ip, %|lr", operands);
-
   if (TARGET_INTERWORK)
     {
       output_asm_insn ("ldr%?\t%|ip, %0", operands);
       output_asm_insn ("mov%?\t%|lr, %|pc", operands);
       output_asm_insn ("bx%?\t%|ip", operands);
     }
+  else if (regno_use_in (LR_REGNUM, operands[0]))
+    {
+      /* LR is used in the memory address.  We load the address in the
+        first instruction.  It's safe to use IP as the target of the
+        load since the call will kill it anyway.  */
+      output_asm_insn ("ldr%?\t%|ip, %0", operands);
+      output_asm_insn ("mov%?\t%|lr, %|pc", operands);
+      output_asm_insn ("mov%?\t%|pc, %|ip", operands);
+    }
   else
     {
       output_asm_insn ("mov%?\t%|lr, %|pc", operands);