From fac435147512513c1b8fa55bee061c8e3a767ba9 Mon Sep 17 00:00:00 2001 From: erich Date: Thu, 23 Jun 1994 16:02:41 +0000 Subject: [PATCH] (TARGET_WHEN_DEBUGGING): Delete. (MODES_TIEABLE_P): All modes of the same class are tieable. (CONST_OK_FOR_LETTER_P): Add 'M' for constants valid in a shift. (FUNCTION_PROFILER): Don't call arm_increase_location. (INITIAL_ELIMINATION_OFFSET): Call saved regs are no-longer pushed for functions that don't return. (LEGITIMIZE_ADDRESS): Push constants that will never be legitimate -- symbols and labels -- into registers. Handle DImode better. (DEFAULT_SIGNED_CHAR): Use unsigned unless already defined. (RTX_COSTS): Call arm_rtx_costs. (ADDRESS_COST): Since most operations have the same rtx cost, make the more complex addresses cheaper. (PREDICATE_CODES): Add ROTATERT to shift_operator; and new predicates for reg_or_int_operand and multi_register_push. (DBX_CONTIN_LENGTH): Only define if not already done. (PRINT_OPERAND_ADDRESS): Let arm_print operand output the ", " for shifts. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@7536 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/config/arm/arm.h | 248 +++++++++++++++++++++++---------------------------- 1 file changed, 110 insertions(+), 138 deletions(-) diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 2898ad3348b..984bbca4fd2 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -136,9 +136,6 @@ extern enum processor_type arm_cpu; - if floating point is done by emulation, forget about instruction scheduling. Note that this only saves compilation time; it doesn't matter for the final code. */ -#ifndef TARGET_WHEN_DEBUGGING -#define TARGET_WHEN_DEBUGGING 1 -#endif #define OVERRIDE_OPTIONS \ { \ @@ -374,8 +371,7 @@ extern enum processor_type arm_cpu; If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, for any hard reg, then this must be 0 for correct output. */ #define MODES_TIEABLE_P(MODE1, MODE2) \ - (((MODE1) == SFmode || (MODE1) == DFmode) \ - == ((MODE2) == SFmode || (MODE2) == DFmode)) + (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2)) /* Specify the registers used for certain standard purposes. The values of these macros are register numbers. */ @@ -494,12 +490,16 @@ enum reg_class I: immediate arithmetic operand (i.e. 8 bits shifted as required). J: valid indexing constants. K: ~value ok in rhs argument of data operand. - L: -value ok in rhs argument of data operand. */ + L: -value ok in rhs argument of data operand. + M: 0..32, or a power of 2 (for shifts, or mult done by shift). */ #define CONST_OK_FOR_LETTER_P(VALUE, C) \ ((C) == 'I' ? const_ok_for_arm (VALUE) : \ (C) == 'J' ? ((VALUE) < 4096 && (VALUE) > -4096) : \ (C) == 'K' ? (const_ok_for_arm (~(VALUE))) : \ - (C) == 'L' ? (const_ok_for_arm (-(VALUE))) : 0) + (C) == 'L' ? (const_ok_for_arm (-(VALUE))) : \ + (C) == 'M' ? (((VALUE >= 0 && VALUE <= 32)) \ + || (((VALUE) & ((VALUE) - 1)) == 0)) \ + : 0) /* For the ARM, `Q' means that this is a memory operand that is just an offset from a register. @@ -696,7 +696,6 @@ enum reg_class fprintf(STREAM, "\tmov\t%sip, %slr\n", ARM_REG_PREFIX, ARM_REG_PREFIX); \ fprintf(STREAM, "\tbl\tmcount\n"); \ fprintf(STREAM, "\t.word\tLP%d\n", (LABELNO)); \ - arm_increase_location (12); \ } /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, @@ -749,6 +748,7 @@ enum reg_class its replacement, at the start of a routine. */ #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ { \ + int volatile_func = arm_volatile_func (); \ if ((FROM) == ARG_POINTER_REGNUM && (TO) == HARD_FRAME_POINTER_REGNUM)\ (OFFSET) = 0; \ else if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM)\ @@ -759,19 +759,22 @@ enum reg_class int offset = 12; \ int saved_hard_reg = 0; \ \ - for (regno = 0; regno <= 10; regno++) \ - if (regs_ever_live[regno] && ! call_used_regs[regno]) \ - saved_hard_reg = 1, offset += 4; \ - for (regno = 16; regno <=23; regno++) \ - if (regs_ever_live[regno] && ! call_used_regs[regno]) \ - offset += 12; \ + if (! volatile_func) \ + { \ + for (regno = 0; regno <= 10; regno++) \ + if (regs_ever_live[regno] && ! call_used_regs[regno]) \ + saved_hard_reg = 1, offset += 4; \ + for (regno = 16; regno <=23; regno++) \ + if (regs_ever_live[regno] && ! call_used_regs[regno]) \ + offset += 12; \ + } \ if ((FROM) == FRAME_POINTER_REGNUM) \ (OFFSET) = -offset; \ else \ { \ if (! regs_ever_live[HARD_FRAME_POINTER_REGNUM]) \ offset -= 16; \ - if (regs_ever_live[14] || saved_hard_reg) \ + if (! volatile_func && (regs_ever_live[14] || saved_hard_reg)) \ offset += 4; \ (OFFSET) = (get_frame_size () + 3 & ~3) + offset; \ } \ @@ -1049,48 +1052,66 @@ do \ On the ARM, try to convert [REG, #BIGCONST] into ADD BASE, REG, #UPPERCONST and [BASE, #VALIDCONST], where VALIDCONST == 0 in case of TImode. */ -#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ -{ \ - if (GET_CODE (X) == PLUS) \ - { \ - rtx xop0 = XEXP (X, 0); \ - rtx xop1 = XEXP (X, 1); \ - \ - if (BASE_REGISTER_RTX_P (xop0) && GET_CODE (xop1) == CONST_INT) \ - { \ - int n = INTVAL (xop1); \ - int low_n = ((MODE) == TImode ? 0 \ - : n >= 0 ? (n & 0xFFF) : -((-n) & 0xFFF)); \ - rtx base_reg = gen_reg_rtx (SImode); \ - rtx val = force_operand (gen_rtx (PLUS, SImode, xop0, \ - gen_rtx (CONST_INT, \ - VOIDmode, n - low_n)), \ - 0); \ - emit_move_insn (base_reg, val); \ - (X) = (low_n == 0 ? base_reg \ - : gen_rtx (PLUS, SImode, base_reg, \ - gen_rtx (CONST_INT, VOIDmode, low_n))); \ - } \ - else if (BASE_REGISTER_RTX_P (xop1) && GET_CODE (xop0) == CONST_INT) \ - { \ - int n = INTVAL (xop0); \ - int low_n = ((MODE) == TImode ? 0 \ - : n >= 0 ? (n & 0xFFF) : -((-n) & 0xFFF)); \ - rtx base_reg = gen_reg_rtx (SImode); \ - rtx val = force_operand (gen_rtx (PLUS, SImode, xop1, \ - gen_rtx (CONST_INT, \ - VOIDmode, n - low_n)), \ - 0); \ - emit_move_insn (base_reg, val); \ - (X) = (low_n == 0 ? base_reg \ - : gen_rtx (PLUS, SImode, base_reg, \ - gen_rtx (CONST_INT, VOIDmode, low_n))); \ - } \ - } \ - if (memory_address_p (MODE, X)) \ - goto win; \ +#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ +{ \ + if (GET_CODE (X) == PLUS) \ + { \ + rtx xop0 = XEXP (X, 0); \ + rtx xop1 = XEXP (X, 1); \ + \ + if (CONSTANT_P (xop0) && ! LEGITIMATE_CONSTANT_P (xop0)) \ + xop0 = force_reg (SImode, xop0); \ + if (CONSTANT_P (xop1) && ! LEGITIMATE_CONSTANT_P (xop1)) \ + xop1 = force_reg (SImode, xop1); \ + if (BASE_REGISTER_RTX_P (xop0) && GET_CODE (xop1) == CONST_INT) \ + { \ + HOST_WIDE_INT n, low_n; \ + rtx base_reg, val; \ + n = INTVAL (xop1); \ + \ + if (MODE == DImode) \ + { \ + low_n = n & 0x0f; \ + n &= ~0x0f; \ + if (low_n > 4) \ + { \ + n += 16; \ + low_n -= 16; \ + } \ + } \ + else \ + { \ + low_n = ((MODE) == TImode ? 0 \ + : n >= 0 ? (n & 0xfff) : -((-n) & 0xfff)); \ + n -= low_n; \ + } \ + base_reg = gen_reg_rtx (SImode); \ + val = force_operand (gen_rtx (PLUS, SImode, xop0, \ + GEN_INT (n)), NULL_RTX); \ + emit_move_insn (base_reg, val); \ + (X) = (low_n == 0 ? base_reg \ + : gen_rtx (PLUS, SImode, base_reg, GEN_INT (low_n))); \ + } \ + else if (xop0 != XEXP (X, 0) || xop1 != XEXP (x, 1)) \ + (X) = gen_rtx (PLUS, SImode, xop0, xop1); \ + } \ + else if (GET_CODE (X) == MINUS) \ + { \ + rtx xop0 = XEXP (X, 0); \ + rtx xop1 = XEXP (X, 1); \ + \ + if (CONSTANT_P (xop0)) \ + xop0 = force_reg (SImode, xop0); \ + if (CONSTANT_P (xop1) && ! LEGITIMATE_CONSTANT_P (xop1)) \ + xop1 = force_reg (SImode, xop1); \ + if (xop0 != XEXP (X, 0) || xop1 != XEXP (X, 1)) \ + (X) = gen_rtx (MINUS, SImode, xop0, xop1); \ + } \ + if (memory_address_p (MODE, X)) \ + goto WIN; \ } + /* Go to LABEL if ADDR (a legitimate address expression) has an effect that depends on the machine mode it is used for. */ #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ @@ -1118,7 +1139,7 @@ do \ /* signed 'char' is most compatible, but RISC OS wants it unsigned. unsigned is probably best, but may break some code. */ #ifndef DEFAULT_SIGNED_CHAR -#define DEFAULT_SIGNED_CHAR 1 +#define DEFAULT_SIGNED_CHAR 0 #endif /* Don't cse the address of the function being compiled. */ @@ -1204,91 +1225,38 @@ do \ return -1; \ return(7); +#define ARM_FRAME_RTX(X) \ + ((X) == frame_pointer_rtx || (X) == stack_pointer_rtx \ + || (X) == arg_pointer_rtx) + #define RTX_COSTS(X,CODE,OUTER_CODE) \ - case MEM: \ - { \ - int num_words = (GET_MODE_SIZE (GET_MODE (X)) > UNITS_PER_WORD) ? 2 : 1;\ - return (COSTS_N_INSNS (10*num_words)); \ - } \ - case MULT: \ - if (GET_CODE (XEXP (X, 1)) == CONST_INT \ - && exact_log2 (INTVAL (XEXP (X, 1))) >= 0) \ - return rtx_cost (XEXP (X, 0), GET_CODE (X))+1; \ - return COSTS_N_INSNS (9); \ - case ASHIFT: \ - case LSHIFTRT: \ - case ASHIFTRT: \ - if (GET_CODE (XEXP (X, 1)) == CONST_INT) \ - return rtx_cost (XEXP (X, 0), GET_CODE (X))+1; \ - break; \ - case MINUS: \ - { \ - enum rtx_code code = GET_CODE (XEXP (X, 1)); \ - if (code == MULT) \ - { \ - if (GET_CODE (XEXP (XEXP (X, 1), 1)) == CONST_INT \ - && exact_log2 (INTVAL (XEXP (XEXP (X, 0), 1))) >= 0) \ - return COSTS_N_INSNS (1); \ - break; \ - } \ - else if (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT) \ - return COSTS_N_INSNS (1); \ - } /* fall through */ \ - case PLUS: \ - case IOR: \ - case XOR: \ - case AND: \ - { \ - enum rtx_code code = GET_CODE (XEXP (X, 0)); \ - if (code == MULT) \ - { \ - if (GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \ - && exact_log2 (INTVAL (XEXP (XEXP (X, 0), 1))) >= 0) \ - return COSTS_N_INSNS (1); \ - if (GET_CODE (X) == PLUS) \ - return COSTS_N_INSNS (12); \ - break; \ - } \ - else if (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT) \ - return COSTS_N_INSNS (1); \ - break; \ - } \ - case NOT: \ - return rtx_cost (XEXP (X, 0), GET_CODE (XEXP (X, 0))); \ - case IF_THEN_ELSE: \ - { \ - if (GET_CODE (XEXP(X,1)) == PC || GET_CODE (XEXP(X,2)) == PC) \ - return COSTS_N_INSNS (4); \ - return COSTS_N_INSNS (1); \ - } \ - case SIGN_EXTEND: \ - return COSTS_N_INSNS (2); \ - case ZERO_EXTEND: \ - if (GET_MODE (XEXP (X, 0)) == QImode) \ - { \ - if (GET_CODE (XEXP (X, 0)) == MEM) \ - return COSTS_N_INSNS (10); \ - return COSTS_N_INSNS (1); \ - } \ - break; \ - case COMPARE: \ - if (GET_CODE (XEXP (X, 1)) == REG) \ - return 4; \ - case SMIN: \ - case SMAX: \ - case UMIN: \ - case UMAX: \ - return COSTS_N_INSNS (3); \ - case ABS: \ - if (GET_MODE (X) == SImode) \ - return COSTS_N_INSNS (2); \ - return COSTS_N_INSNS (1); + default: \ + return arm_rtx_costs (X, CODE, OUTER_CODE); /* Moves to and from memory are quite expensive */ #define MEMORY_MOVE_COST(MODE) 10 -/* All address computations that can be done are free */ -#define ADDRESS_COST(x) 2 +/* All address computations that can be done are free, but rtx cost returns + the same for practically all of them. So we weight the differnt types + of address here in the order (most pref first): + PRE/POST_INC/DEC, SHIFT or NON-INT sum, INT sum, REG, MEM or LABEL. */ +#define ADDRESS_COST(X) \ + (10 - ((GET_CODE (X) == MEM || GET_CODE (X) == LABEL_REF \ + || GET_CODE (X) == SYMBOL_REF) \ + ? 0 \ + : ((GET_CODE (X) == PRE_INC || GET_CODE (X) == PRE_DEC \ + || GET_CODE (X) == POST_INC || GET_CODE (X) == POST_DEC) \ + ? 10 \ + : (((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS) \ + ? 6 + (GET_CODE (XEXP (X, 1)) == CONST_INT ? 2 \ + : ((GET_RTX_CLASS (GET_CODE (XEXP (X, 0))) == '2' \ + || GET_RTX_CLASS (GET_CODE (XEXP (X, 0))) == 'c' \ + || GET_RTX_CLASS (GET_CODE (XEXP (X, 1))) == '2' \ + || GET_RTX_CLASS (GET_CODE (XEXP (X, 1))) == 'c') \ + ? 1 : 0)) \ + : 4))))) + + /* Try to generate sequences that don't involve branches, we can then use conditional instructions */ @@ -1342,7 +1310,7 @@ extern int arm_compare_fp; {"arm_not_operand", {SUBREG, REG, CONST_INT}}, \ {"shiftable_operator", {PLUS, MINUS, AND, IOR, XOR}}, \ {"minmax_operator", {SMIN, SMAX, UMIN, UMAX}}, \ - {"shift_operator", {ASHIFT, ASHIFTRT, LSHIFTRT, MULT}}, \ + {"shift_operator", {ASHIFT, ASHIFTRT, LSHIFTRT, ROTATERT, MULT}}, \ {"di_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM}}, \ {"load_multiple_operation", {PARALLEL}}, \ {"store_multiple_operation", {PARALLEL}}, \ @@ -1350,6 +1318,8 @@ extern int arm_compare_fp; {"arm_rhsm_operand", {SUBREG, REG, CONST_INT, MEM}}, \ {"const_shift_operand", {CONST_INT}}, \ {"index_operand", {SUBREG, REG, CONST_INT}}, \ + {"reg_or_int_operand", {SUBREG, REG, CONST_INT}}, \ + {"multi_register_push", {PARALLEL}}, \ {"cc_register", {REG}}, @@ -1430,7 +1400,9 @@ extern int arm_compare_fp; #define DBX_DEBUGGING_INFO 1 /* Acorn dbx moans about continuation chars, so don't use any. */ +#ifndef DBX_CONTIN_LENGTH #define DBX_CONTIN_LENGTH 0 +#endif /* Output a source filename for the debugger. RISCiX dbx insists that the ``desc'' field is set to compiler version number >= 315 (sic). */ @@ -1709,7 +1681,7 @@ do { char dstr[30]; \ case ASHIFT: \ case ROTATERT: \ { \ - fprintf (STREAM, "[%s%s, %s%s%s, ", ARM_REG_PREFIX, \ + fprintf (STREAM, "[%s%s, %s%s%s", ARM_REG_PREFIX, \ base_reg_name, is_minus ? "-" : "", ARM_REG_PREFIX,\ reg_names[REGNO (XEXP (index, 0))]); \ arm_print_operand (STREAM, index, 'S'); \ -- 2.11.4.GIT