https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126939
Bug ID: 126939
Summary: Fix memmove source operand in finish_arith_overflow at
gimple-lower-bitint.cc
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: mmatti at linux dot vnet.ibm.com
Target Milestone: ---
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:
else if (obj && bitint_big_endian && nelts != obj_nelts)
{
...
tree src = build2 (MEM_REF, atype,
build_fold_addr_expr (unshare_expr (obj)), off);
g = gimple_build_call (fn, 3,
build_fold_addr_expr (unshare_expr (obj)),
src, ...);
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.
On powerpc64 big-endian gcc.dg/torture/bitint-93.c fails with
Program received signal SIGSEGV, Segmentation fault.
__memmove_power7 () at memmove.S:707
#1 f1 (q=<error reading variable: Cannot access memory at address 0x1>, ...)
at bitint-93.c:20
Similar failures are observed
gcc.dg/torture/bitint-32.c -m64 -O0 only (passes -O2)
gcc.dg/torture/bitint-33.c -m64 -O0 only (passes -O2)
gcc.dg/torture/bitint-34.c -m64 -O0 only (passes -O2)
gcc.dg/torture/bitint-35.c -m64 -O0 only (passes -O2)
gcc.dg/torture/bitint-36.c -m64 -O0 only (passes -O2)
gcc.dg/torture/bitint-37.c -m64 -O0 only (passes -O2)
gcc.dg/torture/bitint-93.c -m64 both -O0 and -O2
gcc.dg/torture/bitint-94.c -m64 both -O0 and -O2
Debugging this issues, which points me to a code block in
gcc/gcc/gimple-lower-bitint.cc
=> tree src = build2 (MEM_REF, atype,
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));