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

--- Comment #10 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #9)
> The question is how far we want to go and what we just ignore.
> With -fmerge-all-constants, we can have:
> const char var[] = "foobar";
> int foo (void) { return &var[0] != "foobar"; }
> which will likely be now miscompiled.

GCC 8 produces the following and so doesn't actually merge the constants

.LC0:
        .string "foobar"
        .section        .text.startup,"ax",@progbits
        .p2align 4,,15
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        movl    $var, %eax
        cmpq    $.LC0, %rax
        setne   %al
        movzbl  %al, %eax
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .globl  var
        .section        .rodata.str1.1
        .type   var, @object
        .size   var, 7
var:
        .string "foobar"

And with -O0 it's even more obvious:

var:
        .string "foobar"
.LC0:
        .string "foobar"

and yes, we now optimize this.

> But we could even have two sources,
> const char var2[] = "foobar";
> compiled with -fmerge-all-constants and
> extern char var2[];
> int bar (void) { return &var2[0] != "foobar"; }
> compiled with -fmerge-constants (the default).
>
> So, can we e.g. optimize less if we see flag_merge_all_constants and a
> TREE_READONLY decl(s) (both the above first case and your const int case)?
> If the decl(s) have DECL_INITIAL and bind to current TU, we could of course
> check further the initializers, and ignore the nasty second case above, by
> saying that
> if you define vars as const and declare as non-const, it is your problem and
> similarly, if you -fmerge-all-constants the defining TUs but not uses of
> those decls, it is again your fault?  I'd lean towards that.

I didn't manage to merge the variable and the string literal, so I believe
this is a theoretical issue?

Reply via email to