Hi, we’re having issues after migrating from LLVM 10 to LLVM 11. We have the feeling this is a bug in LLVM, but perhaps we’re missing something. The problem has two parts to it, but they’re somewhat related so I’m posting them together.
Part 1, mysterious freeze instructions
The first part is related to freeze
instructions that appears in our generated .ll
files. We aren’t inserting them, so this is done by the C api. Why is that, and how can we disable it? I have a mild understanding of what this instruction does, but I don’t know the reasons to be automatically inserted into our code. In principle, they shouldn’t harm, however…
Part 2, incorrect? asm generation
There seems to be a bug in the generation of x86 asm code when there is a freeze
operation. The bug only appears when performing div/rem operations on constants. The following two functions only differ in that in the first one the freeze
operation is called before doing the urem
operation on a truncated argument.
define fastcc i32 @frozen(i64 %a) nounwind {
entry:
%x = trunc i64 %a to i32
%y = freeze i32 %x
%z = urem i32 %y, 10
ret i32 %z
}
define fastcc i32 @thawn(i64 %a) nounwind {
entry:
%x = trunc i64 %a to i32
%z = urem i32 %x, 10
ret i32 %z
}
However, the assembly code differs in a critical aspect: the code for the first one seems to “forget” to truncate the argument:
movq %rdi, %rax
movl $3435973837, %ecx # imm = 0xCCCCCCCD
imulq %rdi, %rcx
...
Instead, the function without the freeze is compiled correctly:
movq %rdi, %rax
movl %eax, %ecx # <---- truncation here
movl $3435973837, %edx # imm = 0xCCCCCCCD
imulq %rcx, %rdx
...
This only happens when the operation is performed on a constant, which lead us to believe it has to do with the optimization when doing division/remainder with a constant. The bug is not present if we disable optimizations.
Thanks a lot for any pointer to solve this issue! And please let us know if we should file it in the issue tracker.