Bootstrapped and regression tested on powerpc64-linux (-m32/-m64), s390 and
powerpc64le-linux.

finish_arith_overflow builds a memmove call to shift the result of a
double-width multiplication down inside the destination object, on
big-endian targets where the computed value occupies more limbs than
the destination.

The destination argument correctly takes the address of OBJ, but SRC is
a MEM_REF, that is a value of array type, and it is passed directly as
memmove's second argument, which is a pointer.  Wrap it in
build_fold_addr_expr so that the address is passed instead.  Since
build_fold_addr_expr of a MEM_REF folds back to the pointer, no
dereference is materialised.

The affected code is guarded by bitint_big_endian, and is only reached
for widths whose value needs more limbs than the destination object,
that is huge _BitInt operands of __builtin_{add,sub,mul}_overflow, so
it needs a big-endian target with _BitInt support to be exercised at
all.  It is being hit now that _BitInt is being enabled for powerpc
(PR117584).

Existing coverage is sufficient: on powerpc64 big-endian this fixes
gcc.dg/torture/bitint-93.c and bitint-94.c at -O0 and -O2, and
gcc.dg/torture/bitint-32.c through bitint-37.c at -O0.  No new test is
added.

2026-08-19  Manjunath Matti  <[email protected]>

PR middle-end/126939

gcc/
        * gimple-lower-bitint.cc (bitint_large_huge::finish_arith_overflow):
        Take the address of the memmove source operand.

diff --git a/gcc/gimple-lower-bitint.cc b/gcc/gimple-lower-bitint.cc
index 52d0acad249..e36534ba13d 100644
--- a/gcc/gimple-lower-bitint.cc
+++ b/gcc/gimple-lower-bitint.cc
@@ -4594,8 +4594,9 @@ bitint_large_huge::finish_arith_overflow (tree var, tree 
obj, tree type,
                             build_fold_addr_expr (unshare_expr (obj)), off);
          g = gimple_build_call (fn, 3,
                                 build_fold_addr_expr (unshare_expr (obj)),
-                                src, build_int_cst (size_type_node,
-                                                    obj_nelts * m_limb_size));
+                                build_fold_addr_expr (src),
+                                build_int_cst (size_type_node,
+                                               obj_nelts * m_limb_size));
          insert_before (g);
        }
       if (orig_obj == NULL_TREE && obj)
-- 
2.52.0

Reply via email to