From c1b5514124ab7a8aceec1ae4a82d2149fc687ecf Mon Sep 17 00:00:00 2001 From: Richard Biener <rguenther@suse.de> Date: Thu, 17 Aug 2023 15:21:33 +0200 Subject: [PATCH] tree-optimization/111019 - invariant motion and aliasing 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. (cherry picked from commit 745ec2135aabfbe2c0fb7780309837d17e8986d4) --- gcc/testsuite/g++.dg/torture/pr111019.C | 65 +++++++++++++++++++++++++ gcc/tree-ssa-loop-im.cc | 14 +++++- 2 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr111019.C diff --git a/gcc/testsuite/g++.dg/torture/pr111019.C b/gcc/testsuite/g++.dg/torture/pr111019.C new file mode 100644 index 000000000000..ce21a311c96e --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr111019.C @@ -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; +} diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc index 86ce6acb0231..28813f11b99a 100644 --- a/gcc/tree-ssa-loop-im.cc +++ b/gcc/tree-ssa-loop-im.cc @@ -1656,11 +1656,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, -- GitLab