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 |