&gt; But why can&#x27;t it just produce something different on each system?<p>It could. That is indeed how Rust, for example, defines it.<p>But in C &quot;unspecified values&quot; have a way of turning into undefined behavior really quickly.<p>Here&#x27;s an actual bug we have in Rust [1]:<p><pre><code>    let index = 1.04E+17 as u8;
    let array = vec![1, 2, 3, 4, 5];
    println!(&quot;{}&quot;, array[index as usize]); &#x2F;&#x2F; segfault
</code></pre>
Why does that segfault instead of emitting a safe panic? Because the IR looks something roughly like this (in C notation):<p><pre><code>    double tmp = 1.04e+17;
    uint8_t index = (uint8_t)tmp;
    vector *array = make_a_vector();
    if (index &gt;= array-&gt;length)
        panic();
    printf(&quot;%d\n&quot;, array-&gt;ptr[index]);
</code></pre>
The optimizer correctly determines that the cast from double to uint8_t results in an undefined value. In LLVM terminology, <i>undefined values can arbitrarily change value over their live range</i>, and this is allowed per the C specification. So LLVM is allowed to replace the conditional &quot;index &gt;= array-&gt;length&quot; with &quot;false&quot;, and this is indeed what it does, leading to this code:<p><pre><code>    double tmp = 1.04e+17;
    uint8_t index = (uint8_t)tmp;
    vector *array = make_a_vector();
    printf(&quot;%d\n&quot;, array-&gt;ptr[index]);
</code></pre>
And with that, LLVM optimizes out our bounds check, and safe code is able to perform arbitrary memory reads and writes. Note that all we needed was an unspecified value resulting from a floating point cast!<p>The fix is probably going to be to stop using LLVM&#x27;s floating point conversion instructions and to instead use some &quot;safe conversion&quot; intrinsics that we&#x27;ll define.<p>&gt; What compilers do today should be the recourse of absolute last resort, and the sort of thing that makes its authors feel bad. But it seems to be treated as a matter of course. I don&#x27;t know what to say.<p>You might think that I would think this way too after fighting bugs like the above, but I actually don&#x27;t. I appreciate the performance that undefined behavior brings to C, and I think we&#x27;d have much slower programs without it. Undefined behavior resulting from strict aliasing is the reason why a for loop setting an array to zero can optimize to a 10x faster memset, for example. And heavily inlined series of functions, as well as generic libraries like the C++ STL, frequently require these optimizations to get reasonable performance. I think it&#x27;s not an exaggeration to say that much of the software performance we take for granted—stuff you care about, like codecs, games, browser implementations—is the result of optimizations that are enabled by undefined behavior.<p>[1]: <a href="https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;10184" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;10184</a>