c-decl.c (init_decl_processing): Provide proper fallback symbol for __builtin_memset.

* c-decl.c (init_decl_processing): Provide proper fallback symbol
for __builtin_memset.
* expr.c (expand_builtin) [MEMSET]: Arg 3 type code is INTEGER_TYPE
not INTEGER_CST.  Assert arg 3 is a constant.
* alpha.c (mode_width_operand): Accept 64-bit modes.
(mode_mask_operand): Likewise.
(print_operand): Likewise for 'M' and 'U' codes.
(alpha_expand_unaligned_load): New function.
(alpha_expand_unaligned_store): Likewise.
(alpha_expand_unaligned_load_words): Likewise.
(alpha_expand_unaligned_store_words): Likewise.
(alpha_expand_block_move): Likewise.
(alpha_expand_block_clear): Likewise.
* alpha.h (MOVE_RATIO): New define.
* alpha.md (extxl, ext*h, ins*l, mskxl): Name them.
(insql, insxh, mskxh, extv, extzv, insv, movstrqi, clrstrqi): New.
* alpha.h (ASM_OUTPUT_LOOP_ALIGN, ASM_OUTPUT_ALIGN_CODE): Set to 3.
(CONSTANT_ALIGNMENT, DATA_ALIGNMENT): Disable.

From-SVN: r17278
This commit is contained in:
Richard Henderson 1998-01-01 20:48:04 -08:00 committed by Richard Henderson
parent 8fbf199e91
commit 6c174fc0e6
6 changed files with 812 additions and 24 deletions

View File

@ -1,3 +1,26 @@
Fri Jan 2 04:34:14 1998 Richard Henderson <rth@cygnus.com>
* c-decl.c (init_decl_processing): Provide proper fallback symbol
for __builtin_memset.
* expr.c (expand_builtin) [MEMSET]: Arg 3 type code is INTEGER_TYPE
not INTEGER_CST. Assert arg 3 is a constant.
* alpha.c (mode_width_operand): Accept 64-bit modes.
(mode_mask_operand): Likewise.
(print_operand): Likewise for 'M' and 'U' codes.
(alpha_expand_unaligned_load): New function.
(alpha_expand_unaligned_store): Likewise.
(alpha_expand_unaligned_load_words): Likewise.
(alpha_expand_unaligned_store_words): Likewise.
(alpha_expand_block_move): Likewise.
(alpha_expand_block_clear): Likewise.
* alpha.h (MOVE_RATIO): New define.
* alpha.md (extxl, ext*h, ins*l, mskxl): Name them.
(insql, insxh, mskxh, extv, extzv, insv, movstrqi, clrstrqi): New.
* alpha.h (ASM_OUTPUT_LOOP_ALIGN, ASM_OUTPUT_ALIGN_CODE): Set to 3.
(CONSTANT_ALIGNMENT, DATA_ALIGNMENT): Disable.
Thu Jan 1 15:40:15 1998 Richard Henderson <rth@cygnus.com>
* configure.in: Put parenthesis around TARGET_CPU_DEFAULT's value.

View File

@ -3353,7 +3353,7 @@ init_decl_processing ()
builtin_function ("__builtin_memcmp", int_ftype_cptr_cptr_sizet,
BUILT_IN_MEMCMP, "memcmp");
builtin_function ("__builtin_memset", memset_ftype,
BUILT_IN_MEMSET, NULL_PTR);
BUILT_IN_MEMSET, "memset");
builtin_function ("__builtin_strcmp", int_ftype_string_string,
BUILT_IN_STRCMP, "strcmp");
builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr,
@ -3450,8 +3450,6 @@ init_decl_processing ()
BUILT_IN_FMOD, NULL_PTR);
builtin_function ("__builtin_frem", double_ftype_double_double,
BUILT_IN_FREM, NULL_PTR);
builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int,
BUILT_IN_MEMSET, NULL_PTR);
builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP,
NULL_PTR);
builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN,

View File

