# DP: Some fixes for ARM from Philip Blundell Tue Jul 27 18:42:12 1999 Bernd Schmidt * reload1.c (reload_reg_free_for_value_p): RELOAD_OTHER reloads with an earlyclobbered output conflict with RELOAD_INPUT reloads. Tue Jul 27 18:42:12 1999 Bernd Schmidt * reload1.c (reload_reg_free_for_value_p): If two reloads overlap in their lifetimes, and one of them has an output, they conflict. Fri Jul 16 10:29:48 1999 Philip Blundell * config/arm/arm.c (legitimize_pic_address): Handle LABEL_REF correctly. (arm_poke_function_name): Avoid warning. * config/arm/arm.h (LEGITIMATE_CONSTANT_P): Allow anything when generating PIC. (GO_IF_LEGITIMATE_INDEX): Fix handling of HImode values. (LEGITIMATE_PIC_OPERAND): Disallow references to labels. * config/arm/linux-elf.h (MULTILIB_DEFAULTS): Define. (SUBTARGET_EXTRA_LINK_SPEC): Provide alternative definition for use with new binutils. * config/arm/linux-elf26.h (MULTILIB_DEFAULTS): Define. * config/arm/t-linux (EXTRA_MULTILIB_PARTS): Define. (MULTILIB_OPTIONS, MULTILIB_DIRNAMES): Multilib for hard/soft float by default. * function.c (rtx_equal_for_addressof_p): New function. (purge_addressof_1): Use it instead of rtx_equal_p. --- gcc/function.c 1999/05/20 22:26:35 1.90.4.1 +++ gcc/function.c 1999/07/16 09:30:04 @@ -3042,6 +3042,105 @@ extracted by usage MEM with narrower mode. */ static rtx purge_addressof_replacements; +/* Return 1 if X and Y are identical-looking rtx's. + This is the Lisp function EQUAL for rtx arguments. */ + +int +rtx_equal_for_addressof_p (x, y) + rtx x, y; +{ + register int i; + register int j; + register enum rtx_code code; + register char *fmt; + + if (x == y) + return 1; + if (x == 0 || y == 0) + return 0; + + code = GET_CODE (x); + /* Rtx's of different codes cannot be equal. */ + if (code != GET_CODE (y)) + return 0; + + /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. + (REG:SI x) and (REG:HI x) are NOT equivalent. + But (MEM:SI x) and (MEM:HI x) are equivalent for our purposes. */ + + if (code != MEM && (GET_MODE (x) != GET_MODE (y))) + return 0; + + /* REG, LABEL_REF, and SYMBOL_REF can be compared nonrecursively. */ + + if (code == REG) + return REGNO (x) == REGNO (y); + else if (code == LABEL_REF) + return XEXP (x, 0) == XEXP (y, 0); + else if (code == SYMBOL_REF) + return XSTR (x, 0) == XSTR (y, 0); + else if (code == SCRATCH || code == CONST_DOUBLE) + return 0; + + /* Compare the elements. If any pair of corresponding elements + fail to match, return 0 for the whole things. */ + + fmt = GET_RTX_FORMAT (code); + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + switch (fmt[i]) + { + case 'w': + if (XWINT (x, i) != XWINT (y, i)) + return 0; + break; + + case 'n': + case 'i': + if (XINT (x, i) != XINT (y, i)) + return 0; + break; + + case 'V': + case 'E': + /* Two vectors must have the same length. */ + if (XVECLEN (x, i) != XVECLEN (y, i)) + return 0; + + /* And the corresponding elements must match. */ + for (j = 0; j < XVECLEN (x, i); j++) + if (rtx_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0) + return 0; + break; + + case 'e': + if (rtx_equal_p (XEXP (x, i), XEXP (y, i)) == 0) + return 0; + break; + + case 'S': + case 's': + if (strcmp (XSTR (x, i), XSTR (y, i))) + return 0; + break; + + case 'u': + /* These are just backpointers, so they don't matter. */ + break; + + case '0': + break; + + /* It is believed that rtx's at this level will never + contain anything but integers and other rtx's, + except for within LABEL_REFs and SYMBOL_REFs. */ + default: + abort (); + } + } + return 1; +} + /* Helper function for purge_addressof. See if the rtx expression at *LOC in INSN needs to be changed. If FORCE, always put any ADDRESSOFs into the stack. */ @@ -3122,7 +3221,7 @@ for (tem = purge_bitfield_addressof_replacements; tem != NULL_RTX; tem = XEXP (XEXP (tem, 1), 1)) - if (rtx_equal_p (x, XEXP (tem, 0))) + if (rtx_equal_for_addressof_p (x, XEXP (tem, 0))) { *loc = XEXP (XEXP (tem, 1), 0); return; @@ -3132,7 +3231,7 @@ for (tem = purge_addressof_replacements; tem != NULL_RTX; tem = XEXP (XEXP (tem, 1), 1)) - if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0))) + if (rtx_equal_for_addressof_p (XEXP (x, 0), XEXP (tem, 0))) { rtx z = XEXP (XEXP (tem, 1), 0); --- gcc/config/arm/arm.c 1999/06/19 06:34:36 1.43.4.5 +++ gcc/config/arm/arm.c 1999/07/16 09:27:53 @@ -1528,7 +1528,20 @@ legitimize_pic_address (orig, mode, reg) return gen_rtx_PLUS (Pmode, base, offset); } else if (GET_CODE (orig) == LABEL_REF) - current_function_uses_pic_offset_table = 1; + { + current_function_uses_pic_offset_table = 1; + + if (NEED_PLT_GOT) + { + rtx pic_ref, address = gen_reg_rtx (Pmode); + + emit_insn (gen_pic_load_addr (address, orig)); + pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, + address); + emit_move_insn (address, pic_ref); + return address; + } + } return orig; } @@ -5445,7 +5458,7 @@ arm_poke_function_name (stream, name) rtx x; length = strlen (name); - alignlength = (length + 1) + 3 & ~3; + alignlength = ((length + 1) + 3) & ~3; ASM_OUTPUT_ASCII (stream, name, length + 1); ASM_OUTPUT_ALIGN (stream, 2); --- gcc/config/arm/arm.h 1999/06/19 05:37:07 1.34.4.3 +++ gcc/config/arm/arm.h 1999/07/16 09:28:04 @@ -1378,9 +1378,11 @@ do { \ On the ARM, allow any integer (invalid ones are removed later by insn patterns), nice doubles and symbol_refs which refer to the function's - constant pool XXX. */ -#define LEGITIMATE_CONSTANT_P(X) (! label_mentioned_p (X)) + constant pool XXX. + When generating PIC code, allow anything. */ +#define LEGITIMATE_CONSTANT_P(X) (flag_pic || ! label_mentioned_p (X)) + /* Symbols in the text segment can be accessed without indirecting via the constant pool; it may take an extra binary operation, but this is still faster than indirecting via memory. Don't do this when not optimizing, @@ -1495,9 +1497,8 @@ do \ && INTVAL (op) <= 31) \ goto LABEL; \ } \ - /* NASTY: Since this limits the addressing of unsigned byte loads */ \ range = ((MODE) == HImode || (MODE) == QImode) \ - ? (arm_arch4 ? 256 : 4095) : 4096; \ + ? (((MODE) == HImode && arm_arch4) ? 256 : 4095) : 4096; \ if (code == CONST_INT && INTVAL (INDEX) < range \ && INTVAL (INDEX) > -range) \ goto LABEL; \ @@ -1813,12 +1814,13 @@ extern int arm_pic_register; #define FINALIZE_PIC arm_finalize_pic () -/* We can't directly access anything that contains a symbol, +/* We can't directly access anything that contains a symbol or label, nor can we indirect via the constant pool. */ #define LEGITIMATE_PIC_OPERAND_P(X) \ - (! symbol_mentioned_p (X) \ + (! symbol_mentioned_p (X) && ! label_mentioned_p (X) \ && (! CONSTANT_POOL_ADDRESS_P (X) \ - || ! symbol_mentioned_p (get_pool_constant (X)))) + || (! symbol_mentioned_p (get_pool_constant (X))) \ + && (! label_mentioned_p (get_pool_constant (X))))) /* We need to know when we are making a constant pool; this determines whether data needs to be in the GOT or can be referenced via a GOT --- gcc/config/arm/arm.md 1999/06/02 06:43:14 1.27.4.2 +++ gcc/config/arm/arm.md 1999/07/16 09:28:31 @@ -2627,7 +2627,8 @@ : preserve_subexpressions_p ())); DONE; } - if (CONSTANT_P (operands[1]) && flag_pic) + if ((CONSTANT_P (operands[1]) || symbol_mentioned_p (operands[1]) + || label_mentioned_p (operands[1])) && flag_pic) operands[1] = legitimize_pic_address (operands[1], SImode, ((reload_in_progress || reload_completed) --- gcc/config/arm/linux-elf.h 1999/03/31 10:25:34 1.7 +++ gcc/config/arm/linux-elf.h 1999/07/16 09:28:33 @@ -28,10 +28,16 @@ Boston, MA 02111-1307, USA. */ /* Default is to use APCS-32 mode. */ #ifndef SUBTARGET_DEFAULT_APCS26 #define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_SHORT_BYTE) +#if 1 #define SUBTARGET_EXTRA_LINK_SPEC \ + " %{mapcs-26:-m armelf_linux26} %{!mapcs-26:-m armelf_linux} -p" +#else +#define SUBTARGET_EXTRA_LINK_SPEC \ " %{mapcs-26:-m elf32arm26} %{!mapcs-26:-m elf32arm}" +#endif #define SUBTARGET_EXTRA_ASM_SPEC \ " %{mapcs-26:-mapcs-26} %(!mapcs-26:-mapcs-32}" +#define MULTILIB_DEFAULTS { "mlittle-endian", "mhard-float", "mapcs-32", "mno-thumb-interwork" } #endif /* This was defined in linux.h. Define it here also. */ --- gcc/config/arm/linux-elf26.h 1998/12/16 21:01:40 1.2 +++ gcc/config/arm/linux-elf26.h 1999/07/16 09:28:33 @@ -29,4 +29,6 @@ Boston, MA 02111-1307, USA. */ #define TARGET_DEFAULT (ARM_FLAG_SHORT_BYTE) +#define MULTILIB_DEFAULTS { "mlittle-endian", "mhard-float", "mapcs-26", "mno-thumb-interwork" } + #include "arm/linux-elf.h" --- gcc/config/arm/t-linux 1999/03/26 15:30:20 1.5 +++ gcc/config/arm/t-linux 1999/07/16 09:28:33 @@ -13,10 +13,15 @@ LIBGCC1 = libgcc1-asm.a LIB1ASMSRC = arm/lib1funcs.asm LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx +MULTILIB_OPTIONS = mhard-float/msoft-float +MULTILIB_DIRNAMES = hard-float soft-float + # If you want to build both APCS variants as multilib options this is how # to do it. -#MULTILIB_OPTIONS = mapcs-32/apcs-26 -#MULTILIB_DIRNAMES = apcs-32 apcs-26 +#MULTILIB_OPTIONS += mapcs-32/mapcs-26 +#MULTILIB_DIRNAMES += apcs-32 apcs-26 + +EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o LIBGCC = stmp-multilib INSTALL_LIBGCC = install-multilib --- gcc/jump.c 1999/05/31 13:30:06 1.59.4.2 +++ gcc/jump.c 1999/07/30 10:14:30 @@ -115,7 +115,7 @@ static rtx delete_unreferenced_labels PROTO((rtx)); static void delete_noop_moves PROTO((rtx)); static int calculate_can_reach_end PROTO((rtx, int, int)); -static int duplicate_loop_exit_test PROTO((rtx)); +static int duplicate_loop_exit_test PROTO((rtx, int)); static void find_cross_jump PROTO((rtx, rtx, int, rtx *, rtx *)); static void do_cross_jump PROTO((rtx, rtx, rtx)); static int jump_back_p PROTO((rtx, rtx)); @@ -338,7 +338,7 @@ && simplejump_p (temp1)) { temp = PREV_INSN (insn); - if (duplicate_loop_exit_test (insn)) + if (duplicate_loop_exit_test (insn, after_regscan)) { changed = 1; next = NEXT_INSN (temp); @@ -2544,8 +2544,9 @@ values of regno_first_uid and regno_last_uid. */ static int -duplicate_loop_exit_test (loop_start) +duplicate_loop_exit_test (loop_start, after_regscan) rtx loop_start; + int after_regscan; { rtx insn, set, reg, p, link; rtx copy = 0; @@ -2658,6 +2659,9 @@ reg_map[REGNO (reg)] = gen_reg_rtx (GET_MODE (reg)); } } + + if (after_regscan) + reg_scan_update (exitcode, lastexit, max_reg); /* Now copy each insn. */ for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn)) --- gcc/reload1.c 1999/07/07 01:05:39 1.145.4.1 +++ gcc/reload1.c 1999/07/30 10:15:23 @@ -5281,7 +5281,7 @@ if (! reload_in[i] || ! rtx_equal_p (reload_in[i], value) || reload_out[i] || out) { - int time2; + int j, time2; switch (reload_when_needed[i]) { case RELOAD_FOR_OTHER_ADDRESS: @@ -5360,6 +5360,11 @@ if (! reload_in[i] || rtx_equal_p (reload_in[i], value)) { time2 = MAX_RECOG_OPERANDS * 4 + 4; + /* Earlyclobbered outputs must conflict with inputs. */ + for (j = 0; j < n_earlyclobbers; j++) + if (reload_out[i] == reload_earlyclobbers[j]) + time2 = MAX_RECOG_OPERANDS * 4 + 3; + break; } time2 = 1; @@ -5375,7 +5380,8 @@ } if ((time1 >= time2 && (! reload_in[i] || reload_out[i] - || ! rtx_equal_p (reload_in[i], value))) + || ! rtx_equal_p (reload_in[i], value) + || out)) || (out && reload_out_reg[reloadnum] && time2 >= MAX_RECOG_OPERANDS * 4 + 3)) return 0;