Commit 2ff5ffb6 by Martin Liska Committed by Martin Liska

Come up with memop_ret enum instead of int endp for memory operations.

2018-11-27  Martin Liska  <mliska@suse.cz>

	* asan.c (asan_emit_stack_protection): Use new enum values
	instead of int constants.
	* builtins.c (expand_builtin_memory_copy_args): Replace int
	type with memop_ret enum type.
	(expand_builtin_mempcpy_args): Likewise.
	(expand_builtin_memcpy): Use new enum values
	instead of int constants. Likewise.
	(expand_builtin_mempcpy): Likewise.
	(expand_movstr): Likewise.
	(expand_builtin_strcpy_args): Likewise.
	(expand_builtin_stpcpy_1): Likewise.
	(expand_builtin_strncpy): Likewise.
	(expand_builtin_memset_args): Likewise.
	* expr.c (move_by_pieces_d::finish_endp): Rename to ...
	(move_by_pieces_d::finish_retmode): ... this.
	(move_by_pieces): Change last argument type to memop_ret.
	(store_by_pieces): Use new enum values
	instead of int constants.
	(emit_block_move_hints): Likewise.
	(emit_push_insn): Likewise.
	(store_expr): Likewise.
	* expr.h (store_by_pieces): Change int to newly added enum
	type.
	* rtl.h (enum memop_ret): Define.
	(move_by_pieces): Use the enum type.

