<story><title>Clang vs. Clang</title><url>https://blog.cr.yp.to/20240803-clang.html</url></story><parent_chain><item><author>Dylan16807</author><text>&amp;gt; What should the compiler emit here?&lt;p&gt;It should emit an instruction to access memory location some_array + i.&lt;p&gt;That&amp;#x27;s all most people that complain about optimizations on undefined behavior want.  Sometimes there are questions that are hard to answer, but in a situation like this, the answer is &amp;quot;Try it and hope it doesn&amp;#x27;t corrupt memory.&amp;quot;  The behavior that&amp;#x27;s not wanted is for the compiler to wildly change behavior on purpose when something is undefined.  For example, the compiler could optimize&lt;p&gt;&lt;pre&gt;&lt;code&gt;  if(foo) {
      misbehaving_code();
      return puppies;
  } else {
      delete_data();
  }
&lt;/code&gt;&lt;/pre&gt;
into&lt;p&gt;&lt;pre&gt;&lt;code&gt;  delete_data();&lt;/code&gt;&lt;/pre&gt;</text></item><item><author>opnitro</author><text>I think this is a point of view that seems sensible, but probably hasn&amp;#x27;t really thought through how this works. For example&lt;p&gt;&lt;pre&gt;&lt;code&gt;  some_array[i]
&lt;/code&gt;&lt;/pre&gt;
What should the compiler emit here? Should it emit a bounds check? In the event the bounds check fails, what should it do? It is only through the practice of undefined behavior that the compiler can consistently generate code that avoids the bounds check. (We don&amp;#x27;t need it, because if `i` is out-of-bounds then it&amp;#x27;s undefined behavior and illegal).&lt;p&gt;If you think this is bad, then you&amp;#x27;re arguing against memory unsafe languages in general. A sane position is the one the Rust takes, which is by default, yes indeed you should always generate the bounds check (unless you can prove it always succeeds). But there will likely always be hot inner loops where we need to discharge the bounds checks statically. Ideally that would be done with some kind of formal reasoning support, but the industry is far that atm.&lt;p&gt;For a more in depth read: &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;blog.regehr.org&amp;#x2F;archives&amp;#x2F;213&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;blog.regehr.org&amp;#x2F;archives&amp;#x2F;213&lt;/a&gt;</text></item><item><author>moomin</author><text>There are only two models of UB that are useful to compiler users:&lt;p&gt;1) This is a bad idea and refuse to compile.&lt;p&gt;2) Do something sensible and stable.&lt;p&gt;Silently fail and generate impossible to predict code is a third model that is only of use to compiler writers. Hiding behind the spec benefits no actual user.</text></item><item><author>josephcsible</author><text>&amp;gt; compiler writers refuse to take responsibility for the bugs they introduced, even though the compiled code worked fine before the &amp;quot;optimizations&amp;quot;. The excuse for not taking responsibility is that there are &amp;quot;language standards&amp;quot; saying that these bugs should be blamed on millions of programmers writing code that bumps into &amp;quot;undefined behavior&amp;quot;&lt;p&gt;But that&amp;#x27;s not an excuse for having a bug; it&amp;#x27;s the exact evidence that it&amp;#x27;s not a bug at all. Calling the compiler buggy for not doing what you want when you commit Undefined Behavior is like calling dd buggy for destroying your data when you call it with the wrong arguments.</text></item></parent_chain><comment><author>opnitro</author><text>I think the &amp;quot;do the normal&amp;quot; thing is very easy to say and very hard to do in general. Should every case of `a &amp;#x2F; b` inject a `(b != 0) &amp;amp;&amp;amp; ((a != INT_MAX &amp;amp;&amp;amp; b != -1))`? If that evaluates to `true` then what should the program do? Or: should the compiler assume this can&amp;#x27;t happen. Languages with rich runtimes get around this by having an agreed upon way to signal errors, at the expense of runtime checking. An example directly stolen from the linked blog post:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  int stupid (int a) {
    return (a+1) &amp;gt; a;
  }
