From: H.J. Lu Date: Fri, 26 Jun 2026 00:43:20 +0000 (+0800) Subject: determine_block_size: Set len_rtx to min size if min size == max size X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cbc56384029c9224280b0a1018fb9502797f243d;p=thirdparty%2Fgcc.git determine_block_size: Set len_rtx to min size if min size == max size Update determine_block_size to set len_rtx to min size if min size == max size. gcc/ PR middle-end/125977 * builtins.cc (determine_block_size): Change len_rtx to reference and set it to min size if min size == max size. * expr.cc (emit_block_move_via_pattern): Assert count == min_size if min_size == max_size. (set_storage_via_setmem): Likewise. gcc/testsuite/ PR middle-end/125977 * g++.dg/pr125977.C: New test. Signed-off-by: H.J. Lu --- diff --git a/gcc/builtins.cc b/gcc/builtins.cc index 59ac630e30c..52dd51bad55 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -3589,7 +3589,7 @@ builtin_memcpy_read_str (void *data, void *, HOST_WIDE_INT offset, set it into PROBABLE_MAX_SIZE. */ static void -determine_block_size (tree len, rtx len_rtx, +determine_block_size (tree len, rtx &len_rtx, unsigned HOST_WIDE_INT *min_size, unsigned HOST_WIDE_INT *max_size, unsigned HOST_WIDE_INT *probable_max_size) @@ -3650,9 +3650,13 @@ determine_block_size (tree len, rtx len_rtx, *probable_max_size = min.to_uhwi () - 1; } } - gcc_checking_assert (*max_size <= - (unsigned HOST_WIDE_INT) - GET_MODE_MASK (GET_MODE (len_rtx))); + + if (*min_size == *max_size) + len_rtx = GEN_INT (*min_size); + else + gcc_checking_assert (*max_size <= + (unsigned HOST_WIDE_INT) + GET_MODE_MASK (GET_MODE (len_rtx))); } /* Expand a call EXP to the memcpy builtin. diff --git a/gcc/expr.cc b/gcc/expr.cc index de73215ccc6..43931687d63 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -2320,6 +2320,8 @@ emit_block_move_via_pattern (rtx x, rtx y, rtx size, unsigned int align, else create_fixed_operand (&ops[8], NULL); } + gcc_assert (min_size != max_size + || rtx_equal_p (ops[2].value, ops[6].value)); if (maybe_expand_insn (code, nops, ops)) return true; } @@ -4045,6 +4047,8 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align, else create_fixed_operand (&ops[8], NULL); } + gcc_assert (min_size != max_size + || rtx_equal_p (ops[1].value, ops[6].value)); if (maybe_expand_insn (code, nops, ops)) return true; } diff --git a/gcc/testsuite/g++.dg/pr125977.C b/gcc/testsuite/g++.dg/pr125977.C new file mode 100644 index 00000000000..de174b72ecc --- /dev/null +++ b/gcc/testsuite/g++.dg/pr125977.C @@ -0,0 +1,50 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -std=gnu++17" } */ + +template class allocator; +char copy___s2[12]; +void assign(char, char &); +template struct allocator_traits; +template struct allocator_traits> { + using pointer = _Tp *; +}; +allocator_traits>::pointer _M_p; +struct _Alloc_result { + allocator_traits>::pointer __ptr; +}; +unsigned _M_string_length; +enum { _S_local_capacity = 5 } _M_allocated_capacity; +bool _M_is_local() { + if (_M_p) { + if (_M_string_length > _S_local_capacity) + __builtin_unreachable(); + return true; + } + return false; +} +int capacity() { + long __sz = _M_is_local() ? _S_local_capacity : _M_allocated_capacity; + return __sz; +} +struct Trans_NS___cxx11_basic_string { + void operator=(char) { _M_string_length = 0; } + void operator+=(char __c) { + _Alloc_result __trans_tmp_7; + if (_M_string_length + 1 > capacity()) { + char __s; + if (_M_string_length == 1) + assign(*__trans_tmp_7.__ptr, __s); + __builtin_memcpy(__trans_tmp_7.__ptr, ©___s2, _M_string_length); + if (_M_string_length > _S_local_capacity) + __builtin_unreachable(); + } + assign(_M_string_length, __c); + } +}; +long build_attr_access_from_parms_specend; +void build_attr_access_from_parms() { + Trans_NS___cxx11_basic_string spec; + if (build_attr_access_from_parms_specend) + spec = '+'; + spec += '['; +}