@ -450,7 +450,8 @@ mode_width_operand (op, mode)
enum machine_mode mode;
{
return (GET_CODE (op) == CONST_INT
&& (INTVAL (op) == 8 || INTVAL (op) == 16 || INTVAL (op) == 32));
&& (INTVAL (op) == 8 || INTVAL (op) == 16
|| INTVAL (op) == 32 || INTVAL (op) == 64));
}
/* Return 1 if OP is a constant that is the width of an integral machine mode
@ -463,7 +464,12 @@ mode_mask_operand (op, mode)
{
#if HOST_BITS_PER_WIDE_INT == 32
if (GET_CODE (op) == CONST_DOUBLE)
return CONST_DOUBLE_HIGH (op) == 0 && CONST_DOUBLE_LOW (op) == -1;
return (CONST_DOUBLE_LOW (op) == -1
&& (CONST_DOUBLE_HIGH (op) == -1
|| CONST_DOUBLE_HIGH (op) == 0));
#else
if (GET_CODE (op) == CONST_DOUBLE)
return (CONST_DOUBLE_LOW (op) == -1 && CONST_DOUBLE_HIGH (op) == 0);
#endif
return (GET_CODE (op) == CONST_INT
@ -471,6 +477,7 @@ mode_mask_operand (op, mode)
|| INTVAL (op) == 0xffff
#if HOST_BITS_PER_WIDE_INT == 64
|| INTVAL (op) == 0xffffffff
|| INTVAL (op) == 0xffffffffffffffff
#endif
));
}
@ -1262,6 +1269,587 @@ alpha_emit_conditional_move (cmp, mode)
emit_move_insn (tem, gen_rtx (code, cmp_op_mode, op0, op1));
return gen_rtx (cmov_code, VOIDmode, tem, CONST0_RTX (cmp_op_mode));
}
/* Use ext[wlq][lh] as the Architecture Handbook describes for extracting
unaligned data:
unsigned: signed:
word: ldq_u r1,X(r11) ldq_u r1,X(r11)
ldq_u r2,X+1(r11) ldq_u r2,X+1(r11)
lda r3,X(r11) lda r3,X+2(r11)
extwl r1,r3,r1 extql r1,r3,r1
extwh r2,r3,r2 extqh r2,r3,r2
or r1.r2.r1 or r1,r2,r1
sra r1,48,r1
long: ldq_u r1,X(r11) ldq_u r1,X(r11)
ldq_u r2,X+3(r11) ldq_u r2,X+3(r11)
lda r3,X(r11) lda r3,X(r11)
extll r1,r3,r1 extll r1,r3,r1
extlh r2,r3,r2 extlh r2,r3,r2
or r1.r2.r1 addl r1,r2,r1
quad: ldq_u r1,X(r11)
ldq_u r2,X+7(r11)
lda r3,X(r11)
extql r1,r3,r1
extqh r2,r3,r2
or r1.r2.r1
*/
void
alpha_expand_unaligned_load (tgt, mem, size, ofs, sign)
rtx tgt, mem;
HOST_WIDE_INT size, ofs;
int sign;
{
rtx meml, memh, addr, extl, exth;
meml = gen_reg_rtx (DImode);
memh = gen_reg_rtx (DImode);
addr = gen_reg_rtx (DImode);
extl = gen_reg_rtx (DImode);
exth = gen_reg_rtx (DImode);
emit_move_insn (meml,
change_address (mem, DImode,
gen_rtx (AND, DImode,
plus_constant (XEXP (mem, 0), ofs),
GEN_INT (-8))));
emit_move_insn (memh,
change_address (mem, DImode,
gen_rtx (AND, DImode,
plus_constant (XEXP (mem, 0),
ofs + size - 1),
GEN_INT (-8))));
if (sign && size == 2)
{
emit_move_insn (addr, plus_constant (XEXP (mem, 0), ofs+2));
emit_insn (gen_extxl (extl, meml, GEN_INT (64), addr));
emit_insn (gen_extqh (exth, memh, addr));
expand_binop (DImode, ior_optab, extl, exth, addr, 1, OPTAB_WIDEN);
expand_binop (DImode, ashr_optab, addr, GEN_INT (48), addr,
1, OPTAB_WIDEN);
emit_move_insn (tgt, addr);
return;
}
emit_move_insn (addr, plus_constant (XEXP (mem, 0), ofs));
emit_insn (gen_extxl (extl, meml, GEN_INT (size*8), addr));
switch (size)
{
case 2:
emit_insn (gen_extwh (exth, memh, addr));
break;
case 4:
emit_insn (gen_extlh (exth, memh, addr));
break;
case 8:
emit_insn (gen_extqh (exth, memh, addr));
break;
}
expand_binop (DImode, ior_optab, extl, exth, tgt, sign, OPTAB_WIDEN);
}
/* Similarly, use ins and msk instructions to perform unaligned stores. */
void
alpha_expand_unaligned_store (dst, src, size, ofs)
rtx dst, src;
HOST_WIDE_INT size, ofs;
{
rtx dstl, dsth, addr, insl, insh, meml, memh;
dstl = gen_reg_rtx (DImode);
dsth = gen_reg_rtx (DImode);
insl = gen_reg_rtx (DImode);
insh = gen_reg_rtx (DImode);
meml = change_address (dst, DImode,
gen_rtx (AND, DImode,
plus_constant (XEXP (dst, 0), ofs),
GEN_INT (-8)));
memh = change_address (dst, DImode,
gen_rtx (AND, DImode,
plus_constant (XEXP (dst, 0), ofs+size-1),
GEN_INT (-8)));
emit_move_insn (dsth, memh);
emit_move_insn (dstl, meml);
addr = copy_addr_to_reg (plus_constant (XEXP (dst, 0), ofs));
if (src != const0_rtx)
{
emit_insn (gen_insxh (insh, src, GEN_INT (size*8), addr));
switch (size)
{
case 2:
emit_insn (gen_inswl (insl, gen_lowpart (HImode, src), addr));
break;
case 4:
emit_insn (gen_insll (insl, gen_lowpart (SImode, src), addr));
break;
case 8:
emit_insn (gen_insql (insl, src, addr));
break;
}
}
emit_insn (gen_mskxh (dsth, dsth, GEN_INT (size*8), addr));
switch (size)
{
case 2:
emit_insn (gen_mskxl (dstl, dstl, GEN_INT (0xffff), addr));
break;
case 4:
emit_insn (gen_mskxl (dstl, dstl, GEN_INT (0xffffffff), addr));
break;
case 8:
{
#if HOST_BITS_PER_WIDE_INT == 32
rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
#else
rtx msk = immed_double_const (0xffffffffffffffff, 0, DImode);
#endif
emit_insn (gen_mskxl (dstl, dstl, msk, addr));
}
break;
}
if (src != const0_rtx)
{
expand_binop (DImode, ior_optab, insh, dsth, dsth, 0, OPTAB_WIDEN);
expand_binop (DImode, ior_optab, insl, dstl, dstl, 0, OPTAB_WIDEN);
}
/* Must store high before low for degenerate case of aligned. */
emit_move_insn (memh, dsth);
emit_move_insn (meml, dstl);
}
/* Load an integral number of consecutive unaligned quadwords. */
#define MAX_MOVE_WORDS 4
static void
alpha_expand_unaligned_load_words (data_regs, src_addr, words)
rtx data_regs[MAX_MOVE_WORDS+1];
rtx src_addr;
HOST_WIDE_INT words;
{
rtx const im8 = GEN_INT (-8);
rtx const i64 = GEN_INT (64);
rtx ext_tmps[MAX_MOVE_WORDS];
rtx src_reg, and_reg;
HOST_WIDE_INT i;
/* Generate all the tmp registers we need. */
for (i = 0; i < words; ++i)
ext_tmps[i] = gen_reg_rtx(DImode);
/* Load up all of the source data. */
for (i = 0; i < words; ++i)
{
emit_move_insn (data_regs[i],
change_address (src_addr, DImode,
gen_rtx (AND, DImode,
plus_constant (XEXP(src_addr,0),
8*i),
im8)));
}
emit_move_insn (data_regs[words],
change_address (src_addr, DImode,
gen_rtx (AND, DImode,
plus_constant (XEXP(src_addr,0),
8*words - 1),
im8)));
/* Extract the half-word fragments. Unfortunately DEC decided to make
extxh with offset zero a noop instead of zeroing the register, so
we must take care of that edge condition ourselves with cmov. */
src_reg = copy_addr_to_reg (XEXP (src_addr, 0));
and_reg = expand_binop (DImode, and_optab, src_reg, GEN_INT (7), NULL,
1, OPTAB_WIDEN);
for (i = 0; i < words; ++i)
{
emit_insn (gen_extxl (data_regs[i], data_regs[i], i64, src_reg));
emit_insn (gen_extqh (ext_tmps[i], data_regs[i+1], src_reg));
emit_insn (gen_rtx (SET, VOIDmode, ext_tmps[i],
gen_rtx (IF_THEN_ELSE, DImode,
gen_rtx (EQ, DImode, and_reg, const0_rtx),
const0_rtx, ext_tmps[i])));
}
/* Merge the half-words into whole words. */
for (i = 0; i < words; ++i)
{
expand_binop (DImode, ior_optab, data_regs[i], ext_tmps[i],
data_regs[i], 1, OPTAB_WIDEN);
}
}
/* Store an integral number of consecutive unaligned quadwords. DATA_REGS
may be NULL to store zeros. */
static void
alpha_expand_unaligned_store_words (data_regs, dst_addr, words)
rtx *data_regs;
rtx dst_addr;
HOST_WIDE_INT words;
{
rtx const im8 = GEN_INT (-8);
rtx const i64 = GEN_INT (64);
#if HOST_BITS_PER_WIDE_INT == 32
rtx const im1 = immed_double_const (0xffffffff, 0xffffffff, DImode);
#else
rtx const im1 = immed_double_const (0xffffffffffffffff, 0, DImode);
#endif
rtx ins_tmps[MAX_MOVE_WORDS];
rtx st_tmp_1, st_tmp_2, dst_reg;
rtx st_addr_1, st_addr_2;
HOST_WIDE_INT i;
/* Generate all the tmp registers we need. */
if (data_regs != NULL)
for (i = 0; i < words; ++i)
ins_tmps[i] = gen_reg_rtx(DImode);
st_tmp_1 = gen_reg_rtx(DImode);
st_tmp_2 = gen_reg_rtx(DImode);
st_addr_2 = change_address (dst_addr, DImode,
gen_rtx (AND, DImode,
plus_constant (XEXP(dst_addr,0),
words*8 - 1),
im8));
st_addr_1 = change_address (dst_addr, DImode,
gen_rtx (AND, DImode,
XEXP (dst_addr, 0),
im8));
/* Load up the destination end bits. */
emit_move_insn (st_tmp_2, st_addr_2);
emit_move_insn (st_tmp_1, st_addr_1);
/* Shift the input data into place. */
dst_reg = copy_addr_to_reg (XEXP (dst_addr, 0));
if (data_regs != NULL)
{
for (i = words-1; i >= 0; --i)
{
emit_insn (gen_insxh (ins_tmps[i], data_regs[i], i64, dst_reg));
emit_insn (gen_insql (data_regs[i], data_regs[i], dst_reg));
}
for (i = words-1; i > 0; --i)
{
expand_binop (DImode, ior_optab, data_regs[i], ins_tmps[i-1],
ins_tmps[i-1], 1, OPTAB_WIDEN);
}
}
/* Split and merge the ends with the destination data. */
emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dst_reg));
emit_insn (gen_mskxl (st_tmp_1, st_tmp_1, im1, dst_reg));
if (data_regs != NULL)
{
expand_binop (DImode, ior_optab, st_tmp_2, ins_tmps[words-1],
st_tmp_2, 1, OPTAB_WIDEN);
expand_binop (DImode, ior_optab, st_tmp_1, data_regs[0],
st_tmp_1, 1, OPTAB_WIDEN);
}
/* Store it all. */
emit_move_insn (st_addr_2, st_tmp_2);
for (i = words-1; i > 0; --i)
{
emit_move_insn (change_address (dst_addr, DImode,
gen_rtx (AND, DImode,
plus_constant(XEXP (dst_addr,0),
i*8),
im8)),
data_regs ? ins_tmps[i-1] : const0_rtx);
}
emit_move_insn (st_addr_1, st_tmp_1);
}
/* Expand string/block move operations.
operands[0] is the pointer to the destination.
operands[1] is the pointer to the source.
operands[2] is the number of bytes to move.
operands[3] is the alignment. */
int
alpha_expand_block_move (operands)
rtx operands[];
{
rtx bytes_rtx = operands[2];
rtx align_rtx = operands[3];
HOST_WIDE_INT bytes = INTVAL (bytes_rtx);
HOST_WIDE_INT align = INTVAL (align_rtx);
rtx orig_src = operands[1];
rtx orig_dst = operands[0];
rtx tmp = NULL_RTX;
rtx data_regs[2*MAX_MOVE_WORDS];
HOST_WIDE_INT i, words, ofs = 0;
if (bytes <= 0)
return 1;
if (bytes > MAX_MOVE_WORDS*8)
return 0;
/* Handle a block of contiguous words first. */
if (align >= 8 && bytes >= 8)
{
words = bytes / 8;
/* Make some data registers. */
for (i = 0; i < words; ++i)
data_regs[i] = gen_reg_rtx(DImode);
/* Move in aligned hunks. */
for (i = 0; i < words; ++i)
{
emit_move_insn (data_regs[i],
change_address(orig_src, DImode,
plus_constant (XEXP (orig_src, 0),
i*8)));
}
for (i = 0; i < words; ++i)
{
emit_move_insn (change_address(orig_dst, DImode,
plus_constant (XEXP (orig_dst, 0),
i*8)),
data_regs[i]);
}
bytes -= words * 8;
ofs = words * 8;
}
if (align >= 4 && bytes >= 4)
{
words = bytes / 4;
/* Make some data registers. */
for (i = 0; i < words; ++i)
data_regs[i] = gen_reg_rtx(SImode);
/* Move in aligned hunks. */
for (i = 0; i < words; ++i)
{
emit_move_insn (data_regs[i],
change_address(orig_src, SImode,
plus_constant (XEXP (orig_src, 0),
i*4)));
}
for (i = 0; i < words; ++i)
{
emit_move_insn (change_address(orig_dst, SImode,
plus_constant (XEXP (orig_dst, 0),
i*4)),
data_regs[i]);
}
bytes -= words * 4;
ofs = words * 4;
}
if (bytes >= 16)
{
words = bytes / 8;
/* Make some data registers. */
for (i = 0; i < words+1; ++i)
data_regs[i] = gen_reg_rtx(DImode);
/* Move in unaligned hunks. */
alpha_expand_unaligned_load_words (data_regs, orig_src, words);
alpha_expand_unaligned_store_words (data_regs, orig_dst, words);
bytes -= words * 8;
ofs = words * 8;
}
/* Next clean up any trailing pieces. We know from the contiguous
block move that there are no aligned SImode or DImode hunks left. */
if (!TARGET_BWX && bytes >= 8)
{
tmp = gen_reg_rtx (DImode);
alpha_expand_unaligned_load (tmp, orig_src, 8, ofs, 0);
alpha_expand_unaligned_store (orig_dst, tmp, 8, ofs);
bytes -= 8;
ofs += 8;
}
if (!TARGET_BWX && bytes >= 4)
{
tmp = gen_reg_rtx (DImode);
alpha_expand_unaligned_load (tmp, orig_src, 4, ofs, 0);
alpha_expand_unaligned_store (orig_dst, tmp, 4, ofs);
bytes -= 4;
ofs += 4;
}
if (bytes >= 2)
{
if (align >= 2)
{
do {
emit_move_insn (change_address (orig_dst, HImode,
plus_constant (XEXP (orig_dst, 0),
ofs)),
change_address (orig_src, HImode,
plus_constant (XEXP (orig_src, 0),
ofs)));
bytes -= 2;
ofs += 2;
} while (bytes >= 2);
}
else if (!TARGET_BWX)
{
tmp = gen_reg_rtx (DImode);
alpha_expand_unaligned_load (tmp, orig_src, 2, ofs, 0);
alpha_expand_unaligned_store (orig_dst, tmp, 2, ofs);
bytes -= 2;
ofs += 2;
}
}
while (bytes > 0)
{
emit_move_insn (change_address (orig_dst, QImode,
plus_constant (XEXP (orig_dst, 0),
ofs)),
change_address (orig_src, QImode,
plus_constant (XEXP (orig_src, 0),
ofs)));
bytes -= 1;
ofs += 1;
}
return 1;
}
int
alpha_expand_block_clear (operands)
rtx operands[];
{
rtx bytes_rtx = operands[1];
rtx align_rtx = operands[2];
HOST_WIDE_INT bytes = INTVAL (bytes_rtx);
HOST_WIDE_INT align = INTVAL (align_rtx);
rtx orig_dst = operands[0];
HOST_WIDE_INT i, words, ofs = 0;
if (bytes <= 0)
return 1;
if (bytes > MAX_MOVE_WORDS*8)
return 0;
/* Handle a block of contiguous words first. */
if (align >= 8 && bytes >= 8)
{
words = bytes / 8;
for (i = 0; i < words; ++i)
{
emit_move_insn (change_address(orig_dst, DImode,
plus_constant (XEXP (orig_dst, 0),
i*8)),
const0_rtx);
}
bytes -= words * 8;
ofs = words * 8;
}
else if (align >= 4 && bytes >= 4)
{
words = bytes / 4;
for (i = 0; i < words; ++i)
{
emit_move_insn (change_address(orig_dst, SImode,
plus_constant (XEXP (orig_dst, 0),
i*4)),
const0_rtx);
}
bytes -= words * 4;
ofs = words * 4;
}
else if (bytes >= 16)
{
words = bytes / 8;
alpha_expand_unaligned_store_words (NULL, orig_dst, words);
bytes -= words * 8;
ofs = words * 8;
}
/* Next clean up any trailing pieces. We know from the contiguous
block move that there are no aligned SImode or DImode hunks left. */
if (!TARGET_BWX && bytes >= 8)
{
alpha_expand_unaligned_store (orig_dst, const0_rtx, 8, ofs);
bytes -= 8;
ofs += 8;
}
if (!TARGET_BWX && bytes >= 4)
{
alpha_expand_unaligned_store (orig_dst, const0_rtx, 4, ofs);
bytes -= 4;
ofs += 4;
}
if (bytes >= 2)
{
if (align >= 2)
{
do {
emit_move_insn (change_address (orig_dst, HImode,
plus_constant (XEXP (orig_dst, 0),
ofs)),
const0_rtx);
bytes -= 2;
ofs += 2;
} while (bytes >= 2);
}
else if (!TARGET_BWX)
{
alpha_expand_unaligned_store (orig_dst, const0_rtx, 2, ofs);
bytes -= 2;
ofs += 2;
}
}
while (bytes > 0)
{
emit_move_insn (change_address (orig_dst, QImode,
plus_constant (XEXP (orig_dst, 0),
ofs)),
const0_rtx);
bytes -= 1;
ofs += 1;
}
return 1;
}
/* Adjust the cost of a scheduling dependency. Return the new cost of
a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
@ -1667,13 +2255,17 @@ print_operand (file, x, code)
break;
case 'M':
/* 'b', 'w', or 'l' as the value of the constant. */
/* 'b', 'w', 'l', or 'q' as the value of the constant. */
if (GET_CODE (x) != CONST_INT
|| (INTVAL (x) != 8 && INTVAL (x) != 16 && INTVAL (x) != 32))
|| (INTVAL (x) != 8 && INTVAL (x) != 16
&& INTVAL (x) != 32 && INTVAL (x) != 64))
output_operand_lossage ("invalid %%M value");
fprintf (file, "%s",
INTVAL (x) == 8 ? "b" : INTVAL (x) == 16 ? "w" : "l");
(INTVAL (x) == 8 ? "b"
: INTVAL (x) == 16 ? "w"
: INTVAL (x) == 32 ? "l"
: "q"));
break;
case 'U':
@ -1687,9 +2279,19 @@ print_operand (file, x, code)
&& CONST_DOUBLE_HIGH (x) == 0
&& CONST_DOUBLE_LOW (x) == -1)
fprintf (file, "l");
else if (GET_CODE (x) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (x) == -1
&& CONST_DOUBLE_LOW (x) == -1)
fprintf (file, "q");
#else
else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff)
fprintf (file, "l");
else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffffffffffff)
fprintf (file, "q");
else if (GET_CODE (x) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (x) == 0
&& CONST_DOUBLE_LOW (x) == -1)
fprintf (file, "q");
#endif
else
output_operand_lossage ("invalid %%U value");