&lt;/code&gt;&lt;/pre&gt;
What should the compiler emit for this? Should it check for overflow, or should it emit the asm equivalent of `return 1`? If your answer is check for overflow: then should the compiler be forced to check for overflow every time it increments an integer in a for loop? If your answer is don&amp;#x27;t check: then how do you explain this function behaving completely weird in the overflow case? The point I&amp;#x27;m trying to get at is that &amp;quot;do the obvious thing&amp;quot; is completely dependent on context.</text></comment>
<story><title>Clang vs. Clang</title><url>https://blog.cr.yp.to/20240803-clang.html</url></story><parent_chain><item><author>Dylan16807</author><text>&amp;gt; What should the compiler emit here?&lt;p&gt;It should emit an instruction to access memory location some_array + i.&lt;p&gt;That&amp;#x27;s all most people that complain about optimizations on undefined behavior want.  Sometimes there are questions that are hard to answer, but in a situation like this, the answer is &amp;quot;Try it and hope it doesn&amp;#x27;t corrupt memory.&amp;quot;  The behavior that&amp;#x27;s not wanted is for the compiler to wildly change behavior on purpose when something is undefined.  For example, the compiler could optimize&lt;p&gt;&lt;pre&gt;&lt;code&gt;  if(foo) {
      misbehaving_code();
      return puppies;
  } else {
      delete_data();
  }
&lt;/code&gt;&lt;/pre&gt;
into&lt;p&gt;&lt;pre&gt;&lt;code&gt;  delete_data();&lt;/code&gt;&lt;/pre&gt;</text></item><item><author>opnitro</author><text>I think this is a point of view that seems sensible, but probably hasn&amp;#x27;t really thought through how this works. For example&lt;p&gt;&lt;pre&gt;&lt;code&gt;  some_array[i]
&lt;/code&gt;&lt;/pre&gt;
What should the compiler emit here? Should it emit a bounds check? In the event the bounds check fails, what should it do? It is only through the practice of undefined behavior that the compiler can consistently generate code that avoids the bounds check. (We don&amp;#x27;t need it, because if `i` is out-of-bounds then it&amp;#x27;s undefined behavior and illegal).&lt;p&gt;If you think this is bad, then you&amp;#x27;re arguing against memory unsafe languages in general. A sane position is the one the Rust takes, which is by default, yes indeed you should always generate the bounds check (unless you can prove it always succeeds). But there will likely always be hot inner loops where we need to discharge the bounds checks statically. Ideally that would be done with some kind of formal reasoning support, but the industry is far that atm.&lt;p&gt;For a more in depth read: &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;blog.regehr.org&amp;#x2F;archives&amp;#x2F;213&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;blog.regehr.org&amp;#x2F;archives&amp;#x2F;213&lt;/a&gt;</text></item><item><author>moomin</author><text>There are only two models of UB that are useful to compiler users:&lt;p&gt;1) This is a bad idea and refuse to compile.&lt;p&gt;2) Do something sensible and stable.&lt;p&gt;Silently fail and generate impossible to predict code is a third model that is only of use to compiler writers. Hiding behind the spec benefits no actual user.</text></item><item><author>josephcsible</author><text>&amp;gt; compiler writers refuse to take responsibility for the bugs they introduced, even though the compiled code worked fine before the &amp;quot;optimizations&amp;quot;. The excuse for not taking responsibility is that there are &amp;quot;language standards&amp;quot; saying that these bugs should be blamed on millions of programmers writing code that bumps into &amp;quot;undefined behavior&amp;quot;&lt;p&gt;But that&amp;#x27;s not an excuse for having a bug; it&amp;#x27;s the exact evidence that it&amp;#x27;s not a bug at all. Calling the compiler buggy for not doing what you want when you commit Undefined Behavior is like calling dd buggy for destroying your data when you call it with the wrong arguments.</text></item></parent_chain><comment><author>cobbal</author><text>Ah, but what if it writes so far off the array that it messes with the contents of another variable on the stack that is currently cached in a register? Should the compiler reload that register because the out of bounds write might have updated it? Probably not, let&amp;#x27;s just assume they didn&amp;#x27;t mean to do that and use the in-register version. That&amp;#x27;s taking advantage of undefined behavior to optimize a program.</text></comment>