asm goto miscompilation · Issue #74483 · llvm/llvm-project (original) (raw)
As far as I understand asm goto
now supports output arguments on all paths. If I am reading this correctly, in this case asm goto
corrupts local state (output variable has incorrect value). The code is:
#include <stdio.h>
long foo(long a, long b) {
long x, y, z;
asm goto(
"movq %[a], %[x]; testq %[a], %[a]; jnz %l[label1]"
: [x] "=&r"(x), [y] "=&r"(y), [z] "=&r"(z)
: [a]"r"(a), [b]"r"(b)
: "memory" : label1, label2);
return 0;
{
label1:
return x;
}
label2:
return 1;
}
int main() {
printf("%lu\n", foo(11, 22));
}
foo(long, long): # @foo(long, long)
pushq %rbp
movq %rsp, %rbp
movq %rdi, -16(%rbp)
movq %rsi, -24(%rbp)
movq -16(%rbp), %rsi
movq -24(%rbp), %rdi
movq %rsi, %rax
testq %rsi, %rsi
jne .LBB0_2
movq %rdx, -96(%rbp) # 8-byte Spill
movq %rcx, -88(%rbp) # 8-byte Spill
movq %rax, -80(%rbp) # 8-byte Spill
movq %rdx, -72(%rbp) # 8-byte Spill
movq %rcx, -64(%rbp) # 8-byte Spill
movq %rax, -56(%rbp) # 8-byte Spill
jmp .LBB0_1
.LBB0_1:
movq -72(%rbp), %rax # 8-byte Reload
movq -64(%rbp), %rcx # 8-byte Reload
movq -56(%rbp), %rdx # 8-byte Reload
movq %rdx, -32(%rbp)
movq %rcx, -40(%rbp)
movq %rax, -48(%rbp)
movq $0, -8(%rbp)
jmp .LBB0_6
.LBB0_2: # Block address taken
movq %rdx, -96(%rbp) # 8-byte Spill
movq -80(%rbp), %rdx # 8-byte Reload
movq %rcx, -88(%rbp) # 8-byte Spill
movq -88(%rbp), %rcx # 8-byte Reload
movq %rax, -80(%rbp) # 8-byte Spill
movq -96(%rbp), %rax # 8-byte Reload
movq %rdx, -32(%rbp)
movq %rcx, -40(%rbp)
movq %rax, -48(%rbp)
jmp .LBB0_4
.LBB0_3: # Block address taken
movq %rdx, -96(%rbp) # 8-byte Spill
movq -80(%rbp), %rdx # 8-byte Reload
movq %rcx, -88(%rbp) # 8-byte Spill
movq -88(%rbp), %rcx # 8-byte Reload
movq %rax, -80(%rbp) # 8-byte Spill
movq -96(%rbp), %rax # 8-byte Reload
movq %rdx, -32(%rbp)
movq %rcx, -40(%rbp)
movq %rax, -48(%rbp)
jmp .LBB0_5
.LBB0_4:
movq -32(%rbp), %rax
movq %rax, -8(%rbp)
jmp .LBB0_6
.LBB0_5:
movq $1, -8(%rbp)
.LBB0_6:
movq -8(%rbp), %rax
popq %rbp
retq
If we track the x
variable, it's spilled to -80(%rbp)
, but then loaded from -32(%rbp)
:
foo(long, long): # @foo(long, long)
...
movq %rsi, %rax
...
jne .LBB0_2
...
.LBB0_2: # Block address taken
...
movq %rax, -80(%rbp) # 8-byte Spill
...
jmp .LBB0_4
...
.LBB0_4:
movq -32(%rbp), %rax
movq %rax, -8(%rbp)
jmp .LBB0_6
...
.LBB0_6:
movq -8(%rbp), %rax
popq %rbp
retq