I tend to say clang is wrong here.

Quoting the standard:

ISO/IEC WG14 Draft N1570 (Programming languages — C):
[quote]
6.2.2 Linkages of identifiers
6 The following identifiers have no linkage: an identifier declared to be 
anything other than
an object or a function; an identifier declared to be a function parameter; a 
block scope
identifier for an object declared without the storage-class specifier extern.

6.2.4 Storage durations of objects
6 An object whose identifier is declared with no linkage and without the 
storage-class
specifier static has automatic storage duration, as do some compound literals. 
...
7 For such an object that does have a variable length array type, its lifetime 
extends from
the declaration of the object until execution of the program leaves the scope 
of the
declaration.35) If the scope is entered recursively, a new instance of the 
object is created
each time. The initial value of the object is indeterminate.
[/quote]

Your identifier 'a' has no linkage. Your object designated by 'a' does not have 
a storage-class specifier.
So it has automatic storage duration and 6.2.4/7 applies: 'If the scope is 
entered recursively, a new instance of the object is created each time.'

Interesting enough, ISO C doesn't say whether distinct objects should have 
distinct addresses.
It is worth noting that this is explicitly forbidden in ISO C++ because 
distinct complete objects shall have distinct addresses:

ISO/IEC WG21 N4582 (Working Draft, Standard for Programming Language C++) :
[quote]
1.9 Program execution [intro.execution]
7 An instance of each object with automatic storage duration (3.7.3) is 
associated with each entry into its
block. Such an object exists and retains its last-stored value during the 
execution of the block and while the
block is suspended (by a call of a function or receipt of a signal).

1.8 The C++ object model [intro.object]
6 Unless an object is a bit-field or a base class subobject of zero size, the 
address of that object is the address of
the first byte it occupies. Two objects that are not bit-fields may have the 
same address if one is a subobject
of the other, or if at least one is a base class subobject of zero size and 
they are of different types; otherwise,
they shall have distinct addresses.4
[/quote]


------------------                               
Best regards,
lh_mouse
2016-04-20

-------------------------------------------------------------
发件人:Bingfeng Mei <bingfeng....@broadcom.com>
发送日期:2016-04-20 23:38
收件人:gcc
抄送:
主题:Why does gcc generate const local array on stack?

Hi,
I came across the following issue.

int foo (int N)
{
  const int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

  return a[N];
}

Compile with x86 O2

foo:
.LFB0:
.cfi_startproc
movslq %edi, %rdi
movl $0, -56(%rsp)
movl $1, -52(%rsp)
movl $2, -48(%rsp)
movl $3, -44(%rsp)
movl $4, -40(%rsp)
movl $5, -36(%rsp)
movl $6, -32(%rsp)
movl $7, -28(%rsp)
movl $8, -24(%rsp)
movl $9, -20(%rsp)
movl -56(%rsp,%rdi,4), %eax
ret

The array is placed on stack and GCC has to generate a sequence of
instructions to
initialize the array every time the function is called.

On the contrary, LLVM moves the array to global data and doesn't need
initialization
within the function.

If I add static to the array, GCC behaves the same as LLVM, just as expected.

Is there some subtle C standard issue or some switch I didn't turned
on? I understand
if this function is recursive and pointer of the array is involved,
GCC would have to maintain
the array on stack and hence the initialization. But here the code is
very simple. I don't understand the logic of generated code, or maybe
missing optimization opportunity?

Thanks,
Bingfeng Mei


Reply via email to