builtins.c: (expand_builtin_memset): Rewrite to support 'set_storage_via_setmem'.
2006-06-28 Adrian Straetling <straetling@de.ibm.com> * builtins.c: (expand_builtin_memset): Rewrite to support 'set_storage_via_setmem'. * expr.c: (enum insn_code setmem_optab): Define. (enum insn_code clrmem_optab): Remove. (set_storage_via_setmem): New function. (clear_storage_via_setmem): Remove. (clear_storage): Replace call to "clear_storage_via_clrmem" with "set_storage_via_setmem". * expr.h: (set_storage_via_setmem): Declare. (CLEAR_RATIO): Redefine using HAVE_setmemM. * optabs.h: (enum insn_code setmem_optab): Declare. (enum insn_code clrmem_optab): Remove. * optabs.c: (init_optabs): Initialize setmem_optab. (enum insn_code clrmem_optab): Remove. * genopinit.c: (otabs): Likewise. * doc/md.texi: Document new standard pattern 'setmem'. Remove 'clrmem'. * config/alpha/alpha.c: (alpha_expand_block_clear): Adjust 'operands' ordering. * config/frv/frv.c: (frv_expand_block_clear): Likewise. * config/rs6000/rs6000.c: (expand_block_clear): Likewise. * config/alpha/alpha.md: ("clrmemqi", "clrmemdi"): Rename to "setmemM". FAIL on operands[2]!=const0_rtx. Adjust 'operands' ordering. * config/avr/avr.md: ("clrmemhi"): Likewise. * config/frv/frv.md: ("clrmemsi"): Likewise. * config/i386/i386.md: ("clrmemsi", "clrmemdi"): Likewise. * config/pa/pa.md: ("clrmemsi", "clrmemdi"): Likewise. * config/rs6000/rs6000.md: ("clrmemsi"): Likewise. * config/s390/s390.md: ("clrmem<mode>"): Likewise. From-SVN: r101386
This commit is contained in:
parent
617a1b7144
commit
57e84f1840
@ -1,3 +1,35 @@
|
||||
2006-06-28 Adrian Straetling <straetling@de.ibm.com>
|
||||
|
||||
* builtins.c: (expand_builtin_memset): Rewrite to support
|
||||
'set_storage_via_setmem'.
|
||||
* expr.c: (enum insn_code setmem_optab): Define.
|
||||
(enum insn_code clrmem_optab): Remove.
|
||||
(set_storage_via_setmem): New function.
|
||||
(clear_storage_via_setmem): Remove.
|
||||
(clear_storage): Replace call to "clear_storage_via_clrmem" with
|
||||
"set_storage_via_setmem".
|
||||
* expr.h: (set_storage_via_setmem): Declare.
|
||||
(CLEAR_RATIO): Redefine using HAVE_setmemM.
|
||||
* optabs.h: (enum insn_code setmem_optab): Declare.
|
||||
(enum insn_code clrmem_optab): Remove.
|
||||
* optabs.c: (init_optabs): Initialize setmem_optab.
|
||||
(enum insn_code clrmem_optab): Remove.
|
||||
* genopinit.c: (otabs): Likewise.
|
||||
* doc/md.texi: Document new standard pattern 'setmem'. Remove
|
||||
'clrmem'.
|
||||
* config/alpha/alpha.c: (alpha_expand_block_clear): Adjust
|
||||
'operands' ordering.
|
||||
* config/frv/frv.c: (frv_expand_block_clear): Likewise.
|
||||
* config/rs6000/rs6000.c: (expand_block_clear): Likewise.
|
||||
* config/alpha/alpha.md: ("clrmemqi", "clrmemdi"): Rename to "setmemM".
|
||||
FAIL on operands[2]!=const0_rtx. Adjust 'operands' ordering.
|
||||
* config/avr/avr.md: ("clrmemhi"): Likewise.
|
||||
* config/frv/frv.md: ("clrmemsi"): Likewise.
|
||||
* config/i386/i386.md: ("clrmemsi", "clrmemdi"): Likewise.
|
||||
* config/pa/pa.md: ("clrmemsi", "clrmemdi"): Likewise.
|
||||
* config/rs6000/rs6000.md: ("clrmemsi"): Likewise.
|
||||
* config/s390/s390.md: ("clrmem<mode>"): Likewise.
|
||||
|
||||
2005-06-28 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* Makefile.in: Set and use UNWIND_H. Install as unwind.h.
|
||||
|
@ -3335,33 +3335,34 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
|
||||
return expand_expr (dest, target, mode, EXPAND_NORMAL);
|
||||
}
|
||||
|
||||
len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
|
||||
dest_mem = get_memory_rtx (dest);
|
||||
|
||||
if (TREE_CODE (val) != INTEGER_CST)
|
||||
{
|
||||
rtx val_rtx;
|
||||
|
||||
if (!host_integerp (len, 1))
|
||||
return 0;
|
||||
|
||||
if (optimize_size && tree_low_cst (len, 1) > 1)
|
||||
return 0;
|
||||
val = fold_build1 (CONVERT_EXPR, unsigned_char_type_node, val);
|
||||
val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
|
||||
|
||||
/* Assume that we can memset by pieces if we can store the
|
||||
* the coefficients by pieces (in the required modes).
|
||||
* We can't pass builtin_memset_gen_str as that emits RTL. */
|
||||
c = 1;
|
||||
if (!can_store_by_pieces (tree_low_cst (len, 1),
|
||||
builtin_memset_read_str,
|
||||
&c, dest_align))
|
||||
if (host_integerp (len, 1)
|
||||
&& !(optimize_size && tree_low_cst (len, 1) > 1)
|
||||
&& can_store_by_pieces (tree_low_cst (len, 1),
|
||||
builtin_memset_read_str, &c, dest_align))
|
||||
{
|
||||
val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
|
||||
val_rtx);
|
||||
store_by_pieces (dest_mem, tree_low_cst (len, 1),
|
||||
builtin_memset_gen_str, val_rtx, dest_align, 0);
|
||||
}
|
||||
else if (!set_storage_via_setmem(dest_mem, len_rtx, val_rtx,
|
||||
dest_align))
|
||||
return 0;
|
||||
|
||||
val = fold_build1 (CONVERT_EXPR, unsigned_char_type_node, val);
|
||||
val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
|
||||
val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
|
||||
val_rtx);
|
||||
dest_mem = get_memory_rtx (dest);
|
||||
store_by_pieces (dest_mem, tree_low_cst (len, 1),
|
||||
builtin_memset_gen_str,
|
||||
val_rtx, dest_align, 0);
|
||||
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
|
||||
dest_mem = convert_memory_address (ptr_mode, dest_mem);
|
||||
return dest_mem;
|
||||
@ -3372,25 +3373,21 @@ expand_builtin_memset (tree arglist, rtx target, enum machine_mode mode,
|
||||
|
||||
if (c)
|
||||
{
|
||||
if (!host_integerp (len, 1))
|
||||
return 0;
|
||||
if (!can_store_by_pieces (tree_low_cst (len, 1),
|
||||
builtin_memset_read_str, &c,
|
||||
dest_align))
|
||||
if (host_integerp (len, 1)
|
||||
&& !(optimize_size && tree_low_cst (len, 1) > 1)
|
||||
&& can_store_by_pieces (tree_low_cst (len, 1),
|
||||
builtin_memset_read_str, &c, dest_align))
|
||||
store_by_pieces (dest_mem, tree_low_cst (len, 1),
|
||||
builtin_memset_read_str, &c, dest_align, 0);
|
||||
else if (!set_storage_via_setmem (dest_mem, len_rtx, GEN_INT (c),
|
||||
dest_align))
|
||||
return 0;
|
||||
|
||||
dest_mem = get_memory_rtx (dest);
|
||||
store_by_pieces (dest_mem, tree_low_cst (len, 1),
|
||||
builtin_memset_read_str,
|
||||
&c, dest_align, 0);
|
||||
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
|
||||
dest_mem = convert_memory_address (ptr_mode, dest_mem);
|
||||
return dest_mem;
|
||||
}
|
||||
|
||||
len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
|
||||
|
||||
dest_mem = get_memory_rtx (dest);
|
||||
set_mem_align (dest_mem, dest_align);
|
||||
dest_addr = clear_storage (dest_mem, len_rtx,
|
||||
CALL_EXPR_TAILCALL (orig_exp)
|
||||
|
@ -4069,7 +4069,7 @@ int
|
||||
alpha_expand_block_clear (rtx operands[])
|
||||
{
|
||||
rtx bytes_rtx = operands[1];
|
||||
rtx align_rtx = operands[2];
|
||||
rtx align_rtx = operands[3];
|
||||
HOST_WIDE_INT orig_bytes = INTVAL (bytes_rtx);
|
||||
HOST_WIDE_INT bytes = orig_bytes;
|
||||
HOST_WIDE_INT align = INTVAL (align_rtx) * BITS_PER_UNIT;
|
||||
|
@ -6552,25 +6552,29 @@
|
||||
[(set_attr "type" "multi")
|
||||
(set_attr "length" "28")])
|
||||
|
||||
(define_expand "clrmemqi"
|
||||
(define_expand "setmemqi"
|
||||
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
|
||||
(const_int 0))
|
||||
(match_operand 2 "const_int_operand" ""))
|
||||
(use (match_operand:DI 1 "immediate_operand" ""))
|
||||
(use (match_operand:DI 2 "immediate_operand" ""))])]
|
||||
(use (match_operand:DI 3 "immediate_operand" ""))])]
|
||||
""
|
||||
{
|
||||
/* If value to set is not zero, use the library routine. */
|
||||
if (operands[2] != const0_rtx)
|
||||
FAIL;
|
||||
|
||||
if (alpha_expand_block_clear (operands))
|
||||
DONE;
|
||||
else
|
||||
FAIL;
|
||||
})
|
||||
|
||||
(define_expand "clrmemdi"
|
||||
(define_expand "setmemdi"
|
||||
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
|
||||
(const_int 0))
|
||||
(match_operand 2 "const_int_operand" ""))
|
||||
(use (match_operand:DI 1 "immediate_operand" ""))
|
||||
(use (match_operand:DI 2 "immediate_operand" ""))
|
||||
(use (match_dup 3))
|
||||
(use (match_operand:DI 3 "immediate_operand" ""))
|
||||
(use (match_dup 4))
|
||||
(clobber (reg:DI 25))
|
||||
(clobber (reg:DI 16))
|
||||
(clobber (reg:DI 17))
|
||||
@ -6578,8 +6582,12 @@
|
||||
(clobber (reg:DI 27))])]
|
||||
"TARGET_ABI_OPEN_VMS"
|
||||
{
|
||||
operands[3] = gen_rtx_SYMBOL_REF (Pmode, "OTS$ZERO");
|
||||
alpha_need_linkage (XSTR (operands[3], 0), 0);
|
||||
/* If value to set is not zero, use the library routine. */
|
||||
if (operands[2] != const0_rtx)
|
||||
FAIL;
|
||||
|
||||
operands[4] = gen_rtx_SYMBOL_REF (Pmode, "OTS$ZERO");
|
||||
alpha_need_linkage (XSTR (operands[4], 0), 0);
|
||||
})
|
||||
|
||||
(define_insn "*clrmemdi_1"
|
||||
|
@ -410,28 +410,32 @@
|
||||
DONE;
|
||||
}")
|
||||
|
||||
;; =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0 =0
|
||||
;; memset (%0, 0, %1)
|
||||
;; =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2 =%2
|
||||
;; memset (%0, %2, %1)
|
||||
|
||||
(define_expand "clrmemhi"
|
||||
(define_expand "setmemhi"
|
||||
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
|
||||
(const_int 0))
|
||||
(match_operand 2 "const_int_operand" ""))
|
||||
(use (match_operand:HI 1 "const_int_operand" ""))
|
||||
(use (match_operand:HI 2 "const_int_operand" "n"))
|
||||
(clobber (match_scratch:HI 3 ""))
|
||||
(clobber (match_dup 4))])]
|
||||
(use (match_operand:HI 3 "const_int_operand" "n"))
|
||||
(clobber (match_scratch:HI 4 ""))
|
||||
(clobber (match_dup 5))])]
|
||||
""
|
||||
"{
|
||||
rtx addr0;
|
||||
int cnt8;
|
||||
enum machine_mode mode;
|
||||
|
||||
/* If value to set is not zero, use the library routine. */
|
||||
if (operands[2] != const0_rtx)
|
||||
FAIL;
|
||||
|
||||
if (GET_CODE (operands[1]) != CONST_INT)
|
||||
FAIL;
|
||||
|
||||
cnt8 = byte_immediate_operand (operands[1], GET_MODE (operands[1]));
|
||||
mode = cnt8 ? QImode : HImode;
|
||||
operands[4] = gen_rtx_SCRATCH (mode);
|
||||
operands[5] = gen_rtx_SCRATCH (mode);
|
||||
operands[1] = copy_to_mode_reg (mode,
|
||||
gen_int_mode (INTVAL (operands[1]), mode));
|
||||
addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
|
||||
|
@ -2298,14 +2298,14 @@ frv_expand_block_move (rtx operands[])
|
||||
|
||||
operands[0] is the destination
|
||||
operands[1] is the length
|
||||
operands[2] is the alignment */
|
||||
operands[3] is the alignment */
|
||||
|
||||
int
|
||||
frv_expand_block_clear (rtx operands[])
|
||||
{
|
||||
rtx orig_dest = operands[0];
|
||||
rtx bytes_rtx = operands[1];
|
||||
rtx align_rtx = operands[2];
|
||||
rtx align_rtx = operands[3];
|
||||
int constp = (GET_CODE (bytes_rtx) == CONST_INT);
|
||||
int align;
|
||||
int bytes;
|
||||
|
@ -2139,19 +2139,24 @@
|
||||
FAIL;
|
||||
}")
|
||||
|
||||
;; String/block clear insn.
|
||||
;; String/block set insn.
|
||||
;; Argument 0 is the destination
|
||||
;; Argument 1 is the length
|
||||
;; Argument 2 is the alignment
|
||||
;; Argument 2 is the byte value -- ignore any value but zero
|
||||
;; Argument 3 is the alignment
|
||||
|
||||
(define_expand "clrmemsi"
|
||||
(define_expand "setmemsi"
|
||||
[(parallel [(set (match_operand:BLK 0 "" "")
|
||||
(const_int 0))
|
||||
(match_operand 2 "" ""))
|
||||
(use (match_operand:SI 1 "" ""))
|
||||
(use (match_operand:SI 2 "" ""))])]
|
||||
(use (match_operand:SI 3 "" ""))])]
|
||||
""
|
||||
"
|
||||
{
|
||||
/* If value to set is not zero, use the library routine. */
|
||||
if (operands[2] != const0_rtx)
|
||||
FAIL;
|
||||
|
||||
if (frv_expand_block_clear (operands))
|
||||
DONE;
|
||||
else
|
||||
|
@ -17182,25 +17182,35 @@
|
||||
(set_attr "memory" "both")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
(define_expand "clrmemsi"
|
||||
(define_expand "setmemsi"
|
||||
[(use (match_operand:BLK 0 "memory_operand" ""))
|
||||
(use (match_operand:SI 1 "nonmemory_operand" ""))
|
||||
(use (match_operand 2 "const_int_operand" ""))]
|
||||
(use (match_operand 2 "const_int_operand" ""))
|
||||
(use (match_operand 3 "const_int_operand" ""))]
|
||||
""
|
||||
{
|
||||
if (ix86_expand_clrmem (operands[0], operands[1], operands[2]))
|
||||
/* If value to set is not zero, use the library routine. */
|
||||
if (operands[2] != const0_rtx)
|
||||
FAIL;
|
||||
|
||||
if (ix86_expand_clrmem (operands[0], operands[1], operands[3]))
|
||||
DONE;
|
||||
else
|
||||
FAIL;
|
||||
})
|
||||
|
||||
(define_expand "clrmemdi"
|
||||
(define_expand "setmemdi"
|
||||
[(use (match_operand:BLK 0 "memory_operand" ""))
|
||||
(use (match_operand:DI 1 "nonmemory_operand" ""))
|
||||
(use (match_operand 2 "const_int_operand" ""))]
|
||||
(use (match_operand 2 "const_int_operand" ""))
|
||||
(use (match_operand 3 "const_int_operand" ""))]
|
||||
"TARGET_64BIT"
|
||||
{
|
||||
if (ix86_expand_clrmem (operands[0], operands[1], operands[2]))
|
||||
/* If value to set is not zero, use the library routine. */
|
||||
if (operands[2] != const0_rtx)
|
||||
FAIL;
|
||||
|
||||
if (ix86_expand_clrmem (operands[0], operands[1], operands[3]))
|
||||
DONE;
|
||||
else
|
||||
FAIL;
|
||||
|
@ -3518,24 +3518,28 @@
|
||||
"* return output_block_move (operands, !which_alternative);"
|
||||
[(set_attr "type" "multi,multi")])
|
||||
|
||||
(define_expand "clrmemsi"
|
||||
(define_expand "setmemsi"
|
||||
[(parallel [(set (match_operand:BLK 0 "" "")
|
||||
(const_int 0))
|
||||
(clobber (match_dup 3))
|
||||
(match_operand 2 "const_int_operand" ""))
|
||||
(clobber (match_dup 4))
|
||||
(clobber (match_dup 5))
|
||||
(use (match_operand:SI 1 "arith_operand" ""))
|
||||
(use (match_operand:SI 2 "const_int_operand" ""))])]
|
||||
(use (match_operand:SI 3 "const_int_operand" ""))])]
|
||||
"!TARGET_64BIT && optimize > 0"
|
||||
"
|
||||
{
|
||||
int size, align;
|
||||
|
||||
/* If value to set is not zero, use the library routine. */
|
||||
if (operands[2] != const0_rtx)
|
||||
FAIL;
|
||||
|
||||
/* Undetermined size, use the library routine. */
|
||||
if (GET_CODE (operands[1]) != CONST_INT)
|
||||
FAIL;
|
||||
|
||||
size = INTVAL (operands[1]);
|
||||
align = INTVAL (operands[2]);
|
||||
align = INTVAL (operands[3]);
|
||||
align = align > 4 ? 4 : align;
|
||||
|
||||
/* If size/alignment is large, then use the library routines. */
|
||||
@ -3550,8 +3554,8 @@
|
||||
operands[0]
|
||||
= replace_equiv_address (operands[0],
|
||||
copy_to_mode_reg (SImode, XEXP (operands[0], 0)));
|
||||
operands[3] = gen_reg_rtx (SImode);
|
||||
operands[4] = gen_reg_rtx (SImode);
|
||||
operands[5] = gen_reg_rtx (SImode);
|
||||
}")
|
||||
|
||||
(define_insn "clrmemsi_prereload"
|
||||
@ -3628,24 +3632,28 @@
|
||||
"* return output_block_clear (operands, !which_alternative);"
|
||||
[(set_attr "type" "multi,multi")])
|
||||
|
||||
(define_expand "clrmemdi"
|
||||
(define_expand "setmemdi"
|
||||
[(parallel [(set (match_operand:BLK 0 "" "")
|
||||
(const_int 0))
|
||||
(clobber (match_dup 3))
|
||||
(match_operand 2 "const_int_operand" ""))
|
||||
(clobber (match_dup 4))
|
||||
(clobber (match_dup 5))
|
||||
(use (match_operand:DI 1 "arith_operand" ""))
|
||||
(use (match_operand:DI 2 "const_int_operand" ""))])]
|
||||
(use (match_operand:DI 3 "const_int_operand" ""))])]
|
||||
"TARGET_64BIT && optimize > 0"
|
||||
"
|
||||
{
|
||||
int size, align;
|
||||
|
||||
/* If value to set is not zero, use the library routine. */
|
||||
if (operands[2] != const0_rtx)
|
||||
FAIL;
|
||||
|
||||
/* Undetermined size, use the library routine. */
|
||||
if (GET_CODE (operands[1]) != CONST_INT)
|
||||
FAIL;
|
||||
|
||||
size = INTVAL (operands[1]);
|
||||
align = INTVAL (operands[2]);
|
||||
align = INTVAL (operands[3]);
|
||||
align = align > 8 ? 8 : align;
|
||||
|
||||
/* If size/alignment is large, then use the library routines. */
|
||||
@ -3660,8 +3668,8 @@
|
||||
operands[0]
|
||||
= replace_equiv_address (operands[0],
|
||||
copy_to_mode_reg (DImode, XEXP (operands[0], 0)));
|
||||
operands[3] = gen_reg_rtx (DImode);
|
||||
operands[4] = gen_reg_rtx (DImode);
|
||||
operands[5] = gen_reg_rtx (DImode);
|
||||
}")
|
||||
|
||||
(define_insn "clrmemdi_prereload"
|
||||
|
@ -8588,14 +8588,14 @@ rs6000_init_libfuncs (void)
|
||||
|
||||
operands[0] is the destination
|
||||
operands[1] is the length
|
||||
operands[2] is the alignment */
|
||||
operands[3] is the alignment */
|
||||
|
||||
int
|
||||
expand_block_clear (rtx operands[])
|
||||
{
|
||||
rtx orig_dest = operands[0];
|
||||
rtx bytes_rtx = operands[1];
|
||||
rtx align_rtx = operands[2];
|
||||
rtx align_rtx = operands[3];
|
||||
bool constp = (GET_CODE (bytes_rtx) == CONST_INT);
|
||||
HOST_WIDE_INT align;
|
||||
HOST_WIDE_INT bytes;
|
||||
|
@ -8613,14 +8613,18 @@
|
||||
"{stsi|stswi} %2,%1,%O0"
|
||||
[(set_attr "type" "store")])
|
||||
|
||||
(define_expand "clrmemsi"
|
||||
(define_expand "setmemsi"
|
||||
[(parallel [(set (match_operand:BLK 0 "" "")
|
||||
(const_int 0))
|
||||
(match_operand 2 "const_int_operand" "" ""))
|
||||
(use (match_operand:SI 1 "" ""))
|
||||
(use (match_operand:SI 2 "" ""))])]
|
||||
(use (match_operand:SI 3 "" ""))])]
|
||||
""
|
||||
"
|
||||
{
|
||||
/* If value to set is not zero, use the library routine. */
|
||||
if (operand[2] != const0_rtx)
|
||||
FAIL;
|
||||
|
||||
if (expand_block_clear (operands))
|
||||
DONE;
|
||||
else
|
||||
|
@ -1919,16 +1919,23 @@
|
||||
(set_attr "type" "vs")])
|
||||
|
||||
;
|
||||
; clrmemM instruction pattern(s).
|
||||
; setmemM instruction pattern(s).
|
||||
;
|
||||
|
||||
(define_expand "clrmem<mode>"
|
||||
(define_expand "setmem<mode>"
|
||||
[(set (match_operand:BLK 0 "memory_operand" "")
|
||||
(const_int 0))
|
||||
(match_operand 2 "const_int_operand" ""))
|
||||
(use (match_operand:GPR 1 "general_operand" ""))
|
||||
(match_operand 2 "" "")]
|
||||
(match_operand 3 "" "")]
|
||||
""
|
||||
"s390_expand_clrmem (operands[0], operands[1]); DONE;")
|
||||
{
|
||||
/* If value to set is not zero, use the library routine. */
|
||||
if (operands[2] != const0_rtx)
|
||||
FAIL;
|
||||
|
||||
s390_expand_clrmem (operands[0], operands[1]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
; Clear a block that is up to 256 bytes in length.
|
||||
; The block length is taken as (operands[1] % 256) + 1.
|
||||
|
@ -3253,19 +3253,21 @@ destination and source strings are operands 1 and 2, and both are
|
||||
the expansion of this pattern should store in operand 0 the address in
|
||||
which the @code{NUL} terminator was stored in the destination string.
|
||||
|
||||
@cindex @code{clrmem@var{m}} instruction pattern
|
||||
@item @samp{clrmem@var{m}}
|
||||
Block clear instruction. The destination string is the first operand,
|
||||
@cindex @code{setmem@var{m}} instruction pattern
|
||||
@item @samp{setmem@var{m}}
|
||||
Block set instruction. The destination string is the first operand,
|
||||
given as a @code{mem:BLK} whose address is in mode @code{Pmode}. The
|
||||
number of bytes to clear is the second operand, in mode @var{m}. See
|
||||
number of bytes to set is the second operand, in mode @var{m}. The value to
|
||||
initialize the memory with is the third operand. Targets that only support the
|
||||
clearing of memory should reject any value that is not the constant 0. See
|
||||
@samp{movmem@var{m}} for a discussion of the choice of mode.
|
||||
|
||||
The third operand is the known alignment of the destination, in the form
|
||||
The fourth operand is the known alignment of the destination, in the form
|
||||
of a @code{const_int} rtx. Thus, if the compiler knows that the
|
||||
destination is word-aligned, it may provide the value 4 for this
|
||||
operand.
|
||||
|
||||
The use for multiple @code{clrmem@var{m}} is as for @code{movmem@var{m}}.
|
||||
The use for multiple @code{setmem@var{m}} is as for @code{movmem@var{m}}.
|
||||
|
||||
@cindex @code{cmpstr@var{m}} instruction pattern
|
||||
@item @samp{cmpstr@var{m}}
|
||||
|
124
gcc/expr.c
124
gcc/expr.c
@ -134,7 +134,6 @@ static void clear_by_pieces (rtx, unsigned HOST_WIDE_INT, unsigned int);
|
||||
static void store_by_pieces_1 (struct store_by_pieces *, unsigned int);
|
||||
static void store_by_pieces_2 (rtx (*) (rtx, ...), enum machine_mode,
|
||||
struct store_by_pieces *);
|
||||
static bool clear_storage_via_clrmem (rtx, rtx, unsigned);
|
||||
static rtx clear_storage_via_libcall (rtx, rtx, bool);
|
||||
static tree clear_storage_libcall_fn (int);
|
||||
static rtx compress_float_constant (rtx, rtx);
|
||||
@ -200,8 +199,8 @@ static bool float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
|
||||
/* This array records the insn_code of insns to perform block moves. */
|
||||
enum insn_code movmem_optab[NUM_MACHINE_MODES];
|
||||
|
||||
/* This array records the insn_code of insns to perform block clears. */
|
||||
enum insn_code clrmem_optab[NUM_MACHINE_MODES];
|
||||
/* This array records the insn_code of insns to perform block sets. */
|
||||
enum insn_code setmem_optab[NUM_MACHINE_MODES];
|
||||
|
||||
/* These arrays record the insn_code of two different kinds of insns
|
||||
to perform block compares. */
|
||||
@ -2478,7 +2477,7 @@ clear_storage (rtx object, rtx size, enum block_op_methods method)
|
||||
if (GET_CODE (size) == CONST_INT
|
||||
&& CLEAR_BY_PIECES_P (INTVAL (size), align))
|
||||
clear_by_pieces (object, INTVAL (size), align);
|
||||
else if (clear_storage_via_clrmem (object, size, align))
|
||||
else if (set_storage_via_setmem (object, size, const0_rtx, align))
|
||||
;
|
||||
else
|
||||
return clear_storage_via_libcall (object, size,
|
||||
@ -2487,62 +2486,6 @@ clear_storage (rtx object, rtx size, enum block_op_methods method)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* A subroutine of clear_storage. Expand a clrmem pattern;
|
||||
return true if successful. */
|
||||
|
||||
static bool
|
||||
clear_storage_via_clrmem (rtx object, rtx size, unsigned int align)
|
||||
{
|
||||
/* Try the most limited insn first, because there's no point
|
||||
including more than one in the machine description unless
|
||||
the more limited one has some advantage. */
|
||||
|
||||
rtx opalign = GEN_INT (align / BITS_PER_UNIT);
|
||||
enum machine_mode mode;
|
||||
|
||||
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
|
||||
mode = GET_MODE_WIDER_MODE (mode))
|
||||
{
|
||||
enum insn_code code = clrmem_optab[(int) mode];
|
||||
insn_operand_predicate_fn pred;
|
||||
|
||||
if (code != CODE_FOR_nothing
|
||||
/* We don't need MODE to be narrower than
|
||||
BITS_PER_HOST_WIDE_INT here because if SIZE is less than
|
||||
the mode mask, as it is returned by the macro, it will
|
||||
definitely be less than the actual mode mask. */
|
||||
&& ((GET_CODE (size) == CONST_INT
|
||||
&& ((unsigned HOST_WIDE_INT) INTVAL (size)
|
||||
<= (GET_MODE_MASK (mode) >> 1)))
|
||||
|| GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
|
||||
&& ((pred = insn_data[(int) code].operand[0].predicate) == 0
|
||||
|| (*pred) (object, BLKmode))
|
||||
&& ((pred = insn_data[(int) code].operand[2].predicate) == 0
|
||||
|| (*pred) (opalign, VOIDmode)))
|
||||
{
|
||||
rtx op1;
|
||||
rtx last = get_last_insn ();
|
||||
rtx pat;
|
||||
|
||||
op1 = convert_to_mode (mode, size, 1);
|
||||
pred = insn_data[(int) code].operand[1].predicate;
|
||||
if (pred != 0 && ! (*pred) (op1, mode))
|
||||
op1 = copy_to_mode_reg (mode, op1);
|
||||
|
||||
pat = GEN_FCN ((int) code) (object, op1, opalign);
|
||||
if (pat)
|
||||
{
|
||||
emit_insn (pat);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
delete_insns_since (last);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* A subroutine of clear_storage. Expand a call to memset.
|
||||
Return the return value of memset, 0 otherwise. */
|
||||
|
||||
@ -2635,6 +2578,67 @@ clear_storage_libcall_fn (int for_call)
|
||||
|
||||
return block_clear_fn;
|
||||
}
|
||||
|
||||
/* Expand a setmem pattern; return true if successful. */
|
||||
|
||||
bool
|
||||
set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align)
|
||||
{
|
||||
/* Try the most limited insn first, because there's no point
|
||||
including more than one in the machine description unless
|
||||
the more limited one has some advantage. */
|
||||
|
||||
rtx opalign = GEN_INT (align / BITS_PER_UNIT);
|
||||
enum machine_mode mode;
|
||||
|
||||
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
|
||||
mode = GET_MODE_WIDER_MODE (mode))
|
||||
{
|
||||
enum insn_code code = setmem_optab[(int) mode];
|
||||
insn_operand_predicate_fn pred;
|
||||
|
||||
if (code != CODE_FOR_nothing
|
||||
/* We don't need MODE to be narrower than
|
||||
BITS_PER_HOST_WIDE_INT here because if SIZE is less than
|
||||
the mode mask, as it is returned by the macro, it will
|
||||
definitely be less than the actual mode mask. */
|
||||
&& ((GET_CODE (size) == CONST_INT
|
||||
&& ((unsigned HOST_WIDE_INT) INTVAL (size)
|
||||
<= (GET_MODE_MASK (mode) >> 1)))
|
||||
|| GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
|
||||
&& ((pred = insn_data[(int) code].operand[0].predicate) == 0
|
||||
|| (*pred) (object, BLKmode))
|
||||
&& ((pred = insn_data[(int) code].operand[3].predicate) == 0
|
||||
|| (*pred) (opalign, VOIDmode)))
|
||||
{
|
||||
rtx opsize,opchar;
|
||||
rtx last = get_last_insn ();
|
||||
rtx pat;
|
||||
|
||||
opsize = convert_to_mode (mode, size, 1);
|
||||
pred = insn_data[(int) code].operand[1].predicate;
|
||||
if (pred != 0 && ! (*pred) (opsize, mode))
|
||||
opsize = copy_to_mode_reg (mode, opsize);
|
||||
|
||||
opchar = convert_to_mode (mode, val, 1);
|
||||
pred = insn_data[(int) code].operand[2].predicate;
|
||||
if (pred != 0 && ! (*pred) (opchar, mode))
|
||||
opchar = copy_to_mode_reg (mode, opchar);
|
||||
|
||||
pat = GEN_FCN ((int) code) (object, opsize, opchar, opalign);
|
||||
if (pat)
|
||||
{
|
||||
emit_insn (pat);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
delete_insns_since (last);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Write to one of the components of the complex value CPLX. Write VAL to
|
||||
the real part if IMAG_P is false, and the imaginary part if its true. */
|
||||
|
@ -75,10 +75,10 @@ enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM,
|
||||
#endif
|
||||
|
||||
/* If a clear memory operation would take CLEAR_RATIO or more simple
|
||||
move-instruction sequences, we will do a clrmem or libcall instead. */
|
||||
move-instruction sequences, we will do a setmem or libcall instead. */
|
||||
|
||||
#ifndef CLEAR_RATIO
|
||||
#if defined (HAVE_clrmemqi) || defined (HAVE_clrmemhi) || defined (HAVE_clrmemsi) || defined (HAVE_clrmemdi) || defined (HAVE_clrmemti)
|
||||
#if defined (HAVE_setmemqi) || defined (HAVE_setmemhi) || defined (HAVE_setmemsi) || defined (HAVE_setmemdi) || defined (HAVE_setmemti)
|
||||
#define CLEAR_RATIO 2
|
||||
#else
|
||||
/* If we are optimizing for space, cut down the default clear ratio. */
|
||||
@ -423,6 +423,9 @@ extern void use_group_regs (rtx *, rtx);
|
||||
If OBJECT has BLKmode, SIZE is its length in bytes. */
|
||||
extern rtx clear_storage (rtx, rtx, enum block_op_methods);
|
||||
|
||||
/* Expand a setmem pattern; return true if successful. */
|
||||
extern bool set_storage_via_setmem (rtx, rtx, rtx, unsigned int);
|
||||
|
||||
/* Determine whether the LEN bytes can be moved by using several move
|
||||
instructions. Return nonzero if a call to move_by_pieces should
|
||||
succeed. */
|
||||
|
@ -168,9 +168,9 @@ static const char * const optabs[] =
|
||||
"reload_in_optab[$A] = CODE_FOR_$(reload_in$a$)",
|
||||
"reload_out_optab[$A] = CODE_FOR_$(reload_out$a$)",
|
||||
"movmem_optab[$A] = CODE_FOR_$(movmem$a$)",
|
||||
"clrmem_optab[$A] = CODE_FOR_$(clrmem$a$)",
|
||||
"cmpstr_optab[$A] = CODE_FOR_$(cmpstr$a$)",
|
||||
"cmpmem_optab[$A] = CODE_FOR_$(cmpmem$a$)",
|
||||
"setmem_optab[$A] = CODE_FOR_$(setmem$a$)",
|
||||
"sync_add_optab[$A] = CODE_FOR_$(sync_add$I$a$)",
|
||||
"sync_sub_optab[$A] = CODE_FOR_$(sync_sub$I$a$)",
|
||||
"sync_ior_optab[$A] = CODE_FOR_$(sync_ior$I$a$)",
|
||||
|
@ -5162,9 +5162,9 @@ init_optabs (void)
|
||||
for (i = 0; i < NUM_MACHINE_MODES; i++)
|
||||
{
|
||||
movmem_optab[i] = CODE_FOR_nothing;
|
||||
clrmem_optab[i] = CODE_FOR_nothing;
|
||||
cmpstr_optab[i] = CODE_FOR_nothing;
|
||||
cmpmem_optab[i] = CODE_FOR_nothing;
|
||||
setmem_optab[i] = CODE_FOR_nothing;
|
||||
|
||||
sync_add_optab[i] = CODE_FOR_nothing;
|
||||
sync_sub_optab[i] = CODE_FOR_nothing;
|
||||
|
@ -444,8 +444,8 @@ extern enum insn_code vcondu_gen_code[NUM_MACHINE_MODES];
|
||||
/* This array records the insn_code of insns to perform block moves. */
|
||||
extern enum insn_code movmem_optab[NUM_MACHINE_MODES];
|
||||
|
||||
/* This array records the insn_code of insns to perform block clears. */
|
||||
extern enum insn_code clrmem_optab[NUM_MACHINE_MODES];
|
||||
/* This array records the insn_code of insns to perform block sets. */
|
||||
extern enum insn_code setmem_optab[NUM_MACHINE_MODES];
|
||||
|
||||
/* These arrays record the insn_code of two different kinds of insns
|
||||
to perform block compares. */
|
||||
|
Loading…
Reference in New Issue
Block a user