aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2002-01-04 00:15:22 -0800
committerRichard Henderson <rth@gcc.gnu.org>2002-01-04 00:15:22 -0800
commit551cc6fdfdad7ff69b81df17da4d0703e1b7c68c (patch)
treee88c13ed604cc0ea9b1a2b47638f129faa9c99dc
parent1eaea05433cd21e35d5b544e2215cdb7bcb389be (diff)
downloadgcc-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/ChangeLog29
-rw-r--r--gcc/config/alpha/alpha-protos.h10
-rw-r--r--gcc/config/alpha/alpha.c318
-rw-r--r--gcc/config/alpha/alpha.h67
-rw-r--r--gcc/config/alpha/alpha.md80
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")