https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117327

            Bug ID: 117327
           Summary: SPARC miscompile - branch past end of function
           Product: gcc
           Version: 13.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: brad.moody at oracle dot com
  Target Milestone: ---

Created attachment 59468
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=59468&action=edit
Minimized reproducer

Reproducer program test.c:

int printf(const char *restrict, ...);

__attribute__((noinline))
void foo(int *self, int *x) {
    printf("foo\n");
    if (x) {
        while (1) {
            ++*self;
            if (*self == 6) break;
            if (*self == 7) __builtin_unreachable();
        }
    }
}
int main() {
    int y = 0;
    foo(&y, 0);
}   

======================

Steps to reproduce, on a SPARC machine, using gcc 13:

gcc -O1 test.c -o test
./test

The program prints foo repeatedly before segfaulting (I believe due to
overflowing the stack). I've only been able to reproduce the issue on SPARC.
Reproduces with -m32 and -m64. Does not reproduce with -O3, but other less
minimized inputs did show the problem at -O3.

>From examining the resulting assembly, I believe this is a miscompile. The
assembly output:

    .file   "a.c"
    .section    ".text"
    .section    .rodata.str1.8,"aMS",@progbits,1
    .align 8
.LLC0:
    .asciz  "foo"
    .section    ".text"
    .align 4
    .global foo
    .type   foo, #function
    .proc   020
foo:
    save    %sp, -176, %sp
    sethi   %h44(.LLC0), %o0
    or  %o0, %m44(.LLC0), %o0
    sllx    %o0, 12, %o0
    call    puts, 0
     or %o0, %l44(.LLC0), %o0
    brz,pn  %i1, .LL6
     nop
    ba,pt   %xcc, .LL4
     lduw   [%i0], %g1
.LL7:
    be,a,pn %icc, .LL8
     st %g1, [%i0]
.LL4:
    add %g1, 1, %g1
    cmp %g1, 6
    bne,pt  %icc, .LL7
     cmp    %g1, 7
    mov 6, %g1
    st  %g1, [%i0]
.LL8:
    return  %i7+8
     nop
.LL6:
    .size   foo, .-foo
    .align 4
    .global main
    .type   main, #function
    .proc   04
main:
    save    %sp, -192, %sp
    st  %g0, [%fp+2043]
    mov 0, %o1
    call    foo, 0
     add    %fp, 2043, %o0
    return  %i7+8
     mov    0, %o0
    .size   main, .-main
    .ident  "GCC: (GNU) 13.2.0"

The branch for `if (x)` to .LL6 is off the end of the function - it should be
to .LL8. Removing the call to __builtin_unreachable causes the problem to
disappear.

I don't have any other SPARC gcc installs on hand to test, but I did experiment
with other versions using Compiler Explorer. gcc 12.4, appears to reproduce the
problem at -O1, -O2 and -O3. gcc 14.1 doesn't appear to reproduce the problem
at all, but I think the bug could very well still be present in gcc 14 and just
not manifesting for this specific reproducer program.

======================

Other info:

The OS is Solaris 11.4.74.176.3

gcc -v output:

Using built-in specs.
COLLECT_GCC=gcc
Target: sparcv9-sun-solaris2.11
Configured with:
/builds/11.4-SRU/11.4.72.0.1.176.0/components/gcc13/gcc-13.2.0/configure
--prefix=/usr/gcc/13 --mandir=/usr/gcc/13/share/man --bindir=/usr/gcc/13/bin
--sbindir=/usr/gcc/13/sbin --libdir=/usr/gcc/13/lib
--infodir=/usr/gcc/13/share/info --libexecdir=/usr/gcc/13/lib
--enable-languages=ada,c,c++,fortran,go,objc --enable-shared
--enable-initfini-array --disable-rpath --with-system-zlib
--with-build-config=no --without-gnu-ld --with-ld=/usr/bin/ld --with-gnu-as
--with-as=/usr/gnu/bin/as --disable-bootstrap 'BOOT_CFLAGS=-g -O2'
sparcv9-sun-solaris2.11
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.2.0 (GCC) 
COLLECT_GCC_OPTIONS='-v' '-O1' '-c' '-mcpu=v9'
 /usr/gcc/13/lib/gcc/sparcv9-sun-solaris2.11/13.2.0/cc1 -quiet -v -D__arch64__
-D__sparcv9 a.c -quiet -dumpbase a.c -dumpbase-ext .c -mcpu=v9 -O1 -version -o
/var/tmp//ccj8.0wb.s
GNU C17 (GCC) version 13.2.0 (sparcv9-sun-solaris2.11)
        compiled by GNU C version 13.2.0, GMP version 6.3.0, MPFR version
4.2.1, MPC version 1.3.1, isl version isl-0.26-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/local/include"
ignoring nonexistent directory
"/usr/gcc/13/lib/gcc/sparcv9-sun-solaris2.11/13.2.0/../../../../sparcv9-sun-solaris2.11/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/gcc/13/lib/gcc/sparcv9-sun-solaris2.11/13.2.0/include
 /usr/gcc/13/include
 /usr/gcc/13/lib/gcc/sparcv9-sun-solaris2.11/13.2.0/include-fixed
 /usr/include
End of search list.
Compiler executable checksum: 92a7a4e1db50327821c291fc4325641f
COLLECT_GCC_OPTIONS='-v' '-O1' '-c' '-mcpu=v9'
 /usr/gnu/bin/as -v -V -Qy -s -xarch=v9 -64 -no-undeclared-regs -o a.o
/var/tmp//ccj8.0wb.s
GNU assembler version 2.40 (sparcv9-sun-solaris2.11) using BFD version (GNU
Binutils) 2.40
COMPILER_PATH=/usr/gcc/13/lib/gcc/sparcv9-sun-solaris2.11/13.2.0/:/usr/gcc/13/lib/gcc/sparcv9-sun-solaris2.11/13.2.0/:/usr/gcc/13/lib/gcc/sparcv9-sun-solaris2.11/:/usr/gcc/13/lib/gcc/sparcv9-sun-solaris2.11/13.2.0/:/usr/gcc/13/lib/gcc/sparcv9-sun-solaris2.11/:/usr/ccs/bin/
LIBRARY_PATH=/usr/gcc/13/lib/gcc/sparcv9-sun-solaris2.11/13.2.0/:/usr/gcc/13/lib/gcc/sparcv9-sun-solaris2.11/13.2.0/../../../sparcv9/:/lib/sparcv9/:/usr/lib/sparcv9/:/usr/gcc/13/lib/gcc/sparcv9-sun-solaris2.11/13.2.0/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-O1' '-c' '-mcpu=v9'

Reply via email to