Commit 7d3eecca by Martin Liska Committed by Martin Liska

Revert r250771

2017-08-01  Martin Liska  <mliska@suse.cz>

	Revert r250771
	Make mempcpy more optimal (PR middle-end/70140).
2017-08-01  Martin Liska  <mliska@suse.cz>

	Revert r250771
	Make mempcpy more optimal (PR middle-end/70140).

From-SVN: r250788
parent 32341663
2017-08-01 Martin Liska <mliska@suse.cz>
Revert r250771
Make mempcpy more optimal (PR middle-end/70140).
2017-08-01 Jakub Jelinek <jakub@redhat.com> 2017-08-01 Jakub Jelinek <jakub@redhat.com>
PR target/81622 PR target/81622
......
...@@ -121,12 +121,12 @@ static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, machine_mode); ...@@ -121,12 +121,12 @@ static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, machine_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_memcpy_with_bounds (tree, rtx); static rtx expand_builtin_memcpy_with_bounds (tree, rtx);
static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len, static rtx expand_builtin_memcpy_args (tree, tree, tree, rtx, tree);
rtx target, tree exp, int endp);
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, machine_mode);
static rtx expand_builtin_mempcpy_with_bounds (tree, rtx); static rtx expand_builtin_mempcpy_with_bounds (tree, rtx, machine_mode);
static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, int); static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx,
machine_mode, int, tree);
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, rtx); static rtx expand_builtin_strcpy_args (tree, tree, rtx);
...@@ -2961,6 +2961,81 @@ determine_block_size (tree len, rtx len_rtx, ...@@ -2961,6 +2961,81 @@ determine_block_size (tree len, rtx len_rtx,
GET_MODE_MASK (GET_MODE (len_rtx))); GET_MODE_MASK (GET_MODE (len_rtx)));
} }
/* Helper function to do the actual work for expand_builtin_memcpy. */
static rtx
expand_builtin_memcpy_args (tree dest, tree src, tree len, rtx target, tree exp)
{
const char *src_str;
unsigned int src_align = get_pointer_alignment (src);
unsigned int dest_align = get_pointer_alignment (dest);
rtx dest_mem, src_mem, dest_addr, len_rtx;
HOST_WIDE_INT expected_size = -1;
unsigned int expected_align = 0;
unsigned HOST_WIDE_INT min_size;
unsigned HOST_WIDE_INT max_size;
unsigned HOST_WIDE_INT probable_max_size;
/* If DEST is not a pointer type, call the normal function. */
if (dest_align == 0)
return NULL_RTX;
/* If either SRC is not a pointer type, don't do this
operation in-line. */
if (src_align == 0)
return NULL_RTX;
if (currently_expanding_gimple_stmt)
stringop_block_profile (currently_expanding_gimple_stmt,
&expected_align, &expected_size);
if (expected_align < dest_align)
expected_align = dest_align;
dest_mem = get_memory_rtx (dest, len);
set_mem_align (dest_mem, dest_align);
len_rtx = expand_normal (len);
determine_block_size (len, len_rtx, &min_size, &max_size,
&probable_max_size);
src_str = c_getstr (src);
/* If SRC is a string constant and block move would be done
by pieces, we can avoid loading the string from memory
and only stored the computed constants. */
if (src_str
&& CONST_INT_P (len_rtx)
&& (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
&& can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
CONST_CAST (char *, src_str),
dest_align, false))
{
dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
builtin_memcpy_read_str,
CONST_CAST (char *, src_str),
dest_align, false, 0);
dest_mem = force_operand (XEXP (dest_mem, 0), target);
dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem;
}
src_mem = get_memory_rtx (src, len);
set_mem_align (src_mem, src_align);
/* Copy word part most expediently. */
dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
CALL_EXPR_TAILCALL (exp)
? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
expected_align, expected_size,
min_size, max_size, probable_max_size);
if (dest_addr == 0)
{
dest_addr = force_operand (XEXP (dest_mem, 0), target);
dest_addr = convert_memory_address (ptr_mode, dest_addr);
}
return dest_addr;
}
/* Try to verify that the sizes and lengths of the arguments to a string /* Try to verify that the sizes and lengths of the arguments to a string
manipulation function given by EXP are within valid bounds and that manipulation function given by EXP are within valid bounds and that
the operation does not lead to buffer overflow. Arguments other than the operation does not lead to buffer overflow. Arguments other than
...@@ -3303,8 +3378,7 @@ expand_builtin_memcpy (tree exp, rtx target) ...@@ -3303,8 +3378,7 @@ expand_builtin_memcpy (tree exp, rtx target)
check_memop_sizes (exp, dest, src, len); check_memop_sizes (exp, dest, src, len);
return expand_builtin_memory_copy_args (dest, src, len, target, exp, return expand_builtin_memcpy_args (dest, src, len, target, exp);
/*endp=*/ 0);
} }
/* Check a call EXP to the memmove built-in for validity. /* Check a call EXP to the memmove built-in for validity.
...@@ -3344,8 +3418,7 @@ expand_builtin_memcpy_with_bounds (tree exp, rtx target) ...@@ -3344,8 +3418,7 @@ expand_builtin_memcpy_with_bounds (tree exp, rtx target)
tree dest = CALL_EXPR_ARG (exp, 0); tree dest = CALL_EXPR_ARG (exp, 0);
tree src = CALL_EXPR_ARG (exp, 2); tree src = CALL_EXPR_ARG (exp, 2);
tree len = CALL_EXPR_ARG (exp, 4); tree len = CALL_EXPR_ARG (exp, 4);
rtx res = expand_builtin_memory_copy_args (dest, src, len, target, exp, rtx res = expand_builtin_memcpy_args (dest, src, len, target, exp);
/*end_p=*/ 0);
/* Return src bounds with the result. */ /* Return src bounds with the result. */
if (res) if (res)
...@@ -3367,7 +3440,7 @@ expand_builtin_memcpy_with_bounds (tree exp, rtx target) ...@@ -3367,7 +3440,7 @@ expand_builtin_memcpy_with_bounds (tree exp, rtx target)
stpcpy. */ stpcpy. */
static rtx static rtx
expand_builtin_mempcpy (tree exp, rtx target) expand_builtin_mempcpy (tree exp, rtx target, machine_mode mode)
{ {
if (!validate_arglist (exp, if (!validate_arglist (exp,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
...@@ -3384,7 +3457,8 @@ expand_builtin_mempcpy (tree exp, rtx target) ...@@ -3384,7 +3457,8 @@ 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, mode, /*endp=*/ 1,
exp);
} }
/* Expand an instrumented call EXP to the mempcpy builtin. /* Expand an instrumented call EXP to the mempcpy builtin.
...@@ -3393,7 +3467,7 @@ expand_builtin_mempcpy (tree exp, rtx target) ...@@ -3393,7 +3467,7 @@ expand_builtin_mempcpy (tree exp, rtx target)
mode MODE if that's convenient). */ mode MODE if that's convenient). */
static rtx static rtx
expand_builtin_mempcpy_with_bounds (tree exp, rtx target) expand_builtin_mempcpy_with_bounds (tree exp, rtx target, machine_mode mode)
{ {
if (!validate_arglist (exp, if (!validate_arglist (exp,
POINTER_TYPE, POINTER_BOUNDS_TYPE, POINTER_TYPE, POINTER_BOUNDS_TYPE,
...@@ -3406,7 +3480,7 @@ expand_builtin_mempcpy_with_bounds (tree exp, rtx target) ...@@ -3406,7 +3480,7 @@ expand_builtin_mempcpy_with_bounds (tree exp, rtx target)
tree src = CALL_EXPR_ARG (exp, 2); tree src = CALL_EXPR_ARG (exp, 2);
tree len = CALL_EXPR_ARG (exp, 4); tree len = CALL_EXPR_ARG (exp, 4);
rtx res = expand_builtin_mempcpy_args (dest, src, len, target, rtx res = expand_builtin_mempcpy_args (dest, src, len, target,
exp, 1); mode, 1, exp);
/* Return src bounds with the result. */ /* Return src bounds with the result. */
if (res) if (res)
...@@ -3419,111 +3493,94 @@ expand_builtin_mempcpy_with_bounds (tree exp, rtx target) ...@@ -3419,111 +3493,94 @@ expand_builtin_mempcpy_with_bounds (tree exp, rtx target)
} }
} }
/* Helper function to do the actual work for expand of memory copy family /* Helper function to do the actual work for expand_builtin_mempcpy. The
functions (memcpy, mempcpy, stpcpy). Expansing should assign LEN bytes arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out
of memory from SRC to DEST and assign to TARGET if convenient. so that this can also be called without constructing an actual CALL_EXPR.
If ENDP is 0 return the The other arguments and return value are the same as for
destination pointer, if ENDP is 1 return the end pointer ala expand_builtin_mempcpy. */
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_mempcpy_args (tree dest, tree src, tree len,
rtx target, tree exp, int endp) rtx target, machine_mode mode, int endp,
tree orig_exp)
{ {
const char *src_str; tree fndecl = get_callee_fndecl (orig_exp);
unsigned int src_align = get_pointer_alignment (src);
unsigned int dest_align = get_pointer_alignment (dest);
rtx dest_mem, src_mem, dest_addr, len_rtx;
HOST_WIDE_INT expected_size = -1;
unsigned int expected_align = 0;
unsigned HOST_WIDE_INT min_size;
unsigned HOST_WIDE_INT max_size;
unsigned HOST_WIDE_INT probable_max_size;
/* If DEST is not a pointer type, call the normal function. */
if (dest_align == 0)
return NULL_RTX;
/* If either SRC is not a pointer type, don't do this
operation in-line. */
if (src_align == 0)
return NULL_RTX;
if (currently_expanding_gimple_stmt)
stringop_block_profile (currently_expanding_gimple_stmt,
&expected_align, &expected_size);
if (expected_align < dest_align)
expected_align = dest_align;
dest_mem = get_memory_rtx (dest, len);
set_mem_align (dest_mem, dest_align);
len_rtx = expand_normal (len);
determine_block_size (len, len_rtx, &min_size, &max_size,
&probable_max_size);
src_str = c_getstr (src);
/* If SRC is a string constant and block move would be done /* If return value is ignored, transform mempcpy into memcpy. */
by pieces, we can avoid loading the string from memory if (target == const0_rtx
and only stored the computed constants. */ && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK_CHKP
if (src_str && builtin_decl_implicit_p (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK_CHKP))
&& CONST_INT_P (len_rtx)
&& (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
&& can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
CONST_CAST (char *, src_str),
dest_align, false))
{ {
dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx), tree fn = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK_CHKP);
builtin_memcpy_read_str, tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
CONST_CAST (char *, src_str), dest, src, len);
dest_align, false, endp); return expand_expr (result, target, mode, EXPAND_NORMAL);
dest_mem = force_operand (XEXP (dest_mem, 0), target); }
dest_mem = convert_memory_address (ptr_mode, dest_mem); else if (target == const0_rtx
return dest_mem; && builtin_decl_implicit_p (BUILT_IN_MEMCPY))
{
tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3,
dest, src, len);
return expand_expr (result, target, mode, EXPAND_NORMAL);
} }
else
{
const char *src_str;
unsigned int src_align = get_pointer_alignment (src);
unsigned int dest_align = get_pointer_alignment (dest);
rtx dest_mem, src_mem, len_rtx;
src_mem = get_memory_rtx (src, len); /* If either SRC or DEST is not a pointer type, don't do this
set_mem_align (src_mem, src_align); operation in-line. */
if (dest_align == 0 || src_align == 0)
return NULL_RTX;
/* Copy word part most expediently. */ /* If LEN is not constant, call the normal function. */
dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, if (! tree_fits_uhwi_p (len))
CALL_EXPR_TAILCALL (exp) return NULL_RTX;
? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
expected_align, expected_size,
min_size, max_size, probable_max_size);
if (dest_addr == 0) len_rtx = expand_normal (len);
{ src_str = c_getstr (src);
dest_addr = force_operand (XEXP (dest_mem, 0), target);
dest_addr = convert_memory_address (ptr_mode, dest_addr);
return dest_addr;
}
if (endp) /* If SRC is a string constant and block move would be done
{ by pieces, we can avoid loading the string from memory
rtx tmp1 = gen_reg_rtx (ptr_mode); and only stored the computed constants. */
dest_addr = emit_move_insn (tmp1, gen_rtx_PLUS (ptr_mode, dest_addr, if (src_str
len_rtx)); && CONST_INT_P (len_rtx)
/* stpcpy pointer to last byte. */ && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
if (endp == 2) && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
CONST_CAST (char *, src_str),
dest_align, false))
{ {
rtx tmp2 = emit_move_insn (tmp1, gen_rtx_MINUS (ptr_mode, dest_addr, dest_mem = get_memory_rtx (dest, len);
const1_rtx)); set_mem_align (dest_mem, dest_align);
tmp1 = tmp2; dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
builtin_memcpy_read_str,
CONST_CAST (char *, src_str),
dest_align, false, endp);
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem;
} }
emit_move_insn (target, force_operand (tmp1, NULL_RTX));
return target;
}
return dest_addr; if (CONST_INT_P (len_rtx)
} && can_move_by_pieces (INTVAL (len_rtx),
MIN (dest_align, src_align)))
{
dest_mem = get_memory_rtx (dest, len);
set_mem_align (dest_mem, dest_align);
src_mem = get_memory_rtx (src, len);
set_mem_align (src_mem, src_align);
dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx),
MIN (dest_align, src_align), endp);
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem;
}
static rtx return NULL_RTX;
expand_builtin_mempcpy_args (tree dest, tree src, tree len, }
rtx target, tree orig_exp, int endp)
{
return expand_builtin_memory_copy_args (dest, src, len, target, orig_exp,
endp);
} }
/* 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
...@@ -3681,7 +3738,8 @@ expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode) ...@@ -3681,7 +3738,8 @@ expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode)
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, mode, /*endp=*/2,
exp);
if (ret) if (ret)
return ret; return ret;
...@@ -6844,7 +6902,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, ...@@ -6844,7 +6902,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
break; break;
case BUILT_IN_MEMPCPY: case BUILT_IN_MEMPCPY:
target = expand_builtin_mempcpy (exp, target); target = expand_builtin_mempcpy (exp, target, mode);
if (target) if (target)
return target; return target;
break; break;
...@@ -7623,7 +7681,7 @@ expand_builtin_with_bounds (tree exp, rtx target, ...@@ -7623,7 +7681,7 @@ expand_builtin_with_bounds (tree exp, rtx target,
break; break;
case BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK_CHKP: case BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK_CHKP:
target = expand_builtin_mempcpy_with_bounds (exp, target); target = expand_builtin_mempcpy_with_bounds (exp, target, mode);
if (target) if (target)
return target; return target;
break; break;
......
2017-08-01 Martin Liska <mliska@suse.cz>
Revert r250771
Make mempcpy more optimal (PR middle-end/70140).
2017-08-01 Jakub Jelinek <jakub@redhat.com> 2017-08-01 Jakub Jelinek <jakub@redhat.com>
PR target/81622 PR target/81622
......
/* Ensure mempcpy is "optimized" into memcpy followed by addition. */ /* Ensure mempcpy is not "optimized" into memcpy followed by addition. */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2" } */ /* { dg-options "-O2" } */
...@@ -8,5 +8,4 @@ fn (char *x, char *y, int z) ...@@ -8,5 +8,4 @@ fn (char *x, char *y, int z)
return __builtin_mempcpy (x, y, z); return __builtin_mempcpy (x, y, z);
} }
/* { dg-final { scan-assembler-not "mempcpy" } } */ /* { dg-final { scan-assembler-not "memcpy" } } */
/* { dg-final { scan-assembler "memcpy" } } */
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