Commit 72910a0b by Richard Henderson Committed by Richard Henderson

re PR target/19518 ([alpha] unrecognizable insn (set (reg:V4HI) (const_vector:V4HI)) with builtins)

        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.

From-SVN: r93943
parent ae727129
2005-01-19 Richard Henderson <rth@redhat.com>
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.
2005-01-19 Zdenek Dvorak <dvorakz@suse.cz>
PR tree-optimization/19038
......
......@@ -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 *);
......
......@@ -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,
......
......@@ -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.
......
......@@ -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")
......
......@@ -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 ();
......
# Copyright (C) 2005 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# GCC testsuite that uses the `dg.exp' driver.
# Exit immediately if this isn't an Alpha target.
if ![istarget alpha*-*-*] then {
return
}
# Load support procs.
load_lib gcc-dg.exp
# If a testcase doesn't have special options, use these.
global DEFAULT_CFLAGS
if ![info exists DEFAULT_CFLAGS] then {
set DEFAULT_CFLAGS " -ansi -pedantic-errors"
}
# Initialize `dg'.
dg-init
# Main loop.
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \
"" $DEFAULT_CFLAGS
# All done.
dg-finish
/* { dg-do compile } */
/* { dg-options "-O2 -mcpu=ev67" } */
typedef short INT16;
typedef unsigned int CARD32;
typedef unsigned short CARD16;
typedef unsigned char CARD8;
typedef struct _Picture *PicturePtr;
typedef int FbStride;
typedef unsigned long __m64;
extern __m64 load8888 (__m64);
static __inline __m64 _mm_adds_pu8(__m64 __m1, __m64 __m2)
{
return __m1 + __builtin_alpha_minsb8(__m2, ~__m1);
}
static __inline __m64 _mm_packs_pu16(__m64 __m1, __m64 __m2)
{
__m1 = __builtin_alpha_minuw4(__m1, 0x00ff00ff00ff00ff);
__m2 = __builtin_alpha_minuw4(__m2, 0x00ff00ff00ff00ff);
return __m1 | (__m2 << 32);
}
typedef unsigned long long ullong;
static __inline__ __m64 pix_multiply(__m64 a)
{
if (a)
return a;
}
static __inline__ __m64 over(__m64 src, __m64 srca, __m64 dest)
{
return _mm_adds_pu8(src, pix_multiply(dest));
}
void fbCompositeSolid_nx8888mmx(CARD8 op, PicturePtr pSrc, PicturePtr pMask,
INT16 yDst, CARD16 width, CARD16 height)
{
CARD32 src;
CARD32 *dstLine, *dst;
CARD16 w;
FbStride dstStride;
__m64 vsrc, vsrca;
vsrc = load8888(src);
while (height--) {
dst = dstLine;
dstLine += dstStride;
while (w && (unsigned long) dst & 7) {
*dst = _mm_packs_pu16(_mm_adds_pu8(vsrc, load8888(*dst)),
_mm_setzero_si64());
dst++;
}
while (w >= 2) {
__m64 dest0, dest1;
*(__m64 *) dst = _mm_packs_pu16(dest0, dest1);
w -= 2;
}
while (w) {
*dst = _mm_packs_pu16(_mm_adds_pu8(vsrc, pix_multiply(0)), 0);
w--;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment