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 |