8 ms·
The x86 architecture is the weirdo (2004)
- comex 5y agoLet's see how things have changed since 2004 when this was published: > The x86 has a small number (8) of general-purpose registers x86-64 added more general-purpose registers. > The x86 uses the stack to pass function parameters; the others use registers. OS vendors switched to registers for x86-64. > The x86 forgives access to unaligned data, silently fixing up the misalignment. Now ubiquitous on application processors. > The x86 has variable-sized instructions. The others use fixed-sized instructions. ARM introduced Thumb-2, with a mix of 2-byte and 4-byte instructions, in 2003. PowerPC and RISC-V also added some form of variable-length instruction support. On the other hand, ARM turned around and dropped variable-length instructions with its 64-bit architecture released in 2011. > The x86 has a strict memory model … The others have weak memory models Still x86-only. > The x86 supports atomic load-modify-store operations. None of the others do. As opposed to load-linked/store-conditional, which is a different way to express the same basic idea? Or is he claiming that other processors didn't support any form of atomic instructions, which definitely isn't true? At any rate, ARM previously had load-linked/store-conditional but recently added a native compare-and-swap instruction with ARMv8.1. > The x86 passes function return addresses on the stack. The others use a link register. Still x86-only.
- ungamedplayer 5y agoThank you for writing this. I was going to cover quite a lot of these points and you have done it so very succinctly. It may be obvious, but I think it bears repeating. This blog entry should not reflect badly on Raymond C as he was reporting on the architecture at this time.
- zinekeller 5y agoThe 2022 follow-up also said "And by x86 I mean specifically x86-32." Also, I don't he was on the AMD64 team yet at that time (still Itanium) so probably that is something.
- ncmncm 5y agoApple M1 supports optional x86-style memory event ordering, so that its x86 emulation could be made to work without penalty. When SPARC got new microcode supporting unaligned access, it turned out to be a big performance win, as the alignment padding had made for a bigger cache footprint. That was an embarrassment for the whole RISC industry. Nobody today would field a chip that enforced alignment. The alignment penalty might have been smaller back when clock rates were closer to memory latency, but caches were radically smaller then, too, so even more affected by inflated footprint.
- jnordwick 5y ago> as the alignment padding had made for a bigger cache footprint I argues with some of the Rust compiler members the other day about wanting to just ditch almost all alighnment restrictions because I of this exact thing. They laughed and basically told me i didnt know what i was talking about. I remember about 15 years ago when i worked at market making firm and we test this and it was a great gain - we started packing almost all our structs after that. Now, at another MM shop, and we're trying to push the same thing but having to fight these areguments again (the only alignmets I want to keep are for AVX and hardware accessed buffers).
- ncmncm 5y agoSuperstition is as powerful as it ever was.
- MBCook 5y agoIs this superstition or more received wisdom, which may have been true at one point in the past as is now just orthodoxy?
- notriddle 5y agoFifty bucks says it isn't even about performance, but is instead about passing pointers to C code. Zero-overhead FFI has killed a lot of radical performance improvements that Rust could have otherwise made. I don't know, because nobody's actually posting a link to it.
- NtGuy25 5y agoIn regards to memory alignment, it's even worse. Most instructions work on unaligned data. But some instructions require 8 byte, 16 byte, 32 byte, 64 byte and I think there's even some 128 and 256 byte alignment. One of the more common pitfalls someone can find themselves in when coding x86-64 asm.
- ceeplusplus 5y agoThere is still one big thing that hasn't changed but has been the subject of discussion on whether x86-64 is fundamentally bottlenecking CPU architecture. Variable length instructions means decoder complexity scales quadratically rather than linearly. It's been speculated this is one reason why even the latest x86 architectures stick with relatively narrow decode but Arm CPUs with lower performance levels (e.g. Cortex X1/2) are already 5-wide and Apple is 8-wide.
- cesarb 5y ago> ARM introduced Thumb-2, with a mix of 2-byte and 4-byte instructions, in 2003. PowerPC and RISC-V also [...] x86 is still the weirdo. Both Thumb-2 and the RISC-V C extension (I don't know about PowerPC) have only 2-byte and 4-byte instructions, aligned to 2 bytes; x86 instructions can vary from 1 to 15 bytes, with no alignment requirement.
- classichasclass 5y agoPower10 has prefixed instructions. These are essentially 64-bit instructions in two pieces. They are odd even (particularly?) to those of us who have worked with the architecture for a long time, and not much otherwise supports them yet. Their motivation is primarily to more efficiently represent constants and offsets.
- cryptonector 5y agoI suspect variable-length instructions are a big gain because you get to pack instructions more tightly and so have fewer cache misses. Though, obviously, it's going to depend on having an instruction set that yields shorter text for typical assembly than fixed-sized instructions would. (In a way, opcodes need a bit of Huffman encoding!) Any losses from having to do more decoding work are probably offset by having sufficiently deep pipelines and enough decoders.
- phdelightful 5y agoThe counterpoint is that variable-length decoding introduces sequential dependence in the decoding, i.e. you don’t know where instruction 2 starts until you’ve decoded instruction 1. This probably limits how many decoders you can have. If you know all your instructions are 4B you can basically decode as many as you want in parallel.
- gpderetta 5y agoI think what happen in practice is that the decoders still speculatively decode in parallel then drop all misdecoded instructions. Easy when instructions have only a couple of sizes. Hard and wasteful for something like x86.
- phamilton 5y agoI vaguely recall that LL/SC solves the ABA problem whereas load-modify-store does not. It's been a while, so I'm going to define my understanding of the ABA problem in case I misunderstood it: x86 only supplies cmpxchange instructions on which will update a value only if it matches the passed in previous value. There's a class of concurrency bugs where the value is modified away from it's initial value and then modified again back to it's value. cmpxchange can't detect that condition, so if it's a meaningful difference often the 128-bit cmpxchange will be used with a counter in the second 64-bits that is incremented on each write to catch this case. LL/SC will trigger on any write, rather than comparing the value, providing the stronger guarantee. (Please correct me if this is inaccurate, it's been a hit minute since I learned this and I'd love to be more current on it).
- zozbot234 5y agoAIUI, a cmpxchg loop is enough to implement read-modify-write of any atomically sized value. The ABA problem becomes relevant when trying to implement more complex lock-free data structures.
- wolpoli 5y agoThanks for summarizing this. Did they do any other clean-up when moving to 64 bit?
- moonchild 5y agoPC-relative code.
- gpderetta 5y ago>>The x86 has a strict memory model … The others have weak memory models > Still x86-only. SPARC supported (eventually exclusively) TSO well before x86 committed to it. For a while Intel claimed to support some form of Processor Ordering which I understand is slightly weaker than TSO, although no Intel CPU ever took advantage of the weakened constraints.
- moonchild 5y ago>> The x86 supports atomic load-modify-store operations. None of the others do. > As opposed to load-linked/store-conditional, which is a different way to express the same basic idea? Perhaps that x86 has atomic addition, where other architectures must use a cas/ll+sc loop?
- ttybird2 5y ago"As opposed to load-linked/store-conditional, which is a different way to express the same basic idea? Or is he claiming that other processors didn't support any form of atomic instructions, which definitely isn't true?" It refers specifically to things like fetch_and_add. Supported by risc-v and i64.
- aap_ 5y agoI wouldn't say the x86 is the weirdo in these cases, it's just not a RISC.
- lynguist 5y agoIn essence, it is a RISC since the days of Pentium Pro. Each instruction is decoded to several micro-operations and the trick of making the CPU run fast lies in the decoder. This also leads to situations where many instructions in x86 asm will run faster than fewer complex instructions which the decoder may not decode to its most optimal micro-operations sequence.
- phamilton 5y agoTo what extent is the decoding consistent? It always felt weird to me that we'd do something in hardware on every execution that could be done once in software at compile time. But if the decoder does smart things that would make more sense to me. For example, with SMT the decoder could choose not to use certain ops if the compute units are in use by the other thread.
- buildbot 5y agoI am not sure of any arch that does this, but having a second stage decode buys 2 things off the top of my head - better instruction cache usage, esp. for small loops, and the flexibility to decode ops differently on different versions of the same arch from one binary. Otherwise you would have to have tons of different versions for each flavor of x86 out there.
- imtringued 5y agoIntel and AMD CPUs have micro op caches for tight loops.
- akira2501 5y ago> on every execution that could be done once in software at compile time Which is to me, essentially, VLIW. Those architectures didn't work out very well. There's a lot of memory pressure just to move instructions around and the costs didn't seem to outweigh the benefits.
- anticensor 5y agoPart 2: https://devblogs.microsoft.com/oldnewthing/20220418-00/?p=106489 https://devblogs.microsoft.com/oldnewthing/20220418-00/?p=10...
- Findecanor 5y ago> The x86 has a strict memory model x86 doesn't really impose sequential consistency between cores/threads. It imposes a Total Store Order (TSO) in which stores are always in order to each other but a store can be reordered after a load. SPARC had TSO on later chips whereas earlier chips had weaker models. MIPS developed the other way: with older versions having stronger memory ordering and later getting relaxed memory ordering. RISC-V chips can optionally support TSO but it seems that the motivation is programs ported from x86. IBM's z/Architecture (with lineage back to IBM/360) is still alive and also has TSO. BTW. The Mill is supposed to offer sequential consistency, but it remains to be seen if that will be a performance bottleneck.
- ajross 5y ago> x86 doesn't really impose sequential consistency between cores/threads. It imposes a Total Store Order (TSO) in which stores are always in order to each other but a store can be reordered after a load. To be more pedantic (and hoping I remember this correctly): TSO is indistinguishable in software from full sequential consistency. Any code to detect the difference must by definition be subject to race conditions (or must be an atomic read/write operation that on x86 would be serializing anyway). So x86 in fact does provide SC semantics "between cores/threads". It does have visible reordering artifacts from the perspective of hardware designs (e.g. MMIO registers) where a load has side effects.
- dmatech 5y agoThat strictness of x86 execution order has been substantially relaxed in the last two decades and can be a bit of a pain to deal with in multithreaded code for the novice. The Pentium 3 added SFENCE (with SSE) and the Pentium 4 added LFENCE and MFENCE (with SSE2). I believe that prior to that, only the LOCK prefix was available.
- deleted 5y ago[deleted]
- fmajid 5y agoAn article by the Raymond Chen. Here's Joel Spolsky's contemporary take on Chen: https://www.joelonsoftware.com/2004/06/13/how-microsoft-lost-the-api-war/ https://www.joelonsoftware.com/2004/06/13/how-microsoft-lost...
- anonymousiam 5y agoI would argue that in 2004 there were still more processor architectures that used the stack for function parameters and return addresses than those that used registers.
- xg15 5y ago> Note from the future: At the time of writing, the term “x86” was used exclusively to refer to what later became known as “x86-32”. The name “x86-64” wouldn’t be invented until 2006. Notes from the future are always a risky business. Now we're in the future and we call them x86 and x64 - which makes far less sense than x86-32 and x86-64, but I guess is shorter and doesn't require you to learn a new name for an old concept. I guess the actual future always turns out a bit more messy than the science fiction version of it.
- cesarb 5y ago> The name “x86-64” wouldn’t be invented until 2006. While x86-32 is AFAIK a backronym which would only be invented later, the original name of the AMD64 architecture is x86-64, and has been since that architecture was first revealed at the turn of the millennium. If you weren't following these developments back then, you can still see it for yourself in the Internet Archive: https://web.archive.org/web/20000817014037/http://www.x86-64.org/ https://web.archive.org/web/20000817014037/http://www.x86-64... is the earliest snapshot of the official page for the x86-64 Linux porting effort, which links to https://web.archive.org/web/20000817071303/http://www.amd.com/news/corppr/20152.html https://web.archive.org/web/20000817071303/http://www.amd.co... which is a snapshot of a press release dated 2000-08-15 announcing that porting effort. Quoting from that press release: "AMD publicly released its 64-bit architecture specification, the x86-64™ Architecture Programmers Overview, last week to enable the industry to begin incorporating x86-64 technology support into their operating systems, applications, drivers, and development tools." That is, the x86-64 name was first used publicly, as the official name of that architecture, no later than early August of the year 2000.
- tabtab 5y agox86 is a hack on top of a chip design that was originally intended as a low-cost calculator CPU that gradually grew up to power big-iron servers. Most of its competitors were designed for medium or large computers from the get-go, so had far less backward-compatibility baggage to deal with.
- thedeadfish 5y agoNot at all, the original 16bit x86 was well designed. The 32bit extensions were pretty decent too. Its not until much later that it really started to turn to shit. The real disaster started when Intel started haphazardly adding terribly thought out SIMD instructions. AMD64 truly sucks though, this is where the original encoding should have been replaced.
- tabtab 5y agoThe 16bit chip had to be backward compatible with the 8bit, no?
- thedeadfish 5y agoKind of but not really, whilst it shares some design choices, the 8086 is neither source or binary compatible with the 8080.
- xyzzy21 5y agoEven weirder, x86 is only a superficial layer - all x86 code has been compiled to RISC on-the-fly since the 1990s. This is an economic artifact of the unpredicted success of the IBM PC.