Commit 9f3dcd14 by Janne Blomqvist

PR 78534 Reinstate better string copy algorithm

As part of the change to larger character lengths, the string copy
algorithm was temporarily pessimized to get around some spurious
-Wstringop-overflow warnings.  Having tried a number of variations of
this algorithm I have managed to get it down to one spurious warning,
only with -O1 optimization, in the testsuite.  This patch reinstates
the optimized variant and modifies this one testcase to ignore the
warning.

Regtested on x86_64-pc-linux-gnu.

gcc/fortran/ChangeLog:

2018-01-31  Janne Blomqvist  <jb@gcc.gnu.org>

	PR fortran/78534
	* trans-expr.c (fill_with_spaces): Use memset instead of
	generating loop.
	(gfc_trans_string_copy): Improve opportunity to use builtins with
	constant lengths.

gcc/testsuite/ChangeLog:

2018-01-31  Janne Blomqvist  <jb@gcc.gnu.org>

	PR fortran/78534
	* gfortran.dg/allocate_deferred_char_scalar_1.f03: Prune
	-Wstringop-overflow warnings due to spurious warning with -O1.
	* gfortran.dg/char_cast_1.f90: Update dump scan pattern.
	* gfortran.dg/transfer_intrinsic_1.f90: Likewise.

From-SVN: r257233
parent 957a25ab
2018-01-31 Janne Blomqvist <jb@gcc.gnu.org>
PR fortran/78534
* trans-expr.c (fill_with_spaces): Use memset instead of
generating loop.
(gfc_trans_string_copy): Improve opportunity to use builtins with
constant lengths.
2018-01-30 Jakub Jelinek <jakub@redhat.com>
PR debug/84131
......
......@@ -6411,8 +6411,6 @@ fill_with_spaces (tree start, tree type, tree size)
tree i, el, exit_label, cond, tmp;
/* For a simple char type, we can call memset(). */
/* TODO: This code does work and is potentially more efficient, but
causes spurious -Wstringop-overflow warnings.
if (compare_tree_int (TYPE_SIZE_UNIT (type), 1) == 0)
return build_call_expr_loc (input_location,
builtin_decl_explicit (BUILT_IN_MEMSET),
......@@ -6420,7 +6418,6 @@ fill_with_spaces (tree start, tree type, tree size)
build_int_cst (gfc_get_int_type (gfc_c_int_kind),
lang_hooks.to_target_charset (' ')),
fold_convert (size_type_node, size));
*/
/* Otherwise, we use a loop:
for (el = start, i = size; i > 0; el--, i+= TYPE_SIZE_UNIT (type))
......@@ -6526,11 +6523,20 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
/* The string copy algorithm below generates code like
if (dlen > 0) {
memmove (dest, src, min(dlen, slen));
if (slen < dlen)
memset(&dest[slen], ' ', dlen - slen);
}
if (destlen > 0)
{
if (srclen < destlen)
{
memmove (dest, src, srclen);
// Pad with spaces.
memset (&dest[srclen], ' ', destlen - srclen);
}
else
{
// Truncate if too long.
memmove (dest, src, destlen);
}
}
*/
/* Do nothing if the destination length is zero. */
......@@ -6559,21 +6565,16 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
else
src = gfc_build_addr_expr (pvoid_type_node, src);
/* First do the memmove. */
tmp2 = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (dlen), dlen,
slen);
tmp2 = build_call_expr_loc (input_location,
builtin_decl_explicit (BUILT_IN_MEMMOVE),
3, dest, src,
fold_convert (size_type_node, tmp2));
stmtblock_t tmpblock2;
gfc_init_block (&tmpblock2);
gfc_add_expr_to_block (&tmpblock2, tmp2);
/* If the destination is longer, fill the end with spaces. */
/* Truncate string if source is too long. */
cond2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node, slen,
dlen);
/* Copy and pad with spaces. */
tmp3 = build_call_expr_loc (input_location,
builtin_decl_explicit (BUILT_IN_MEMMOVE),
3, dest, src,
fold_convert (size_type_node, slen));
/* Wstringop-overflow appears at -O3 even though this warning is not
explicitly available in fortran nor can it be switched off. If the
source length is a constant, its negative appears as a very large
......@@ -6588,14 +6589,19 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
tmp4 = fill_with_spaces (tmp4, chartype, tmp);
gfc_init_block (&tempblock);
gfc_add_expr_to_block (&tempblock, tmp3);
gfc_add_expr_to_block (&tempblock, tmp4);
tmp3 = gfc_finish_block (&tempblock);
/* The truncated memmove if the slen >= dlen. */
tmp2 = build_call_expr_loc (input_location,
builtin_decl_explicit (BUILT_IN_MEMMOVE),
3, dest, src,
fold_convert (size_type_node, dlen));
/* The whole copy_string function is there. */
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond2,
tmp3, build_empty_stmt (input_location));
gfc_add_expr_to_block (&tmpblock2, tmp);
tmp = gfc_finish_block (&tmpblock2);
tmp3, tmp2);
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp,
build_empty_stmt (input_location));
gfc_add_expr_to_block (block, tmp);
......
2018-01-31 Janne Blomqvist <jb@gcc.gnu.org>
PR fortran/78534
* gfortran.dg/allocate_deferred_char_scalar_1.f03: Prune
-Wstringop-overflow warnings due to spurious warning with -O1.
* gfortran.dg/char_cast_1.f90: Update dump scan pattern.
* gfortran.dg/transfer_intrinsic_1.f90: Likewise.
2018-01-31 Richard Biener <rguenther@suse.de>
PR tree-optimization/84132
......
......@@ -265,3 +265,5 @@ contains
if(len(p4) /= 3) call abort()
end subroutine source3
end program test
! Spurious -Wstringop-overflow warning with -O1
! { dg-prune-output "\\\[-Wstringop-overflow=]" }
......@@ -25,6 +25,6 @@
return
end function Upper
end
! The sign that all is well is that [S.10][1] appears twice.
! Platform dependent variations are [S$10][1], [__S_10][1], [S___10][1]
! { dg-final { scan-tree-dump-times "10\\\]\\\[1\\\]" 2 "original" } }
! The sign that all is well is that [S.6][1] appears twice.
! Platform dependent variations are [S$6][1], [__S_6][1], [S___6][1]
! { dg-final { scan-tree-dump-times "6\\\]\\\[1\\\]" 2 "original" } }
......@@ -14,4 +14,4 @@ subroutine BytesToString(bytes, string)
character(len=*) :: string
string = transfer(bytes, string)
end subroutine
! { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "original" } }
! { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "original" } }
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