[llvm-bugs] [Bug 48862] New: Inline assembly allocated register clash with multi-register constraints

via llvm-bugs llvm-bugs at lists.llvm.org
Sun Jan 24 01:56:46 PST 2021


https://bugs.llvm.org/show_bug.cgi?id=48862

            Bug ID: 48862
           Summary: Inline assembly allocated register clash with
                    multi-register constraints
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Register Allocator
          Assignee: unassignedbugs at nondot.org
          Reporter: nva280 at nn.kiev.ua
                CC: llvm-bugs at lists.llvm.org, quentin.colombet at gmail.com

Consider the following sample program (targeting Linux/x86-64):

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
  unsigned arg1 = strtoul(argv[1], NULL, 0);
  unsigned arg2 = strtoul(argv[2], NULL, 0);
  asm(
    "mov %[arg1], %%ecx\n\t"
    "add %[arg2], %[arg1]\n\t"
    "add %[arg2], %%ecx\n\t"
    "xchg %%ecx, %[arg2]"
    : [arg1] "+&abdSD" (arg1), [arg2] "+&abdSD" (arg2)
    :
    : "cc", "ecx");
  printf("%u %u\n", arg1, arg2);
}

(xchg is used just for easy grepping of compiled instructions in listing. This
is just an example crafted to reproduce the issue, far from real code, but
clear enough.)

With GCC, it works as expected - different registers are assigned to arg1 and
arg2, for example:

    11bf:       e8 cc fe ff ff          callq  1090 <strtoul at plt>
    11c4:       89 da                   mov    %ebx,%edx
    11c6:       89 d1                   mov    %edx,%ecx
    11c8:       01 c2                   add    %eax,%edx
    11ca:       01 c1                   add    %eax,%ecx
    11cc:       91                      xchg   %eax,%ecx

(so, arg1 in edx, arg2 in eax)

But, compiling with Clang (confirmed on all from 6.0 to trunk) results in
assigning the same register for arg1 and arg2:

  401174:       e8 d7 fe ff ff          callq  401050 <strtoul at plt>
  401179:       44 89 f0                mov    %r14d,%eax ; <--
  40117c:       89 c1                   mov    %eax,%ecx
  40117e:       01 c0                   add    %eax,%eax ; <-- so, arg1 and
arg2 both in eax
  401180:       01 c1                   add    %eax,%ecx
  401182:       91                      xchg   %eax,%ecx

The issue remains with multiple variations as e.g.: + instead of +& in
constraint strings; numeric forms like %0 to address operands; replacing xchg
with another rare instruction; and so on.

The issue is of importance on x86 because a lots of its instructions are
allowing only fixed registers, but a desire to alleviate allocation causes
constraint suggestion as explicit list except 1-2 reserved ones.

A workaround is accessible to use generic constraints like 'r' while marking
all disallowed registers as clobbered, but Iʼm uncertain whether it wonʼt
explode with "rm" or analogs.

Discussed also at https://stackoverflow.com/q/65644864 (with an explicit
suggestion this is really a bug).

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210124/5a711578/attachment.html>


More information about the llvm-bugs mailing list