Skip to content

LLVM trashes registers for primitive calls

When calling, the LLVM backend will generate code that sets a number of global registers to "undefined" to prevent LLVM from saving them. I suppose that's a good idea for C calls, but for primitive calls it is unnecessary, even dangerous. "tan 0.5" will have the backend generate code like follows:

...
store i64 %ln1zX, i64* %ln1zZ
store i64 undef, i64* %R3_Var
store i64 undef, i64* %R4_Var
store i64 undef, i64* %R5_Var
store i64 undef, i64* %R6_Var
store float undef, float* %F1_Var
store float undef, float* %F2_Var
store float undef, float* %F3_Var
store float undef, float* %F4_Var
store double undef, double* %D1_Var
store double undef, double* %D2_Var
%ln1A0 = call ccc double (double)* @tan( double 0x3FE0000000000000 ) nounwind
...

A few lines later, these registers are then read again, with LLVM probably assuming that the read results don't matter, as it can deduce that "tan" can't have written them.

I discovered this when investigating why my programs using additional primitive operations kept crashing. Removing the trashing for primitive calls seems to fix the problem nicely, patch attached.

Trac metadata
Trac field Value
Version 7.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler (LLVM)
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information