[llvm-dev] LTO renaming of constants with inline assembly

Teresa Johnson via llvm-dev llvm-dev at lists.llvm.org
Wed Apr 6 10:49:55 PDT 2016


On Wed, Apr 6, 2016 at 10:46 AM, Peter Collingbourne <peter at pcc.me.uk>
wrote:

> I suspect that the right way to do promotion/renaming of this sort is to
> rename at the MC layer just before writing the symbol table to the object
> file.
>

I think that is too late - how would the symbols be distinguished in the
LTO case below after the IR is linked but before we renamed the duplicate?

Teresa


> Peter
>
> On Wed, Apr 6, 2016 at 10:37 AM, Teresa Johnson via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
>
>> I encountered an issue with ThinLTO handling of inline assembly, where
>> the inline assembly referenced a constant that was a local variable. The
>> local var was renamed because it was promoted in ThinLTO mode, but the
>> inline assembly copy was not renamed and we ended up with an undef at link
>> time.
>>
>> It looks like this is a general problem with inline assembly and LTO.
>> Wondering if it is a known issue. E.g. if I link in LTO mode two files that
>> have inline assembly referencing local constants with the same name, the
>> LTO linking will rename the second. However, the renaming doesn't propagate
>> to inline assembly, resulting in the wrong output.
>>
>> For example, let's say we have two modules with inline assembly that
>> writes a local constant var named "myvar" into the memory pointed to by its
>> parameter "v", and a simple main that calls each function:
>>
>> $ cat inlineasm1.c
>> static const unsigned char __attribute__((used)) __attribute__ ((aligned
>> (1))) myvar = 1;
>>
>> void foo(unsigned long int *v) {
>>   __asm__ volatile("movzbl     myvar(%%rip), %%eax\n\t"
>>                    "movq %%rax, %0\n\t"
>>                        : "=*m" (*v)
>>     :
>>     : "%eax"
>>     );
>> }
>>
>> $ cat inlineasm2.c
>> static const unsigned char __attribute__((used)) __attribute__ ((aligned
>> (1))) myvar = 2;
>>
>> void bar(unsigned long int *v) {
>>   __asm__ volatile("movzbl     myvar(%%rip), %%eax\n\t"
>>                    "movq %%rax, %0\n\t"
>>                        : "=*m" (*v)
>>     :
>>     : "%eax"
>>     );
>> }
>>
>> $ cat inlineasm.c
>> #include <stdio.h>
>> extern void foo(unsigned long int *v);
>> extern void bar(unsigned long int *v);
>> int main() {
>>   unsigned long int f,b;
>>   foo(&f);
>>   bar(&b);
>>   printf("%lu %lu\n", f, b);
>> }
>>
>>
>> If compiled at -O2 (no LTO) this correctly prints out "1 2".
>>
>> However, when linked with LTO, the second copy of local "myvar" is
>> renamed to "myvar.6". But the inline assembly which is still hidden within
>> a call that hasn't been lowered, still references "myvar" in that second
>> linked copy in bar(). The output is thus incorrect: "1 1" (or "2 2" if the
>> bar() copy was linked first).
>>
>> Is this a known issue? Any ideas on how we could handle this?
>>
>> Thanks,
>> Teresa
>>
>> --
>> Teresa Johnson |  Software Engineer |  tejohnson at google.com |
>> 408-460-2413
>>
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>
>>
>
>
> --
> --
> Peter
>



-- 
Teresa Johnson |  Software Engineer |  tejohnson at google.com |  408-460-2413
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160406/b8119199/attachment.html>


More information about the llvm-dev mailing list