yann@1: See http://gcc.gnu.org/PR16201 yann@1: yann@1: Should fix "bad immediate value for offset" errors for several flavors of arm, e.g. yann@1: yann@1: /tmp/ccmdoQyg.s: Assembler messages: yann@1: /tmp/ccmdoQyg.s:6235: Error: bad immediate value for offset (4096) yann@1: make[2]: *** [crosstool-0.32/build/arm-xscale-linux-gnu/gcc-3.4.3-glibc-2.3.3/build-glibc/locale/ld-collate.o] Error 1 yann@1: yann@1: /tmp/cc0c7qop.s: Assembler messages: yann@1: /tmp/cc0c7qop.s:6234: Error: bad immediate value for offset (4104) yann@1: make[2]: *** [crosstool-0.32/build/armv5b-softfloat-linux/gcc-3.4.3-glibc-2.3.3/build-glibc/locale/ld-collate.o] Error 1 yann@1: yann@1: yann@1: CVSROOT: /cvs/gcc yann@1: Module name: gcc yann@1: Branch: gcc-3_4-branch yann@1: Changes by: rearnsha@gcc.gnu.org 2005-02-01 15:07:05 yann@1: yann@1: Modified files: yann@1: gcc : ChangeLog yann@1: gcc/config/arm : arm-protos.h arm.c yann@1: yann@1: Log message: yann@1: PR target/16201 yann@1: * arm.c (arm_eliminable_register): New function. yann@1: (adjacent_mem_locations): Don't allow eliminable registers. Use yann@1: HOST_WIDE_INT for address offsets. yann@1: * arm-protos.h (arm_eliminable_register): Add prototype. yann@1: yann@1: Patches: yann@1: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=2.2326.2.790&r2=2.2326.2.791 yann@1: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/arm/arm-protos.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.61&r2=1.61.4.1 yann@1: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/arm/arm.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.317.4.8&r2=1.317.4.9 yann@1: yann@1: =================================================================== yann@1: RCS file: /cvs/gcc/gcc/gcc/config/arm/arm-protos.h,v yann@1: retrieving revision 1.61 yann@1: retrieving revision 1.61.4.1 yann@1: diff -u -r1.61 -r1.61.4.1 yann@1: --- gcc/gcc/config/arm/arm-protos.h 2003/11/20 11:44:18 1.61 yann@1: +++ gcc/gcc/config/arm/arm-protos.h 2005/02/01 15:07:02 1.61.4.1 yann@1: @@ -1,5 +1,6 @@ yann@1: /* Prototypes for exported functions defined in arm.c and pe.c yann@1: - Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. yann@1: + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005 yann@1: + Free Software Foundation, Inc. yann@1: Contributed by Richard Earnshaw (rearnsha@arm.com) yann@1: Minor hacks by Nick Clifton (nickc@cygnus.com) yann@1: yann@1: @@ -138,6 +139,7 @@ yann@1: extern int arm_is_longcall_p (rtx, int, int); yann@1: extern int arm_emit_vector_const (FILE *, rtx); yann@1: extern const char * arm_output_load_gr (rtx *); yann@1: +extern int arm_eliminable_register (rtx); yann@1: yann@1: #if defined TREE_CODE yann@1: extern rtx arm_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int); yann@1: =================================================================== yann@1: RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v yann@1: retrieving revision 1.317.4.8 yann@1: retrieving revision 1.317.4.9 yann@1: diff -u -r1.317.4.8 -r1.317.4.9 yann@1: --- gcc/gcc/config/arm/arm.c 2004/04/29 19:52:41 1.317.4.8 yann@1: +++ gcc/gcc/config/arm/arm.c 2005/02/01 15:07:02 1.317.4.9 yann@1: @@ -1,6 +1,6 @@ yann@1: /* Output routines for GCC for ARM. yann@1: Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, yann@1: - 2002, 2003, 2004 Free Software Foundation, Inc. yann@1: + 2002, 2003, 2004, 2005 Free Software Foundation, Inc. yann@1: Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) yann@1: and Martin Simmons (@harleqn.co.uk). yann@1: More major hacks by Richard Earnshaw (rearnsha@arm.com). yann@1: @@ -4056,6 +4056,16 @@ yann@1: && INTVAL (op) < 64); yann@1: } yann@1: yann@1: +/* Return true if X is a register that will be eliminated later on. */ yann@1: +int yann@1: +arm_eliminable_register (rtx x) yann@1: +{ yann@1: + return REG_P (x) && (REGNO (x) == FRAME_POINTER_REGNUM yann@1: + || REGNO (x) == ARG_POINTER_REGNUM yann@1: + || (REGNO (x) >= FIRST_VIRTUAL_REGISTER yann@1: + && REGNO (x) <= LAST_VIRTUAL_REGISTER)); yann@1: +} yann@1: + yann@1: /* Returns TRUE if INSN is an "LDR REG, ADDR" instruction. yann@1: Use by the Cirrus Maverick code which has to workaround yann@1: a hardware bug triggered by such instructions. */ yann@1: @@ -4569,33 +4579,42 @@ yann@1: || (GET_CODE (XEXP (b, 0)) == PLUS yann@1: && GET_CODE (XEXP (XEXP (b, 0), 1)) == CONST_INT))) yann@1: { yann@1: - int val0 = 0, val1 = 0; yann@1: - int reg0, reg1; yann@1: - yann@1: + HOST_WIDE_INT val0 = 0, val1 = 0; yann@1: + rtx reg0, reg1; yann@1: + int val_diff; yann@1: + yann@1: if (GET_CODE (XEXP (a, 0)) == PLUS) yann@1: { yann@1: - reg0 = REGNO (XEXP (XEXP (a, 0), 0)); yann@1: + reg0 = XEXP (XEXP (a, 0), 0); yann@1: val0 = INTVAL (XEXP (XEXP (a, 0), 1)); yann@1: } yann@1: else yann@1: - reg0 = REGNO (XEXP (a, 0)); yann@1: + reg0 = XEXP (a, 0); yann@1: yann@1: if (GET_CODE (XEXP (b, 0)) == PLUS) yann@1: { yann@1: - reg1 = REGNO (XEXP (XEXP (b, 0), 0)); yann@1: + reg1 = XEXP (XEXP (b, 0), 0); yann@1: val1 = INTVAL (XEXP (XEXP (b, 0), 1)); yann@1: } yann@1: else yann@1: - reg1 = REGNO (XEXP (b, 0)); yann@1: + reg1 = XEXP (b, 0); yann@1: yann@1: /* Don't accept any offset that will require multiple yann@1: instructions to handle, since this would cause the yann@1: arith_adjacentmem pattern to output an overlong sequence. */ yann@1: if (!const_ok_for_op (PLUS, val0) || !const_ok_for_op (PLUS, val1)) yann@1: return 0; yann@1: - yann@1: - return (reg0 == reg1) && ((val1 - val0) == 4 || (val0 - val1) == 4); yann@1: + yann@1: + /* Don't allow an eliminable register: register elimination can make yann@1: + the offset too large. */ yann@1: + if (arm_eliminable_register (reg0)) yann@1: + return 0; yann@1: + yann@1: + val_diff = val1 - val0; yann@1: + return ((REGNO (reg0) == REGNO (reg1)) yann@1: + && (val_diff == 4 || val_diff == -4)); yann@1: } yann@1: + yann@1: return 0; yann@1: } yann@1: yann@1: @@ -7301,7 +7320,6 @@ yann@1: return ""; yann@1: } yann@1: yann@1: - yann@1: /* Output a move from arm registers to an fpa registers. yann@1: OPERANDS[0] is an fpa register. yann@1: OPERANDS[1] is the first registers of an arm register pair. */