]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/16201 (Assembler messages:Error: bad immediate value for offset (4116))
authorRichard Earnshaw <rearnsha@arm.com>
Tue, 1 Feb 2005 15:07:02 +0000 (15:07 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Tue, 1 Feb 2005 15:07:02 +0000 (15:07 +0000)
PR target/16201
* arm.c (arm_eliminable_register): New function.
(adjacent_mem_locations): Don't allow eliminable registers.  Use
HOST_WIDE_INT for address offsets.
* arm-protos.h (arm_eliminable_register): Add prototype.

From-SVN: r94541

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

index 6e15b90ae26699b5e4dc5bb51c5342248f312308..89d15d54b15e03495c6eea97d168bcddd3127703 100644 (file)
@@ -1,3 +1,11 @@
+2005-02-01  Richard Earnshaw  <rearnsha@arm.com>
+
+       PR target/16201
+       * arm.c (arm_eliminable_register): New function.
+       (adjacent_mem_locations): Don't allow eliminable registers.  Use
+       HOST_WIDE_INT for address offsets.
+       * arm-protos.h (arm_eliminable_register): Add prototype.
+
 2005-01-31  Daniel Jacobowitz  <dan@codesourcery.com>
 
        2004-09-22  Mark Mitchell  <mark@codesourcery.com>
index 471254efe4e1a8d6f53aab3cb32c58abf233989e..2da99b82d6777799e1c786cd9218173889b63c85 100644 (file)
@@ -1,5 +1,6 @@
 /* Prototypes for exported functions defined in arm.c and pe.c
-   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005
+   Free Software Foundation, Inc.
    Contributed by Richard Earnshaw (rearnsha@arm.com)
    Minor hacks by Nick Clifton (nickc@cygnus.com)
 
@@ -138,6 +139,7 @@ extern int arm_debugger_arg_offset (int, rtx);
 extern int arm_is_longcall_p (rtx, int, int);
 extern int    arm_emit_vector_const (FILE *, rtx);
 extern const char * arm_output_load_gr (rtx *);
+extern int arm_eliminable_register (rtx);
 
 #if defined TREE_CODE
 extern rtx arm_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
index 91e4486d0bbbfc4dfa670c61e7d1f153dbf6cc53..95188944be3d2a60eae70dfd6632b1fdc9eca60a 100644 (file)
@@ -1,6 +1,6 @@
 /* Output routines for GCC for ARM.
    Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004  Free Software Foundation, Inc.
+   2002, 2003, 2004, 2005  Free Software Foundation, Inc.
    Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
    and Martin Simmons (@harleqn.co.uk).
    More major hacks by Richard Earnshaw (rearnsha@arm.com).
@@ -4056,6 +4056,16 @@ cirrus_shift_const (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
          && INTVAL (op) < 64);
 }
 
+/* Return true if X is a register that will be eliminated later on.  */
+int
+arm_eliminable_register (rtx x)
+{
+  return REG_P (x) && (REGNO (x) == FRAME_POINTER_REGNUM
+                      || REGNO (x) == ARG_POINTER_REGNUM
+                      || (REGNO (x) >= FIRST_VIRTUAL_REGISTER
+                          && REGNO (x) <= LAST_VIRTUAL_REGISTER));
+}
+
 /* Returns TRUE if INSN is an "LDR REG, ADDR" instruction.
    Use by the Cirrus Maverick code which has to workaround
    a hardware bug triggered by such instructions.  */
@@ -4569,33 +4579,42 @@ adjacent_mem_locations (rtx a, rtx b)
          || (GET_CODE (XEXP (b, 0)) == PLUS
              && GET_CODE (XEXP (XEXP (b, 0), 1)) == CONST_INT)))
     {
-      int val0 = 0, val1 = 0;
-      int reg0, reg1;
-  
+      HOST_WIDE_INT val0 = 0, val1 = 0;
+      rtx reg0, reg1;
+      int val_diff;
+
       if (GET_CODE (XEXP (a, 0)) == PLUS)
         {
-         reg0 = REGNO  (XEXP (XEXP (a, 0), 0));
+         reg0 = XEXP (XEXP (a, 0), 0);
          val0 = INTVAL (XEXP (XEXP (a, 0), 1));
         }
       else
-       reg0 = REGNO (XEXP (a, 0));
+       reg0 = XEXP (a, 0);
 
       if (GET_CODE (XEXP (b, 0)) == PLUS)
         {
-         reg1 = REGNO  (XEXP (XEXP (b, 0), 0));
+         reg1 = XEXP (XEXP (b, 0), 0);
          val1 = INTVAL (XEXP (XEXP (b, 0), 1));
         }
       else
-       reg1 = REGNO (XEXP (b, 0));
+       reg1 = XEXP (b, 0);
 
       /* Don't accept any offset that will require multiple
         instructions to handle, since this would cause the
         arith_adjacentmem pattern to output an overlong sequence.  */
       if (!const_ok_for_op (PLUS, val0) || !const_ok_for_op (PLUS, val1))
        return 0;
-      
-      return (reg0 == reg1) && ((val1 - val0) == 4 || (val0 - val1) == 4);
+
+      /* Don't allow an eliminable register: register elimination can make
+        the offset too large.  */
+      if (arm_eliminable_register (reg0))
+       return 0;
+
+      val_diff = val1 - val0;
+      return ((REGNO (reg0) == REGNO (reg1))
+             && (val_diff == 4 || val_diff == -4));
     }
+
   return 0;
 }
 
@@ -7301,7 +7320,6 @@ output_call_mem (rtx *operands)
   return "";
 }
 
-
 /* Output a move from arm registers to an fpa registers.
    OPERANDS[0] is an fpa register.
    OPERANDS[1] is the first registers of an arm register pair.  */