[Bug tree-optimization/93982] New: Assignment incorrectly omitted by -foptimize-strlen

nate at thatsmathematics dot com gcc-bugzilla@gcc.gnu.org
Sat Feb 29 16:19:00 GMT 2020


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

            Bug ID: 93982
           Summary: Assignment incorrectly omitted by -foptimize-strlen
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: nate at thatsmathematics dot com
  Target Milestone: ---

Created attachment 47937
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=47937&action=edit
Reduced testcase

If the attached testcase is compiled with `-O1 -foptimize-strlen' on amd64, the
function foo is miscompiled: the assignment to res.target[1] is omitted.  It
also happens with -O2, but not with -O1 alone or -O3.

This bug is somewhat similar to bug 93213.  It is a regression from 9.2.0.

The generated assembly is:

foo:
        subq    $8, %rsp
        call    my_alloc
        movq    $.LC0, (%rax)
        movq    $.LC1, 16(%rax)
        movq    $.LC1, 24(%rax)
        movq    $.LC1, 32(%rax)
        addq    $8, %rsp
        ret

Note the absence of `movq $.LC1, 8(%rax)'.

I tested with trunk, latest pull from git, revision 117baab8.  In particular
the patch for bug 93213 (e13f37d9) is included.  The program is compiled
correctly by gcc 9.2.0 with the same options (and all others I tried). I did a
git bisect and the offending commit is 34fcf41e.

The cast in foo() at first looked questionable from a strict aliasing
standpoint, but I believe the code is legal since the memory returned by calloc
has no declared type, and we never access this memory except as objects of type
`const char *'.  Also, the miscompilation persists with -fno-strict-aliasing.

I am no gcc expert, but I dug into the source a little bit, out of curiosity.  
It looks like the deletion happens in handle_store(), at
gcc/tree-ssa-strlen.c:5021.  It seems that in this function, the code is being
treated as if the string "12345678" itself were being stored at address
res.target, rather than the address of the string; as if the code were
`strcpy(res.target, "12345678")'.  In particular, it thinks the trailing null
was stored at address res.target+8.  The following statement, `res.target[1] =
""', is likewise treated as if it were `strcpy(res.target+8, "")', which would
also just store a null byte at res.target+8, so it is seen as redundant and is
removed.

I would like to acknowledge StackOverflow user BrodieG for initially
discovering this bug and helping to investigate, as well as users KamilCuk and
John Bollinger for helpful comments. The original question is at
https://stackoverflow.com/q/60406042/634919.

Output of `gcc -v`:

Using built-in specs.
COLLECT_GCC=/home/nate/gcc/bin/gcc
COLLECT_LTO_WRAPPER=/home/nate/do-not-backup/gcc-inst/bin/../libexec/gcc/x86_64-pc-linux-gnu/10.0.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../configure --prefix=/home/nate/gcc --disable-bootstrap
--enable-languages=c
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 10.0.1 20200229 (experimental) (GCC)


More information about the Gcc-bugs mailing list