<p>Yes.</p>
<p>Decades ago, <a href="https://en.wikipedia.org/wiki/Lisp_machine" rel="nofollow noreferrer">Lisp machines</a> performed simultaneous validation checks (e.g. type checks and bounds checks) as the program ran with the assumption the program and state were valid, jumping &quot;back in time&quot; if the check failed - unfortunately this ability to get &quot;free&quot; runtime validation was lost when conventional (i.e. x86) machines became dominant.</p>
<blockquote>
<p><a href="https://en.wikipedia.org/wiki/Lisp_machine" rel="nofollow noreferrer">https://en.wikipedia.org/wiki/Lisp_machine</a></p>
<p>Lisp Machines ran the tests in parallel with the more conventional single instruction additions. If the simultaneous tests failed, then the result was discarded and recomputed; this meant in many cases a speed increase by several factors. <strong>This simultaneous checking approach was used as well in testing the bounds of arrays when referenced</strong>, and other memory management necessities (not merely garbage collection or arrays).</p>
</blockquote>
<p>Fortunately we're finally learning from the past and slowly, and by piecemeal, reintroducing those innovations - <a href="https://en.wikipedia.org/wiki/Intel_MPX" rel="nofollow noreferrer">Intel's &quot;MPX&quot; (Memory Protection eXtensions)</a> for x86 were introduced in Skylake-generation processors for hardware bounds-checking - though it isn't perfect.</p>
<p>(x86 is a regression in other ways too: IBM's mainframes had true hardware-accelerated system virtualization in the 1980s - we didn't get it on x86 until 2005 with Intel's &quot;VT-x&quot; and AMD's &quot;AMD-V&quot; extensions).</p>
<h3 id="x86-bound-qv0y">x86 <code>BOUND</code></h3>
<p>Technically, x86 <em>does</em> have hardware bounds-checking: the <a href="http://x86.renejeschke.de/html/file_module_x86_id_18.html" rel="nofollow noreferrer">the <code>BOUND</code> instruction</a> was introduced in 1982 in the <a href="http://zsmith.co/intel_b.html#bound" rel="nofollow noreferrer">Intel 80188</a> (as well as the Intel 286 and above, but not the Intel 8086, 8088 or 80186 processors).</p>
<p>While the <code>BOUND</code> instruction does provide hardware bounds-checking, I understand it indirectly caused performance issues because it breaks the hardware branch predictor (<a href="https://www.reddit.com/r/rust/comments/2qlbx1/is_intel_mpx_relevant_for_rust/" rel="nofollow noreferrer">according to a Reddit thread</a>, but I'm unsure why), but also because it requires the bounds to be specified in a tuple <em>in memory</em> - that's terrible for performance - I understand at runtime it's no faster than manually having the instructions to do an &quot;if <code>index</code> not in range <code>[x,y]</code> then signal the <code>BR</code> exception to the program or OS&quot; (so you might imagine the <code>BOUND</code> instruction was added for the convenience of people who coded assembly by-hand, which was quite common in the 1980s).</p>
<p>The <code>BOUND</code> instruction is still present in today's processors, but it was not included in AMD64 (x64) - likely for the performance reasons I explained above, and also because likely very few people were using it (and compilers could trivially replace it with a manual bounds check, that might have <em>better</em> performance anyway, as that could use registers).</p>
<p>Another disadvantage to storing the array bounds in memory is that code elsewhere (that wasn't subject to <code>BOUNDS</code> checking) could overwrite the previously written bounds for another pointer and circumvent the check that way - this is mostly a problem with code that <em>intentionally</em> tries to disable safety features (i.e. malware), but if the bounds were stored in the stack - and given how easy it is to corrupt the stack, it has even less utility.</p>
<h3 id="intel-mpx-qizo">Intel MPX</h3>
<p>Intel MPX was introduced in Skylake architecture in 2015 and should be present in all Skylake and subsequent processor models in the mainstream Intel Core family (including Xeon, and non-SoC versions of Celeron and Pentium). Intel also implemented MPX in the Goldmont architecture (Atom, and SoC versions of Celeron and Pentium) from 2016 onwards.</p>
<p>MPX is superior to <code>BOUND</code> in that it provides dedicated registers to store the bounds range so the bounds-check should be <em>almost</em> zero-cost compared to <code>BOUND</code> which required a memory access. On the Intel 486 the <code>BOUND</code> instruction <a href="http://zsmith.co/intel_b.html#bound" rel="nofollow noreferrer">takes 7 cycles</a> (compare to <code>CMP</code> which takes <a href="http://zsmith.co/intel_c.html#bound" rel="nofollow noreferrer">only 2 cycles</a> even if the operand was a memory address). In Skylake the MPX equivalent (<code>BNDMK</code>, <code>BNDCL</code> and <code>BNDCU</code>) are all 1-cycle instructions and <code>BNDMK</code> can be amortized as it only needs to be called once for each new pointer).</p>
<p>I cannot find any information on wherever or not AMD has implemented their own version of MPX yet (as of June 2017).</p>
<h3 id="critical-thoughts-on-mpx-r2q2">Critical thoughts on MPX</h3>
<p>Unfortunately the current state of MPX is not all that rosy - <a href="https://arxiv.org/abs/1702.00719" rel="nofollow noreferrer">a recent paper by Oleksenko, Kuvaiskii, et al. in February 2017 &quot;Intel MPX Explained&quot;</a> (<a href="https://arxiv.org/pdf/1702.00719.pdf" rel="nofollow noreferrer">PDF link</a>: caution: not yet peer-reviewed) is a tad critical:</p>
<blockquote>
<p>Our main conclusion is that Intel MPX is a promising technique that is not yet practical for widespread adoption. Intel MPX’s performance overheads are still high (~50% on average), and the supporting infrastructure has bugs which may cause compilation or runtime errors. Moreover, we showcase the design limitations of Intel MPX: it cannot detect temporal errors, may have false positives and false negatives in multithreaded code, and its restrictions
on memory layout require substantial code changes for some programs.</p>
</blockquote>
<p>Also note that compared to the Lisp Machines of yore, Intel MPX is still executed inline - whereas in Lisp Machines (<em>if my understanding is correct</em>) bounds checks happened concurrently in hardware with a retroactive jump backwards if the check failed; thus, so-long as a running program's pointers do not point to out-of-bounds locations then there would be an absolutely zero runtime performance cost, so if you have this C code:</p>
<pre><code>char arr[10];
arr[9] = 'a';
arr[8] = 'b';
</code></pre>
<p>Then under MPX then this would be executed:</p>
<pre><code>Time    Instruction              Notes
1       BNDMK arr, arr+9         Set bounds 0 to 9.
2       BNDCL arr                Check `arr` meets lower-bound.
3       BNDCU arr                Check `arr` meets upper-bound.
4       MOV 'a' arr+9            Assign 'a' to arr+9.
5       MOV 'a' arr+8            Assign 'a' to arr+8.
</code></pre>
<p>But on a Lisp machine (if it were magically possible to compile C to Lisp...), then the program-reader-hardware in the computer has the ability to execute additional &quot;side&quot; instructions concurrently with the &quot;actual&quot; instructions, allowing the &quot;side&quot; instructions to instruct the computer to disregard the results from the &quot;actual&quot; instructions in the event of an error:</p>
<pre><code>Time    Actual instruction    Side instruction
1       MOV 'A' arr+9         ENSURE arr+9 BETWEEN arr, arr+9
2       MOV 'A' arr+8         ENSURE arr+8 BETWEEN arr, arr+9
</code></pre>
<p>I understand the instructions-per-cycle for the &quot;side&quot; instructions are not the same as the &quot;Actual&quot; instructions - so the side-check for the instruction at <code>Time=1</code> might only complete after the &quot;Actual&quot; instructions have already progressed on to <code>Time=3</code> - but if the check failed then it would pass the instruction pointer of the failed instruction to the exception handler that would direct the program to disregard the results of the instructions executed after <code>Time=1</code>. I don't know how they could achieve that without massive amounts of memory or some mandatory execution pauses, possibly memory-fencing too -
that's outside the scope of my answer, but it is at least theoretically possible.</p>
<p>(Note in this contrived example I'm using <code>constexpr</code> index values that a compiler can prove will never be out-of-bounds so would omit the MPX checks entirely - so pretend they're user-supplied variables instead :) ).</p>
<p>I'm not an expert in x86 (or have any experience in microprocessor design, spare a CS500-level course I took at UW and didn't do the homework for...) but I don't believe concurrent execution of bounds-checks nor &quot;time travel&quot; is possible with x86's current design, despite the extant implementation of out-of-order execution - I might be wrong, however. I speculate that if all pointer-types were promoted to 3-tuples ( <code>struct BoundedPointer&lt;T&gt; { T* ptr, T* min, T* max }</code> - which technically already happens with MPX and other software-based bounds-checks as every guarded pointer has its bounds defined when <code>BNDMK</code> is called) then the protection could be provided for free by the MMU - but now pointers will consume 24 bytes of memory, each, instead of the current 8 bytes - or compare to the measly 4 bytes under 32-bit x86 - RAM is plentiful, but still a finite resource that shouldn't be wasted.</p>
<h3 id="mpx-in-gcc-f4ke">MPX in GCC</h3>
<p>GCC supported for MPX from version 5.0 to 9.1 ( <a href="https://gcc.gnu.org/wiki/Intel%20MPX%20support%20in%20the%20GCC%20compiler" rel="nofollow noreferrer">https://gcc.gnu.org/wiki/Intel%20MPX%20support%20in%20the%20GCC%20compiler</a> ) when it was removed due to its <a href="https://gcc.gnu.org/legacy-ml/gcc-patches/2017-05/msg01829.html" rel="nofollow noreferrer">maintenance burden</a>.</p>
<h3 id="mpx-in-visual-studio-visual-c-qjai">MPX in Visual Studio / Visual C++</h3>
<p>Visual Studio 2015 Update 1 (2015.1) added &quot;experimental&quot; support for MPX with the <code>/d2MPX</code> switch ( <a href="https://blogs.msdn.microsoft.com/vcblog/2016/01/20/visual-studio-2015-update-1-new-experimental-feature-mpx/" rel="nofollow noreferrer">https://blogs.msdn.microsoft.com/vcblog/2016/01/20/visual-studio-2015-update-1-new-experimental-feature-mpx/</a> ). Support is still present in Visual Studio 2017 but Microsoft has not announced if it's considered a mainstream (i.e. non-experimental) feature yet.</p>
<h3 id="mpx-in-clang-llvm-5vyt">MPX in Clang / LLVM</h3>
<p>Clang has partially supported manual use of MPX in the past, but that support was fully removed in version 10.0</p>
<p>As of July 2021, LLVM still seems capable of outputting MPX instructions, but I can't see any evidence of an MPX &quot;pass&quot;.</p>
<h3 id="mpx-in-intel-cc-compiler-0bqr">MPX in Intel C/C++ Compiler</h3>
<p>The Intel C/C++ Compiler has supported MPX since version 15.0.</p>
Do any CPUs have hardware support for bounds checking?
<p>It doesn't seem like it would be difficult to associate ranges with segments of memory. Then have an assembly instruction which treats 2 integers as "location" &amp; "offset" (another for "data" if setting), and returns the data and error code. This would mean no longer having to make a choice between speed and security/safety when working with arrays.</p>

<p>Another example might be a function which verifies that instructions originating in a particular memory range cannot physically access memory outside that range. If all hardware connected to the motherboard had this capability (and were made to be compatible with each other), it would be trivial to make perfect virtual machines that run at nearly the same speed as the physical machine.</p>

<p>Dustin Soodak</p>