diff options
author | Jan Hubicka <jh@suse.cz> | 2013-11-19 02:42:34 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2013-11-19 01:42:34 +0000 |
commit | 82bb7d4e8274b5bc22000ea6fc58f169e7e087f0 (patch) | |
tree | f2fcdd731a9c1bb632d77915060a8e36c94837b8 /gcc/expr.c | |
parent | 0874db6e96b721f9545c6b3976eb77601b09533d (diff) | |
download | gcc-82bb7d4e8274b5bc22000ea6fc58f169e7e087f0.zip gcc-82bb7d4e8274b5bc22000ea6fc58f169e7e087f0.tar.gz gcc-82bb7d4e8274b5bc22000ea6fc58f169e7e087f0.tar.bz2 |
md.texi (setmem): Document new parameter.
* md.texi (setmem): Document new parameter.
* optabs.c (maybe_gen_insn): Support 9 operands.
* builtins.c (determine_block_size): Add probable_max_size;
support anti-ranges.
(expand_builtin_memcpy. expand_builtin_memset_args): Pass around
probable_max_size.
* expr.c (emit_block_move_via_movmem, emit_block_move_hints,
emit_block_move, clear_storage_hints, set_storage_via_setmem):
Likewise.
* expr.h (emit_block_move_hints, clear_storage_hints,
set_storage_via_setmem): Update prototype.
* i386.md (setmem, movmem patterns): Add 9th operand.
* i386-protos.h (ix86_expand_set_or_movmem): Update prototype.
* i386.c (ix86_expand_set_or_movmem): Take probable_max_size_exp
argument; pass it to decide_alg.
* gcc.target/i386/memcpy-3.c: New testcase.
From-SVN: r204997
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 57 |
1 files changed, 40 insertions, 17 deletions
@@ -129,7 +129,8 @@ static void move_by_pieces_1 (insn_gen_fn, machine_mode, struct move_by_pieces_d *); static bool block_move_libcall_safe_for_call_parm (void); static bool emit_block_move_via_movmem (rtx, rtx, rtx, unsigned, unsigned, HOST_WIDE_INT, - unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT); + unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, + unsigned HOST_WIDE_INT); static tree emit_block_move_libcall_fn (int); static void emit_block_move_via_loop (rtx, rtx, rtx, unsigned); static rtx clear_by_pieces_1 (void *, HOST_WIDE_INT, enum machine_mode); @@ -1131,7 +1132,8 @@ rtx emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method, unsigned int expected_align, HOST_WIDE_INT expected_size, unsigned HOST_WIDE_INT min_size, - unsigned HOST_WIDE_INT max_size) + unsigned HOST_WIDE_INT max_size, + unsigned HOST_WIDE_INT probable_max_size) { bool may_use_call; rtx retval = 0; @@ -1188,7 +1190,7 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method, move_by_pieces (x, y, INTVAL (size), align, 0); else if (emit_block_move_via_movmem (x, y, size, align, expected_align, expected_size, - min_size, max_size)) + min_size, max_size, probable_max_size)) ; else if (may_use_call && ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)) @@ -1224,7 +1226,7 @@ emit_block_move (rtx x, rtx y, rtx size, enum block_op_methods method) else max = GET_MODE_MASK (GET_MODE (size)); return emit_block_move_hints (x, y, size, method, 0, -1, - min, max); + min, max, max); } /* A subroutine of emit_block_move. Returns true if calling the @@ -1289,7 +1291,8 @@ static bool emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align, unsigned int expected_align, HOST_WIDE_INT expected_size, unsigned HOST_WIDE_INT min_size, - unsigned HOST_WIDE_INT max_size) + unsigned HOST_WIDE_INT max_size, + unsigned HOST_WIDE_INT probable_max_size) { int save_volatile_ok = volatile_ok; enum machine_mode mode; @@ -1298,8 +1301,8 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align, expected_align = align; if (expected_size != -1) { - if ((unsigned HOST_WIDE_INT)expected_size > max_size) - expected_size = max_size; + if ((unsigned HOST_WIDE_INT)expected_size > probable_max_size) + expected_size = probable_max_size; if ((unsigned HOST_WIDE_INT)expected_size < min_size) expected_size = min_size; } @@ -1328,7 +1331,7 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align, || max_size <= (GET_MODE_MASK (mode) >> 1) || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode))) { - struct expand_operand ops[8]; + struct expand_operand ops[9]; unsigned int nops; /* ??? When called via emit_block_move_for_call, it'd be @@ -1336,7 +1339,7 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align, that it doesn't fail the expansion because it thinks emitting the libcall would be more efficient. */ nops = insn_data[(int) code].n_generator_args; - gcc_assert (nops == 4 || nops == 6 || nops == 8); + gcc_assert (nops == 4 || nops == 6 || nops == 8 || nops == 9); create_fixed_operand (&ops[0], x); create_fixed_operand (&ops[1], y); @@ -1348,7 +1351,7 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align, create_integer_operand (&ops[4], expected_align / BITS_PER_UNIT); create_integer_operand (&ops[5], expected_size); } - if (nops == 8) + if (nops >= 8) { create_integer_operand (&ops[6], min_size); /* If we can not represent the maximal size, @@ -1358,6 +1361,15 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align, else create_fixed_operand (&ops[7], NULL); } + if (nops == 9) + { + /* If we can not represent the maximal size, + make parameter NULL. */ + if ((HOST_WIDE_INT) probable_max_size != -1) + create_integer_operand (&ops[8], probable_max_size); + else + create_fixed_operand (&ops[8], NULL); + } if (maybe_expand_insn (code, nops, ops)) { volatile_ok = save_volatile_ok; @@ -2747,7 +2759,8 @@ rtx clear_storage_hints (rtx object, rtx size, enum block_op_methods method, unsigned int expected_align, HOST_WIDE_INT expected_size, unsigned HOST_WIDE_INT min_size, - unsigned HOST_WIDE_INT max_size) + unsigned HOST_WIDE_INT max_size, + unsigned HOST_WIDE_INT probable_max_size) { enum machine_mode mode = GET_MODE (object); unsigned int align; @@ -2789,7 +2802,7 @@ clear_storage_hints (rtx object, rtx size, enum block_op_methods method, clear_by_pieces (object, INTVAL (size), align); else if (set_storage_via_setmem (object, size, const0_rtx, align, expected_align, expected_size, - min_size, max_size)) + min_size, max_size, probable_max_size)) ; else if (ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (object))) return set_storage_via_libcall (object, size, const0_rtx, @@ -2808,7 +2821,7 @@ clear_storage (rtx object, rtx size, enum block_op_methods method) min = max = UINTVAL (size); else max = GET_MODE_MASK (GET_MODE (size)); - return clear_storage_hints (object, size, method, 0, -1, min, max); + return clear_storage_hints (object, size, method, 0, -1, min, max, max); } @@ -2907,7 +2920,8 @@ bool set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align, unsigned int expected_align, HOST_WIDE_INT expected_size, unsigned HOST_WIDE_INT min_size, - unsigned HOST_WIDE_INT max_size) + unsigned HOST_WIDE_INT max_size, + unsigned HOST_WIDE_INT probable_max_size) { /* Try the most limited insn first, because there's no point including more than one in the machine description unless @@ -2942,11 +2956,11 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align, || max_size <= (GET_MODE_MASK (mode) >> 1) || GET_MODE_BITSIZE (mode) >= GET_MODE_BITSIZE (Pmode))) { - struct expand_operand ops[8]; + struct expand_operand ops[9]; unsigned int nops; nops = insn_data[(int) code].n_generator_args; - gcc_assert (nops == 4 || nops == 6 || nops == 8); + gcc_assert (nops == 4 || nops == 6 || nops == 8 || nops == 9); create_fixed_operand (&ops[0], object); /* The check above guarantees that this size conversion is valid. */ @@ -2958,7 +2972,7 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align, create_integer_operand (&ops[4], expected_align / BITS_PER_UNIT); create_integer_operand (&ops[5], expected_size); } - if (nops == 8) + if (nops >= 8) { create_integer_operand (&ops[6], min_size); /* If we can not represent the maximal size, @@ -2968,6 +2982,15 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align, else create_fixed_operand (&ops[7], NULL); } + if (nops == 9) + { + /* If we can not represent the maximal size, + make parameter NULL. */ + if ((HOST_WIDE_INT) probable_max_size != -1) + create_integer_operand (&ops[8], probable_max_size); + else + create_fixed_operand (&ops[8], NULL); + } if (maybe_expand_insn (code, nops, ops)) return true; } |