]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/111019 - invariant motion and aliasing
authorRichard Biener <rguenther@suse.de>
Thu, 17 Aug 2023 13:21:33 +0000 (15:21 +0200)
committerRichard Biener <rguenther@suse.de>
Fri, 18 Aug 2023 13:04:48 +0000 (15:04 +0200)
The following fixes a bad choice in representing things to the alias
oracle by LIM which while correct in pieces is inconsistent with itself.
When canonicalizing a ref to a bare deref instead of leaving the base
object and the extracted offset the same and just substituting an
alternate ref the following replaces the base and the offset as well,
avoiding the confusion that otherwise will arise in
aliasing_matching_component_refs_p.

PR tree-optimization/111019
* tree-ssa-loop-im.cc (gather_mem_refs_stmt): When canonicalizing
also scrap base and offset in case the ref is indirect.

* g++.dg/torture/pr111019.C: New testcase.

gcc/testsuite/g++.dg/torture/pr111019.C [new file with mode: 0644]
gcc/tree-ssa-loop-im.cc

diff --git a/gcc/testsuite/g++.dg/torture/pr111019.C b/gcc/testsuite/g++.dg/torture/pr111019.C
new file mode 100644 (file)
index 0000000..ce21a31
--- /dev/null
@@ -0,0 +1,65 @@
+// { dg-do run }
+// { dg-additional-options "-fstrict-aliasing" }
+
+#include <cassert>
+#include <memory>
+#include <string>
+
+class Base
+{
+public:
+  Base* previous = nullptr;
+  Base* next = nullptr;
+  Base* target = nullptr;
+};
+
+class Target : public Base
+{
+public:
+  __attribute__((always_inline)) ~Target()
+  {
+    while (this->next)
+    {
+      Base* n = this->next;
+
+      if (n->previous)
+        n->previous->next = n->next;
+      if (n->next)
+        n->next->previous = n->previous;
+      n->previous = nullptr;
+      n->next = nullptr;
+      n->target = nullptr;
+    }
+  }
+};
+
+template <typename T>
+class TargetWithData final : public Target
+{
+public:
+  TargetWithData(T data)
+    : data(data)
+  {}
+  T data;
+};
+
+void test()
+{
+  printf("test\n");
+  Base ptr;
+  {
+    auto data = std::make_unique<TargetWithData<std::string>>(std::string("asdf"));
+    ptr.target = &*data;
+    ptr.previous = &*data;
+    data->next = &ptr;
+
+    assert(ptr.target != nullptr);
+  }
+  assert(ptr.target == nullptr);
+}
+
+int main(int, char**)
+{
+  test();
+  return 0;
+}
index 268f466bdc9f547525763ef9748c9aae58195cd5..b8e33a4d49a131c422eacb1754ca55d9564ae9d4 100644 (file)
@@ -1665,11 +1665,21 @@ gather_mem_refs_stmt (class loop *loop, gimple *stmt)
                                     unshare_expr (mem_base));
                  if (TYPE_ALIGN (ref_type) != ref_align)
                    ref_type = build_aligned_type (ref_type, ref_align);
-                 (*slot)->mem.ref
+                 tree new_ref
                    = fold_build2 (MEM_REF, ref_type, tmp,
                                   build_int_cst (ref_alias_type, mem_off));
                  if ((*slot)->mem.volatile_p)
-                   TREE_THIS_VOLATILE ((*slot)->mem.ref) = 1;
+                   TREE_THIS_VOLATILE (new_ref) = 1;
+                 (*slot)->mem.ref = new_ref;
+                 /* Make sure the recorded base and offset are consistent
+                    with the newly built ref.  */
+                 if (TREE_CODE (TREE_OPERAND (new_ref, 0)) == ADDR_EXPR)
+                   ;
+                 else
+                   {
+                     (*slot)->mem.base = new_ref;
+                     (*slot)->mem.offset = 0;
+                   }
                  gcc_checking_assert (TREE_CODE ((*slot)->mem.ref) == MEM_REF
                                       && is_gimple_mem_ref_addr
                                            (TREE_OPERAND ((*slot)->mem.ref,