* [PATCH] PR35258: Prevent CSE from generating overlapping memmoves
@ 2008-02-22 14:55 Andreas Krebbel
2008-02-22 14:57 ` Richard Guenther
0 siblings, 1 reply; 4+ messages in thread
From: Andreas Krebbel @ 2008-02-22 14:55 UTC (permalink / raw)
To: gcc-patches
Hi,
the attached patch prevents cse from creating overlapping mem to mem
copies. This fixes PR 35258.
Bootstrapped on x86_64, s390 and s390x.
No testsuite regressions.
Ok for mainline? What about 4.3?
Bye,
-Andreas-
2008-02-22 Andreas Krebbel <krebbel1@de.ibm.com>
* cse.c (cse_mem_cannot_overlap_p): New function.
(cse_insn): Avoid creation of overlapping MEMs.
2008-02-22 Andreas Krebbel <krebbel1@de.ibm.com>
* gcc.dg/pr35258.c: New testcase.
Index: gcc/cse.c
===================================================================
*** gcc/cse.c.orig 2008-02-22 10:46:18.000000000 +0100
--- gcc/cse.c 2008-02-22 11:27:11.000000000 +0100
*************** fixed_base_plus_p (rtx x)
*** 640,645 ****
--- 640,681 ----
}
}
+ /* Return true if it can be proven that the memory locations MEM1 and
+ MEM2 do not overlap. */
+ static bool
+ cse_mem_cannot_overlap_p (rtx mem1, rtx mem2, HOST_WIDE_INT size)
+ {
+ HOST_WIDE_INT delta;
+ rtx addr_delta;
+
+ gcc_assert (MEM_P (mem1));
+ gcc_assert (MEM_P (mem2));
+
+ mem1 = XEXP (mem1, 0);
+ mem2 = XEXP (mem2, 0);
+
+ if (GET_CODE (mem1) == CONST)
+ mem1 = XEXP (mem1, 0);
+ if (GET_CODE (mem2) == CONST)
+ mem2 = XEXP (mem2, 0);
+
+ if (size == 0)
+ return true;
+
+ addr_delta = simplify_binary_operation (MINUS, Pmode, mem1, mem2);
+
+ if (!addr_delta || GET_CODE (addr_delta) != CONST_INT)
+ return false;
+
+ delta = INTVAL (addr_delta);
+
+ if ((delta >= 0 && delta < size)
+ || (delta < 0 && -delta < size))
+ return false;
+
+ return true;
+ }
+
/* Dump the expressions in the equivalence class indicated by CLASSP.
This function is used only for debugging. */
void
*************** cse_insn (rtx insn, rtx libcall_insn)
*** 4753,4758 ****
--- 4789,4812 ----
src_elt_cost = MAX_COST;
}
+ /* Avoid creation of overlapping memory moves. */
+ if (MEM_P (trial) && MEM_P (SET_DEST (sets[i].rtl)))
+ {
+ rtx src, dest;
+
+ /* BLKmode moves are not handled by cse anyway. */
+ if (GET_MODE (trial) == BLKmode)
+ break;
+
+ src = canon_rtx (trial);
+ dest = canon_rtx (SET_DEST (sets[i].rtl));
+
+ if (!MEM_P (src) || !MEM_P (dest)
+ || !cse_mem_cannot_overlap_p (src, dest,
+ GET_MODE_SIZE (GET_MODE (src))))
+ break;
+ }
+
/* We don't normally have an insn matching (set (pc) (pc)), so
check for this separately here. We will delete such an
insn below.
Index: gcc/testsuite/gcc.dg/pr35258.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/pr35258.c 2008-02-22 10:47:55.000000000 +0100
***************
*** 0 ****
--- 1,28 ----
+ /* { dg-do run } */
+ /* { dg-options "-O1" } */
+
+ extern void *memcpy (void *, const void *, __SIZE_TYPE__);
+ extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+ extern void abort(void);
+
+ char str[9] = "1234";
+
+ void
+ bar (void)
+ {
+ unsigned int temp;
+ char *p = &str[2];
+
+ memcpy (&temp, &str[1], 4);
+ memcpy (p, &temp, 4);
+ str[1] = '.';
+ }
+
+ int main()
+ {
+ bar();
+ if (memcmp (str, "1.234", 5) != 0)
+ abort ();
+
+ return 0;
+ }
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] PR35258: Prevent CSE from generating overlapping memmoves
2008-02-22 14:55 [PATCH] PR35258: Prevent CSE from generating overlapping memmoves Andreas Krebbel
@ 2008-02-22 14:57 ` Richard Guenther
2008-02-25 13:43 ` Andreas Krebbel
0 siblings, 1 reply; 4+ messages in thread
From: Richard Guenther @ 2008-02-22 14:57 UTC (permalink / raw)
To: Andreas Krebbel; +Cc: gcc-patches
On Fri, Feb 22, 2008 at 3:29 PM, Andreas Krebbel
<Andreas.Krebbel@de.ibm.com> wrote:
> Hi,
>
> the attached patch prevents cse from creating overlapping mem to mem
> copies. This fixes PR 35258.
>
> Bootstrapped on x86_64, s390 and s390x.
> No testsuite regressions.
>
> Ok for mainline? What about 4.3?
It looks like you can use nonoverlapping_memrefs_p from alias.c
instead of adding cse_mem_cannot_overlap_p?
Richard.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] PR35258: Prevent CSE from generating overlapping memmoves
2008-02-22 14:57 ` Richard Guenther
@ 2008-02-25 13:43 ` Andreas Krebbel
2008-02-25 14:58 ` Richard Guenther
0 siblings, 1 reply; 4+ messages in thread
From: Andreas Krebbel @ 2008-02-25 13:43 UTC (permalink / raw)
To: Richard Guenther; +Cc: gcc-patches
Hi,
> It looks like you can use nonoverlapping_memrefs_p from alias.c
> instead of adding cse_mem_cannot_overlap_p?
I thought that one is only supposed to be used from within alias.c but
actually I don't see a reason for that.
So here is the patch.
Bootstrapped and regtested on x86_64, s390 and s390x.
OK for mainline and 4.3?
Bye,
-Andreas-
2008-02-25 Andreas Krebbel <krebbel1@de.ibm.com>
* cse.c (cse_insn): Avoid creation of overlapping MEMs.
* alias.c (nonoverlapping_memrefs_p): Export for use in other modules.
* alias.h (nonoverlapping_memrefs_p): Likewise.
2008-02-25 Andreas Krebbel <krebbel1@de.ibm.com>
* gcc.dg/pr35258.c: New testcase.
Index: gcc/cse.c
===================================================================
*** gcc/cse.c.orig 2008-02-22 10:46:18.000000000 +0100
--- gcc/cse.c 2008-02-25 09:15:34.000000000 +0100
*************** cse_insn (rtx insn, rtx libcall_insn)
*** 4753,4758 ****
--- 4753,4775 ----
src_elt_cost = MAX_COST;
}
+ /* Avoid creation of overlapping memory moves. */
+ if (MEM_P (trial) && MEM_P (SET_DEST (sets[i].rtl)))
+ {
+ rtx src, dest;
+
+ /* BLKmode moves are not handled by cse anyway. */
+ if (GET_MODE (trial) == BLKmode)
+ break;
+
+ src = canon_rtx (trial);
+ dest = canon_rtx (SET_DEST (sets[i].rtl));
+
+ if (!MEM_P (src) || !MEM_P (dest)
+ || !nonoverlapping_memrefs_p (src, dest))
+ break;
+ }
+
/* We don't normally have an insn matching (set (pc) (pc)), so
check for this separately here. We will delete such an
insn below.
Index: gcc/testsuite/gcc.dg/pr35258.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/pr35258.c 2008-02-22 10:47:55.000000000 +0100
***************
*** 0 ****
--- 1,28 ----
+ /* { dg-do run } */
+ /* { dg-options "-O1" } */
+
+ extern void *memcpy (void *, const void *, __SIZE_TYPE__);
+ extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+ extern void abort(void);
+
+ char str[9] = "1234";
+
+ void
+ bar (void)
+ {
+ unsigned int temp;
+ char *p = &str[2];
+
+ memcpy (&temp, &str[1], 4);
+ memcpy (p, &temp, 4);
+ str[1] = '.';
+ }
+
+ int main()
+ {
+ bar();
+ if (memcmp (str, "1.234", 5) != 0)
+ abort ();
+
+ return 0;
+ }
Index: gcc/alias.c
===================================================================
*** gcc/alias.c.orig 2007-10-26 10:35:40.000000000 +0200
--- gcc/alias.c 2008-02-25 09:11:51.000000000 +0100
*************** static int aliases_everything_p (const_r
*** 164,170 ****
static bool nonoverlapping_component_refs_p (const_tree, const_tree);
static tree decl_for_component_ref (tree);
static rtx adjust_offset_for_component_ref (tree, rtx);
- static int nonoverlapping_memrefs_p (const_rtx, const_rtx);
static int write_dependence_p (const_rtx, const_rtx, int);
static void memory_modified_1 (rtx, const_rtx, void *);
--- 164,169 ----
*************** adjust_offset_for_component_ref (tree x,
*** 1976,1982 ****
/* Return nonzero if we can determine the exprs corresponding to memrefs
X and Y and they do not overlap. */
! static int
nonoverlapping_memrefs_p (const_rtx x, const_rtx y)
{
tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
--- 1975,1981 ----
/* Return nonzero if we can determine the exprs corresponding to memrefs
X and Y and they do not overlap. */
! int
nonoverlapping_memrefs_p (const_rtx x, const_rtx y)
{
tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
Index: gcc/alias.h
===================================================================
*** gcc/alias.h.orig 2007-08-28 08:51:49.000000000 +0200
--- gcc/alias.h 2008-02-25 09:10:48.000000000 +0100
*************** extern alias_set_type get_varargs_alias_
*** 28,33 ****
--- 28,34 ----
extern alias_set_type get_frame_alias_set (void);
extern bool component_uses_parent_alias_set (const_tree);
extern bool alias_set_subset_of (alias_set_type, alias_set_type);
+ extern int nonoverlapping_memrefs_p (const_rtx, const_rtx);
/* This alias set can be used to force a memory to conflict with all
other memories, creating a barrier across which no memory reference
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] PR35258: Prevent CSE from generating overlapping memmoves
2008-02-25 13:43 ` Andreas Krebbel
@ 2008-02-25 14:58 ` Richard Guenther
0 siblings, 0 replies; 4+ messages in thread
From: Richard Guenther @ 2008-02-25 14:58 UTC (permalink / raw)
To: Andreas Krebbel; +Cc: gcc-patches
On Mon, Feb 25, 2008 at 2:24 PM, Andreas Krebbel
<Andreas.Krebbel@de.ibm.com> wrote:
> Hi,
>
>
> > It looks like you can use nonoverlapping_memrefs_p from alias.c
> > instead of adding cse_mem_cannot_overlap_p?
>
> I thought that one is only supposed to be used from within alias.c but
> actually I don't see a reason for that.
>
> So here is the patch.
>
> Bootstrapped and regtested on x86_64, s390 and s390x.
>
> OK for mainline and 4.3?
Ok for mainline and 4.3.1 (please wait until after 4.3.0 is out).
Thanks,
Richard.
> Bye,
>
> -Andreas-
>
> 2008-02-25 Andreas Krebbel <krebbel1@de.ibm.com>
>
> * cse.c (cse_insn): Avoid creation of overlapping MEMs.
> * alias.c (nonoverlapping_memrefs_p): Export for use in other modules.
> * alias.h (nonoverlapping_memrefs_p): Likewise.
>
> 2008-02-25 Andreas Krebbel <krebbel1@de.ibm.com>
>
>
> * gcc.dg/pr35258.c: New testcase.
>
> Index: gcc/cse.c
> ===================================================================
> *** gcc/cse.c.orig 2008-02-22 10:46:18.000000000 +0100
> --- gcc/cse.c 2008-02-25 09:15:34.000000000 +0100
>
> *************** cse_insn (rtx insn, rtx libcall_insn)
> *** 4753,4758 ****
> --- 4753,4775 ----
>
> src_elt_cost = MAX_COST;
> }
>
> + /* Avoid creation of overlapping memory moves. */
> + if (MEM_P (trial) && MEM_P (SET_DEST (sets[i].rtl)))
> + {
> + rtx src, dest;
> +
> + /* BLKmode moves are not handled by cse anyway. */
> + if (GET_MODE (trial) == BLKmode)
> + break;
> +
> + src = canon_rtx (trial);
> + dest = canon_rtx (SET_DEST (sets[i].rtl));
> +
> + if (!MEM_P (src) || !MEM_P (dest)
> + || !nonoverlapping_memrefs_p (src, dest))
>
>
> + break;
> + }
> +
> /* We don't normally have an insn matching (set (pc) (pc)), so
> check for this separately here. We will delete such an
> insn below.
> Index: gcc/testsuite/gcc.dg/pr35258.c
> ===================================================================
> *** /dev/null 1970-01-01 00:00:00.000000000 +0000
> --- gcc/testsuite/gcc.dg/pr35258.c 2008-02-22 10:47:55.000000000 +0100
> ***************
> *** 0 ****
> --- 1,28 ----
> + /* { dg-do run } */
> + /* { dg-options "-O1" } */
> +
> + extern void *memcpy (void *, const void *, __SIZE_TYPE__);
> + extern int memcmp (const void *, const void *, __SIZE_TYPE__);
> + extern void abort(void);
> +
> + char str[9] = "1234";
> +
> + void
> + bar (void)
> + {
> + unsigned int temp;
> + char *p = &str[2];
> +
> + memcpy (&temp, &str[1], 4);
> + memcpy (p, &temp, 4);
> + str[1] = '.';
> + }
> +
> + int main()
> + {
> + bar();
> + if (memcmp (str, "1.234", 5) != 0)
> + abort ();
> +
> + return 0;
> + }
> Index: gcc/alias.c
> ===================================================================
> *** gcc/alias.c.orig 2007-10-26 10:35:40.000000000 +0200
> --- gcc/alias.c 2008-02-25 09:11:51.000000000 +0100
> *************** static int aliases_everything_p (const_r
> *** 164,170 ****
> static bool nonoverlapping_component_refs_p (const_tree, const_tree);
> static tree decl_for_component_ref (tree);
> static rtx adjust_offset_for_component_ref (tree, rtx);
> - static int nonoverlapping_memrefs_p (const_rtx, const_rtx);
> static int write_dependence_p (const_rtx, const_rtx, int);
>
> static void memory_modified_1 (rtx, const_rtx, void *);
> --- 164,169 ----
> *************** adjust_offset_for_component_ref (tree x,
> *** 1976,1982 ****
> /* Return nonzero if we can determine the exprs corresponding to memrefs
> X and Y and they do not overlap. */
>
> ! static int
> nonoverlapping_memrefs_p (const_rtx x, const_rtx y)
> {
> tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
> --- 1975,1981 ----
> /* Return nonzero if we can determine the exprs corresponding to memrefs
> X and Y and they do not overlap. */
>
> ! int
> nonoverlapping_memrefs_p (const_rtx x, const_rtx y)
> {
> tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
> Index: gcc/alias.h
> ===================================================================
> *** gcc/alias.h.orig 2007-08-28 08:51:49.000000000 +0200
> --- gcc/alias.h 2008-02-25 09:10:48.000000000 +0100
> *************** extern alias_set_type get_varargs_alias_
> *** 28,33 ****
> --- 28,34 ----
> extern alias_set_type get_frame_alias_set (void);
> extern bool component_uses_parent_alias_set (const_tree);
> extern bool alias_set_subset_of (alias_set_type, alias_set_type);
> + extern int nonoverlapping_memrefs_p (const_rtx, const_rtx);
>
> /* This alias set can be used to force a memory to conflict with all
> other memories, creating a barrier across which no memory reference
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2008-02-25 14:25 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-02-22 14:55 [PATCH] PR35258: Prevent CSE from generating overlapping memmoves Andreas Krebbel
2008-02-22 14:57 ` Richard Guenther
2008-02-25 13:43 ` Andreas Krebbel
2008-02-25 14:58 ` Richard Guenther
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).