aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2013-11-19 02:42:34 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2013-11-19 01:42:34 +0000
commit82bb7d4e8274b5bc22000ea6fc58f169e7e087f0 (patch)
treef2fcdd731a9c1bb632d77915060a8e36c94837b8 /gcc/expr.c
parent0874db6e96b721f9545c6b3976eb77601b09533d (diff)
downloadgcc-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.c57
1 files changed, 40 insertions, 17 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index f4d03ab..ece5d0f 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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;
}