View File

@ -384,18 +384,22 @@ extern void override_options ();
??? Kludge this and the next macro for the moment by not doing anything if
we don't optimize and also if we are writing ECOFF symbols to work around
a bug in DEC's assembler. */
/* Aligning past 2**3 wastes insn cache lines, and doesn't buy much
issue-wise on average anyway. */
#define ASM_OUTPUT_LOOP_ALIGN(FILE) \
if (optimize > 0 && write_symbols != SDB_DEBUG) \
ASM_OUTPUT_ALIGN (FILE, 5)
ASM_OUTPUT_ALIGN (FILE, 3)
/* This is how to align an instruction for optimal branching.
On Alpha we'll get better performance by aligning on a quadword
boundary. */
/* Aligning past 2**3 wastes insn cache lines, and doesn't buy much
issue-wise on average anyway. */
#define ASM_OUTPUT_ALIGN_CODE(FILE) \
if (optimize > 0 && write_symbols != SDB_DEBUG) \
ASM_OUTPUT_ALIGN ((FILE), 4)
ASM_OUTPUT_ALIGN ((FILE), 3)
/* No data type wants to be aligned rounder than this. */
#define BIGGEST_ALIGNMENT 64
@ -406,8 +410,12 @@ extern void override_options ();
/* Align all constants and variables to at least a word boundary so
we can pick up pieces of them faster. */
/* ??? Only if block-move stuff knows about different source/destination
alignment. */
#if 0
#define CONSTANT_ALIGNMENT(EXP, ALIGN) MAX ((ALIGN), BITS_PER_WORD)
#define DATA_ALIGNMENT(EXP, ALIGN) MAX ((ALIGN), BITS_PER_WORD)
#endif
/* Set this non-zero if move instructions will actually fail to work
when given unaligned data.
@ -1509,6 +1517,12 @@ extern void alpha_init_expanders ();
#define MOVE_MAX 8
/* Controls how many units are moved by expr.c before resorting to movstr.
Without byte/word accesses, we want no more than one; with, several single
byte accesses are better. */
#define MOVE_RATIO (TARGET_BWX ? 7 : 2)
/* Largest number of bytes of an object that can be placed in a register.
On the Alpha we have plenty of registers, so use TImode. */
#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TImode)

