rtl-optimization/120182 - wrong-code with RTL DSE and constant addresses
authorRichard Biener <rguenther@suse.de>
Fri, 9 May 2025 06:38:45 +0000 (08:38 +0200)
committerRichard Biener <rguenther@suse.de>
Fri, 9 May 2025 09:32:03 +0000 (11:32 +0200)
RTL DSE forms store groups from unique invariant bases but that is
confused when presented with constant addresses where it assigns
one store group per unique address.  That causes it to not consider
0x101:QI to alias 0x100:SI.  Constant accesses can really alias
to every object, in practice they appear for I/O and for access
to objects fixed via linker scripts for example.  So simply avoid
registering a store group for them.

PR rtl-optimization/120182
* dse.cc (canon_address): Constant addresses have no
separate store group.

* gcc.dg/torture/pr120182.c: New testcase.

gcc/dse.cc
gcc/testsuite/gcc.dg/torture/pr120182.c [new file with mode: 0644]

index ffc86ffabe5ea4c8d0317fd447658727038ab2b0..14f82c364c06f6956bac69a46e59dcef675da70b 100644 (file)
@@ -1190,7 +1190,10 @@ canon_address (rtx mem,
       address = strip_offset_and_add (address, offset);
 
       if (ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (mem))
-         && const_or_frame_p (address))
+         && const_or_frame_p (address)
+         /* Literal addresses can alias any base, avoid creating a
+            group for them.  */
+         && ! CONST_SCALAR_INT_P (address))
        {
          group_info *group = get_group_info (address);
 
diff --git a/gcc/testsuite/gcc.dg/torture/pr120182.c b/gcc/testsuite/gcc.dg/torture/pr120182.c
new file mode 100644 (file)
index 0000000..5e2d171
--- /dev/null
@@ -0,0 +1,42 @@
+/* { dg-do run { target { { *-*-linux* *-*-gnu* *-*-uclinux* } && mmap } } } */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+struct S
+{
+  struct S *next;
+};
+
+static void __attribute__((noipa))
+allocate(void *addr, unsigned long long size)
+{
+  void *ptr = mmap((void *)addr, size,
+                  PROT_READ | PROT_WRITE,
+                  MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE,
+                  -1, 0);
+  if(ptr != addr)
+    exit(0);
+}
+
+int main (void)
+{
+  int size = 0x8000;
+  char *ptr = (char *)0x288000ull;
+  allocate((void *)ptr, size);
+
+  struct S *s1 = (struct S *)ptr;
+  struct S *s2 = (struct S *)256;
+  for (int i = 0; i < 3; i++)
+    {
+      for(char *addr = (char *)s1; addr < (char *)s1 + sizeof(*s1); ++addr)
+       *addr = 0;
+
+      if(s1->next)
+       s1->next = s1->next->next = s2;
+      else
+       s1->next = s2;
+    }
+  return 0;
+}
This page took 0.062617 seconds and 5 git commands to generate.