summaryrefslogtreecommitdiff
path: root/gcc/config/alpha
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2005-01-20 03:59:00 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2005-01-20 03:59:00 +0000
commit91bc47b0da3cd48bd112287ebdbf508712647243 (patch)
treecda4b7c4fa5fd8c63fdd336bd609206fd5423cd2 /gcc/config/alpha
parent54d60d02d41bba36cdfa8aab8e7b7b923cdf336d (diff)
downloadgcc-91bc47b0da3cd48bd112287ebdbf508712647243.tar.gz
PR target/19518
* config/alpha/alpha.c (alpha_rtx_costs): Handle HIGH. (alpha_preferred_reload_class): Handle CONST_VECTOR. (alpha_emit_set_const_1): Add no_output parameter; don't emit rtl if true. (alpha_emit_set_const): Likewise. Make static. (alpha_emit_set_long_const): Make static. (alpha_extract_integer): Split out from alpha_expand_mov. (alpha_split_const_mov): Likewise. (alpha_expand_mov): Use them. Handle CONST_VECTOR. (alpha_legitimate_constant_p): New. * config/alpha/alpha-protos.h: Update. * config/alpha/alpha.h (REGISTER_MOVE_COST): Correct fp<->gp cost. (LEGITIMATE_CONSTANT_P): Re-implement with a function. * config/alpha/alpha.md (movsi): Add n alternative. (movsi_nt_vms, movdi_er_nofix, movdi_er_fix, movdi_fix): Likewise. (mov<VEC>_fix, mov<VEC>_nofix): Add i alternative. (splitters for all of the above): Use alpha_split_const_mov. * config/alpha/predicates.md (non_add_const_operand): New. (non_zero_const_operand): New. (input_operand): Use alpha_legitimate_constant_p after reload. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@93943 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/alpha')
-rw-r--r--gcc/config/alpha/alpha-protos.h4
-rw-r--r--gcc/config/alpha/alpha.c342
-rw-r--r--gcc/config/alpha/alpha.h12
-rw-r--r--gcc/config/alpha/alpha.md99
-rw-r--r--gcc/config/alpha/predicates.md21
5 files changed, 335 insertions, 143 deletions
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index 24f24e6b2bf..d1ffada3dcf 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -42,6 +42,7 @@ extern bool alpha_extra_constraint (rtx, int);
extern rtx alpha_tablejump_addr_vec (rtx);
extern rtx alpha_tablejump_best_label (rtx);
+extern bool alpha_legitimate_constant_p (rtx);
extern bool alpha_legitimate_address_p (enum machine_mode, rtx, int);
extern rtx alpha_legitimize_address (rtx, rtx, enum machine_mode);
extern rtx alpha_legitimize_reload_address (rtx, enum machine_mode,
@@ -56,8 +57,7 @@ extern enum reg_class secondary_reload_class (enum reg_class,
enum machine_mode, rtx, int);
extern void alpha_set_memflags (rtx, rtx);
-extern rtx alpha_emit_set_const (rtx, enum machine_mode, HOST_WIDE_INT, int);
-extern rtx alpha_emit_set_long_const (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
+extern bool alpha_split_const_mov (enum machine_mode, rtx *);
extern bool alpha_expand_mov (enum machine_mode, rtx *);
extern bool alpha_expand_mov_nobwx (enum machine_mode, rtx *);
extern void alpha_expand_movmisalign (enum machine_mode, rtx *);
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index aed7ada5619..037dc4ad33e 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -1384,6 +1384,11 @@ alpha_rtx_costs (rtx x, int code, int outer_code, int *total)
*total = COSTS_N_INSNS (optimize_size ? 1 : alpha_memory_latency);
return true;
+ case HIGH:
+ /* This is effectively an add_operand. */
+ *total = 2;
+ return true;
+
case PLUS:
case MINUS:
if (float_mode_p)
@@ -1557,7 +1562,9 @@ alpha_preferred_reload_class(rtx x, enum reg_class class)
return class;
/* These sorts of constants we can easily drop to memory. */
- if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
+ if (GET_CODE (x) == CONST_INT
+ || GET_CODE (x) == CONST_DOUBLE
+ || GET_CODE (x) == CONST_VECTOR)
{
if (class == FLOAT_REGS)
return NO_REGS;
@@ -1679,11 +1686,16 @@ alpha_set_memflags (rtx insn, rtx ref)
for_each_rtx (base_ptr, alpha_set_memflags_1, (void *) ref);
}
-/* Internal routine for alpha_emit_set_const to check for N or below insns. */
+static rtx alpha_emit_set_const (rtx, enum machine_mode, HOST_WIDE_INT,
+ int, bool);
+
+/* Internal routine for alpha_emit_set_const to check for N or below insns.
+ If NO_OUTPUT is true, then we only check to see if N insns are possible,
+ and return pc_rtx if successful. */
static rtx
alpha_emit_set_const_1 (rtx target, enum machine_mode mode,
- HOST_WIDE_INT c, int n)
+ HOST_WIDE_INT c, int n, bool no_output)
{
HOST_WIDE_INT new;
int i, bits;
@@ -1722,6 +1734,8 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode,
emit_move_insn to gen_movdi. So instead, since we know exactly
what we want, create it explicitly. */
+ if (no_output)
+ return pc_rtx;
if (target == NULL)
target = gen_reg_rtx (mode);
emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (c)));
@@ -1729,6 +1743,8 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode,
}
else if (n >= 2 + (extra != 0))
{
+ if (no_output)
+ return pc_rtx;
if (no_new_pseudos)
{
emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (high << 16)));
@@ -1781,14 +1797,26 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode,
high bits. */
new = ((c & 0xffff) ^ 0x8000) - 0x8000;
- if (new != 0
- && (temp = alpha_emit_set_const (subtarget, mode, c - new, i)) != 0)
- return expand_binop (mode, add_optab, temp, GEN_INT (new),
- target, 0, OPTAB_WIDEN);
+ if (new != 0)
+ {
+ temp = alpha_emit_set_const (subtarget, mode, c - new, i, no_output);
+ if (temp)
+ {
+ if (no_output)
+ return temp;
+ return expand_binop (mode, add_optab, temp, GEN_INT (new),
+ target, 0, OPTAB_WIDEN);
+ }
+ }
/* Next try complementing. */
- if ((temp = alpha_emit_set_const (subtarget, mode, ~ c, i)) != 0)
- return expand_unop (mode, one_cmpl_optab, temp, target, 0);
+ temp = alpha_emit_set_const (subtarget, mode, ~c, i, no_output);
+ if (temp)
+ {
+ if (no_output)
+ return temp;
+ return expand_unop (mode, one_cmpl_optab, temp, target, 0);
+ }
/* Next try to form a constant and do a left shift. We can do this
if some low-order bits are zero; the exact_log2 call below tells
@@ -1799,16 +1827,26 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode,
bits to shift, but try all possibilities in case a ZAPNOT will
be useful. */
- if ((bits = exact_log2 (c & - c)) > 0)
+ bits = exact_log2 (c & -c);
+ if (bits > 0)
for (; bits > 0; bits--)
- if ((temp = (alpha_emit_set_const
- (subtarget, mode, c >> bits, i))) != 0
- || ((temp = (alpha_emit_set_const
- (subtarget, mode,
- ((unsigned HOST_WIDE_INT) c) >> bits, i)))
- != 0))
- return expand_binop (mode, ashl_optab, temp, GEN_INT (bits),
- target, 0, OPTAB_WIDEN);
+ {
+ new = c >> bits;
+ temp = alpha_emit_set_const (subtarget, mode, new, i, no_output);
+ if (!temp && c < 0)
+ {
+ new = (unsigned HOST_WIDE_INT)c >> bits;
+ temp = alpha_emit_set_const (subtarget, mode, new,
+ i, no_output);
+ }
+ if (temp)
+ {
+ if (no_output)
+ return temp;
+ return expand_binop (mode, ashl_optab, temp, GEN_INT (bits),
+ target, 0, OPTAB_WIDEN);
+ }
+ }
/* Now try high-order zero bits. Here we try the shifted-in bits as
all zero and all ones. Be careful to avoid shifting outside the
@@ -1816,35 +1854,53 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode,
/* On narrow hosts, don't shift a 1 into the high bit, since we'll
confuse the recursive call and set all of the high 32 bits. */
- if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
- - floor_log2 (c) - 1 - (HOST_BITS_PER_WIDE_INT < 64))) > 0)
+ bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
+ - floor_log2 (c) - 1 - (HOST_BITS_PER_WIDE_INT < 64));
+ if (bits > 0)
for (; bits > 0; bits--)
- if ((temp = alpha_emit_set_const (subtarget, mode,
- c << bits, i)) != 0
- || ((temp = (alpha_emit_set_const
- (subtarget, mode,
- ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)),
- i)))
- != 0))
- return expand_binop (mode, lshr_optab, temp, GEN_INT (bits),
- target, 1, OPTAB_WIDEN);
+ {
+ new = c << bits;
+ temp = alpha_emit_set_const (subtarget, mode, new, i, no_output);
+ if (!temp)
+ {
+ new = (c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1);
+ temp = alpha_emit_set_const (subtarget, mode, new,
+ i, no_output);
+ }
+ if (temp)
+ {
+ if (no_output)
+ return temp;
+ return expand_binop (mode, lshr_optab, temp, GEN_INT (bits),
+ target, 1, OPTAB_WIDEN);
+ }
+ }
/* Now try high-order 1 bits. We get that with a sign-extension.
But one bit isn't enough here. Be careful to avoid shifting outside
the mode and to avoid shifting outside the host wide int size. */
- if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
- - floor_log2 (~ c) - 2)) > 0)
+ bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
+ - floor_log2 (~ c) - 2);
+ if (bits > 0)
for (; bits > 0; bits--)
- if ((temp = alpha_emit_set_const (subtarget, mode,
- c << bits, i)) != 0
- || ((temp = (alpha_emit_set_const
- (subtarget, mode,
- ((c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1)),
- i)))
- != 0))
- return expand_binop (mode, ashr_optab, temp, GEN_INT (bits),
- target, 0, OPTAB_WIDEN);
+ {
+ new = c << bits;
+ temp = alpha_emit_set_const (subtarget, mode, new, i, no_output);
+ if (!temp)
+ {
+ new = (c << bits) | (((HOST_WIDE_INT) 1 << bits) - 1);
+ temp = alpha_emit_set_const (subtarget, mode, new,
+ i, no_output);
+ }
+ if (temp)
+ {
+ if (no_output)
+ return temp;
+ return expand_binop (mode, ashr_optab, temp, GEN_INT (bits),
+ target, 0, OPTAB_WIDEN);
+ }
+ }
}
#if HOST_BITS_PER_WIDE_INT == 64
@@ -1863,10 +1919,17 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode,
if (mode == SImode)
new = ((new & 0xffffffff) ^ 0x80000000) - 0x80000000;
- if (new != c && new != -1
- && (temp = alpha_emit_set_const (subtarget, mode, new, n - 1)) != 0)
- return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new),
- target, 0, OPTAB_WIDEN);
+ if (new != c)
+ {
+ temp = alpha_emit_set_const (subtarget, mode, new, n - 1, no_output);
+ if (temp)
+ {
+ if (no_output)
+ return temp;
+ return expand_binop (mode, and_optab, temp, GEN_INT (c | ~ new),
+ target, 0, OPTAB_WIDEN);
+ }
+ }
#endif
return 0;
@@ -1878,32 +1941,46 @@ alpha_emit_set_const_1 (rtx target, enum machine_mode mode,
emitted. If it would take more than N insns, zero is returned and no
insns and emitted. */
-rtx
+static rtx
alpha_emit_set_const (rtx target, enum machine_mode mode,
- HOST_WIDE_INT c, int n)
+ HOST_WIDE_INT c, int n, bool no_output)
{
- rtx result = 0;
+ enum machine_mode orig_mode = mode;
rtx orig_target = target;
+ rtx result = 0;
int i;
/* If we can't make any pseudos, TARGET is an SImode hard register, we
can't load this constant in one insn, do this in DImode. */
if (no_new_pseudos && mode == SImode
- && GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER
- && (result = alpha_emit_set_const_1 (target, mode, c, 1)) == 0)
+ && GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER)
+ {
+ result = alpha_emit_set_const_1 (target, mode, c, 1, no_output);
+ if (result)
+ return result;
+
+ target = no_output ? NULL : gen_lowpart (DImode, target);
+ mode = DImode;
+ }
+ else if (mode == V8QImode || mode == V4HImode || mode == V2SImode)
{
- target = gen_lowpart (DImode, target);
+ target = no_output ? NULL : gen_lowpart (DImode, target);
mode = DImode;
}
/* Try 1 insn, then 2, then up to N. */
for (i = 1; i <= n; i++)
{
- result = alpha_emit_set_const_1 (target, mode, c, i);
+ result = alpha_emit_set_const_1 (target, mode, c, i, no_output);
if (result)
{
- rtx insn = get_last_insn ();
- rtx set = single_set (insn);
+ rtx insn, set;
+
+ if (no_output)
+ return result;
+
+ insn = get_last_insn ();
+ set = single_set (insn);
if (! CONSTANT_P (SET_SRC (set)))
set_unique_reg_note (get_last_insn (), REG_EQUAL, GEN_INT (c));
break;
@@ -1911,8 +1988,13 @@ alpha_emit_set_const (rtx target, enum machine_mode mode,
}
/* Allow for the case where we changed the mode of TARGET. */
- if (result == target)
- result = orig_target;
+ if (result)
+ {
+ if (result == target)
+ result = orig_target;
+ else if (mode != orig_mode)
+ result = gen_lowpart (orig_mode, result);
+ }
return result;
}
@@ -1922,7 +2004,7 @@ alpha_emit_set_const (rtx target, enum machine_mode mode,
exponential run times encountered when looking for longer sequences
with alpha_emit_set_const. */
-rtx
+static rtx
alpha_emit_set_long_const (rtx target, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
{
HOST_WIDE_INT d1, d2, d3, d4;
@@ -1976,6 +2058,114 @@ alpha_emit_set_long_const (rtx target, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
return target;
}
+/* Given an integral CONST_INT, CONST_DOUBLE, or CONST_VECTOR, return
+ the low 64 bits. */
+
+static void
+alpha_extract_integer (rtx x, HOST_WIDE_INT *p0, HOST_WIDE_INT *p1)
+{
+ HOST_WIDE_INT i0, i1;
+
+ if (GET_CODE (x) == CONST_VECTOR)
+ x = simplify_subreg (DImode, x, GET_MODE (x), 0);
+
+
+ if (GET_CODE (x) == CONST_INT)
+ {
+ i0 = INTVAL (x);
+ i1 = -(i0 < 0);
+ }
+ else if (HOST_BITS_PER_WIDE_INT >= 64)
+ {
+ i0 = CONST_DOUBLE_LOW (x);
+ i1 = -(i0 < 0);
+ }
+ else
+ {
+ i0 = CONST_DOUBLE_LOW (x);
+ i1 = CONST_DOUBLE_HIGH (x);
+ }
+
+ *p0 = i0;
+ *p1 = i1;
+}
+
+/* Implement LEGITIMATE_CONSTANT_P. This is all constants for which we
+ are willing to load the value into a register via a move pattern.
+ Normally this is all symbolic constants, integral constants that
+ take three or fewer instructions, and floating-point zero. */
+
+bool
+alpha_legitimate_constant_p (rtx x)
+{
+ enum machine_mode mode = GET_MODE (x);
+ HOST_WIDE_INT i0, i1;
+
+ switch (GET_CODE (x))
+ {
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ case HIGH:
+ return true;
+
+ case CONST_DOUBLE:
+ if (x == CONST0_RTX (mode))
+ return true;
+ if (FLOAT_MODE_P (mode))
+ return false;
+ goto do_integer;
+
+ case CONST_VECTOR:
+ if (x == CONST0_RTX (mode))
+ return true;
+ if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
+ return false;
+ if (GET_MODE_SIZE (mode) != 8)
+ return false;
+ goto do_integer;
+
+ case CONST_INT:
+ do_integer:
+ if (TARGET_BUILD_CONSTANTS)
+ return true;
+ alpha_extract_integer (x, &i0, &i1);
+ if (HOST_BITS_PER_WIDE_INT >= 64 || i1 == (-i0 < 0))
+ return alpha_emit_set_const_1 (x, mode, i0, 3, true) != NULL;
+ return false;
+
+ default:
+ return false;
+ }
+}
+
+/* Operand 1 is known to be a constant, and should require more than one
+ instruction to load. Emit that multi-part load. */
+
+bool
+alpha_split_const_mov (enum machine_mode mode, rtx *operands)
+{
+ HOST_WIDE_INT i0, i1;
+ rtx temp = NULL_RTX;
+
+ alpha_extract_integer (operands[1], &i0, &i1);
+
+ if (HOST_BITS_PER_WIDE_INT >= 64 || i1 == -(i0 < 0))
+ temp = alpha_emit_set_const (operands[0], mode, i0, 3, false);
+
+ if (!temp && TARGET_BUILD_CONSTANTS)
+ temp = alpha_emit_set_long_const (operands[0], i0, i1);
+
+ if (temp)
+ {
+ if (!rtx_equal_p (operands[0], temp))
+ emit_move_insn (operands[0], temp);
+ return true;
+ }
+
+ return false;
+}
+
/* Expand a move instruction; return true if all work is done.
We don't handle non-bwx subword loads here. */
@@ -2008,40 +2198,11 @@ alpha_expand_mov (enum machine_mode mode, rtx *operands)
/* Split large integers. */
if (GET_CODE (operands[1]) == CONST_INT
- || GET_CODE (operands[1]) == CONST_DOUBLE)
+ || GET_CODE (operands[1]) == CONST_DOUBLE
+ || GET_CODE (operands[1]) == CONST_VECTOR)
{
- HOST_WIDE_INT i0, i1;
- rtx temp = NULL_RTX;
-
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- i0 = INTVAL (operands[1]);
- i1 = -(i0 < 0);
- }
- else if (HOST_BITS_PER_WIDE_INT >= 64)
- {
- i0 = CONST_DOUBLE_LOW (operands[1]);
- i1 = -(i0 < 0);
- }
- else
- {
- i0 = CONST_DOUBLE_LOW (operands[1]);
- i1 = CONST_DOUBLE_HIGH (operands[1]);
- }
-
- if (HOST_BITS_PER_WIDE_INT >= 64 || i1 == -(i0 < 0))
- temp = alpha_emit_set_const (operands[0], mode, i0, 3);
-
- if (!temp && TARGET_BUILD_CONSTANTS)
- temp = alpha_emit_set_long_const (operands[0], i0, i1);
-
- if (temp)
- {
- if (rtx_equal_p (operands[0], temp))
- return true;
- operands[1] = temp;
- return false;
- }
+ if (alpha_split_const_mov (mode, operands))
+ return true;
}
/* Otherwise we've nothing left but to drop the thing to memory. */
@@ -7029,7 +7190,8 @@ alpha_expand_epilogue (void)
else
{
rtx tmp = gen_rtx_REG (DImode, 23);
- FRP (sp_adj2 = alpha_emit_set_const (tmp, DImode, frame_size, 3));
+ FRP (sp_adj2 = alpha_emit_set_const (tmp, DImode, frame_size,
+ 3, false));
if (!sp_adj2)
{
/* We can't drop new things to memory this late, afaik,
diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h
index e9a409816a1..21a634c39ec 100644
--- a/gcc/config/alpha/alpha.h
+++ b/gcc/config/alpha/alpha.h
@@ -884,10 +884,10 @@ enum reg_class {
reduce the impact of not being able to allocate a pseudo to a
hard register. */
-#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
- (((CLASS1) == FLOAT_REGS) == ((CLASS2) == FLOAT_REGS) \
- ? 2 \
- : TARGET_FIX ? 3 : 4+2*alpha_memory_latency)
+#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
+ (((CLASS1) == FLOAT_REGS) == ((CLASS2) == FLOAT_REGS) ? 2 \
+ : TARGET_FIX ? ((CLASS1) == FLOAT_REGS ? 6 : 8) \
+ : 4+2*alpha_memory_latency)
/* A C expressions returning the cost of moving data of MODE from a register to
or from memory.
@@ -1213,9 +1213,7 @@ do { \
/* Include all constant integers and constant doubles, but not
floating-point, except for floating-point zero. */
-#define LEGITIMATE_CONSTANT_P(X) \
- (GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \
- || (X) == CONST0_RTX (GET_MODE (X)))
+#define LEGITIMATE_CONSTANT_P alpha_legitimate_constant_p
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 2679324d10a..0f68d36b93b 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -5128,8 +5128,8 @@
})
(define_insn "*movsi"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m")
- (match_operand:SI 1 "input_operand" "rJ,K,L,m,rJ"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,m")
+ (match_operand:SI 1 "input_operand" "rJ,K,L,n,m,rJ"))]
"(TARGET_ABI_OSF || TARGET_ABI_UNICOSMK)
&& (register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))"
@@ -5137,13 +5137,14 @@
bis $31,%r1,%0
lda %0,%1($31)
ldah %0,%h1($31)
+ #
ldl %0,%1
stl %r1,%0"
- [(set_attr "type" "ilog,iadd,iadd,ild,ist")])
+ [(set_attr "type" "ilog,iadd,iadd,multi,ild,ist")])
(define_insn "*movsi_nt_vms"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,m")
- (match_operand:SI 1 "input_operand" "rJ,K,L,s,m,rJ"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m")
+ (match_operand:SI 1 "input_operand" "rJ,K,L,s,n,m,rJ"))]
"(TARGET_ABI_WINDOWS_NT || TARGET_ABI_OPEN_VMS)
&& (register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))"
@@ -5152,9 +5153,10 @@
lda %0,%1
ldah %0,%h1
lda %0,%1
+ #
ldl %0,%1
stl %r1,%0"
- [(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist")])
+ [(set_attr "type" "ilog,iadd,iadd,ldsym,multi,ild,ist")])
(define_insn "*movhi_nobwx"
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -5221,15 +5223,11 @@
(define_split
[(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "! add_operand (operands[1], SImode)"
- [(set (match_dup 0) (match_dup 2))
- (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
+ (match_operand:SI 1 "non_add_const_operand" ""))]
+ ""
+ [(const_int 0)]
{
- rtx tem
- = alpha_emit_set_const (operands[0], SImode, INTVAL (operands[1]), 2);
-
- if (tem == operands[0])
+ if (alpha_split_const_mov (SImode, operands))
DONE;
else
FAIL;
@@ -5452,8 +5450,8 @@
})
(define_insn "*movdi_er_nofix"
- [(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"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,r,m,*f,*f,Q")
+ (match_operand:DI 1 "input_operand" "rJ,K,L,T,s,n,m,rJ,*fJ,Q,*f"))]
"TARGET_EXPLICIT_RELOCS && ! TARGET_FIX
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
@@ -5463,21 +5461,22 @@
ldah %0,%h1($31)
#
#
+ #
ldq%A1 %0,%1
stq%A0 %r1,%0
fmov %R1,%0
ldt %0,%1
stt %R1,%0"
- [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")
- (set_attr "usegp" "*,*,*,yes,*,*,*,*,*,*")])
+ [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,multi,ild,ist,fcpys,fld,fst")
+ (set_attr "usegp" "*,*,*,yes,*,*,*,*,*,*,*")])
;; 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
;; possibility of them getting through.
(define_insn "*movdi_nofix"
- [(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,U,s,m,rJ,*fJ,Q,*f"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,r,m,*f,*f,Q")
+ (match_operand:DI 1 "input_operand" "rJ,K,L,U,s,n,m,rJ,*fJ,Q,*f"))]
"! TARGET_FIX
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
@@ -5487,19 +5486,20 @@
ldah %0,%h1($31)
laum %0,%t1($31)\;sll %0,32,%0\;lalm %0,%t1(%0)\;lal %0,%t1(%0)
lda %0,%1
+ #
ldq%A1 %0,%1
stq%A0 %r1,%0
cpys %R1,%R1,%0
ldt %0,%1
stt %R1,%0"
- [(set_attr "type" "ilog,iadd,iadd,ldsym,ldsym,ild,ist,fcpys,fld,fst")
- (set_attr "length" "*,*,*,16,*,*,*,*,*,*")])
+ [(set_attr "type" "ilog,iadd,iadd,ldsym,ldsym,multi,ild,ist,fcpys,fld,fst")
+ (set_attr "length" "*,*,*,16,*,*,*,*,*,*,*")])
(define_insn "*movdi_er_fix"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=r,r,r,r,r,r, m, *f,*f, Q, r,*f")
+ "=r,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"))]
+ "rJ,K,L,T,s,n,m,rJ,*fJ, Q,*f,*f, r"))]
"TARGET_EXPLICIT_RELOCS && TARGET_FIX
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
@@ -5509,6 +5509,7 @@
ldah %0,%h1($31)
#
#
+ #
ldq%A1 %0,%1
stq%A0 %r1,%0
fmov %R1,%0
@@ -5516,12 +5517,12 @@
stt %R1,%0
ftoit %1,%0
itoft %1,%0"
- [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst,ftoi,itof")
- (set_attr "usegp" "*,*,*,yes,*,*,*,*,*,*,*,*")])
+ [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,multi,ild,ist,fcpys,fld,fst,ftoi,itof")
+ (set_attr "usegp" "*,*,*,yes,*,*,*,*,*,*,*,*,*")])
(define_insn "*movdi_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,s,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,s,n,m,rJ,*fJ,Q,*f,*f,r"))]
"! TARGET_EXPLICIT_RELOCS && TARGET_FIX
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
@@ -5530,6 +5531,7 @@
lda %0,%1($31)
ldah %0,%h1($31)
lda %0,%1
+ #
ldq%A1 %0,%1
stq%A0 %r1,%0
cpys %R1,%R1,%0
@@ -5537,7 +5539,7 @@
stt %R1,%0
ftoit %1,%0
itoft %1,%0"
- [(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst,ftoi,itof")])
+ [(set_attr "type" "ilog,iadd,iadd,ldsym,multi,ild,ist,fcpys,fld,fst,ftoi,itof")])
;; VMS needs to set up "vms_base_regno" for unwinding. This move
;; often appears dead to the life analysis code, at which point we
@@ -5568,15 +5570,11 @@
(define_split
[(set (match_operand:DI 0 "register_operand" "")
- (match_operand:DI 1 "const_int_operand" ""))]
- "! add_operand (operands[1], DImode)"
- [(set (match_dup 0) (match_dup 2))
- (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
+ (match_operand:DI 1 "non_add_const_operand" ""))]
+ ""
+ [(const_int 0)]
{
- rtx tem
- = alpha_emit_set_const (operands[0], DImode, INTVAL (operands[1]), 2);
-
- if (tem == operands[0])
+ if (alpha_split_const_mov (DImode, operands))
DONE;
else
FAIL;
@@ -6103,6 +6101,19 @@
DONE;
})
+(define_split
+ [(set (match_operand:VEC 0 "register_operand" "")
+ (match_operand:VEC 1 "non_zero_const_operand" ""))]
+ ""
+ [(const_int 0)]
+{
+ if (alpha_split_const_mov (<MODE>mode, operands))
+ DONE;
+ else
+ FAIL;
+})
+
+
(define_expand "movmisalign<mode>"
[(set (match_operand:VEC 0 "nonimmediate_operand" "")
(match_operand:VEC 1 "general_operand" ""))]
@@ -6113,13 +6124,14 @@
})
(define_insn "*mov<mode>_fix"
- [(set (match_operand:VEC 0 "nonimmediate_operand" "=r,r,m,*f,*f,m,r,*f")
- (match_operand:VEC 1 "input_operand" "rW,m,rW,*fW,m,*f,*f,r"))]
+ [(set (match_operand:VEC 0 "nonimmediate_operand" "=r,r,r,m,*f,*f,m,r,*f")
+ (match_operand:VEC 1 "input_operand" "rW,i,m,rW,*fW,m,*f,*f,r"))]
"TARGET_FIX
&& (register_operand (operands[0], <MODE>mode)
|| reg_or_0_operand (operands[1], <MODE>mode))"
"@
bis $31,%r1,%0
+ #
ldq %0,%1
stq %r1,%0
cpys %R1,%R1,%0
@@ -6127,22 +6139,23 @@
stt %R1,%0
ftoit %1,%0
itoft %1,%0"
- [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst,ftoi,itof")])
+ [(set_attr "type" "ilog,multi,ild,ist,fcpys,fld,fst,ftoi,itof")])
(define_insn "*mov<mode>_nofix"
- [(set (match_operand:VEC 0 "nonimmediate_operand" "=r,r,m,*f,*f,m")
- (match_operand:VEC 1 "input_operand" "rW,m,rW,*fW,m,*f"))]
+ [(set (match_operand:VEC 0 "nonimmediate_operand" "=r,r,r,m,*f,*f,m")
+ (match_operand:VEC 1 "input_operand" "rW,i,m,rW,*fW,m,*f"))]
"! TARGET_FIX
&& (register_operand (operands[0], <MODE>mode)
|| reg_or_0_operand (operands[1], <MODE>mode))"
"@
bis $31,%r1,%0
+ #
ldq %0,%1
stq %r1,%0
cpys %R1,%R1,%0
ldt %0,%1
stt %R1,%0"
- [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst")])
+ [(set_attr "type" "ilog,multi,ild,ist,fcpys,fld,fst")])
(define_insn "uminv8qi3"
[(set (match_operand:V8QI 0 "register_operand" "=r")
diff --git a/gcc/config/alpha/predicates.md b/gcc/config/alpha/predicates.md
index b060dd17741..6a58ed67905 100644
--- a/gcc/config/alpha/predicates.md
+++ b/gcc/config/alpha/predicates.md
@@ -66,6 +66,17 @@
|| CONST_OK_FOR_LETTER_P (INTVAL (op), 'O')")
(match_operand 0 "register_operand")))
+;; Return 1 if the operand is a non-symbolic constant operand that
+;; does not satisfy add_operand.
+(define_predicate "non_add_const_operand"
+ (and (match_code "const_int,const_double,const_vector")
+ (not (match_operand 0 "add_operand"))))
+
+;; Return 1 if the operand is a non-symbolic, non-zero constant operand.
+(define_predicate "non_zero_const_operand"
+ (and (match_code "const_int,const_double,const_vector")
+ (match_test "op != CONST0_RTX (mode)")))
+
;; Return 1 if OP is the constant 4 or 8.
(define_predicate "const48_operand"
(and (match_code "const_int")
@@ -205,11 +216,19 @@
&& general_operand (op, mode));
case CONST_DOUBLE:
+ return op == CONST0_RTX (mode);
+
case CONST_VECTOR:
+ if (reload_in_progress || reload_completed)
+ return alpha_legitimate_constant_p (op);
return op == CONST0_RTX (mode);
case CONST_INT:
- return mode == QImode || mode == HImode || add_operand (op, mode);
+ if (mode == QImode || mode == HImode)
+ return true;
+ if (reload_in_progress || reload_completed)
+ return alpha_legitimate_constant_p (op);
+ return add_operand (op, mode);
default:
abort ();