Live data from Hacker News

The x86 architecture is the weirdo, part 2

devblogs.microsoft.com

71–80 of 170 posts

Re: The x86 architecture is the weirdo, part 2

#71
post #62

Earlier quoted context omitted.

> C's memory aliasing model does this mean that because you can’t be sure if two vectors don’t overlap in C you therefore can’t auto-vectorize loops?

That's an example. It also constrains some optimizations like reordering.

> It also constrains some optimizations like reordering.

Ha! As if C compilers really cared about correctness. This is why type-punning and aliasing memory through different typed pointers is fraught with peril, often UB. It's so C compilers can cheat and use type-based alias analysis, breaking programs that have "UB" but would work absolutely fine if the compiler wasn't so aggressive.

In general, almost all arguments between language design and optimization for C/C++ are settled with "let's not think too hard about how to help users; go ahead and optimize this and make it their fault (UB) when they observe the hard cases". It's so rude.

Re: The x86 architecture is the weirdo, part 2

#72
post #64

Earlier quoted context omitted.

So which language has handled ILP, OOO, delay slots, cache hints, etc. particularly well? Anything that's ergonomic and actually used (i.e. not awkward and academic)?

But that's my point: the dominance of a C monoculture has relegated alternatives to being "awkward and academic". When you're in a C straightjacket it's hard to take advantages of other architectures like transputer, connection machine, or cell. Ever run bsd unix on a Cray? It was dog slow because the CPU assumed very deep pipelining and always had to continually resynchronize because of the frequent branches in the…

> And we have CUDA which is an attempt to, yes, get back to the C model

CUDA allows different programming models, it's the point of having the PTX virtual machine as the exposed programming model.

CUDA C++ is popular, but is far from the only option people have.

