From e8969a86c1052e2949028f38daf8e273e7ecb106 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 28 Aug 2025 14:27:01 +0200 Subject: tree-optimization/121685 - accesses to *this are not trapping When inside a method then we know the this pointer points to an object of at least the size of the methods base type. We can use this to compute more references as not trapping and enable invariant motion and in turn vectorization as for a slightly modified version of the testcase in the PR. PR tree-optimization/121685 * tree-eh.cc (ref_outside_object_p): Split out from ... (tree_could_trap_p): ... here. Assume the this pointer of a method refers to an object of at least size of its base type. * g++.dg/vect/pr121685-1.cc: New testcase. --- gcc/testsuite/g++.dg/vect/pr121685-1.cc | 20 +++++++++++++++ gcc/tree-eh.cc | 45 +++++++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/vect/pr121685-1.cc (limited to 'gcc') diff --git a/gcc/testsuite/g++.dg/vect/pr121685-1.cc b/gcc/testsuite/g++.dg/vect/pr121685-1.cc new file mode 100644 index 0000000..faac9ba --- /dev/null +++ b/gcc/testsuite/g++.dg/vect/pr121685-1.cc @@ -0,0 +1,20 @@ +// { dg-do compile } +// { dg-additional-options "-mavx2" { target avx2 } } + +#include + +class Foo +{ +public: + void fun (std::vector& blacksq); + std::vector m_mcowner; +}; + +void Foo::fun(std::vector& blacksq) +{ + for (unsigned int i = 0; i < (unsigned int)blacksq.size(); i++) + if (blacksq[i]) + m_mcowner[i]++; +} + +// { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { target avx2 } } } diff --git a/gcc/tree-eh.cc b/gcc/tree-eh.cc index 8cc81eb..5c62e6b 100644 --- a/gcc/tree-eh.cc +++ b/gcc/tree-eh.cc @@ -2674,6 +2674,25 @@ access_in_bounds_of_type_p (tree type, poly_uint64 size, poly_uint64 offset) return true; } +/* Return whether an access at [off, refsz[ to an object spanning [0, size[ + accesses storage outside of the object. */ + +static bool +ref_outside_object_p (tree size, poly_offset_int off, tree refsz) +{ + if (size == NULL_TREE + || refsz == NULL_TREE + || !poly_int_tree_p (size) + || !poly_int_tree_p (refsz) + || maybe_le (wi::to_poly_offset (size), off) + || maybe_gt (off + wi::to_poly_offset (refsz), + wi::to_poly_offset (size))) + return true; + /* Now we are sure the whole base of the access is inside + the object. */ + return false; +} + /* Return true if EXPR can trap, as in dereferencing an invalid pointer location or floating point arithmetic. C.f. the rtl version, may_trap_p. This routine expects only GIMPLE lhs or rhs input. */ @@ -2771,17 +2790,23 @@ tree_could_trap_p (tree expr) return maybe_le (TREE_STRING_LENGTH (base), off); tree size = DECL_SIZE_UNIT (base); tree refsz = TYPE_SIZE_UNIT (TREE_TYPE (expr)); - if (size == NULL_TREE - || refsz == NULL_TREE - || !poly_int_tree_p (size) - || !poly_int_tree_p (refsz) - || maybe_le (wi::to_poly_offset (size), off) - || maybe_gt (off + wi::to_poly_offset (refsz), - wi::to_poly_offset (size))) + return ref_outside_object_p (size, off, refsz); + } + if (cfun + && TREE_CODE (TREE_TYPE (cfun->decl)) == METHOD_TYPE + && ((TREE_CODE (TREE_OPERAND (expr, 0)) == SSA_NAME + && SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (expr, 0)) + && (SSA_NAME_VAR (TREE_OPERAND (expr, 0)) + == DECL_ARGUMENTS (cfun->decl))) + || TREE_OPERAND (expr, 0) == DECL_ARGUMENTS (cfun->decl))) + { + poly_offset_int off = mem_ref_offset (expr); + if (maybe_lt (off, 0)) return true; - /* Now we are sure the whole base of the access is inside - the object. */ - return false; + tree size = TYPE_SIZE_UNIT + (TYPE_METHOD_BASETYPE (TREE_TYPE (cfun->decl))); + tree refsz = TYPE_SIZE_UNIT (TREE_TYPE (expr)); + return ref_outside_object_p (size, off, refsz); } return true; -- cgit v1.1