<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - Clang considers extended asm empty input constraint to be invalid"
   href="https://bugs.llvm.org/show_bug.cgi?id=48605">48605</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Clang considers extended asm empty input constraint to be invalid
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>-New Bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>nsajko@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org, neeilans@live.com, richard-llvm@metafoo.co.uk
          </td>
        </tr></table>
      <p>
        <div>
        <pre>The issue is that Clang does not accept the GCC extended asm empty input
constraint, giving the error "error: invalid input constraint '' in asm".

Note that <a href="https://clang.llvm.org/compatibility.html#inline-asm">https://clang.llvm.org/compatibility.html#inline-asm</a> says that all
constraints allowed by GCC are also allowed by Clang:

<span class="quote">> In general, Clang is highly compatible with the GCC inline assembly extensions, allowing the same set of constraints, modifiers and operands as GCC inline assembly.</span >

The use case for this feature is when the user wants to prevent the compiler
from optimizing away a piece of code (the relevant asm declaration effectively
pretends to be a live store), but without causing unnecessary additional code
generation. This is desirable in, e.g., benchmarking and testing.

The following code should illustrate the issue and the desired behavior:

<span class="quote">> #include <vector></span >
>
<span class="quote">> int
> main() {
>       // Greater than or equal to zero.
>       constexpr int asmV = ASM_V;</span >
>
<span class="quote">>       std::vector<char> v{7, 6, 9, 3, 2, 0};
>       for (int i{0}; i < (1 << 28); i++) {
>               for (int j{0}; j < 6; j++) {
>                       v[j]++;</span >
>
<span class="quote">>                       if constexpr (1 <= asmV) {
>                               asm volatile ("" :: ""(v.size()));
>                               for (auto x: v) {
>                                       asm volatile ("" :: ""(x));
>                               }
>                       }
>                       if constexpr (2 <= asmV) {
>                               asm volatile ("" :: ""(v.size()));
>                               for (auto x: v) {
>                                       asm volatile ("" :: ""(x));
>                               }
>                       }
>                       if constexpr (3 <= asmV) {
>                               asm volatile ("" :: ""(v.size()));
>                               for (auto x: v) {
>                                       asm volatile ("" :: ""(x));
>                               }
>                       }
>               }
>       }</span >
>
<span class="quote">>       return 0;
> }</span >

Built with (try replacing "=0" with "=1", "=2", "=3":

<span class="quote">> clang++ clang++ -std=c++20 -D ASM_V=0 asm.cc</span >

This is the Radare2 graph view of the disassembly for the main function with
ASM_V defined as 1, 2 or 3:

[0x00001050]> 0x1050 # int main (int argc, char **argv, char **envp);
  ┌─────────────────────────────────────────────────────┐
  │ [0x1050]                                            │
  │ ; [13] -r-x section size 517 named .text            │
  │   ; DATA XREF from entry0 @ 0x1101                  │
  │   ;-- section..text:                                │
  │   ;-- .text:                                        │
  │ 129: int main (int argc, char **argv, char **envp); │
  │ movl $6, %edi                                       │
  │ subq $8, %rsp                                       │
  │ callq sym operator new(unsigned long);[oa]          │
  │ ; [0x3090607:4]=-1                                  │
  │ movl $0x3090607, (%rax)                             │
  │ movq %rax, %r9                                      │
  │ movl $2, %eax                                       │
  │ movw %ax, 4(%r9)                                    │
  │ movl $0x10000000, %r10d                             │
  │ movl $6, %r8d                                       │
  │ movl $9, %edi                                       │
  │ movl $3, %esi                                       │
  │ movl $2, %ecx                                       │
  │ xorl %edx, %edx                                     │
  │ nop                                                 │
  └─────────────────────────────────────────────────────┘
      v
      │
      └──────────────────────┐
                             │
                             │
                             │
                  ┌──────────┘
┌───────────────────┐
│                 │ │
│           ┌────────────────────────────────┐
│           │  0x1090 [oc]                   │
│           │ ; CODE XREF from main @ 0x10bb │
│           │ movzbl (%r9), %eax             │
│           │ incl %eax                      │
│           │ movb %al, (%r9)                │
│           │ incl %r8d                      │
│           │ movb %r8b, 1(%r9)              │
│           │ incl %edi                      │
│           │ movb %dil, 2(%r9)              │
│           │ incl %esi                      │
│           │ movb %sil, 3(%r9)              │
│           │ incl %ecx                      │
│           │ movb %cl, 4(%r9)               │
│           │ incl %edx                      │
│           │ movb %dl, 5(%r9)               │
│           │ decl %r10d                     │
│           │ jne 0x1090                     │
│           └────────────────────────────────┘
│                   f t
│                   │ │
└─────────────────────┘
     ┌──────────────┘
     │
 ┌──────────────────────────────────────────────────────┐
 │  0x10bd [oe]                                         │
 │ movl $6, %esi                                        │
 │ movq %r9, %rdi                                       │
 │ callq sym operator delete(void*, unsigned long);[od] │
 │ xorl %eax, %eax                                      │
 │ addq $8, %rsp                                        │
 │ retq                                                 │
 └──────────────────────────────────────────────────────┘

This is the main function with ASM_V defined as 0, notice how the loop is gone:

[0x00001050]> 0x1050 # int main (int argc, char **argv, char **envp);
 ┌──────────────────────────────────────────────────────┐
 │ [0x1050]                                             │
 │ ; [13] -r-x section size 437 named .text             │
 │   ; DATA XREF from entry0 @ 0x10b1                   │
 │   ;-- section..text:                                 │
 │   ;-- .text:                                         │
 │ 49: int main (int argc, char **argv, char **envp);   │
 │ subq $8, %rsp                                        │
 │ movl $6, %edi                                        │
 │ callq sym operator new(unsigned long);[oa]           │
 │ ; [0x3090607:4]=-1                                   │
 │ movl $0x3090607, (%rax)                              │
 │ movq %rax, %rdi                                      │
 │ movl $2, %eax                                        │
 │ movw %ax, 4(%rdi)                                    │
 │ movl $6, %esi                                        │
 │ callq sym operator delete(void*, unsigned long);[ob] │
 │ xorl %eax, %eax                                      │
 │ addq $8, %rsp                                        │
 │ retq                                                 │
 └──────────────────────────────────────────────────────┘</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>