If you ever have a question about computer architecture, ask two questions: 1) where does the memory bandwidth go, and 2) where does the die area go. All else follows from this.
RISC only made sense when CPU clock speeds were at rough parity with central memory speed, on-chip I-caches were limited, pipelines were short, and compilers were only good at modest optimizations.
If you look at functionality per instruction byte, RISC is fairly low. In today's world, CPU clocks are hugely faster than memory speeds, on-chip I-Caches are huge, pipelines are very very deep, branch prediction hardware is very good, and compiler back-ends are much much smarter than the peak days of RISC. CISC wins because the amount of functionality that you can move into the I-Cache per clock is higher and the amount of functionality you can keep in a given amount of I-Cache die area is higher, and compilers are good enough to target specialized instructions efficiently.
Is what Intel has crammed into X86 impressive? Yes, very. And it was damn hard work. I can tell you that walking all the way out to byte 15 of an instruction to look at the MOD R/M byte to decide if you have to raise an illegal instruction exception is a painful long path to squeeze under the clock constraint. But breaking backwards compatibility is just not something customers will put up with. So logic and circuit designers get to ply their trade in it's most convoluted form with the X86.
Perhaps these days I should amend my question list and add a third: 3) where does the power go? This is where ARM has an advantage over X86. The equations that you have to resolve to issue an X86 instruction are simply more complex than for ARM, and all that bit-flipping consumes power.
ARM conditional execution is very clever.
also mostly dead in 64bit armv8
[1] interestingly, POWER8 is capable of converting unpredictable conditional jumps over a small number of instructions to conditional execution.
There's no reason to believe this to be an immutable law going forward for much longer. With more and more going into the browser & cloud, how much is really left on the client side to be backwards compatable with these days?
The first thing I do when I reformat is install chrome, login, and sync my Google Account. I have all my important documents on Google Drive, a full office suite in Google Docs, all my bookmarks, account logins, etc.
Personally for me the web is HTML + CSS, for everything else there is a native application, even though I have done my share of web application projects.
I also don't put my private data in the hands of strangers.
Also do know lots of people that think like I do.
For desktops/laptops and mobile phones, this may be true. For embedded device (where a lot of ARM chips end up) it is not an option, usually.
Likewise, on Windows, there is a huge amount of third-party software that is, for better or worse, tied to the CPU architecture. And for a fair amount of that software, vendors are either unwilling to port it to a new CPU or have stopped supporting the software altogether (or have gone out of business). Consider the sad fate of Windows RT. Windows on low-end ARM devices might have been sweet (as far as Windows goes), but if the only piece of software it runs is IE/Edge and Office, it is not terribly useful.
You should watch this video: https://www.youtube.com/watch?v=Ii_pEXKKYUg
The most important information therein is that the difference in code density is minuscule between x86, ARM and RISC-V. The differences between GCC versions is even bigger.
> The equations that you have to resolve to issue an X86 instruction are simply more complex than for ARM, and all that bit-flipping consumes power.
It's actually just 3-10% of power consumption [1] and I even heard it claimed that the instruction decoding on ARM is larger than x86
[1] https://www.usenix.org/system/files/conference/cooldc16/cool...
ARMv7 OK, is-it still true with ARMv8? It seems to be a much more 'reduced' ISA.
Admittedly some of AArch64 is much cleaner, it involves fewer new conditional instructions than you would expect for an ARM architecture; however it sure as hell ain't RISC.
No, RISC was a response to CPUs becoming faster relative to memory access. Smaller decode logic meant more die space for registers and cache.
Arguably code density can be higher on a CISC device. You'll note that ARM has implemented basically code compression in their ISA with thumb.
As for microcode on x86, most of the actual instructions running on the processor are pulled from L1 already translated. This used to be the trace cache, but after P4 that was dropped and now comes back as a u-op cache, meaning mostly that the instructions are stored in decoded format and so don't get run through translation again. (In P4's trace cache, branches were smashed and whole trace sequences up to three branches long were cached and then speculatively retrieved and executed.)
Interestingly, there's research that shows you can spend plenty of time and gates to optimize the instructions as they come out of translation and go into the trace or u-op cache without negatively affecting performance, which allows some optimization basically for free. No one would do this these days because it's extra power and heat, but it was seriously considered back in the gigahertz wars.
In addition, it should be noted that the translation between x86_64 and u-op is not super larger or challenging and is much much less challenging than most things we'd think about as a compiler pass.
Decoupling internal architecture from externally exposed ISA is not an unreasonable choice, but x86 is certainly no longer a highly desirable external interface these days either.
In a world where single thread performance isn't a significant differentiator, there's fewer reasons to use x86.
Uh, no. CISC is far more efficient than RISC. You can do much more with fewer bytes, increasing your cache efficiency. Also, the fastest instructions are just as quickly decoded as RISC, if not faster. And any complex instructions we can leave for microcode.
The fact that early microprocessors are CISC shows you how much they could do with just a few thousand transistors. RISC architectures never took off until they could pack millions of transistors in, which should hint at how inefficient they were. This inefficiency manifests itself in modern times through power consumption. DEC Alphas & Power CPUS were already power consumption beasts, which is why Apple had to switch from Power to x86 for Macs.
Right now there is nothing intrinsically better about RISC architectures. Like VLIW, RISC is a nice theoretical computer-engineering experiment, nothing more.
This was the case briefly when RISC came out (e.g. Alpha), but x86 fought back with improved fab technology and also threw more power at the problem. Lots of power.
What blindsided RISC was that the CPU clock speed is not as much a limitation as memory access speed[1]. The voracious appetite of RISC instruction fetching[2] through the memory subsystem slowed it down more than it could speed up the CPU clock. (Yeah, yeah, broad generalizations.)
Oh man, my point in a great graphic! https://www.cs.virginia.edu/stream/
[1] If you run the numbers, todays DDRn SDRAM latency is maybe half the latency of the original IBM-AT even though the advertised when streaming bandwidth is several orders of magnitude faster. In other words, if you are not streaming the memory accesses, your memories are not much more than 2x faster than the IBM-AT. Caching enables streaming. Branches break the stream. That is why both caches and branch prediction logic is huge.
My numbers are out of date, but when I ran the numbers for the DDR2(?) memory in my hardware, the worst case latency was 56 clock cycles (e.g. if you had to close a page, open a new page, CAS latency, etc.).
[2] RISC takes 1.5-2x more instructions than CISC in my experience. YMMV.
See slide 31: https://riscv.org/wp-content/uploads/2016/07/Tue1130celio-fu...
English is far from the best language, but everyone on this site speaks it. Gasoline is far from the best source of fuel for a vehicle, but every corner has a gas station. x86 is far from the best architecture, but basically every OS at leasts supports it in some way.
That gives less flexibility to the processor maker for individual optimizations. A CPU can optimize its microcode generation to use its hardware as efficiently as possible. Made a hardware change that can be used for more performance?
Update the microcode generator and ship the new CPU, all updated (complex) instructions build on that are automatically faster/more efficient/whatever you optimized.
If you compile to microcode-equivalent, your compilers don't know about the new detail, so they won't try to use it. So you need to ship a new CPU, and then update all compilers to know about your new microcode, and get software recompiled, and worst case shipped in both a version for your new and all old CPUs, ...
Giving the CPU abilities to change things about how it exactly executes code means the compiler has to know less about the specific CPU running the code later.
AFAIK this is one of the things that killed the Itanium line: they tried to rely on sufficiently smart compilers instead of hardware optimizations, and had a hard time to adapt the code running to innovations on the hardware level.
Object code, in some cases, can be smaller. That's why modern RISC ISAs like RISC-V include a "compressed" instruction set option, to combat the object code size disparity with CISC ISAs.
I wonder how it works. If the opcodes can all be compressed, why not just make them smaller to begin with? I guess I always thought of opcodes as being enumerations of "commands".
The 16 bit instructions map 1:1 to the 32 bit instructions, so decoding is unchanged, The difference is a pre-decoding transmogrificaiton stage where some of the resulting fields in the transmogrified 32 bit instruction are fixed (e.g. 0) and some are filled in from the original 16 bit instruction fields.
Switching between 32 bit and "thumb" is fairly painless but the instructions cannot be intermingled. When you do a call, you have the opportunity to switch 32/thumb. When you return, the processor switches back as appropriate.
The resulting thumb code is more compact than full 32 bit instructions, but it isn't 2x more compact because you still need some 32 bit instructions (subroutines) and the 16 bit instructions are not as powerful as the full 32 bit instructions.
There is very little reason to use ARM code in ARMv7 and up.
Incidentally, ARMv8's 64-bit mode (AArch64) adds a whole new instruction set, called A64. It's fixed width 32-bit per instruction, and the only option for 64-bit code.
* Excluding some really obscure, mostly long deprecated ones
Any halfword where bit[15:13]=='111' && bit[12:11]!='00' is the leading half of a 32-bit Thumb instruction
See slide 31: https://riscv.org/wp-content/uploads/2016/07/Tue1130celio-fu...
RISC and CISC are both philophies that rose out of the contstraints of the eras they originated in and both, in their pure forms, are totally obsolete.
The effort that goes into the design of a modern CPU micro architecture is so high that the number of instructions has a pretty small impact on the overall design effort. The descendants of the original RISC ISAs have kept adding new instructions and for good reason.
On the other hand part of the increase in micro architectural complexity is that chips are designed to decode and issue multiple instructions per clock cycle. So the ease of multiple decode where every instruction is aligned to 32 bit boundaries is actually a noticable advantage.
The size of the instruction stream is still an issue but on that front x86-64 and ARM-64 are more or less tied these days in terms of bytes of instruction per task so that's a wash in practice these days.
I wouldn't go that far. In particular, the encoding of instructions in x86-64 makes zero sense except for backwards compatibility. Since all code is littered with REX prefixes, you have the same i-cache footprint as RISC architectures do without the benefits (die area for decoding, etc.).
If you fixed the instruction encoding, extended the three-address forms of instructions introduced in AVX2 to scalar integer operations, and finally threw away real mode and port mapped I/O, etc., I agree that x86-64 would be pretty nice. I'd be happy to get even one of those improvements, honestly :)