<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </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 --- - Intrinsics llvm.read_register, llvm.write_register and ISel node types ISD::READ_REGISTER, ISD::WRITE_REGISTER are broken."
   href="https://llvm.org/bugs/show_bug.cgi?id=23389">23389</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Intrinsics llvm.read_register, llvm.write_register and ISel node types ISD::READ_REGISTER, ISD::WRITE_REGISTER are broken.
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>new-bugs
          </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>normal
          </td>
        </tr>

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

        <tr>
          <th>Component</th>
          <td>new bugs
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>Nicholas.Paul.Johnson@DEShawResearch.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=14275" name="attach_14275" title="Testcase of register-asm syntax">attachment 14275</a> <a href="attachment.cgi?id=14275&action=edit" title="Testcase of register-asm syntax">[details]</a></span>
Testcase of register-asm syntax

(0) Background

I am developing a backend for a custom architecture.  Our ABI reserves a few
registers which we reserve for the application.  Those registers are accessed
from the C++-language by use of the assembly register syntax, like so:

  register int r0 asm("r0");

Clang lowers these accesses in LLVM IR using the llvm.read_register and
llvm.write_register intrinsics.



There is a minor difficulty while reporting this bug, since you do not have the
code for my backend.  Nonetheless, the bug is in the llvm mainline and will
manifest in any backend that exposes registers in this manner.

I'll try to explain this bug with respect to x86.  To do that, we need a minor
change to X86 so that it exposes register r15 at the C language level:

diff --git a/lib/Target/X86/X86ISelLowering.cpp
b/lib/Target/X86/X86ISelLowering.cpp
index 98a19ee..91f2b8d 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -15598,6 +15598,7 @@ unsigned X86TargetLowering::getRegisterByName(const
char* RegName,
   unsigned Reg = StringSwitch<unsigned>(RegName)
                        .Case("esp", X86::ESP)
                        .Case("rsp", X86::RSP)
+                       .Case("r15", X86::R15)
                        .Default(0);
   if (Reg)
     return Reg;



(1) Symptoms

Compilation gives different results under -O0 and -O3.  To reproduce:

Compile
  clang++ -O0 -c -emit-llvm -S bug.cpp -o bug.o0.ll
  clang++ -O3 -c -emit-llvm -S bug.cpp -o bug.o3.ll


Specifically, bug.o0.ll will re-load the latest value of the register (via
llvm.read_register) before each printf.  From bug.o0.ll:

   ...
   call void @_Z4zerov()
   %0 = call i64 @llvm.read_register.i64(metadata !0)
   store i64 %0, i64* %observation1, align 8
   %1 = load i64, i64* %observation1, align 8
   %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8],
[12 x i8]* @.str, i32 0, i32 0), i64 %1)
   call void @_Z3onev()
   %2 = call i64 @llvm.read_register.i64(metadata !0)
   store i64 %2, i64* %observation2, align 8
   %3 = load i64, i64* %observation2, align 8
   %call1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8],
[13 x i8]* @.str1, i32 0, i32 0), i64 %3)
   ...

In contrast, bug.o3.ll will only read the register once, providing the same
integer argument to each printf.

 ; Function Attrs: nounwind uwtable
 define i32 @main(i32 %argc, i8** nocapture readnone %argv) #0 {
 entry:
   tail call void @llvm.write_register.i64(metadata !0, i64 0) #1
   %0 = tail call i64 @llvm.read_register.i64(metadata !0)
   %call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x
i8], [12 x i8]* @.str, i64 0, i64 0), i64 %0)
   %add.i = add i64 %0, 1
   tail call void @llvm.write_register.i64(metadata !0, i64 %add.i) #1
   %call1 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x
i8], [13 x i8]* @.str1, i64 0, i64 0), i64 %0)
   ret i32 0
 }



Also note: if you try to compile directly to a binary, clang / llc will crash
with "Invalid child # of SDNode".  I'll discuss that symptom below also.



(2) Analysis

There are several problems:

(2a) The intrinsic llvm.read_register is marked with IntrNoMem.  Consequently,
optimizations treat it as independent of llvm.write_register.  They incorrectly
reorder llvm.read_register w.r.t. llvm.write_register.
==> Instead, llvm.read_register should NOT have the IntrNoMem attribute, just
like llvm.write_register.

(2b) When SelectionDAGBuilder lowers llvm.write_register to
ISD::WRITE_REGISTER, it uses some nonsense value for the SDNode's chain
argument.  This is part of the "Invalid child" problem mentioned above.
==> Instead, the Chain operand should be from DAG.getRoot().

(2c) SelectionDAGISelLowering clobbers the value of the chain operand when it
translates ISD::WRITE_REGISTER into ISD::CopyToReg.
==> In should preserve Op->getOperand(0) rather than replacing it with
CurDAG->getEntryNode().



(3) Patch

I have a patch, but it seems can only submit one attachment at this time.  I'll
post a follow-up with the patch.</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>