<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 --- - LLVM remove one must instruction to produce wrong result in optimization under global register variable condition"
   href="https://llvm.org/bugs/show_bug.cgi?id=24756">24756</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>LLVM remove one must instruction to produce wrong result in optimization under global register variable condition
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>tools
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>3.6
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>Other
          </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>opt
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>bluechristlove@163.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Firstly, let us see follow simple example:

[Example]

#include <stdio.h>

register signed int ina asm("r21");
int main()
{
   ina = -244;
   __asm("addi 21,21,5" : "=r"(ina) : "r"(ina) );
  printf("ina: %d\n", ina);
}

[/Example]

We specific global variable as register r21, then we  read from register r21
and add value 5 to r21, then print the value of ina.

The expected value is -239.

When we emit its llvm-ir in O0:

[LLVM-IR-O0]

; ModuleID = 't.c'
target datalayout = "e-m:e-i64:64-n32:64"
target triple = "powerpc64le-unknown-linux-gnu"

@.str = private unnamed_addr constant [9 x i8] c"ina: %d\0A\00", align 1

; Function Attrs: nounwind
define signext i32 @main() #0 {
entry:
  call void @llvm.write_register.i32(metadata !0, i32 -244)
  %0 = call i32 @llvm.read_register.i32(metadata !0)
  %1 = call i32 asm "addi 21,21,5", "={r21},{r21}"(i32 %0) #1, !srcloc !2
  call void @llvm.write_register.i32(metadata !0, i32 %1)
  %2 = call i32 @llvm.read_register.i32(metadata !0)
  %call = call signext i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x
i8]* @.str, i32 0, i32 0), i32 signext %2)
  ret i32 0
}

; Function Attrs: nounwind
declare void @llvm.write_register.i32(metadata, i32) #1

; Function Attrs: nounwind readnone
declare i32 @llvm.read_register.i32(metadata) #2

declare signext i32 @printf(i8*, ...) #3

attributes #0 = { nounwind "less-precise-fpmad"="false"
"no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"
"no-infs-fp-math"="false" "no-nans-fp-math"="false"
"stack-protector-buffer-size"="8" "unsafe-fp-math"="false"
"use-soft-float"="false" }
attributes #1 = { nounwind }
attributes #2 = { nounwind readnone }
attributes #3 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
"no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
"no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
"unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.named.register.r21 = !{!0}
!llvm.ident = !{!1}

!0 = !{!"r21"}
!1 = !{!"clang version 3.6.1 (tags/RELEASE_361/final)"}
!2 = !{i32 95}


[LLVM-IR-O0]

It is right. 

But when we emit the IR in -O2:

[LLVM-IR-O2]

....

; Function Attrs: nounwind
define signext i32 @main() #0 {
entry:
  tail call void @llvm.write_register.i32(metadata !0, i32 -244)
  %0 = tail call i32 @llvm.read_register.i32(metadata !0)
  %1 = tail call i32 asm "addi 21,21,5", "={r21},{r21}"(i32 %0) #1, !srcloc !2
  tail call void @llvm.write_register.i32(metadata !0, i32 %1)
  %call = tail call signext i32 (i8*, ...)* @printf(i8* getelementptr inbounds
([9 x i8]* @.str, i64 0, i64 0), i32 signext %0) #1
  ret i32 0
}

....

!llvm.named.register.r21 = !{!0}
!llvm.ident = !{!1}

!0 = !{!"r21"}
!1 = !{!"clang version 3.6.1 (tags/RELEASE_361/final)"}
!2 = !{i32 95

[/LLVM-IR-O2]

Here we can see that after @llvm.write_register, we remove

%2 = call i32 @llvm.read_register.i32(metadata !0)

But in fact we have modified register 21 value, so we must call
@llvm.read_register function to read value from register 21. But llvm optimizer
remove it and use %0( which is the register 21 value before modified).

Computer Architecture:
PPC64le

OS:
Red Hat Enterprise Linux 7</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>