From: Richard Biener <rguenther@suse.de>
To: Jakub Jelinek <jakub@redhat.com>
Cc: Jeff Law <law@redhat.com>, gcc-patches@gcc.gnu.org
Subject: Re: [PATCH][RFC] Fix PR61473, inline small memcpy/memmove during tree opts
Date: Fri, 11 Jul 2014 13:39:00 -0000 [thread overview]
Message-ID: <alpine.LSU.2.11.1407111535370.5753@zhemvz.fhfr.qr> (raw)
In-Reply-To: <alpine.LSU.2.11.1407111000040.5753@zhemvz.fhfr.qr>
On Fri, 11 Jul 2014, Richard Biener wrote:
> On Thu, 10 Jul 2014, Jakub Jelinek wrote:
>
> > On Thu, Jul 10, 2014 at 04:30:13PM +0200, Richard Biener wrote:
> > > Compromise "hack" below. It simply avoids the transform for
> > > sources that c_strlen can compute a length of. That "fixes" all
> > > strlenopt testcase apart from strlenopt-8.c which does
> > > memcpy (, flag ? "a" : "b"); which then still folds
> > > during gimplification. I have XFAILed that.
> > >
> > > I've tried to comb my way through strlenopt but failed to quickly
> > > add support for generic stores (it has very rough support for
> > > char stores, see also PR61773).
> > >
> > > Does the below look ok?
> >
> > I can look at the tree-ssa-strlen.c stuff and removing the !c_strlen
> > hack incrementally.
>
> Ok, I'll bootstrap/test the patch then and will commit if there are
> no issues left.
This is what I have applied.
Bootstrapped and tested on x86_64-unknown-linux-gnu.
Richard.
2014-07-11 Richard Biener <rguenther@suse.de>
PR middle-end/61473
* builtins.c (fold_builtin_memory_op): Inline memory moves
that can be implemented with a single load followed by a
single store.
(c_strlen): Only warn when only_value is not 2.
* gcc.dg/memmove-4.c: New testcase.
* gcc.dg/strlenopt-8.c: XFAIL.
* gfortran.dg/coarray_lib_realloc_1.f90: Adjust.
Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c.orig 2014-07-11 09:54:49.844932232 +0200
--- gcc/builtins.c 2014-07-11 13:15:35.297102917 +0200
*************** get_pointer_alignment (tree exp)
*** 535,540 ****
--- 535,544 ----
len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
evaluate the side-effects.
+ If ONLY_VALUE is two then we do not emit warnings about out-of-bound
+ accesses. Note that this implies the result is not going to be emitted
+ into the instruction stream.
+
The value returned is of type `ssizetype'.
Unfortunately, string_constant can't access the values of const char
*************** c_strlen (tree src, int only_value)
*** 606,612 ****
/* If the offset is known to be out of bounds, warn, and call strlen at
runtime. */
! if (offset < 0 || offset > max)
{
/* Suppress multiple warnings for propagated constant strings. */
if (! TREE_NO_WARNING (src))
--- 610,617 ----
/* If the offset is known to be out of bounds, warn, and call strlen at
runtime. */
! if (only_value != 2
! && (offset < 0 || offset > max))
{
/* Suppress multiple warnings for propagated constant strings. */
if (! TREE_NO_WARNING (src))
*************** fold_builtin_memory_op (location_t loc,
*** 8637,8647 ****
unsigned int src_align, dest_align;
tree off0;
! if (endp == 3)
{
! src_align = get_pointer_alignment (src);
! dest_align = get_pointer_alignment (dest);
/* Both DEST and SRC must be pointer types.
??? This is what old code did. Is the testing for pointer types
really mandatory?
--- 8642,8698 ----
unsigned int src_align, dest_align;
tree off0;
! /* Build accesses at offset zero with a ref-all character type. */
! off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
! ptr_mode, true), 0);
!
! /* If we can perform the copy efficiently with first doing all loads
! and then all stores inline it that way. Currently efficiently
! means that we can load all the memory into a single integer
! register which is what MOVE_MAX gives us. */
! src_align = get_pointer_alignment (src);
! dest_align = get_pointer_alignment (dest);
! if (tree_fits_uhwi_p (len)
! && compare_tree_int (len, MOVE_MAX) <= 0
! /* ??? Don't transform copies from strings with known length this
! confuses the tree-ssa-strlen.c. This doesn't handle
! the case in gcc.dg/strlenopt-8.c which is XFAILed for that
! reason. */
! && !c_strlen (src, 2))
{
! unsigned ilen = tree_to_uhwi (len);
! if (exact_log2 (ilen) != -1)
! {
! tree type = lang_hooks.types.type_for_size (ilen * 8, 1);
! if (type
! && TYPE_MODE (type) != BLKmode
! && (GET_MODE_SIZE (TYPE_MODE (type)) * BITS_PER_UNIT
! == ilen * 8)
! /* If the pointers are not aligned we must be able to
! emit an unaligned load. */
! && ((src_align >= GET_MODE_ALIGNMENT (TYPE_MODE (type))
! && dest_align >= GET_MODE_ALIGNMENT (TYPE_MODE (type)))
! || !SLOW_UNALIGNED_ACCESS (TYPE_MODE (type),
! MIN (src_align, dest_align))))
! {
! tree srctype = type;
! tree desttype = type;
! if (src_align < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
! srctype = build_aligned_type (type, src_align);
! if (dest_align < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
! desttype = build_aligned_type (type, dest_align);
! if (!ignore)
! dest = builtin_save_expr (dest);
! expr = build2 (MODIFY_EXPR, type,
! fold_build2 (MEM_REF, desttype, dest, off0),
! fold_build2 (MEM_REF, srctype, src, off0));
! goto done;
! }
! }
! }
+ if (endp == 3)
+ {
/* Both DEST and SRC must be pointer types.
??? This is what old code did. Is the testing for pointer types
really mandatory?
*************** fold_builtin_memory_op (location_t loc,
*** 8818,8827 ****
if (!ignore)
dest = builtin_save_expr (dest);
- /* Build accesses at offset zero with a ref-all character type. */
- off0 = build_int_cst (build_pointer_type_for_mode (char_type_node,
- ptr_mode, true), 0);
-
destvar = dest;
STRIP_NOPS (destvar);
if (TREE_CODE (destvar) == ADDR_EXPR
--- 8869,8874 ----
*************** fold_builtin_memory_op (location_t loc,
*** 8888,8893 ****
--- 8935,8941 ----
expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, srcvar);
}
+ done:
if (ignore)
return expr;
Index: gcc/testsuite/gcc.dg/memmove-4.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/memmove-4.c 2014-07-11 12:34:10.168274016 +0200
***************
*** 0 ****
--- 1,12 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-optimized" } */
+
+ typedef int w __attribute__((mode(word)));
+
+ void b(char *a, char *b, int i)
+ {
+ __builtin_memmove (&a[i], &b[i], sizeof(w));
+ }
+
+ /* { dg-final { scan-tree-dump-not "memmove" "optimized" { xfail { ! non_strict_align } } } } */
+ /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: gcc/testsuite/gcc.dg/strlenopt-8.c
===================================================================
*** gcc/testsuite/gcc.dg/strlenopt-8.c.orig 2014-07-11 09:54:49.844932232 +0200
--- gcc/testsuite/gcc.dg/strlenopt-8.c 2014-07-11 12:34:10.168274016 +0200
*************** main ()
*** 43,50 ****
return 0;
}
! /* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
! /* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
--- 43,50 ----
return 0;
}
! /* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" { xfail *-*-* } } } */
! /* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
Index: gcc/testsuite/gfortran.dg/coarray_lib_realloc_1.f90
===================================================================
*** gcc/testsuite/gfortran.dg/coarray_lib_realloc_1.f90.orig 2014-07-11 09:54:49.844932232 +0200
--- gcc/testsuite/gfortran.dg/coarray_lib_realloc_1.f90 2014-07-11 12:34:10.178274015 +0200
*************** end
*** 30,35 ****
! { dg-final { scan-tree-dump-times "__builtin_malloc" 1 "original" } }
! But copy "ii" and "CAF":
! ! { dg-final { scan-tree-dump-times "__builtin_memcpy" 2 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
--- 30,35 ----
! { dg-final { scan-tree-dump-times "__builtin_malloc" 1 "original" } }
! But copy "ii" and "CAF":
! ! { dg-final { scan-tree-dump-times "__builtin_memcpy|= MEM" 2 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
next prev parent reply other threads:[~2014-07-11 13:39 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-12 10:15 Richard Biener
2014-06-12 20:32 ` Jeff Law
2014-06-27 11:52 ` Richard Biener
2014-06-27 11:57 ` Jakub Jelinek
2014-06-27 12:01 ` Richard Biener
2014-07-10 14:33 ` Richard Biener
2014-07-10 15:13 ` Jakub Jelinek
2014-07-11 8:03 ` Richard Biener
2014-07-11 13:39 ` Richard Biener [this message]
2014-07-11 13:42 ` Jakub Jelinek
2014-07-14 7:54 ` Richard Biener
2014-07-14 11:12 ` Richard Biener
2014-06-27 15:44 ` Jeff Law
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alpine.LSU.2.11.1407111535370.5753@zhemvz.fhfr.qr \
--to=rguenther@suse.de \
--cc=gcc-patches@gcc.gnu.org \
--cc=jakub@redhat.com \
--cc=law@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).