]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
determine_block_size: Set len_rtx to min size if min size == max size
authorH.J. Lu <hjl.tools@gmail.com>
Fri, 26 Jun 2026 00:43:20 +0000 (08:43 +0800)
committerH.J. Lu <hjl.tools@gmail.com>
Fri, 26 Jun 2026 12:46:00 +0000 (20:46 +0800)
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 <hjl.tools@gmail.com>
gcc/builtins.cc
gcc/expr.cc
gcc/testsuite/g++.dg/pr125977.C [new file with mode: 0644]

index 59ac630e30c77bd9c5ecb705b8303cc42a22e574..52dd51bad5574686f901a1edadba4f64e7fe94a9 100644 (file)
@@ -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.
index de73215ccc6623fa90f4a90212fd8dc7c50991a9..43931687d63e161bfa8f03ec7882d076bbdcbcf2 100644 (file)
@@ -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 (file)
index 0000000..de174b7
--- /dev/null
@@ -0,0 +1,50 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=gnu++17" } */
+
+template <typename> class allocator;
+char copy___s2[12];
+void assign(char, char &);
+template <typename> struct allocator_traits;
+template <typename _Tp> struct allocator_traits<allocator<_Tp>> {
+  using pointer = _Tp *;
+};
+allocator_traits<allocator<char>>::pointer _M_p;
+struct _Alloc_result {
+  allocator_traits<allocator<char>>::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, &copy___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 += '[';
+}