Rui Ueyama via llvm-dev
2019-Jun-11 12:48 UTC
[llvm-dev] Expected behavior of lld during LTO for global symbols (Attr Internal/Common)
Looks like this is indeed related to r360841. In C, there are distinctions between declarations, definitions and tentative definitions. Global variables declared with "extern" are declarations. Global variables that don't have "extern" and have initializers are definitions. If global variables have neither "extern" nor initializers, they are called tentative definitions. Common symbols represent tentative definitions. Tentative definition get special treatment in the linker. Usually if you define the same symbol in two object files, a linker report an error. However, common symbols are allowed to duplicate. Two or more common symbols are merged and then placed to the .bss section, so that they will be zero-initialized at runtime. So, a global variable defined as `struct Node* head` is actually a common symbol. I'm not sure why LTO cannot internalize common symbols though. Teresa, is this expected? On Mon, Jun 10, 2019 at 11:06 PM Teresa Johnson <tejohnson at google.com> wrote:> My guess is that it is due to lld change r360841 on that date (Introduce > CommonSymbol). +Rui for comments. > > On Mon, Jun 10, 2019 at 4:45 AM Mani, Suresh via llvm-dev < > llvm-dev at lists.llvm.org> wrote: > >> >> >> >> >> Hi , >> >> >> >> I have an issue during LTO phase of llvm compiler which is as follows, >> >> >> >> >> >> File t3.c >> >> --------- >> >> >> >> >> >> #include <stdio.h> >> >> #include <stdlib.h> >> >> >> >> // A linked list node >> >> struct Node { >> >> int data; >> >> struct Node* next; >> >> struct Node* prev; >> >> }; >> >> >> >> *struct Node* head;* >> >> >> >> /* Given a reference (pointer to pointer) to the head of a list >> >> and an int, inserts a new node on the front of the list. */ >> >> void push(struct Node** head_ref, int new_data) >> >> { >> >> struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); >> >> >> >> new_node->data = new_data; >> >> >> >> new_node->next = (*head_ref); >> >> new_node->prev = NULL; >> >> >> >> if ((*head_ref) != NULL) >> >> (*head_ref)->prev = new_node; >> >> >> >> (*head_ref) = new_node; >> >> } >> >> >> >> >> >> // This function prints contents of linked list starting from the given >> node >> >> void printList(struct Node* node) >> >> { >> >> struct Node* last; >> >> printf("\nTraversal in forward direction \n"); >> >> while (node != NULL) { >> >> printf(" %d ", node->data); >> >> last = node; >> >> node = node->next; >> >> } >> >> >> >> printf("\nTraversal in reverse direction \n"); >> >> while (last != NULL) { >> >> printf(" %d ", last->data); >> >> last = last->prev; >> >> } >> >> } >> >> >> >> >> >> /* Driver program to test above functions*/ >> >> int main() >> >> { >> >> >> >> head = NULL; >> >> push(&head, 7); >> >> push(&head, 1); >> >> push(&head, 4); >> >> >> >> printList(head); >> >> >> >> return 0; >> >> } >> >> >> >> >> >> >> >> >> >> Compiler invocation: >> >> -------------------- >> >> >> >> clang -flto -fuse-ld=lld -O3 t3.c -o a.out >> >> >> >> >> >> Expected behavior during LTO: >> >> ------------------------------ >> >> >> >> The compiler optimization during LTO needs to figure out that variable >> "head" is not referred by any precompiled object or library. >> >> Until May-16-2019 variable "head" had internal attribute as follows, >> >> >> >> @head = internal global %struct.Node* null, align 8 >> >> >> >> And the compiler was rightly able to recognize that "head" is not >> referred by any external precompiled object or library. >> >> >> >> But after May-16-2019 the attribute of head was changed as follows, >> >> >> >> @head = common dso_local global %struct.Node* null, align 8 >> >> >> >> >> >> Not sure if this is correct behavior? >> >> >> >> If this is a correct behavior then can you please let me know how could >> the compiler figure out that variable "head" is not referred by any >> external precompiled object or library? >> >> >> >> >> >> Thanks >> >> M Suresh >> _______________________________________________ >> LLVM Developers mailing list >> llvm-dev at lists.llvm.org >> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >> > > > -- > Teresa Johnson | Software Engineer | tejohnson at google.com | >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190611/adbc7f75/attachment.html>
Teresa Johnson via llvm-dev
2019-Jun-11 13:53 UTC
[llvm-dev] Expected behavior of lld during LTO for global symbols (Attr Internal/Common)
LTO can, but it is linker driven. I confirmed that when it is a common symbol the resolution indicates that the symbol is exported, and when I add an initializer so that it is a def we no longer think it is exported and are able to internalize. So this seems to be due to a change in what the linker is telling LTO. I would have to dig in the debugger to confirm, but perhaps lld is now indicating that it might be used by a regular obj? I.e. in BitcodeCompiler::add. Teresa On Tue, Jun 11, 2019 at 5:48 AM Rui Ueyama <ruiu at google.com> wrote:> Looks like this is indeed related to r360841. > > In C, there are distinctions between declarations, definitions and > tentative definitions. Global variables declared with "extern" are > declarations. Global variables that don't have "extern" and have > initializers are definitions. If global variables have neither "extern" nor > initializers, they are called tentative definitions. > > Common symbols represent tentative definitions. > > Tentative definition get special treatment in the linker. Usually if you > define the same symbol in two object files, a linker report an error. > However, common symbols are allowed to duplicate. Two or more common > symbols are merged and then placed to the .bss section, so that they will > be zero-initialized at runtime. > > So, a global variable defined as `struct Node* head` is actually a common > symbol. > > I'm not sure why LTO cannot internalize common symbols though. Teresa, is > this expected? > > On Mon, Jun 10, 2019 at 11:06 PM Teresa Johnson <tejohnson at google.com> > wrote: > >> My guess is that it is due to lld change r360841 on that date (Introduce >> CommonSymbol). +Rui for comments. >> >> On Mon, Jun 10, 2019 at 4:45 AM Mani, Suresh via llvm-dev < >> llvm-dev at lists.llvm.org> wrote: >> >>> >>> >>> >>> >>> Hi , >>> >>> >>> >>> I have an issue during LTO phase of llvm compiler which is as follows, >>> >>> >>> >>> >>> >>> File t3.c >>> >>> --------- >>> >>> >>> >>> >>> >>> #include <stdio.h> >>> >>> #include <stdlib.h> >>> >>> >>> >>> // A linked list node >>> >>> struct Node { >>> >>> int data; >>> >>> struct Node* next; >>> >>> struct Node* prev; >>> >>> }; >>> >>> >>> >>> *struct Node* head;* >>> >>> >>> >>> /* Given a reference (pointer to pointer) to the head of a list >>> >>> and an int, inserts a new node on the front of the list. */ >>> >>> void push(struct Node** head_ref, int new_data) >>> >>> { >>> >>> struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); >>> >>> >>> >>> new_node->data = new_data; >>> >>> >>> >>> new_node->next = (*head_ref); >>> >>> new_node->prev = NULL; >>> >>> >>> >>> if ((*head_ref) != NULL) >>> >>> (*head_ref)->prev = new_node; >>> >>> >>> >>> (*head_ref) = new_node; >>> >>> } >>> >>> >>> >>> >>> >>> // This function prints contents of linked list starting from the given >>> node >>> >>> void printList(struct Node* node) >>> >>> { >>> >>> struct Node* last; >>> >>> printf("\nTraversal in forward direction \n"); >>> >>> while (node != NULL) { >>> >>> printf(" %d ", node->data); >>> >>> last = node; >>> >>> node = node->next; >>> >>> } >>> >>> >>> >>> printf("\nTraversal in reverse direction \n"); >>> >>> while (last != NULL) { >>> >>> printf(" %d ", last->data); >>> >>> last = last->prev; >>> >>> } >>> >>> } >>> >>> >>> >>> >>> >>> /* Driver program to test above functions*/ >>> >>> int main() >>> >>> { >>> >>> >>> >>> head = NULL; >>> >>> push(&head, 7); >>> >>> push(&head, 1); >>> >>> push(&head, 4); >>> >>> >>> >>> printList(head); >>> >>> >>> >>> return 0; >>> >>> } >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> Compiler invocation: >>> >>> -------------------- >>> >>> >>> >>> clang -flto -fuse-ld=lld -O3 t3.c -o a.out >>> >>> >>> >>> >>> >>> Expected behavior during LTO: >>> >>> ------------------------------ >>> >>> >>> >>> The compiler optimization during LTO needs to figure out that variable >>> "head" is not referred by any precompiled object or library. >>> >>> Until May-16-2019 variable "head" had internal attribute as follows, >>> >>> >>> >>> @head = internal global %struct.Node* null, align 8 >>> >>> >>> >>> And the compiler was rightly able to recognize that "head" is not >>> referred by any external precompiled object or library. >>> >>> >>> >>> But after May-16-2019 the attribute of head was changed as follows, >>> >>> >>> >>> @head = common dso_local global %struct.Node* null, align 8 >>> >>> >>> >>> >>> >>> Not sure if this is correct behavior? >>> >>> >>> >>> If this is a correct behavior then can you please let me know how could >>> the compiler figure out that variable "head" is not referred by any >>> external precompiled object or library? >>> >>> >>> >>> >>> >>> Thanks >>> >>> M Suresh >>> _______________________________________________ >>> LLVM Developers mailing list >>> llvm-dev at lists.llvm.org >>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >>> >> >> >> -- >> Teresa Johnson | Software Engineer | tejohnson at google.com | >> >-- Teresa Johnson | Software Engineer | tejohnson at google.com | -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190611/90fb28fe/attachment.html>
Mani, Suresh via llvm-dev
2019-Jun-20 09:36 UTC
[llvm-dev] Expected behavior of lld during LTO for global symbols (Attr Internal/Common)
Hi Teresa, Can you please let me know if there is any update on this issue. Thanks M Suresh From: Teresa Johnson <tejohnson at google.com> Sent: Tuesday, June 11, 2019 7:23 PM To: Rui Ueyama <ruiu at google.com> Cc: Mani, Suresh <Suresh.Mani at amd.com>; llvm-dev <llvm-dev at lists.llvm.org> Subject: Re: [llvm-dev] Expected behavior of lld during LTO for global symbols (Attr Internal/Common) [CAUTION: External Email] LTO can, but it is linker driven. I confirmed that when it is a common symbol the resolution indicates that the symbol is exported, and when I add an initializer so that it is a def we no longer think it is exported and are able to internalize. So this seems to be due to a change in what the linker is telling LTO. I would have to dig in the debugger to confirm, but perhaps lld is now indicating that it might be used by a regular obj? I.e. in BitcodeCompiler::add. Teresa On Tue, Jun 11, 2019 at 5:48 AM Rui Ueyama <ruiu at google.com<mailto:ruiu at google.com>> wrote: Looks like this is indeed related to r360841. In C, there are distinctions between declarations, definitions and tentative definitions. Global variables declared with "extern" are declarations. Global variables that don't have "extern" and have initializers are definitions. If global variables have neither "extern" nor initializers, they are called tentative definitions. Common symbols represent tentative definitions. Tentative definition get special treatment in the linker. Usually if you define the same symbol in two object files, a linker report an error. However, common symbols are allowed to duplicate. Two or more common symbols are merged and then placed to the .bss section, so that they will be zero-initialized at runtime. So, a global variable defined as `struct Node* head` is actually a common symbol. I'm not sure why LTO cannot internalize common symbols though. Teresa, is this expected? On Mon, Jun 10, 2019 at 11:06 PM Teresa Johnson <tejohnson at google.com<mailto:tejohnson at google.com>> wrote: My guess is that it is due to lld change r360841 on that date (Introduce CommonSymbol). +Rui for comments. On Mon, Jun 10, 2019 at 4:45 AM Mani, Suresh via llvm-dev <llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>> wrote: Hi , I have an issue during LTO phase of llvm compiler which is as follows, File t3.c --------- #include <stdio.h> #include <stdlib.h> // A linked list node struct Node { int data; struct Node* next; struct Node* prev; }; struct Node* head; /* Given a reference (pointer to pointer) to the head of a list and an int, inserts a new node on the front of the list. */ void push(struct Node** head_ref, int new_data) { struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); new_node->data = new_data; new_node->next = (*head_ref); new_node->prev = NULL; if ((*head_ref) != NULL) (*head_ref)->prev = new_node; (*head_ref) = new_node; } // This function prints contents of linked list starting from the given node void printList(struct Node* node) { struct Node* last; printf("\nTraversal in forward direction \n"); while (node != NULL) { printf(" %d ", node->data); last = node; node = node->next; } printf("\nTraversal in reverse direction \n"); while (last != NULL) { printf(" %d ", last->data); last = last->prev; } } /* Driver program to test above functions*/ int main() { head = NULL; push(&head, 7); push(&head, 1); push(&head, 4); printList(head); return 0; } Compiler invocation: -------------------- clang -flto -fuse-ld=lld -O3 t3.c -o a.out Expected behavior during LTO: ------------------------------ The compiler optimization during LTO needs to figure out that variable "head" is not referred by any precompiled object or library. Until May-16-2019 variable "head" had internal attribute as follows, @head = internal global %struct.Node* null, align 8 And the compiler was rightly able to recognize that "head" is not referred by any external precompiled object or library. But after May-16-2019 the attribute of head was changed as follows, @head = common dso_local global %struct.Node* null, align 8 Not sure if this is correct behavior? If this is a correct behavior then can you please let me know how could the compiler figure out that variable "head" is not referred by any external precompiled object or library? Thanks M Suresh _______________________________________________ LLVM Developers mailing list llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev -- Teresa Johnson | Software Engineer | tejohnson at google.com<mailto:tejohnson at google.com> | -- Teresa Johnson | Software Engineer | tejohnson at google.com<mailto:tejohnson at google.com> | -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190620/fe780be2/attachment.html>
Rui Ueyama via llvm-dev
2019-Jun-20 13:17 UTC
[llvm-dev] Expected behavior of lld during LTO for global symbols (Attr Internal/Common)
It seems that we do not at least set IsUsedInRegularObj for common symbols passed to LTO. On Tue, Jun 11, 2019 at 10:53 PM Teresa Johnson <tejohnson at google.com> wrote:> LTO can, but it is linker driven. I confirmed that when it is a common > symbol the resolution indicates that the symbol is exported, and when I add > an initializer so that it is a def we no longer think it is exported and > are able to internalize. So this seems to be due to a change in what the > linker is telling LTO. I would have to dig in the debugger to confirm, but > perhaps lld is now indicating that it might be used by a regular obj? I.e. > in BitcodeCompiler::add. > > Teresa > > On Tue, Jun 11, 2019 at 5:48 AM Rui Ueyama <ruiu at google.com> wrote: > >> Looks like this is indeed related to r360841. >> >> In C, there are distinctions between declarations, definitions and >> tentative definitions. Global variables declared with "extern" are >> declarations. Global variables that don't have "extern" and have >> initializers are definitions. If global variables have neither "extern" nor >> initializers, they are called tentative definitions. >> >> Common symbols represent tentative definitions. >> >> Tentative definition get special treatment in the linker. Usually if you >> define the same symbol in two object files, a linker report an error. >> However, common symbols are allowed to duplicate. Two or more common >> symbols are merged and then placed to the .bss section, so that they will >> be zero-initialized at runtime. >> >> So, a global variable defined as `struct Node* head` is actually a common >> symbol. >> >> I'm not sure why LTO cannot internalize common symbols though. Teresa, is >> this expected? >> >> On Mon, Jun 10, 2019 at 11:06 PM Teresa Johnson <tejohnson at google.com> >> wrote: >> >>> My guess is that it is due to lld change r360841 on that date (Introduce >>> CommonSymbol). +Rui for comments. >>> >>> On Mon, Jun 10, 2019 at 4:45 AM Mani, Suresh via llvm-dev < >>> llvm-dev at lists.llvm.org> wrote: >>> >>>> >>>> >>>> >>>> >>>> Hi , >>>> >>>> >>>> >>>> I have an issue during LTO phase of llvm compiler which is as follows, >>>> >>>> >>>> >>>> >>>> >>>> File t3.c >>>> >>>> --------- >>>> >>>> >>>> >>>> >>>> >>>> #include <stdio.h> >>>> >>>> #include <stdlib.h> >>>> >>>> >>>> >>>> // A linked list node >>>> >>>> struct Node { >>>> >>>> int data; >>>> >>>> struct Node* next; >>>> >>>> struct Node* prev; >>>> >>>> }; >>>> >>>> >>>> >>>> *struct Node* head;* >>>> >>>> >>>> >>>> /* Given a reference (pointer to pointer) to the head of a list >>>> >>>> and an int, inserts a new node on the front of the list. */ >>>> >>>> void push(struct Node** head_ref, int new_data) >>>> >>>> { >>>> >>>> struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); >>>> >>>> >>>> >>>> new_node->data = new_data; >>>> >>>> >>>> >>>> new_node->next = (*head_ref); >>>> >>>> new_node->prev = NULL; >>>> >>>> >>>> >>>> if ((*head_ref) != NULL) >>>> >>>> (*head_ref)->prev = new_node; >>>> >>>> >>>> >>>> (*head_ref) = new_node; >>>> >>>> } >>>> >>>> >>>> >>>> >>>> >>>> // This function prints contents of linked list starting from the given >>>> node >>>> >>>> void printList(struct Node* node) >>>> >>>> { >>>> >>>> struct Node* last; >>>> >>>> printf("\nTraversal in forward direction \n"); >>>> >>>> while (node != NULL) { >>>> >>>> printf(" %d ", node->data); >>>> >>>> last = node; >>>> >>>> node = node->next; >>>> >>>> } >>>> >>>> >>>> >>>> printf("\nTraversal in reverse direction \n"); >>>> >>>> while (last != NULL) { >>>> >>>> printf(" %d ", last->data); >>>> >>>> last = last->prev; >>>> >>>> } >>>> >>>> } >>>> >>>> >>>> >>>> >>>> >>>> /* Driver program to test above functions*/ >>>> >>>> int main() >>>> >>>> { >>>> >>>> >>>> >>>> head = NULL; >>>> >>>> push(&head, 7); >>>> >>>> push(&head, 1); >>>> >>>> push(&head, 4); >>>> >>>> >>>> >>>> printList(head); >>>> >>>> >>>> >>>> return 0; >>>> >>>> } >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> Compiler invocation: >>>> >>>> -------------------- >>>> >>>> >>>> >>>> clang -flto -fuse-ld=lld -O3 t3.c -o a.out >>>> >>>> >>>> >>>> >>>> >>>> Expected behavior during LTO: >>>> >>>> ------------------------------ >>>> >>>> >>>> >>>> The compiler optimization during LTO needs to figure out that variable >>>> "head" is not referred by any precompiled object or library. >>>> >>>> Until May-16-2019 variable "head" had internal attribute as follows, >>>> >>>> >>>> >>>> @head = internal global %struct.Node* null, align 8 >>>> >>>> >>>> >>>> And the compiler was rightly able to recognize that "head" is not >>>> referred by any external precompiled object or library. >>>> >>>> >>>> >>>> But after May-16-2019 the attribute of head was changed as follows, >>>> >>>> >>>> >>>> @head = common dso_local global %struct.Node* null, align 8 >>>> >>>> >>>> >>>> >>>> >>>> Not sure if this is correct behavior? >>>> >>>> >>>> >>>> If this is a correct behavior then can you please let me know how could >>>> the compiler figure out that variable "head" is not referred by any >>>> external precompiled object or library? >>>> >>>> >>>> >>>> >>>> >>>> Thanks >>>> >>>> M Suresh >>>> _______________________________________________ >>>> LLVM Developers mailing list >>>> llvm-dev at lists.llvm.org >>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >>>> >>> >>> >>> -- >>> Teresa Johnson | Software Engineer | tejohnson at google.com | >>> >> > > -- > Teresa Johnson | Software Engineer | tejohnson at google.com | >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190620/a6c1311b/attachment.html>