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

Peter Collingbourne via llvm-dev llvm-dev at lists.llvm.org
Wed Apr 6 10:46:43 PDT 2016


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.

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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160406/1690e1f7/attachment-0001.html>


More information about the llvm-dev mailing list