diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 32 | ||||
-rw-r--r-- | gcc/builtins.c | 53 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 2 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.md | 26 | ||||
-rw-r--r-- | gcc/config/avr/avr.md | 20 | ||||
-rw-r--r-- | gcc/config/frv/frv.c | 4 | ||||
-rw-r--r-- | gcc/config/frv/frv.md | 15 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 22 | ||||
-rw-r--r-- | gcc/config/pa/pa.md | 32 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 4 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 10 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 17 | ||||
-rw-r--r-- | gcc/doc/md.texi | 14 | ||||
-rw-r--r-- | gcc/expr.c | 124 | ||||
-rw-r--r-- | gcc/expr.h | 7 | ||||
-rw-r--r-- | gcc/genopinit.c | 2 | ||||
-rw-r--r-- | gcc/optabs.c | 2 | ||||
-rw-r--r-- | gcc/optabs.h | 4 |
18 files changed, 237 insertions, 153 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 81a3106..225451d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/builtins.c b/gcc/builtins.c index 313170b..f308f53 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -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) diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 8ca3d60..daba49d4 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -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; diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 0b32f11..157e8ca 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -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" diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 6632ae9..59d35f0 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -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)); diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index a1b71ae..67bb11e 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -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; diff --git a/gcc/config/frv/frv.md b/gcc/config/frv/frv.md index 4df63c8..b8c37c5 100644 --- a/gcc/config/frv/frv.md +++ b/gcc/config/frv/frv.md @@ -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 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 7d08873..84be8f9 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -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; diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index 17ffc08..de5b75b 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -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" diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index bd78eca..5bc8ccf 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 92eec48..9cde35a 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -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 diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 826261d..8a3e1a4 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -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. diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index ed07a2f..a44c34c 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -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}} @@ -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. */ @@ -2636,6 +2579,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. */ diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 2c74bedd..409ed08 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -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$)", diff --git a/gcc/optabs.c b/gcc/optabs.c index 6f5716e..2ed499e 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -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; diff --git a/gcc/optabs.h b/gcc/optabs.h index c3644be..bba0a5c 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -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. */ |