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));

Reply via email to