4 ms·
CPUs can and do have UB in the instruction specifications. x86 definitely does.
by ahefner 5y ago
CPUs can and do have UB in the instruction specifications. x86 definitely does.
- secondcoming 5y agoIndeed, for example the BSR instruction: > If the content source operand is 0, the content of the destination operand is undefined. [0] https://www.felixcloutier.com/x86/bsr https://www.felixcloutier.com/x86/bsr
- dooglius 5y agoNo, this is not the same thing as "undefined behavior" in the sense the ISO C spec defines it. The content of the output being unspecified would not, for example, allow the processor to write to some part of memory if the source is zero, or change unrelated registers. x86 is doing "undefined" the right way, unlike the ISO C spec.
- mpweiher 5y ago> No, this is not the same thing as "undefined behavior" in the sense the ISO C spec defines it. Well, it's not UB the way optimiser-extremists (mis-)interpret the ISO C standard.
- kllrnohj 5y agoIt's exactly the same as "undefined behavior" in C. The only difference is in the consequences that follow from it when optimizers get ahold of it. If it's undefined behavior if BSR is given 0, then therefore the compiler can assume the value passed to BSR isn't 0 (because it's defined that a well-formed program doesn't encounter undefined behavior). Therefore a check if the value is == 0 can be skipped, because it can't be zero since BSR didn't allow it. And since the code inside the if isn't reachable, that probably means now other things are no longer reachable and can similarly be removed. And etc... That's all the "undefined behavior allows the compiler to murder my cat!" really is - it's just the chain of consequences that result from the compiler following the rules it was told. It was given a rule that a parameter couldn't be null, and so it listened & did what it was told including deleting redundant null checks (since after all, the value was already specified to be not null!). To demonstrate the problem in a different language, let's say I have this code: float asFloat(@Nullable Integer i) { return i == null ? Float.NAN : i.floatValue(); } You'd expect the null check, right? But let's say I call it from this function: void sayHi(@NonNull Integer i) { println("Hello " + asFloat(i)); } The optimizer comes along and inlines the two together and now sees: void sayHi(@NonNull Integer i) { float temp = i == null ? Float.NAN : i.floatValue(); println("Hello " + temp); } Does it still need to keep the null check? After all, I defined that 'i' isn't null, so surely the null check is just unreachable code & can be eliminated, right? If it doesn't, it's obviously wasting performance. If it does, the internet gets angry about the compiler "abusing undefined behavior." Even though as far as the compiler is concerned it isn't undefined behavior! 'i' is defined to be not-null!
- dooglius 5y agoWhat "compiler"? We're talking about the x86 instruction specification. The microcode translator certainly isn't allowed make the sort of optimization you're describing, that would be a violation of the spec that GP linked.
- dooglius 5y agoIn ring zero there are some, but no instructions that userspace can use (or else security would be impossible)