<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/89885>89885</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Difference between compile-time and runtime float precision on 32-bit x86 without SSE can cause miscompilation leading to segfault
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
beetrees
</td>
</tr>
</table>
<pre>
The following program (based on the Rust version from [here](https://github.com/rust-lang/rust/issues/114479#issuecomment-2072945866), which is based on @comex's example from a different issue; they gave an explanation of they found it [here](https://github.com/rust-lang/unsafe-code-guidelines/issues/471#issuecomment-1774261953))
```c
#include <stdio.h>
#include <stddef.h>
void print_vals(float x, size_t i, int vals_i) {
printf("x=%f i=%zu vals[i]=%i\n", x, i, vals_i);
}
void out_of_bounds(float x, size_t i) {
printf("x=%f i=%zu vals[i]=out of bounds\n", x, i);
}
void evil(int vals[300]) {
float x = 0.0;
size_t i = 0;
while (x != 90.0) {
// At compile time, LLVM will brute-force the loop and discover that it
// terminates after 90 iterations, with `i` always less than 300. This bounds
// check therefore gets optimised out.
if (i < 300) {
print_vals(x, i, vals[i]);
} else {
out_of_bounds(x, i);
}
x += 1.0;
// This addition is too small to have any effect on the value of `x` with
// regular `float` precision, which is what LLVM uses at compile-time.
// However, with the extra precision offered by x87 floating point registers,
// the value of `x` will change slightly, meaning it will never hit exactly
// 90.0 and therefore the loop will never terminate at runtime.
x += 2.9802322387695312e-08;
i += 2;
}
}
int main() {
int vals[300];
for (int i = 0; i < 300; i++) {
vals[i] = i;
}
evil(vals);
}
```
compiled with `clang -O3 --target=i686-unknown-linux-gnu -mno-sse code.c` will segfault at runtime. This is due to LLVM evaluating floats at standard float precision at compile-time, but outputting machine code that uses x87 extended precision at runtime. Specifically, [llvm/lib/Analysis/ScalarEvolution.cpp](https://github.com/llvm/llvm-project/blob/46b011d0ccb468613bcc7e9e756518f9f383001d/llvm/lib/Analysis/ScalarEvolution.cpp) will brute force the loop using compile-time semantics, causing the bounds check to be optimised out; however the extra precision of x87 extended precision floats will mean that the loop termination condition is never hit at runtime.
The [LangRef](https://llvm.org/docs/LangRef.html#floatenv) appears to imply that the compile-time semantics are correct, so this is a bug in the x86 backend.
Related to #44218.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJykV1uPozwS_TXOSykRmEvgIQ-TzrT2YVYrzXza15YxBXjH2JFtkvT361dlcu1O71VCCLB9XJdTp4zwXvUGccOKLSt2CzGFwbpNgxgcol80tn3f_DEgdFZre1Smh72zvRMjMF41wmML1kAYEH5OPsABnVfWQOfsCKzYDuiQFTvGqyGEvWfZN8ZfGX_tVRimZiXtyPirm3xYamH68zPjr8r7CT3jr2ma5-ua8Sx-kXYc0YQlT9a8zouqLBmvGX-B46DkAMrD1SSWJ9KOeGJ87QFPYtxrnM0S0KquQ4cmQERl2ZY8eIdeHBCEATzttTAikCe2m8c6O5kWVPifvJqMFx0upW1x2U-qRa1MdO_qZ75OPzqZrtc5L9O6yKKTNUt2LPl2vpfJfMnzO8-UkXpqEVj24kOr7Gpg2fcvRlvs7ofj_WBVC3unTHg7CO0ZrzptRYATxderP_EtgKJnZQLQjDfFeA1svb2g1HF1x3jFOD-xbMd40YGaH_6c4iJWbBWFLn5TrHgxjHNCjdtE_Cs2yy7Q690nS-0U3mz31lBavjT2_zDPToFyf8b_bOe_tg4PSjNeXULFim2WJJEyjyadrQaW7SBZJTfMpL54MY_djZzHj4PSSFV4AsZTmlQTwocN6IrchG8BpB33tCioEcmNHz_-_lc4Kq2hcVPAZWedxFjM2to9CNNCq7y0B3QQBhFAhSfAAd2ojAjoQXQBHdQJqIAu1o-P1anCAKxMFCsTEPoo3j1o9J5ADWRJsoI_BireOdift5ADyt9kmMPOOoQegwe7D2pUsdynsLpfpTqKC0XuhdCfxeTMhgvVH9l3YcF9kudl6x2g9vgE7iMfn_DkAnH_SsnbUvLSx-zffI-REW2rohwpD8Fa8KPQGoKFYZasd8CuQxkuYnwQekLiLyuTE0WdUvAE3GE_aeFoWqQiTd07lIpU_EFYj5T_SJjJU6avbFoSm1ZPsP9ij3hAdyUA2YWn4MRtB7BRiFto3uFUrSHaEJuMpdJx2Csf0BGJnhHvuaNagxyE6RG8Vv0Q9DuZMKIwhKzCPMWQbTCoQM1B0qTPG1BBxSq4Me9aHHcg1wKgqLjJfArINcl8VVcJzzjPqnVZF1nKcZlUH_KurrMfBq68eZQbitMolImy9sjzz-pzh9dZB2eFukkM3GqGXsgOuj6Vz12RxLXquaVJfdbBucqeSealj927dCZWe9UNSW0Uln_LYLkMwvUYWLZTZVUuJ_Pb2KNZamWm07I3EyxHY5feI1CzXckrJTz2nZh0uM_RXFvKQzshFVOkNxKlZhZGOkau-yBMK1w7f7oj8Ic6IKY11DmmsJ9CBBmFHJSZ7ZlVNBYQ0R1PAU2L7SPe1bpfe5SqU1LomcKs2Gp9oLOFVg3jr9-M0O9e0fHhlxRauO8HqyeSiZXc7__tAeWCpQ_jcu_sP1DSyavRlrDzsknStE2kbPKyKtOskXKNNa6Lskirru6yKkuStL3D-U9s4vVdv4EP_WbyFK_7cILHUZigZGwjUswzaMGss5fGYKHBx35A_B1mAfpCeL7KwDnp0UwSjTlnVyMvxU5TpTU3Wb4JyhMVoDsdo1mx_SFM_xO7Z-mhSK6soxNja8nn1_Pk1RBGzXgWbUNzoDiK_R6Fo3YAatzr95udzyMIwtGQczHPL-AthDP9BTRTD2puHaeqhEbI32jaB_N_ohYBW9qP8SzPeVqtFu0ma-usFgvcpOs0q_N8vc4XwyYpqqYRddPmZSGbpioxSypRSZ7WTZWJfKE2POF5kvM8Wedlmq-SVJQ8S1JZJnWZtsjyBEeh9OoSlEU8HG-quqqKhRYNah__Wjg3eDwf5Dmnnxi3iZxupt6zPNHKB39DCSpo3OzOfwASocFwRDSPUSPRP-fwU8lbAxlfNirEUJFG0Vnx16_vIIWJJEUY6dhEeDNRNIo2MtdedWgxOb35r6vz-r8Qw_DPAAAA__-jlzx1">