View File

@ -1431,7 +1431,7 @@
"ext%M2l %r1,%s3,%0"
[(set_attr "type" "shift")])
(define_insn ""
(define_insn "extxl"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
(match_operand:DI 2 "mode_width_operand" "n")
@ -1441,7 +1441,7 @@
"ext%M2l %r1,%3,%0"
[(set_attr "type" "shift")])
(define_insn ""
(define_insn "extqh"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI
(match_operand:DI 1 "reg_or_0_operand" "rJ")
@ -1456,7 +1456,7 @@
"extqh %r1,%2,%0"
[(set_attr "type" "shift")])
(define_insn ""
(define_insn "extlh"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI
(and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
@ -1472,7 +1472,7 @@
"extlh %r1,%2,%0"
[(set_attr "type" "shift")])
(define_insn ""
(define_insn "extwh"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI
(and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
@ -1538,7 +1538,7 @@
"insll %1,%s2,%0"
[(set_attr "type" "shift")])
(define_insn ""
(define_insn "insbl"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "r"))
(ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
@ -1547,7 +1547,7 @@
"insbl %1,%2,%0"
[(set_attr "type" "shift")])
(define_insn ""
(define_insn "inswl"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "r"))
(ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
@ -1556,7 +1556,7 @@
"inswl %1,%2,%0"
[(set_attr "type" "shift")])
(define_insn ""
(define_insn "insll"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
(ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
@ -1565,10 +1565,30 @@
"insll %1,%2,%0"
[(set_attr "type" "shift")])
(define_insn "insql"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (match_operand:DI 1 "register_operand" "r")
(ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
(const_int 3))))]
""
"insql %1,%2,%0"
[(set_attr "type" "shift")])
;; We do not include the insXh insns because they are complex to express
;; and it does not appear that we would ever want to generate them.
;;
;; Since we need them for block moves, though, cop out and use unspec.
(define_insn ""
(define_insn "insxh"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec [(match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "mode_width_operand" "n")
(match_operand:DI 3 "reg_or_8bit_operand" "rI")] 2))]
""
"ins%M2h %1,%3,%0"
[(set_attr "type" "shift")])
(define_insn "mskxl"
[(set (match_operand:DI 0 "register_operand" "=r")
(and:DI (not:DI (ashift:DI
(match_operand:DI 2 "mode_mask_operand" "n")
@ -1580,8 +1600,19 @@
"msk%U2l %r1,%3,%0"
[(set_attr "type" "shift")])
;; We do not include the mskXh insns because it does not appear we would ever
;; generate one.
;; We do not include the mskXh insns because it does not appear we would
;; ever generate one.
;;
;; Again, we do for block moves and we use unspec again.
(define_insn "mskxh"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec [(match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "mode_width_operand" "n")
(match_operand:DI 3 "reg_or_8bit_operand" "rI")] 3))]
""
"msk%M2h %1,%3,%0"
[(set_attr "type" "shift")])
;; Floating-point operations. All the double-precision insns can extend
;; from single, so indicate that. The exception are the ones that simply
@ -4781,6 +4812,122 @@
DONE;
}")
;; Bit field extract patterns which use ext[wlq][lh]
(define_expand "extv"
[(set (match_operand:DI 0 "register_operand" "")
(sign_extract:DI (match_operand:QI 1 "memory_operand" "")
(match_operand:DI 2 "immediate_operand" "")
(match_operand:DI 3 "immediate_operand" "")))]
""
"
{
/* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries. */
if (INTVAL (operands[3]) % 8 != 0
|| (INTVAL (operands[2]) != 16
&& INTVAL (operands[2]) != 32
&& INTVAL (operands[2]) != 64))
FAIL;
/* From mips.md: extract_bit_field doesn't verify that our source
matches the predicate, so we force it to be a MEM here. */
if (GET_CODE (operands[1]) != MEM)
FAIL;
alpha_expand_unaligned_load (operands[0], operands[1],
INTVAL (operands[2]) / 8,
INTVAL (operands[3]) / 8, 1);
DONE;
}")
(define_expand "extzv"
[(set (match_operand:DI 0 "register_operand" "")
(zero_extract:DI (match_operand:QI 1 "memory_operand" "")
(match_operand:DI 2 "immediate_operand" "")
(match_operand:DI 3 "immediate_operand" "")))]
""
"
{
/* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries. */
if (INTVAL (operands[3]) % 8 != 0
|| (INTVAL (operands[2]) != 16
&& INTVAL (operands[2]) != 32
&& INTVAL (operands[2]) != 64))
FAIL;
/* From mips.md: extract_bit_field doesn't verify that our source
matches the predicate, so we force it to be a MEM here. */
if (GET_CODE (operands[1]) != MEM)
FAIL;
alpha_expand_unaligned_load (operands[0], operands[1],
INTVAL (operands[2]) / 8,
INTVAL (operands[3]) / 8, 0);
DONE;
}")
(define_expand "insv"
[(set (zero_extract:DI (match_operand:QI 0 "memory_operand" "")
(match_operand:DI 1 "immediate_operand" "")
(match_operand:DI 2 "immediate_operand" ""))
(match_operand:DI 3 "register_operand" ""))]
""
"
{
/* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries. */
if (INTVAL (operands[2]) % 8 != 0
|| (INTVAL (operands[1]) != 16
&& INTVAL (operands[1]) != 32
&& INTVAL (operands[1]) != 64))
FAIL;
/* From mips.md: store_bit_field doesn't verify that our source
matches the predicate, so we force it to be a MEM here. */
if (GET_CODE (operands[0]) != MEM)
FAIL;
alpha_expand_unaligned_store (operands[0], operands[3],
INTVAL (operands[1]) / 8,
INTVAL (operands[2]) / 8);
DONE;
}")
;; Block move/clear, see alpha.c for more details.
;; Argument 0 is the destination
;; Argument 1 is the source
;; Argument 2 is the length
;; Argument 3 is the alignment
(define_expand "movstrqi"
[(parallel [(set (match_operand:BLK 0 "general_operand" "")
(match_operand:BLK 1 "general_operand" ""))
(use (match_operand:DI 2 "immediate_operand" ""))
(use (match_operand:DI 3 "immediate_operand" ""))])]
""
"
{
if (alpha_expand_block_move (operands))
DONE;
else
FAIL;
}")
(define_expand "clrstrqi"
[(parallel [(set (match_operand:BLK 0 "general_operand" "")
(const_int 0))
(use (match_operand:DI 1 "immediate_operand" ""))
(use (match_operand:DI 2 "immediate_operand" ""))])]
""
"
{
if (alpha_expand_block_clear (operands))
DONE;
else
FAIL;
}")
;; Subroutine of stack space allocation. Perform a stack probe.
(define_expand "probe_stack"
[(set (match_dup 1) (match_operand:DI 0 "const_int_operand" ""))]

View File

@ -9036,7 +9036,7 @@ expand_builtin (exp, target, subtarget, mode, ignore)
|| (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
!= INTEGER_TYPE)
|| TREE_CHAIN (TREE_CHAIN (arglist)) == 0
|| (INTEGER_CST
|| (INTEGER_TYPE
!= (TREE_CODE (TREE_TYPE
(TREE_VALUE
(TREE_CHAIN (TREE_CHAIN (arglist))))))))
@ -9061,11 +9061,16 @@ expand_builtin (exp, target, subtarget, mode, ignore)
if (expand_expr (val, NULL_RTX, VOIDmode, 0) != const0_rtx)
break;
/* If LEN does not expand to a constant, don't do this
operation in-line. */
len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
if (GET_CODE (len_rtx) != CONST_INT)
break;
dest_rtx = expand_expr (dest, NULL_RTX, ptr_mode, EXPAND_SUM);
dest_mem = gen_rtx (MEM, BLKmode,
memory_address (BLKmode, dest_rtx));
len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
/* Just check DST is writable and mark it as readable. */
if (flag_check_memory_usage)
emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
@ -9074,7 +9079,6 @@ expand_builtin (exp, target, subtarget, mode, ignore)
GEN_INT (MEMORY_USE_WO),
TYPE_MODE (integer_type_node));
/* There could be a void* cast on top of the object. */
while (TREE_CODE (dest) == NOP_EXPR)
dest = TREE_OPERAND (dest, 0);