diff options
author | Richard Henderson <rth@redhat.com> | 2002-01-04 00:15:22 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2002-01-04 00:15:22 -0800 |
commit | 551cc6fdfdad7ff69b81df17da4d0703e1b7c68c (patch) | |
tree | e88c13ed604cc0ea9b1a2b47638f129faa9c99dc | |
parent | 1eaea05433cd21e35d5b544e2215cdb7bcb389be (diff) | |
download | gcc-551cc6fdfdad7ff69b81df17da4d0703e1b7c68c.zip gcc-551cc6fdfdad7ff69b81df17da4d0703e1b7c68c.tar.gz gcc-551cc6fdfdad7ff69b81df17da4d0703e1b7c68c.tar.bz2 |
alpha.c (some_operand): Accept HIGH.
* config/alpha/alpha.c (some_operand): Accept HIGH.
(input_operand): Likewise; accept simple references to globals.
(alpha_const_ok_for_letter_p): New, outlined from alpha.h.
(alpha_const_double_ok_for_letter_p): Likewise.
(alpha_extra_constraint): Likewise.
(alpha_preferred_reload_class): Likewise. Do not force
symbolic constants to memory.
(alpha_legitimate_address_p): Accept simple references
to small_symbolic_operand.
(alpha_legitimize_address): New arg scratch. Be prepared to be
called when no_new_pseudos. Emit simple symbolic references.
Split integers into low, high, and rest.
(alpha_expand_mov): Use alpha_legitimize_address.
(some_small_symbolic_mem_operand): New.
(split_small_symbolic_mem_operand): New.
* config/alpha/alpha-protos.h: Update.
* config/alpha/alpha.h (CONST_OK_FOR_LETTER_P): Out-line.
(CONST_DOUBLE_OK_FOR_LETTER_P): Likewise.
(EXTRA_CONSTRAINT): Likewise.
(PREFERRED_RELOAD_CLASS): Likewise.
(LEGITIMIZE_ADDRESS): Update for alpha_legitimize_address change.
(PREDICATE_CODES): Update.
* config/alpha/alpha.md: New post-reload splitters to convert
simplfied symbolic operands to the form that references $29.
(divide expanders): Use emit_move_insn, not gen_movdi_er_high_g.
(movdi_er_nofix, movdi_er_fix): Accept any symbolic operand.
From-SVN: r48531
-rw-r--r-- | gcc/ChangeLog | 29 | ||||
-rw-r--r-- | gcc/config/alpha/alpha-protos.h | 10 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 318 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.h | 67 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.md | 80 |
5 files changed, 364 insertions, 140 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0c58a03..044dce3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +2002-01-04 Richard Henderson <rth@redhat.com> + + * config/alpha/alpha.c (some_operand): Accept HIGH. + (input_operand): Likewise; accept simple references to globals. + (alpha_const_ok_for_letter_p): New, outlined from alpha.h. + (alpha_const_double_ok_for_letter_p): Likewise. + (alpha_extra_constraint): Likewise. + (alpha_preferred_reload_class): Likewise. Do not force + symbolic constants to memory. + (alpha_legitimate_address_p): Accept simple references + to small_symbolic_operand. + (alpha_legitimize_address): New arg scratch. Be prepared to be + called when no_new_pseudos. Emit simple symbolic references. + Split integers into low, high, and rest. + (alpha_expand_mov): Use alpha_legitimize_address. + (some_small_symbolic_mem_operand): New. + (split_small_symbolic_mem_operand): New. + * config/alpha/alpha-protos.h: Update. + * config/alpha/alpha.h (CONST_OK_FOR_LETTER_P): Out-line. + (CONST_DOUBLE_OK_FOR_LETTER_P): Likewise. + (EXTRA_CONSTRAINT): Likewise. + (PREFERRED_RELOAD_CLASS): Likewise. + (LEGITIMIZE_ADDRESS): Update for alpha_legitimize_address change. + (PREDICATE_CODES): Update. + * config/alpha/alpha.md: New post-reload splitters to convert + simplfied symbolic operands to the form that references $29. + (divide expanders): Use emit_move_insn, not gen_movdi_er_high_g. + (movdi_er_nofix, movdi_er_fix): Accept any symbolic operand. + 2002-01-03 Richard Henderson <rth@redhat.com> * local-alloc.c (function_invariant_p): Update commentary. diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index e7da7d2..2ff0350 100644 --- a/gcc/config/alpha/alpha-protos.h +++ b/gcc/config/alpha/alpha-protos.h @@ -59,6 +59,7 @@ extern int current_file_function_operand PARAMS ((rtx, enum machine_mode)); extern int direct_call_operand PARAMS ((rtx, enum machine_mode)); extern int local_symbolic_operand PARAMS ((rtx, enum machine_mode)); extern int small_symbolic_operand PARAMS ((rtx, enum machine_mode)); +extern int some_small_symbolic_mem_operand PARAMS ((rtx, enum machine_mode)); extern int global_symbolic_operand PARAMS ((rtx, enum machine_mode)); extern int call_operand PARAMS ((rtx, enum machine_mode)); extern int symbolic_operand PARAMS ((rtx, enum machine_mode)); @@ -77,6 +78,10 @@ extern int normal_memory_operand PARAMS ((rtx, enum machine_mode)); extern int reg_no_subreg_operand PARAMS ((rtx, enum machine_mode)); extern int addition_operation PARAMS ((rtx, enum machine_mode)); +extern bool alpha_const_ok_for_letter_p PARAMS ((HOST_WIDE_INT, int)); +extern bool alpha_const_double_ok_for_letter_p PARAMS ((rtx, int)); +extern bool alpha_extra_constraint PARAMS ((rtx, int)); + extern rtx alpha_tablejump_addr_vec PARAMS ((rtx)); extern rtx alpha_tablejump_best_label PARAMS ((rtx)); @@ -85,11 +90,16 @@ extern rtx alpha_legitimize_address PARAMS ((rtx, rtx, enum machine_mode)); extern rtx alpha_legitimize_reload_address PARAMS ((rtx, enum machine_mode, int, int, int)); +extern rtx split_small_symbolic_mem_operand PARAMS ((rtx)); + extern void get_aligned_mem PARAMS ((rtx, rtx *, rtx *)); extern rtx get_unaligned_address PARAMS ((rtx, int)); +extern enum reg_class alpha_preferred_reload_class PARAMS ((rtx, + enum reg_class)); extern enum reg_class secondary_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx, int)); + extern void alpha_set_memflags PARAMS ((rtx, rtx)); extern rtx alpha_emit_set_const PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT, int)); diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index dee844b..b928609 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -768,7 +768,7 @@ some_operand (op, mode) switch (GET_CODE (op)) { case REG: case MEM: case CONST_DOUBLE: case CONST_INT: case LABEL_REF: - case SYMBOL_REF: case CONST: + case SYMBOL_REF: case CONST: case HIGH: return 1; case SUBREG: @@ -816,11 +816,22 @@ input_operand (op, mode) case SYMBOL_REF: case CONST: if (TARGET_EXPLICIT_RELOCS) - return 0; + { + /* We don't split symbolic operands into something unintelligable + until after reload, but we do not wish non-small, non-global + symbolic operands to be reconstructed from their high/lo_sum + form. */ + return (small_symbolic_operand (op, mode) + || global_symbolic_operand (op, mode)); + } /* This handles both the Windows/NT and OSF cases. */ return mode == ptr_mode || mode == DImode; + case HIGH: + return (TARGET_EXPLICIT_RELOCS + && local_symbolic_operand (XEXP (op, 0), mode)); + case REG: case ADDRESSOF: return 1; @@ -1354,6 +1365,100 @@ addition_operation (op, mode) return 0; } +/* Implements CONST_OK_FOR_LETTER_P. Return true if the value matches + the range defined for C in [I-P]. */ + +bool +alpha_const_ok_for_letter_p (value, c) + HOST_WIDE_INT value; + int c; +{ + switch (c) + { + case 'I': + /* An unsigned 8 bit constant. */ + return (unsigned HOST_WIDE_INT) value < 0x100; + case 'J': + /* The constant zero. */ + return value == 0; + case 'K': + /* A signed 16 bit constant. */ + return (unsigned HOST_WIDE_INT) (value + 0x8000) < 0x10000; + case 'L': + /* A shifted signed 16 bit constant appropriate for LDAH. */ + return ((value & 0xffff) == 0 + && ((value) >> 31 == -1 || value >> 31 == 0)); + case 'M': + /* A constant that can be AND'ed with using a ZAP insn. */ + return zap_mask (value); + case 'N': + /* A complemented unsigned 8 bit constant. */ + return (unsigned HOST_WIDE_INT) (~ value) < 0x100; + case 'O': + /* A negated unsigned 8 bit constant. */ + return (unsigned HOST_WIDE_INT) (- value) < 0x100; + case 'P': + /* The constant 1, 2 or 3. */ + return value == 1 || value == 2 || value == 3; + + default: + return false; + } +} + +/* Implements CONST_DOUBLE_OK_FOR_LETTER_P. Return true if VALUE + matches for C in [GH]. */ + +bool +alpha_const_double_ok_for_letter_p (value, c) + rtx value; + int c; +{ + switch (c) + { + case 'G': + /* The floating point zero constant. */ + return (GET_MODE_CLASS (GET_MODE (value)) == MODE_FLOAT + && value == CONST0_RTX (GET_MODE (value))); + + case 'H': + /* A valid operand of a ZAP insn. */ + return (GET_MODE (value) == VOIDmode + && zap_mask (CONST_DOUBLE_LOW (value)) + && zap_mask (CONST_DOUBLE_HIGH (value))); + + default: + return false; + } +} + +/* Implements CONST_DOUBLE_OK_FOR_LETTER_P. Return true if VALUE + matches for C. */ + +bool +alpha_extra_constraint (value, c) + rtx value; + int c; +{ + switch (c) + { + case 'Q': + return normal_memory_operand (value, VOIDmode); + case 'R': + return direct_call_operand (value, Pmode); + case 'S': + return (GET_CODE (value) == CONST_INT + && (unsigned HOST_WIDE_INT) INTVAL (value) < 64); + case 'T': + return GET_CODE (value) == HIGH; + case 'U': + return TARGET_ABI_UNICOSMK && symbolic_operand (value, VOIDmode); + + default: + return false; + } +} + /* Return 1 if this function can directly return via $26. */ int @@ -1628,28 +1733,35 @@ alpha_legitimate_address_p (mode, x, strict) return true; } - /* If we're managing explicit relocations, LO_SUM is valid. */ - else if (TARGET_EXPLICIT_RELOCS && GET_CODE (x) == LO_SUM) + /* If we're managing explicit relocations, LO_SUM is valid, as + are small data symbols. */ + else if (TARGET_EXPLICIT_RELOCS) { - rtx ofs = XEXP (x, 1); - x = XEXP (x, 0); - - /* Discard non-paradoxical subregs. */ - if (GET_CODE (x) == SUBREG - && (GET_MODE_SIZE (GET_MODE (x)) - < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))) - x = SUBREG_REG (x); - - /* Must have a valid base register. */ - if (! (REG_P (x) - && (strict - ? STRICT_REG_OK_FOR_BASE_P (x) - : NONSTRICT_REG_OK_FOR_BASE_P (x)))) - return false; - - /* The symbol must be local. */ - if (local_symbolic_operand (ofs, Pmode)) + if (small_symbolic_operand (x, Pmode)) return true; + + if (GET_CODE (x) == LO_SUM) + { + rtx ofs = XEXP (x, 1); + x = XEXP (x, 0); + + /* Discard non-paradoxical subregs. */ + if (GET_CODE (x) == SUBREG + && (GET_MODE_SIZE (GET_MODE (x)) + < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))) + x = SUBREG_REG (x); + + /* Must have a valid base register. */ + if (! (REG_P (x) + && (strict + ? STRICT_REG_OK_FOR_BASE_P (x) + : NONSTRICT_REG_OK_FOR_BASE_P (x)))) + return false; + + /* The symbol must be local. */ + if (local_symbolic_operand (ofs, Pmode)) + return true; + } } return false; @@ -1659,9 +1771,9 @@ alpha_legitimate_address_p (mode, x, strict) to be legitimate. If we find one, return the new, valid address. */ rtx -alpha_legitimize_address (x, oldx, mode) +alpha_legitimize_address (x, scratch, mode) rtx x; - rtx oldx ATTRIBUTE_UNUSED; + rtx scratch; enum machine_mode mode ATTRIBUTE_UNUSED; { HOST_WIDE_INT addend; @@ -1683,7 +1795,8 @@ alpha_legitimize_address (x, oldx, mode) part of the CONST_INT. Then load FOO plus any high-order part of the CONST_INT into a register. Our address is (plus reg low-part-const). This is done to reduce the number of GOT entries. */ - if (GET_CODE (x) == CONST + if (!no_new_pseudos + && GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT) { @@ -1695,7 +1808,8 @@ alpha_legitimize_address (x, oldx, mode) /* If we have a (plus reg const), emit the load as in (2), then add the two registers, and finally generate (plus reg low-part-const) as our address. */ - if (GET_CODE (x) == PLUS + if (!no_new_pseudos + && GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == REG && GET_CODE (XEXP (x, 1)) == CONST && GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS @@ -1711,33 +1825,18 @@ alpha_legitimize_address (x, oldx, mode) /* If this is a local symbol, split the address into HIGH/LO_SUM parts. */ if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode)) { - rtx scratch; if (local_symbolic_operand (x, Pmode)) { if (small_symbolic_operand (x, Pmode)) - scratch = pic_offset_table_rtx; + return x; else { - rtx insn, tmp; - - scratch = gen_reg_rtx (Pmode); - - tmp = gen_rtx_HIGH (Pmode, x); - tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp); - insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp)); - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp, - REG_NOTES (insn)); + if (!no_new_pseudos) + scratch = gen_reg_rtx (Pmode); + emit_insn (gen_rtx_SET (VOIDmode, scratch, + gen_rtx_HIGH (Pmode, x))); + return gen_rtx_LO_SUM (Pmode, scratch, x); } - - return gen_rtx_LO_SUM (Pmode, scratch, x); - } - else - { - scratch = gen_reg_rtx (Pmode); - emit_insn (gen_movdi_er_high_g (scratch, pic_offset_table_rtx, - x, const0_rtx)); - /* ??? FIXME: Tag the use of scratch with a lituse. */ - return scratch; } } @@ -1745,14 +1844,65 @@ alpha_legitimize_address (x, oldx, mode) split_addend: { - HOST_WIDE_INT lowpart = (addend & 0xffff) - 2 * (addend & 0x8000); - HOST_WIDE_INT highpart = addend - lowpart; - x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (highpart), - NULL_RTX, 1, OPTAB_LIB_WIDEN); - return plus_constant (x, lowpart); + HOST_WIDE_INT low, high; + + low = ((addend & 0xffff) ^ 0x8000) - 0x8000; + addend -= low; + high = ((addend & 0xffffffff) ^ 0x80000000) - 0x80000000; + addend -= high; + + if (addend) + x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (addend), + (no_new_pseudos ? scratch : NULL_RTX), + 1, OPTAB_LIB_WIDEN); + if (high) + x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (high), + (no_new_pseudos ? scratch : NULL_RTX), + 1, OPTAB_LIB_WIDEN); + + return plus_constant (x, low); } } +/* For TARGET_EXPLICIT_RELOCS, we don't obfuscate a SYMBOL_REF to a + small symbolic operand until after reload. At which point we need + to replace (mem (symbol_ref)) with (mem (lo_sum $29 symbol_ref)) + so that sched2 has the proper dependency information. */ + +int +some_small_symbolic_mem_operand (x, mode) + rtx x; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + /* Get rid of SIGN_EXTEND, etc. */ + while (GET_RTX_CLASS (GET_CODE (x)) == '1') + x = XEXP (x, 0); + + return (GET_CODE (x) == MEM + && small_symbolic_operand (XEXP (x, 0), Pmode)); +} + +rtx +split_small_symbolic_mem_operand (x) + rtx x; +{ + rtx *p; + + if (GET_CODE (x) == MEM) + { + rtx tmp = gen_rtx_LO_SUM (DImode, pic_offset_table_rtx, XEXP (x, 0)); + return replace_equiv_address (x, tmp); + } + + x = copy_rtx (x); + p = &x; + while (GET_RTX_CLASS (GET_CODE (*p)) == '1') + p = &XEXP (*p, 0); + + *p = split_small_symbolic_mem_operand (*p); + return x; +} + /* Try a machine-dependent way of reloading an illegitimate address operand. If we find one, push the reload and return the new rtx. */ @@ -1886,6 +2036,39 @@ get_unaligned_address (ref, extra_offset) return plus_constant (base, offset + extra_offset); } +/* On the Alpha, all (non-symbolic) constants except zero go into + a floating-point register via memory. Note that we cannot + return anything that is not a subset of CLASS, and that some + symbolic constants cannot be dropped to memory. */ + +enum reg_class +alpha_preferred_reload_class(x, class) + rtx x; + enum reg_class class; +{ + /* Zero is present in any register class. */ + if (x == CONST0_RTX (GET_MODE (x))) + return class; + + /* These sorts of constants we can easily drop to memory. */ + if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE) + { + if (class == FLOAT_REGS) + return NO_REGS; + if (class == ALL_REGS) + return GENERAL_REGS; + return class; + } + + /* All other kinds of constants should not (and in the case of HIGH + cannot) be dropped to memory -- instead we use a GENERAL_REGS + secondary reload. */ + if (CONSTANT_P (x)) + return (class == ALL_REGS ? GENERAL_REGS : class); + + return class; +} + /* Loading and storing HImode or QImode values to and from memory usually requires a scratch register. The exceptions are loading QImode and HImode from an aligned address to a general register @@ -2294,36 +2477,15 @@ alpha_expand_mov (mode, operands) && ! reg_or_0_operand (operands[1], mode)) operands[1] = force_reg (mode, operands[1]); - if (TARGET_EXPLICIT_RELOCS && symbolic_operand (operands[1], mode)) + /* Allow legitimize_address to perform some simplifications. */ + if (symbolic_operand (operands[1], mode)) { - if (local_symbolic_operand (operands[1], mode)) + rtx tmp = alpha_legitimize_address (operands[1], operands[0], mode); + if (tmp) { - rtx scratch; - - if (small_symbolic_operand (operands[1], Pmode)) - scratch = pic_offset_table_rtx; - else - { - rtx insn, tmp; - - scratch = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); - - tmp = gen_rtx_HIGH (Pmode, operands[1]); - tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp); - insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp)); - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp, - REG_NOTES (insn)); - } - - operands[1] = gen_rtx_LO_SUM (Pmode, scratch, operands[1]); + operands[1] = tmp; return false; } - else - { - emit_insn (gen_movdi_er_high_g (operands[0], pic_offset_table_rtx, - operands[1], const0_rtx)); - return true; - } } /* Early out for non-constants and valid constants. */ diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index de2428f..e2d8b38 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -812,17 +812,7 @@ enum reg_class { `O' is used for negated 8-bit constants. `P' is used for the constants 1, 2 and 3. */ -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'I' ? (unsigned HOST_WIDE_INT) (VALUE) < 0x100 \ - : (C) == 'J' ? (VALUE) == 0 \ - : (C) == 'K' ? (unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000 \ - : (C) == 'L' ? (((VALUE) & 0xffff) == 0 \ - && (((VALUE)) >> 31 == -1 || (VALUE) >> 31 == 0)) \ - : (C) == 'M' ? zap_mask (VALUE) \ - : (C) == 'N' ? (unsigned HOST_WIDE_INT) (~ (VALUE)) < 0x100 \ - : (C) == 'O' ? (unsigned HOST_WIDE_INT) (- (VALUE)) < 0x100 \ - : (C) == 'P' ? (VALUE) == 1 || (VALUE) == 2 || (VALUE) == 3 \ - : 0) +#define CONST_OK_FOR_LETTER_P alpha_const_ok_for_letter_p /* Similar, but for floating or large integer constants, and defining letters G and H. Here VALUE is the CONST_DOUBLE rtx itself. @@ -830,13 +820,7 @@ enum reg_class { For Alpha, `G' is the floating-point constant zero. `H' is a CONST_DOUBLE that is the operand of a ZAP insn. */ -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'G' ? (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT \ - && (VALUE) == CONST0_RTX (GET_MODE (VALUE))) \ - : (C) == 'H' ? (GET_MODE (VALUE) == VOIDmode \ - && zap_mask (CONST_DOUBLE_LOW (VALUE)) \ - && zap_mask (CONST_DOUBLE_HIGH (VALUE))) \ - : 0) +#define CONST_DOUBLE_OK_FOR_LETTER_P alpha_const_double_ok_for_letter_p /* Optional extra constraints for this machine. @@ -848,31 +832,18 @@ enum reg_class { 'S' is a 6-bit constant (valid for a shift insn). + 'T' is a HIGH. + 'U' is a symbolic operand. */ -#define EXTRA_CONSTRAINT(OP, C) \ - ((C) == 'Q' ? normal_memory_operand (OP, VOIDmode) \ - : (C) == 'R' ? direct_call_operand (OP, Pmode) \ - : (C) == 'S' ? (GET_CODE (OP) == CONST_INT \ - && (unsigned HOST_WIDE_INT) INTVAL (OP) < 64) \ - : (C) == 'T' ? GET_CODE (OP) == HIGH \ - : (TARGET_ABI_UNICOSMK && (C) == 'U') \ - ? symbolic_operand (OP, VOIDmode) \ - : 0) +#define EXTRA_CONSTRAINT alpha_extra_constraint /* Given an rtx X being reloaded into a reg required to be in class CLASS, return the class of reg to actually use. In general this is just CLASS; but on some machines - in some cases it is preferable to use a more restrictive class. - - On the Alpha, all constants except zero go into a floating-point - register via memory. */ + in some cases it is preferable to use a more restrictive class. */ -#define PREFERRED_RELOAD_CLASS(X, CLASS) \ - (CONSTANT_P (X) && (X) != const0_rtx && (X) != CONST0_RTX (GET_MODE (X)) \ - ? ((CLASS) == FLOAT_REGS || (CLASS) == NO_REGS ? NO_REGS \ - : (CLASS) == ALL_REGS ? GENERAL_REGS : (CLASS)) \ - : (CLASS)) +#define PREFERRED_RELOAD_CLASS alpha_preferred_reload_class /* Loading and storing HImode or QImode values to and from memory usually requires a scratch register. The exceptions are loading @@ -1479,14 +1450,14 @@ do { \ to be legitimate. If we find one, return the new, valid address. This macro is used in only one place: `memory_address' in explow.c. */ -#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ -do { \ - rtx new_x = alpha_legitimize_address (X, OLDX, MODE); \ - if (new_x) \ - { \ - X = new_x; \ - goto WIN; \ - } \ +#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ +do { \ + rtx new_x = alpha_legitimize_address (X, NULL_RTX, MODE); \ + if (new_x) \ + { \ + X = new_x; \ + goto WIN; \ + } \ } while (0) /* Try a machine-dependent way of reloading an illegitimate address @@ -2117,9 +2088,9 @@ do { \ {"global_symbolic_operand", {SYMBOL_REF, CONST}}, \ {"call_operand", {REG, SYMBOL_REF}}, \ {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ - SYMBOL_REF, CONST, LABEL_REF}}, \ + SYMBOL_REF, CONST, LABEL_REF, HIGH}}, \ {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ - SYMBOL_REF, CONST, LABEL_REF}}, \ + SYMBOL_REF, CONST, LABEL_REF, HIGH}}, \ {"some_ni_operand", {SUBREG, REG, MEM}}, \ {"aligned_memory_operand", {MEM}}, \ {"unaligned_memory_operand", {MEM}}, \ @@ -2130,7 +2101,9 @@ do { \ {"reg_not_elim_operand", {SUBREG, REG}}, \ {"reg_no_subreg_operand", {REG}}, \ {"addition_operation", {PLUS}}, \ - {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}}, + {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}}, \ + {"some_small_symbolic_mem_operand", {MEM, SIGN_EXTEND, ZERO_EXTEND, \ + FLOAT_EXTEND}}, /* Define the `__builtin_va_list' type for the ABI. */ #define BUILD_VA_LIST_TYPE(VALIST) \ diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 7ab782a..31d03c4 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -649,6 +649,14 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" "TARGET_EXPLICIT_RELOCS" "ldah %0,%2(%1)\t\t!gprelhigh") +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (high:DI (match_operand:DI 1 "local_symbolic_operand" "")))] + "TARGET_EXPLICIT_RELOCS && reload_completed" + [(set (match_dup 0) + (plus:DI (match_dup 2) (high:DI (match_dup 1))))] + "operands[2] = pic_offset_table_rtx;") + ;; We used to expend quite a lot of effort choosing addq/subq/lda. ;; With complications like ;; @@ -1225,9 +1233,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" default: abort (); } - emit_insn (gen_movdi_er_high_g (operands[0], pic_offset_table_rtx, - gen_rtx_SYMBOL_REF (DImode, str), - const0_rtx)); + emit_move_insn (operands[0], gen_rtx_SYMBOL_REF (DImode, str)); } [(set_attr "type" "jsr") (set_attr "length" "8")]) @@ -1290,9 +1296,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" default: abort (); } - emit_insn (gen_movdi_er_high_g (operands[0], pic_offset_table_rtx, - gen_rtx_SYMBOL_REF (DImode, str), - const0_rtx)); + emit_move_insn (operands[0], gen_rtx_SYMBOL_REF (DImode, str)); } [(set_attr "type" "jsr") (set_attr "length" "8")]) @@ -5459,7 +5463,39 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" return "lda %0,%2(%1)\t\t!gprellow"; }) -(define_insn "movdi_er_high_g" +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (match_operand:DI 1 "small_symbolic_operand" ""))] + "TARGET_EXPLICIT_RELOCS && reload_completed" + [(set (match_dup 0) + (lo_sum:DI (match_dup 2) (match_dup 1)))] + "operands[2] = pic_offset_table_rtx;") + +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (match_operand:DI 1 "local_symbolic_operand" ""))] + "TARGET_EXPLICIT_RELOCS && reload_completed" + [(set (match_dup 0) + (plus:DI (match_dup 2) (high:DI (match_dup 1)))) + (set (match_dup 0) + (lo_sum:DI (match_dup 0) (match_dup 1)))] + "operands[2] = pic_offset_table_rtx;") + +(define_split + [(set (match_operand 0 "some_small_symbolic_mem_operand" "") + (match_operand 1 "" ""))] + "TARGET_EXPLICIT_RELOCS && reload_completed" + [(set (match_dup 0) (match_dup 1))] + "operands[0] = split_small_symbolic_mem_operand (operands[0]);") + +(define_split + [(set (match_operand 0 "" "") + (match_operand 1 "some_small_symbolic_mem_operand" ""))] + "TARGET_EXPLICIT_RELOCS && reload_completed" + [(set (match_dup 0) (match_dup 1))] + "operands[1] = split_small_symbolic_mem_operand (operands[1]);") + +(define_insn "*movdi_er_high_g" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "global_symbolic_operand" "") @@ -5469,9 +5505,19 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" "ldq %0,%2(%1)\t\t!literal" [(set_attr "type" "ldsym")]) +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (match_operand:DI 1 "global_symbolic_operand" ""))] + "TARGET_EXPLICIT_RELOCS && reload_completed" + [(set (match_dup 0) + (unspec:DI [(match_dup 2) + (match_dup 1) + (const_int 0)] UNSPEC_LITERAL))] + "operands[2] = pic_offset_table_rtx;") + (define_insn "*movdi_er_nofix" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q") - (match_operand:DI 1 "input_operand" "rJ,K,L,T,m,rJ,*fJ,Q,*f"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q") + (match_operand:DI 1 "input_operand" "rJ,K,L,T,s,m,rJ,*fJ,Q,*f"))] "TARGET_EXPLICIT_RELOCS && ! TARGET_FIX && (register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode))" @@ -5479,13 +5525,14 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" mov %r1,%0 lda %0,%1($31) ldah %0,%h1($31) - ldah %0,%H1 + # + # ldq%A1 %0,%1 stq%A0 %r1,%0 fmov %R1,%0 ldt %0,%1 stt %R1,%0" - [(set_attr "type" "ilog,iadd,iadd,iadd,ild,ist,fcpys,fld,fst")]) + [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")]) ;; The 'U' constraint matches symbolic operands on Unicos/Mk. Those should ;; have been split up by the rules above but we shouldn't reject the @@ -5512,8 +5559,10 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" (set_attr "length" "*,*,*,16,*,*,*,*,*,*")]) (define_insn "*movdi_er_fix" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q,r,*f") - (match_operand:DI 1 "input_operand" "rJ,K,L,T,m,rJ,*fJ,Q,*f,*f,r"))] + [(set (match_operand:DI 0 "nonimmediate_operand" + "=r,r,r,r,r,r, m, *f,*f, Q, r,*f") + (match_operand:DI 1 "input_operand" + "rJ,K,L,T,s,m,rJ,*fJ, Q,*f,*f, r"))] "TARGET_EXPLICIT_RELOCS && TARGET_FIX && (register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode))" @@ -5521,7 +5570,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" mov %r1,%0 lda %0,%1($31) ldah %0,%h1($31) - ldah %0,%H1 + # + # ldq%A1 %0,%1 stq%A0 %r1,%0 fmov %R1,%0 @@ -5529,7 +5579,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" stt %R1,%0 ftoit %1,%0 itoft %1,%0" - [(set_attr "type" "ilog,iadd,iadd,iadd,ild,ist,fcpys,fld,fst,ftoi,itof")]) + [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst,ftoi,itof")]) (define_insn "*movdi_fix" [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q,r,*f") |