(and it can go very deep, https://www.ibm.com/docs/en/sdk-java-technology/8?topic=egpu... for example)

Re: The x86 architecture is the weirdo, part 2

#73
post #47
post #42

Earlier quoted context omitted.

> + HPPA's upwards-growing stack To be honest, I never really understood why more architectures don't have upwards-growing stacks. Visually, one adds things to the top of a stack, after all, so it makes sense to increment the stack pointer. I suppose it's a relic of the old days when folks just set the start of the stack to some remote part of memory and hoped it never grew down into the code or the heap? > + these d…

> To be honest, I never really understood why more architectures don't have upwards-growing stacks. A downward-growing stack is more intuitive. To access items on a downward-growing stack, you use positive offsets; for instance, sp+0x10 could be the second stack-passed argument to a function. For an upward-growing stack, you have to use negative offsets. > Hard disagree, big-endian is right and little-endian is wrong…

> A downward-growing stack is more intuitive. To access items on a downward-growing stack, you use positive offsets; for instance, sp+0x10 could be the second stack-passed argument to a function. For an upward-growing stack, you have to use negative offsets.

Why would one use negative offsets with the stack pointer instead of positive offsets with the base pointer?

Using the stack pointer, I can never dynamically push something onto the stack without changing the offsets.

Re: The x86 architecture is the weirdo, part 2

#74
post #38

Earlier quoted context omitted.

> CPU architectures implicitly have something I call the "architectural weirdness budget" The point of designing a new architecture is you have a point to make (generally, "doing X will lead to faster execution"). So by definition you are adding unfamiliar architectural weirdness, else why get involved. The big problem is that the pervasiveness of the C model has fossilized design decisions of the PDP-11 that still h…

So which language has handled ILP, OOO, delay slots, cache hints, etc. particularly well? Anything that's ergonomic and actually used (i.e. not awkward and academic)?

These are all microarchitectural things that should not be surfaced in language, IMHO. This is why compilers exist, to raise the level of abstraction. For example, other than sidechannels (i.e. Spectre), OOO is not observable, nor is ILP or cache hints. Delay slots are observable at the ISA level but typically compilers do the work of dealing with them. Thank god delay slots didn't make it into programming languages; they were a wart of ISA design surfaced because of a lack of decent branch prediction. Can you imagine if you had a bizarre feature where the next line of code after a branch still executed even if the branch was taken? That'd be bonkers.

Re: The x86 architecture is the weirdo, part 2

#75
post #9

Earlier quoted context omitted.

ARM spends it on pc being wrong: when you mov from it, it's off by 8 in ARM mode, and off by 4 in Thumb mode, and if you're using it for pc-relative loads (and stores, if you're crazy), it uses a word aligned value. edit: oh, and softfloat vs softfp vs hardfp vs vfp edit: oh, and how they have two incompatible assembly language dialects that are mostly the same, but in non-trivial code, incompatible

By pc you mean "program counter"?

[deleted]

Re: The x86 architecture is the weirdo, part 2

#76
post #70
post #68

This is one of the many reasons that having exceptional control flow explicit in the compiler IR is a Good Thing(tm). The HotSpot client compiler lacked this information (in the beginning) because it was deemed "too expensive to keep" and the result was that many optimizations had ugly special cases (or were disabled altogether). For the most part, if the compiler has some notion of hot/cold code, then these exceptio…

Pretty much exactly. They had a situation with external visibility into information in the stack frame and don't seem to have made an effort to tell the compiler . I mean... it's their compiler! It's their ABI, even! They have all the levers and dials, and somehow the fact that their exception counter is being optimized out means that the "architecture" is the weirdo? Yeah. At its root this is a Conway's Law bug. The…

Indeed. In Java, on every platform that I know of (including x86 and x86-64), exceptions are zero cost, with no dynamic work needed to enter a try. On Windows they are probably stuck with ABI compatibility. It sounds like the design was flawed from the start and definitely not the architecture's fault.

Re: The x86 architecture is the weirdo, part 2

#78
post #65

Earlier quoted context omitted.

Re the zero cost claim, he specifically clarifies that zero cost exceptions have a cost even if you do not use them, which is paid by inhibiting some optimizations. IANACW, but I think that in principle is almost always possible to implement truly zero cost exception path in the non-taken path, by moving all necessary compensation code to undo optimizations into the exceptional path, but in practice it might be too h…

If you spend a lot of time scrutinizing g++ output (which thankfully I haven't had to do in over 20 years) you'll see that the impact is negligible and that was true when Raymond made that statement. As you point out there's a lot the compiler can do to make the common path really fast. But OK, it could potentially be nonzero. Let's say epsilon cost instead.

I concur with this. Java JITs do a ton of optimizations and all of the effects of exceptions are minimal, second-order things, like keeping something alive a little longer (for deoptimization/debugging). If the compiler has a good notion of hot/cold paths, then a lot of optimizations that you'd be tempted to think up for exceptions fall out naturally from the more general notion, including spilling the likely-never-used-but-alive-for-deopt values onto the stack in the important paths.

Re: The x86 architecture is the weirdo, part 2

#79
post #15
post #3

I have a theory that CPU architectures implicitly have something I call the "architectural weirdness budget", which is the extent to which you can get away with design decisions in the architecture or ABI that differ from the existing established consensus. Any time you do something a bit odd that means that existing software has to do awkward things or might not be no-changes portable to your new architecture, you'r…

MIPS delay slots were another example of this. Arguably Itanium's failure was due to exceeding the weirdness budget with VLIW nonsense, leading to the default PC 64-bit architecture being AMD's "x86 with longer registers" instead. What happened to the Mill "unlimited weirdness budget" CPU guys anyway?

I might be missing something, but I never figured out where mill was saving all those gates they claimed. It could be my lack of imagination, but the straightforward way to implement the belt just looks like a ROB and bypass network just like a normal OoO core spends it's gates on.

And on the frontend, sure they mark instruction boundaries within an instruction bundle, but you still need N barrel shifters (where N is the number of max instructions per cycle) to get at them, and that's the expensive part of wide decode. Even 16bit aligned is so much nicer for the critical path than 8-bit, bit aligned is absolutely crazy town.

Re: The x86 architecture is the weirdo, part 2

#80
post #67

Earlier quoted context omitted.

In the article example itself, f1() and f2() can observe the state. Nothing to do with threads.

I don’t think so. It is global state, but it lives outside the abstract C machine, in its implementation. The compiler knows f1 and f2 live in the abstract C machine and cannot access it. I think its like the difference between errno , a global inside the abstract C machine, and __foo , which a compiler might create, and, if it did so, could assume to be completely under its control.

Well, sure we are deep into implementation details, so it is reasonable for the implementation to treat stores to it specially. But the rest of the article goes into details on how treating it specially causes "real pain in the neck" because the optimizer wants to optimize them away. It seems to me that if the store was not treated specially, the issue wouldn't exist in the first place.

So either: exception handling in 32 bit mode is sort of an hack and the exception handling code generation doesn't actually expose the store the store through fs to the rest of the optimizer or, more likely, things are much much more complicated than described in the article.

Post reply on HN