From-SVN: r266508
parent da193a27
2018-11-27 Martin Liska <mliska@suse.cz>
* asan.c (asan_emit_stack_protection): Use new enum values
instead of int constants.
* builtins.c (expand_builtin_memory_copy_args): Replace int
type with memop_ret enum type.
(expand_builtin_mempcpy_args): Likewise.
(expand_builtin_memcpy): Use new enum values
instead of int constants. Likewise.
(expand_builtin_mempcpy): Likewise.
(expand_movstr): Likewise.
(expand_builtin_strcpy_args): Likewise.
(expand_builtin_stpcpy_1): Likewise.
(expand_builtin_strncpy): Likewise.
(expand_builtin_memset_args): Likewise.
* expr.c (move_by_pieces_d::finish_endp): Rename to ...
(move_by_pieces_d::finish_retmode): ... this.
(move_by_pieces): Change last argument type to memop_ret.
(store_by_pieces): Use new enum values
instead of int constants.
(emit_block_move_hints): Likewise.
(emit_push_insn): Likewise.
(store_expr): Likewise.
* expr.h (store_by_pieces): Change int to newly added enum
type.
* rtl.h (enum memop_ret): Define.
(move_by_pieces): Use the enum type.
2018-11-27 Alan Modra <amodra@gmail.com> 2018-11-27 Alan Modra <amodra@gmail.com>
* config/rs6000/aix71.h (ASM_SPEC): Don't select default -maix64 * config/rs6000/aix71.h (ASM_SPEC): Don't select default -maix64
...@@ -1484,7 +1484,7 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, ...@@ -1484,7 +1484,7 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
&& can_store_by_pieces (sz, builtin_memset_read_str, &c, && can_store_by_pieces (sz, builtin_memset_read_str, &c,
BITS_PER_UNIT, true)) BITS_PER_UNIT, true))
store_by_pieces (shadow_mem, sz, builtin_memset_read_str, &c, store_by_pieces (shadow_mem, sz, builtin_memset_read_str, &c,
BITS_PER_UNIT, true, 0); BITS_PER_UNIT, true, RETURN_BEGIN);
else if (use_after_return_class >= 5 else if (use_after_return_class >= 5
|| !set_storage_via_setmem (shadow_mem, || !set_storage_via_setmem (shadow_mem,
GEN_INT (sz), GEN_INT (sz),
......
...@@ -126,10 +126,11 @@ static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, scalar_int_mode); ...@@ -126,10 +126,11 @@ static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, scalar_int_mode);
static rtx expand_builtin_memchr (tree, rtx); static rtx expand_builtin_memchr (tree, rtx);
static rtx expand_builtin_memcpy (tree, rtx); static rtx expand_builtin_memcpy (tree, rtx);
static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len, static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len,
rtx target, tree exp, int endp); rtx target, tree exp,
memop_ret retmode);
static rtx expand_builtin_memmove (tree, rtx); static rtx expand_builtin_memmove (tree, rtx);
static rtx expand_builtin_mempcpy (tree, rtx); static rtx expand_builtin_mempcpy (tree, rtx);
static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, int); static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, memop_ret);
static rtx expand_builtin_strcat (tree, rtx); static rtx expand_builtin_strcat (tree, rtx);
static rtx expand_builtin_strcpy (tree, rtx); static rtx expand_builtin_strcpy (tree, rtx);
static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx); static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx);
...@@ -3751,7 +3752,7 @@ expand_builtin_memcpy (tree exp, rtx target) ...@@ -3751,7 +3752,7 @@ expand_builtin_memcpy (tree exp, rtx target)
check_memop_access (exp, dest, src, len); check_memop_access (exp, dest, src, len);
return expand_builtin_memory_copy_args (dest, src, len, target, exp, return expand_builtin_memory_copy_args (dest, src, len, target, exp,
/*endp=*/ 0); /*retmode=*/ RETURN_BEGIN);
} }
/* Check a call EXP to the memmove built-in for validity. /* Check a call EXP to the memmove built-in for validity.
...@@ -3776,10 +3777,7 @@ expand_builtin_memmove (tree exp, rtx) ...@@ -3776,10 +3777,7 @@ expand_builtin_memmove (tree exp, rtx)
/* Expand a call EXP to the mempcpy builtin. /* Expand a call EXP to the mempcpy builtin.
Return NULL_RTX if we failed; the caller should emit a normal call, Return NULL_RTX if we failed; the caller should emit a normal call,
otherwise try to get the result in TARGET, if convenient (and in otherwise try to get the result in TARGET, if convenient (and in
mode MODE if that's convenient). If ENDP is 0 return the mode MODE if that's convenient). */
destination pointer, if ENDP is 1 return the end pointer ala
mempcpy, and if ENDP is 2 return the end pointer minus one ala
stpcpy. */
static rtx static rtx
expand_builtin_mempcpy (tree exp, rtx target) expand_builtin_mempcpy (tree exp, rtx target)
...@@ -3812,20 +3810,17 @@ expand_builtin_mempcpy (tree exp, rtx target) ...@@ -3812,20 +3810,17 @@ expand_builtin_mempcpy (tree exp, rtx target)
return NULL_RTX; return NULL_RTX;
return expand_builtin_mempcpy_args (dest, src, len, return expand_builtin_mempcpy_args (dest, src, len,
target, exp, /*endp=*/ 1); target, exp, /*retmode=*/ RETURN_END);
} }
/* Helper function to do the actual work for expand of memory copy family /* Helper function to do the actual work for expand of memory copy family
functions (memcpy, mempcpy, stpcpy). Expansing should assign LEN bytes functions (memcpy, mempcpy, stpcpy). Expansing should assign LEN bytes
of memory from SRC to DEST and assign to TARGET if convenient. of memory from SRC to DEST and assign to TARGET if convenient. Return
If ENDP is 0 return the value is based on RETMODE argument. */
destination pointer, if ENDP is 1 return the end pointer ala
mempcpy, and if ENDP is 2 return the end pointer minus one ala
stpcpy. */
static rtx static rtx
expand_builtin_memory_copy_args (tree dest, tree src, tree len, expand_builtin_memory_copy_args (tree dest, tree src, tree len,
rtx target, tree exp, int endp) rtx target, tree exp, memop_ret retmode)
{ {
const char *src_str; const char *src_str;
unsigned int src_align = get_pointer_alignment (src); unsigned int src_align = get_pointer_alignment (src);
...@@ -3872,7 +3867,7 @@ expand_builtin_memory_copy_args (tree dest, tree src, tree len, ...@@ -3872,7 +3867,7 @@ expand_builtin_memory_copy_args (tree dest, tree src, tree len,
dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx), dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
builtin_memcpy_read_str, builtin_memcpy_read_str,
CONST_CAST (char *, src_str), CONST_CAST (char *, src_str),
dest_align, false, endp); dest_align, false, retmode);
dest_mem = force_operand (XEXP (dest_mem, 0), target); dest_mem = force_operand (XEXP (dest_mem, 0), target);
dest_mem = convert_memory_address (ptr_mode, dest_mem); dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem; return dest_mem;
...@@ -3883,9 +3878,10 @@ expand_builtin_memory_copy_args (tree dest, tree src, tree len, ...@@ -3883,9 +3878,10 @@ expand_builtin_memory_copy_args (tree dest, tree src, tree len,
/* Copy word part most expediently. */ /* Copy word part most expediently. */
enum block_op_methods method = BLOCK_OP_NORMAL; enum block_op_methods method = BLOCK_OP_NORMAL;
if (CALL_EXPR_TAILCALL (exp) && (endp == 0 || target == const0_rtx)) if (CALL_EXPR_TAILCALL (exp)
&& (retmode == RETURN_BEGIN || target == const0_rtx))
method = BLOCK_OP_TAILCALL; method = BLOCK_OP_TAILCALL;
if (endp == 1 && target != const0_rtx) if (retmode == RETURN_END && target != const0_rtx)
method = BLOCK_OP_NO_LIBCALL_RET; method = BLOCK_OP_NO_LIBCALL_RET;
dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, method, dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, method,
expected_align, expected_size, expected_align, expected_size,
...@@ -3899,11 +3895,11 @@ expand_builtin_memory_copy_args (tree dest, tree src, tree len, ...@@ -3899,11 +3895,11 @@ expand_builtin_memory_copy_args (tree dest, tree src, tree len,
dest_addr = convert_memory_address (ptr_mode, dest_addr); dest_addr = convert_memory_address (ptr_mode, dest_addr);
} }
if (endp && target != const0_rtx) if (retmode != RETURN_BEGIN && target != const0_rtx)
{ {
dest_addr = gen_rtx_PLUS (ptr_mode, dest_addr, len_rtx); dest_addr = gen_rtx_PLUS (ptr_mode, dest_addr, len_rtx);
/* stpcpy pointer to last byte. */ /* stpcpy pointer to last byte. */
if (endp == 2) if (retmode == RETURN_END_MINUS_ONE)
dest_addr = gen_rtx_MINUS (ptr_mode, dest_addr, const1_rtx); dest_addr = gen_rtx_MINUS (ptr_mode, dest_addr, const1_rtx);
} }
...@@ -3912,21 +3908,19 @@ expand_builtin_memory_copy_args (tree dest, tree src, tree len, ...@@ -3912,21 +3908,19 @@ expand_builtin_memory_copy_args (tree dest, tree src, tree len,
static rtx static rtx
expand_builtin_mempcpy_args (tree dest, tree src, tree len, expand_builtin_mempcpy_args (tree dest, tree src, tree len,
rtx target, tree orig_exp, int endp) rtx target, tree orig_exp, memop_ret retmode)
{ {
return expand_builtin_memory_copy_args (dest, src, len, target, orig_exp, return expand_builtin_memory_copy_args (dest, src, len, target, orig_exp,
endp); retmode);
} }
/* Expand into a movstr instruction, if one is available. Return NULL_RTX if /* Expand into a movstr instruction, if one is available. Return NULL_RTX if
we failed, the caller should emit a normal call, otherwise try to we failed, the caller should emit a normal call, otherwise try to
get the result in TARGET, if convenient. If ENDP is 0 return the get the result in TARGET, if convenient.
destination pointer, if ENDP is 1 return the end pointer ala Return value is based on RETMODE argument. */
mempcpy, and if ENDP is 2 return the end pointer minus one ala
stpcpy. */
static rtx static rtx
expand_movstr (tree dest, tree src, rtx target, int endp) expand_movstr (tree dest, tree src, rtx target, memop_ret retmode)
{ {
struct expand_operand ops[3]; struct expand_operand ops[3];
rtx dest_mem; rtx dest_mem;
...@@ -3937,25 +3931,25 @@ expand_movstr (tree dest, tree src, rtx target, int endp) ...@@ -3937,25 +3931,25 @@ expand_movstr (tree dest, tree src, rtx target, int endp)
dest_mem = get_memory_rtx (dest, NULL); dest_mem = get_memory_rtx (dest, NULL);
src_mem = get_memory_rtx (src, NULL); src_mem = get_memory_rtx (src, NULL);
if (!endp) if (retmode != RETURN_BEGIN)
{ {
target = force_reg (Pmode, XEXP (dest_mem, 0)); target = force_reg (Pmode, XEXP (dest_mem, 0));
dest_mem = replace_equiv_address (dest_mem, target); dest_mem = replace_equiv_address (dest_mem, target);
} }
create_output_operand (&ops[0], endp ? target : NULL_RTX, Pmode); create_output_operand (&ops[0], retmode ? target : NULL_RTX, Pmode);
create_fixed_operand (&ops[1], dest_mem); create_fixed_operand (&ops[1], dest_mem);
create_fixed_operand (&ops[2], src_mem); create_fixed_operand (&ops[2], src_mem);
if (!maybe_expand_insn (targetm.code_for_movstr, 3, ops)) if (!maybe_expand_insn (targetm.code_for_movstr, 3, ops))
return NULL_RTX; return NULL_RTX;
if (endp && target != const0_rtx) if (retmode != RETURN_BEGIN && target != const0_rtx)
{ {
target = ops[0].value; target = ops[0].value;
/* movstr is supposed to set end to the address of the NUL /* movstr is supposed to set end to the address of the NUL
terminator. If the caller requested a mempcpy-like return value, terminator. If the caller requested a mempcpy-like return value,
adjust it. */ adjust it. */
if (endp == 1) if (retmode == RETURN_END)
{ {
rtx tem = plus_constant (GET_MODE (target), rtx tem = plus_constant (GET_MODE (target),
gen_lowpart (GET_MODE (target), target), 1); gen_lowpart (GET_MODE (target), target), 1);
...@@ -4044,7 +4038,7 @@ expand_builtin_strcpy_args (tree exp, tree dest, tree src, rtx target) ...@@ -4044,7 +4038,7 @@ expand_builtin_strcpy_args (tree exp, tree dest, tree src, rtx target)
return NULL_RTX; return NULL_RTX;
} }
return expand_movstr (dest, src, target, /*endp=*/0); return expand_movstr (dest, src, target, /*retmode=*/ RETURN_BEGIN);
} }
/* Expand a call EXP to the stpcpy builtin. /* Expand a call EXP to the stpcpy builtin.
...@@ -4091,14 +4085,16 @@ expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode) ...@@ -4091,14 +4085,16 @@ expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode)
memset (&data, 0, sizeof (c_strlen_data)); memset (&data, 0, sizeof (c_strlen_data));
if (!c_getstr (src, NULL) if (!c_getstr (src, NULL)
|| !(len = c_strlen (src, 0, &data, 1))) || !(len = c_strlen (src, 0, &data, 1)))
return expand_movstr (dst, src, target, /*endp=*/2); return expand_movstr (dst, src, target,
/*retmode=*/ RETURN_END_MINUS_ONE);
if (data.decl && !TREE_NO_WARNING (exp)) if (data.decl && !TREE_NO_WARNING (exp))
warn_string_no_nul (EXPR_LOCATION (exp), "stpcpy", src, data.decl); warn_string_no_nul (EXPR_LOCATION (exp), "stpcpy", src, data.decl);
lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1)); lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1));
ret = expand_builtin_mempcpy_args (dst, src, lenp1, ret = expand_builtin_mempcpy_args (dst, src, lenp1,
target, exp, /*endp=*/2); target, exp,
/*retmode=*/ RETURN_END_MINUS_ONE);
if (ret) if (ret)
return ret; return ret;
...@@ -4132,7 +4128,8 @@ expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode) ...@@ -4132,7 +4128,8 @@ expand_builtin_stpcpy_1 (tree exp, rtx target, machine_mode mode)
} }
} }
return expand_movstr (dst, src, target, /*endp=*/2); return expand_movstr (dst, src, target,
/*retmode=*/ RETURN_END_MINUS_ONE);
} }
} }
...@@ -4378,7 +4375,8 @@ expand_builtin_strncpy (tree exp, rtx target) ...@@ -4378,7 +4375,8 @@ expand_builtin_strncpy (tree exp, rtx target)
dest_mem = get_memory_rtx (dest, len); dest_mem = get_memory_rtx (dest, len);
store_by_pieces (dest_mem, tree_to_uhwi (len), store_by_pieces (dest_mem, tree_to_uhwi (len),
builtin_strncpy_read_str, builtin_strncpy_read_str,
CONST_CAST (char *, p), dest_align, false, 0); CONST_CAST (char *, p), dest_align, false,
RETURN_BEGIN);
dest_mem = force_operand (XEXP (dest_mem, 0), target); dest_mem = force_operand (XEXP (dest_mem, 0), target);
dest_mem = convert_memory_address (ptr_mode, dest_mem); dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem; return dest_mem;
...@@ -4523,7 +4521,7 @@ expand_builtin_memset_args (tree dest, tree val, tree len, ...@@ -4523,7 +4521,7 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
val_rtx = force_reg (val_mode, val_rtx); val_rtx = force_reg (val_mode, val_rtx);
store_by_pieces (dest_mem, tree_to_uhwi (len), store_by_pieces (dest_mem, tree_to_uhwi (len),
builtin_memset_gen_str, val_rtx, dest_align, builtin_memset_gen_str, val_rtx, dest_align,
true, 0); true, RETURN_BEGIN);
} }
else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx, else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
dest_align, expected_align, dest_align, expected_align,
...@@ -4546,7 +4544,8 @@ expand_builtin_memset_args (tree dest, tree val, tree len, ...@@ -4546,7 +4544,8 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
builtin_memset_read_str, &c, dest_align, builtin_memset_read_str, &c, dest_align,
true)) true))
store_by_pieces (dest_mem, tree_to_uhwi (len), store_by_pieces (dest_mem, tree_to_uhwi (len),
builtin_memset_read_str, &c, dest_align, true, 0); builtin_memset_read_str, &c, dest_align, true,
RETURN_BEGIN);
else if (!set_storage_via_setmem (dest_mem, len_rtx, else if (!set_storage_via_setmem (dest_mem, len_rtx,
gen_int_mode (c, val_mode), gen_int_mode (c, val_mode),
dest_align, expected_align, dest_align, expected_align,
......
...@@ -1146,7 +1146,7 @@ class move_by_pieces_d : public op_by_pieces_d ...@@ -1146,7 +1146,7 @@ class move_by_pieces_d : public op_by_pieces_d
: op_by_pieces_d (to, false, from, true, NULL, NULL, len, align) : op_by_pieces_d (to, false, from, true, NULL, NULL, len, align)
{ {
} }
rtx finish_endp (int); rtx finish_retmode (memop_ret);
}; };
/* Return true if MODE can be used for a set of copies, given an /* Return true if MODE can be used for a set of copies, given an
...@@ -1182,15 +1182,14 @@ move_by_pieces_d::generate (rtx op0, rtx op1, ...@@ -1182,15 +1182,14 @@ move_by_pieces_d::generate (rtx op0, rtx op1,
} }
/* Perform the final adjustment at the end of a string to obtain the /* Perform the final adjustment at the end of a string to obtain the
correct return value for the block operation. If ENDP is 1 return correct return value for the block operation.
memory at the end ala mempcpy, and if ENDP is 2 return memory the Return value is based on RETMODE argument. */
end minus one byte ala stpcpy. */
rtx rtx
move_by_pieces_d::finish_endp (int endp) move_by_pieces_d::finish_retmode (memop_ret retmode)
{ {
gcc_assert (!m_reverse); gcc_assert (!m_reverse);
if (endp == 2) if (retmode == RETURN_END_MINUS_ONE)
{ {
m_to.maybe_postinc (-1); m_to.maybe_postinc (-1);
--m_offset; --m_offset;
...@@ -1206,13 +1205,11 @@ move_by_pieces_d::finish_endp (int endp) ...@@ -1206,13 +1205,11 @@ move_by_pieces_d::finish_endp (int endp)
ALIGN is maximum stack alignment we can assume. ALIGN is maximum stack alignment we can assume.
If ENDP is 0 return to, if ENDP is 1 return memory at the end ala Return value is based on RETMODE argument. */
mempcpy, and if ENDP is 2 return memory the end minus one byte ala
stpcpy. */
rtx rtx
move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len, move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
unsigned int align, int endp) unsigned int align, memop_ret retmode)
{ {
#ifndef PUSH_ROUNDING #ifndef PUSH_ROUNDING
if (to == NULL) if (to == NULL)
...@@ -1223,8 +1220,8 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len, ...@@ -1223,8 +1220,8 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
data.run (); data.run ();
if (endp) if (retmode)
return data.finish_endp (endp); return data.finish_retmode (retmode);
else else
return to; return to;
} }
...@@ -1244,7 +1241,7 @@ class store_by_pieces_d : public op_by_pieces_d ...@@ -1244,7 +1241,7 @@ class store_by_pieces_d : public op_by_pieces_d
: op_by_pieces_d (to, false, NULL_RTX, true, cfn, cfn_data, len, align) : op_by_pieces_d (to, false, NULL_RTX, true, cfn, cfn_data, len, align)
{ {
} }
rtx finish_endp (int); rtx finish_retmode (memop_ret);
}; };
/* Return true if MODE can be used for a set of stores, given an /* Return true if MODE can be used for a set of stores, given an
...@@ -1272,15 +1269,14 @@ store_by_pieces_d::generate (rtx op0, rtx op1, machine_mode) ...@@ -1272,15 +1269,14 @@ store_by_pieces_d::generate (rtx op0, rtx op1, machine_mode)
} }
/* Perform the final adjustment at the end of a string to obtain the /* Perform the final adjustment at the end of a string to obtain the
correct return value for the block operation. If ENDP is 1 return correct return value for the block operation.
memory at the end ala mempcpy, and if ENDP is 2 return memory the Return value is based on RETMODE argument. */
end minus one byte ala stpcpy. */
rtx rtx
store_by_pieces_d::finish_endp (int endp) store_by_pieces_d::finish_retmode (memop_ret retmode)
{ {
gcc_assert (!m_reverse); gcc_assert (!m_reverse);
if (endp == 2) if (retmode == RETURN_END_MINUS_ONE)
{ {
m_to.maybe_postinc (-1); m_to.maybe_postinc (-1);
--m_offset; --m_offset;
...@@ -1370,18 +1366,17 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len, ...@@ -1370,18 +1366,17 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
pointer which will be passed as argument in every CONSTFUN call. pointer which will be passed as argument in every CONSTFUN call.
ALIGN is maximum alignment we can assume. MEMSETP is true if this is ALIGN is maximum alignment we can assume. MEMSETP is true if this is
a memset operation and false if it's a copy of a constant string. a memset operation and false if it's a copy of a constant string.
If ENDP is 0 return to, if ENDP is 1 return memory at the end ala Return value is based on RETMODE argument. */
mempcpy, and if ENDP is 2 return memory the end minus one byte ala
stpcpy. */
rtx rtx
store_by_pieces (rtx to, unsigned HOST_WIDE_INT len, store_by_pieces (rtx to, unsigned HOST_WIDE_INT len,
rtx (*constfun) (void *, HOST_WIDE_INT, scalar_int_mode), rtx (*constfun) (void *, HOST_WIDE_INT, scalar_int_mode),
void *constfundata, unsigned int align, bool memsetp, int endp) void *constfundata, unsigned int align, bool memsetp,
memop_ret retmode)
{ {
if (len == 0) if (len == 0)
{ {
gcc_assert (endp != 2); gcc_assert (retmode != RETURN_END_MINUS_ONE);
return to; return to;
} }
...@@ -1393,8 +1388,8 @@ store_by_pieces (rtx to, unsigned HOST_WIDE_INT len, ...@@ -1393,8 +1388,8 @@ store_by_pieces (rtx to, unsigned HOST_WIDE_INT len,
store_by_pieces_d data (to, constfun, constfundata, len, align); store_by_pieces_d data (to, constfun, constfundata, len, align);
data.run (); data.run ();
if (endp) if (retmode)
return data.finish_endp (endp); return data.finish_retmode (retmode);
else else
return to; return to;
} }
...@@ -1624,7 +1619,7 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method, ...@@ -1624,7 +1619,7 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
} }
if (CONST_INT_P (size) && can_move_by_pieces (INTVAL (size), align)) if (CONST_INT_P (size) && can_move_by_pieces (INTVAL (size), align))
move_by_pieces (x, y, INTVAL (size), align, 0); move_by_pieces (x, y, INTVAL (size), align, RETURN_BEGIN);
else if (emit_block_move_via_movmem (x, y, size, align, else if (emit_block_move_via_movmem (x, y, size, align,
expected_align, expected_size, expected_align, expected_size,
min_size, max_size, probable_max_size)) min_size, max_size, probable_max_size))
...@@ -4421,7 +4416,8 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size, ...@@ -4421,7 +4416,8 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size,
&& where_pad != stack_direction) && where_pad != stack_direction)
anti_adjust_stack (gen_int_mode (extra, Pmode)); anti_adjust_stack (gen_int_mode (extra, Pmode));
move_by_pieces (NULL, xinner, INTVAL (size) - used, align, 0); move_by_pieces (NULL, xinner, INTVAL (size) - used, align,
RETURN_BEGIN);
} }
else else
#endif /* PUSH_ROUNDING */ #endif /* PUSH_ROUNDING */
...@@ -5618,7 +5614,8 @@ store_expr (tree exp, rtx target, int call_param_p, ...@@ -5618,7 +5614,8 @@ store_expr (tree exp, rtx target, int call_param_p,
CONST_CAST (char *, CONST_CAST (char *,
TREE_STRING_POINTER (str)), TREE_STRING_POINTER (str)),
MEM_ALIGN (target), false, MEM_ALIGN (target), false,
exp_len > str_copy_len ? 1 : 0); (exp_len > str_copy_len ? RETURN_END :
RETURN_BEGIN));
if (exp_len > str_copy_len) if (exp_len > str_copy_len)
clear_storage (adjust_address (dest_mem, BLKmode, 0), clear_storage (adjust_address (dest_mem, BLKmode, 0),
GEN_INT (exp_len - str_copy_len), GEN_INT (exp_len - str_copy_len),
......
...@@ -219,7 +219,7 @@ extern int can_store_by_pieces (unsigned HOST_WIDE_INT, ...@@ -219,7 +219,7 @@ extern int can_store_by_pieces (unsigned HOST_WIDE_INT,
MEMSETP is true if this is a real memset/bzero, not a copy. MEMSETP is true if this is a real memset/bzero, not a copy.
Returns TO + LEN. */ Returns TO + LEN. */
extern rtx store_by_pieces (rtx, unsigned HOST_WIDE_INT, by_pieces_constfn, extern rtx store_by_pieces (rtx, unsigned HOST_WIDE_INT, by_pieces_constfn,
void *, unsigned int, bool, int); void *, unsigned int, bool, memop_ret);
/* Emit insns to set X from Y. */ /* Emit insns to set X from Y. */
extern rtx_insn *emit_move_insn (rtx, rtx); extern rtx_insn *emit_move_insn (rtx, rtx);
......
...@@ -4046,9 +4046,24 @@ extern void expand_null_return (void); ...@@ -4046,9 +4046,24 @@ extern void expand_null_return (void);
extern void expand_naked_return (void); extern void expand_naked_return (void);
extern void emit_jump (rtx); extern void emit_jump (rtx);
/* Memory operation built-ins differ by return value. Mapping
of the enum values is following:
- RETURN_BEGIN - return destination, e.g. memcpy
- RETURN_END - return destination + n, e.g. mempcpy
- RETURN_END_MINUS_ONE - return a pointer to the terminating
null byte of the string, e.g. strcpy
*/
enum memop_ret
{
RETURN_BEGIN,
RETURN_END,
RETURN_END_MINUS_ONE
};
/* In expr.c */ /* In expr.c */
extern rtx move_by_pieces (rtx, rtx, unsigned HOST_WIDE_INT, extern rtx move_by_pieces (rtx, rtx, unsigned HOST_WIDE_INT,
unsigned int, int); unsigned int, memop_ret);
extern poly_int64 find_args_size_adjust (rtx_insn *); extern poly_int64 find_args_size_adjust (rtx_insn *);
extern poly_int64 fixup_args_size_notes (rtx_insn *, rtx_insn *, poly_int64); extern poly_int64 fixup_args_size_notes (rtx_insn *, rtx_insn *, poly_int64);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment