Bug 47980 - Inefficient code for local const char arrays
Summary: Inefficient code for local const char arrays
Status: RESOLVED DUPLICATE of bug 38615
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: unknown
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-03-03 21:40 UTC by Rafael Avila de Espindola
Modified: 2011-03-04 16:26 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2011-03-03 21:52:14


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Rafael Avila de Espindola 2011-03-03 21:40:36 UTC
gcc will compile

--------------------
void f(const char *p);

void g(void) {
  const char foo[] = "aoeuaoeuaeouaeouaoeuaoeaoxbxod";
  f(foo);
}
----------------------

to

        .cfi_startproc
        subq    $40, %rsp
        .cfi_def_cfa_offset 48
        movl    $.LC0, %esi
        movl    $31, %ecx
        leaq    1(%rsp), %rdi
        rep movsb
        leaq    1(%rsp), %rdi
        call    f
        addq    $40, %rsp
        .cfi_def_cfa_offset 8
        ret
        .cfi_endproc

No idea why it wants to copy the string before calling f.
Comment 1 Kai Tietz 2011-03-03 21:46:48 UTC
This bug is invalid. The compiler did what you told him here. If you have the opinion for 'char s[] = "text"' would be a pointer to the constant, you are wrong.
Comment 2 Rafael Avila de Espindola 2011-03-03 21:50:07 UTC
I agree that the code is correct. The bug is because of a missing optimization, not about wrong behavior.

The only use of foo is passing it function expecting a const pointer. Gcc could remove the copy and just pass a pointer to the global it created to hold the string.

p.s.: how do I reopen the bug?
Comment 3 Kai Tietz 2011-03-03 21:52:14 UTC
As missed optimization it is valid. so reopened
Comment 4 Jakub Jelinek 2011-03-03 21:59:50 UTC
I believe f could do:
  assert (arg != "aoeuaoeuaeouaeouaoeuaoeaoxbxod");
which would then fail with the proposed optimization.  It is unspecified if
two string literals with the same content are distinct objects, but foo must be a distinct object (ok, with static const char foo[] = "aoeuaoeuaeouaeouaoeuaoeaoxbxod"; and -fmerge-all-constants which ignores some C requirements it doesn't have to).
Comment 5 Andrew Pinski 2011-03-03 22:00:36 UTC
Actually the copying is correct.
Take:
void f(const char *p);

void g(int t) {
  const char foo[] = "aoeuaoeuaeouaeouaoeuaoeaoxbxod";
  f(foo, t);
  if (!t)
    g(1);
}

const char *a;

void f(const char *p, int t)
{
  if (!t)
    a = p;
  else if (a == p)
    abort ();
}

void main(void)
{
  g(0);
}

This program should not abort with your "optimization", it will.
Comment 6 Andrew Pinski 2011-03-03 23:07:01 UTC
In fact my testcase in comment #5 is an exact duplicate of bug 38615.

*** This bug has been marked as a duplicate of bug 38615 ***
Comment 7 Jan Hubicka 2011-03-04 16:26:06 UTC
> I believe f could do:
>   assert (arg != "aoeuaoeuaeouaeouaoeuaoeaoxbxod");
> which would then fail with the proposed optimization.  It is unspecified if
> two string literals with the same content are distinct objects, but foo must be
> a distinct object (ok, with static const char foo[] =
> "aoeuaoeuaeouaeouaoeuaoeaoxbxod"; and -fmerge-all-constants which ignores some
> C requirements it doesn't have to).
Hmm, I was not aware of this.

I've seen quite few cases of real world code where such local arrays was used only
for direct references.  It is valid to do the transform in all cases when address
is not escaping and it is not used for inequality tests.  We do not track the second,
but we could.

It is however bit tricky to do the actual promotion of automatic scalar var to
static as gimplification lower initializers very early and thus we will have to
reconstruct it from gimple code.

Worthwhile optimization however I think.

Honza