Live data from Hacker News

We Need Hardware Traps for Integer Overflow

blog.regehr.org

91–100 of 112 posts

Re: We Need Hardware Traps for Integer Overflow

#91
"Those who do not understand the hardware are doomed to blog about it, poorly.

Intel chips already detect overflow, that is what the OF (bit 11) flag in the flags/eflags register indicates. That the most recent operation overflowed.

Testing, and generating a trap, for an overflow is a single instruction (JO – jump if overflow and JNO – jump if no overflow).

This is true of almost all CPU’s. At the hardware/assembly programming level, overflow detection is handled by hardware, and detected by a single instruction. The reason all of your languages listed don’t have any sort of trap/etc. is simple. The language designers did not bother to check the result of their operations. Why, most likely because almost all of them are ultimately implemented in C, and C does not reflect the overflow status back into the C language level.

So the problem isn’t the hardware. It is the software architectural design(s) implemented above the hardware. They are not bothering to communicate to you the results of what the hardware already has available and tells them about."

(Qouting comment from Anon)

Re: We Need Hardware Traps for Integer Overflow

#92
post #91

"Those who do not understand the hardware are doomed to blog about it, poorly. Intel chips already detect overflow, that is what the OF (bit 11) flag in the flags/eflags register indicates. That the most recent operation overflowed. Testing, and generating a trap, for an overflow is a single instruction (JO – jump if overflow and JNO – jump if no overflow). This is true of almost all CPU’s. At the hardware/assembly p…

And it is true, there is already the hardware "overflow" flag, just not visible in "higher" level languages.

Re: We Need Hardware Traps for Integer Overflow

#93

Earlier quoted context omitted.

> The cost of doing it in software is just a highly predictable (not taken) branch after every integer arithmetic operation that the compiler can't prove stays within bounds. While I agree with you that hardware overflow traps are a bad idea, I think the article's author is referring more to the general overhead of a software BIGNUM implementation. Specifically with his JavaScript example, I think it's very plausible…

Note, in case someone blindly takes this as advice: This method of expressing it in C doesn't work for multiplication (you could wrap more than once). I'm not sure you can express an overflow check for multiplication purely in portable C (without library or intrinsic support), actually. Well, I guess you could break the multiplication into checked additions manually, but that's probably not a great idea.

There are better checks. I'm generally not a fan of Microsoft, but the SafeInt library ( https://safeint.codeplex.com/ ) does those kinds of checks in sofware.

I don't remember where I read it, but regarding multiplication: if you multiply two N-bit numbers together, the result will always fit in a 2N-bit number. For instance, the product of two 16 bit numbers will fit in 32 bits, the product of two 32 bit numbers will fit in 64 bits, etc. You can assign the product to an integer able to hold the larger size and then check if it would also fit in an integer of the smaller size.

Re: We Need Hardware Traps for Integer Overflow

#95
post #92
post #91

"Those who do not understand the hardware are doomed to blog about it, poorly. Intel chips already detect overflow, that is what the OF (bit 11) flag in the flags/eflags register indicates. That the most recent operation overflowed. Testing, and generating a trap, for an overflow is a single instruction (JO – jump if overflow and JNO – jump if no overflow). This is true of almost all CPU’s. At the hardware/assembly p…

And it is true, there is already the hardware "overflow" flag, just not visible in "higher" level languages.

Setting a flag is not the same as raising an exception. When you get a segfault that's not because a flag was checked, that's because a chunk of hardware interrupted the next operation.

So yes, you can check for overflow by inspecting a flag, but that's not all that much better from coding around the potential overflow to see if your operands + operation combo will cause an overflow.

Imagine setting a flag on a divide by 0 instead of raising an exception.

So the author is most likely aware of the overflow flag (just like any other old timer that has programmed in assembly and that had a cursory look at the flags register, or in some cases more than a cursory look :) ), he's writing about hardware exceptions, not about how to write in javascript.

But inspecting a flag simply isn't on the same level as raising a hardware exception, right along with segfault, division by 0, FPEs and so on.

That instantly propagates through to any programming language executed on the machine. Checking a flag in a register is a decision by a compiler writer and many compiler writers (consciously!) ignore that (usually because the language specs are vague enough that wrapping is considered acceptable when it is in fact almost always simply wrong).

Re: We Need Hardware Traps for Integer Overflow

#96
post #9

Modern CPUs don't like traps ("exceptions"). The exception causes a pipeline flush which kills performance for math-intensive code. For example, detecting integer overflow on x86 and x86_64 CPUs is easy: check the overflow flag after every arithmetic operation. It would only be slightly more difficult to detect overflow for SSE (vector) operations, which would require doing some bit masking and shifting. For a langua…

Exceptions are - by definition - rare, and when they happen you have other problems than worrying about performance or pipeline flushes.

It means that your program contains a bug.

What's swift got to do with it anyway? A language that was launched last week is now a benchmark for including new features? Has it been open sourced since then? If not how is building it in simple?

Re: We Need Hardware Traps for Integer Overflow

#97

Earlier quoted context omitted.

> The cost of doing it in software is just a highly predictable (not taken) branch after every integer arithmetic operation that the compiler can't prove stays within bounds. While I agree with you that hardware overflow traps are a bad idea, I think the article's author is referring more to the general overhead of a software BIGNUM implementation. Specifically with his JavaScript example, I think it's very plausible…

There probably is close to zero overhead in a small benchmark. Hardware branch prediction is indeed good. However, it's a finite resource. In a large application, lots of needless branches everywhere translates into fewer branch prediction resources available for the branches that matter, which means more mispredictions. Also, they take up icache, itlb, etc. It's not at all obvious that the overhead would be close to…

Would it be possible to mark the JO instruction (jump-if-overflow) as unlikely, so that the CPU would always predict the branch to not be taken, without consuming one branch prediction slot?

Re: We Need Hardware Traps for Integer Overflow

#98
post #70

Earlier quoted context omitted.

here's the best guide i could find on enabling those checks in gcc. it is unclear whether they take advantage of the carry bits, do you have a source for that information? http://www.pixelbeat.org/programming/gcc/integer_overflow.ht...

You can see the implementation in GCC here [1], for example addition starting on line 74. What machine code gets emitted for that obviously depends on the target architecture but it is reasonable to assume that the optimizer recognizes these patterns and uses hardware flags where available. [1] https://github.com/mirrors/gcc/blob/master/libgcc/libgcc2.c

looking over it again, it seems like quite a leap for the optimiser to do that, i have my doubts.

Re: We Need Hardware Traps for Integer Overflow

#99
post #92

Earlier quoted context omitted.

And it is true, there is already the hardware "overflow" flag, just not visible in "higher" level languages.

Setting a flag is not the same as raising an exception. When you get a segfault that's not because a flag was checked, that's because a chunk of hardware interrupted the next operation. So yes, you can check for overflow by inspecting a flag, but that's not all that much better from coding around the potential overflow to see if your operands + operation combo will cause an overflow. Imagine setting a flag on a divid…

No, I don't agree that "the author is most likely aware of the overflow flag" since the author says:

"Processors should support integer math instructions that optionally trap on overflow. Because popular architectures lack this feature, otherwise excellent modern systems programming languages, such as Rust, Go, and D, have default integer types that wrap."

In short, he believes there's no hardware support and therefore Rust, GO and D don't have it.

There is however hardware support in every imaginable CPU -- overflow is important to be able to synthesize adds bigger than the native size (e.g. 128 bit add if your regs are 64-bits) . Except for the implementor of the HLL compiler you as the user wouldn't be able to see how it's implemented in the hardware unless you look at the resulting generated code (you'd see an "exception" triggered no matter how it's implemented).

I know: I had the opportunity to implement the language which has special behavior when the floating point compare involves NaN. Luckily, there is a flag in the Intel CPU for that too and as far as I know you can't access it from any popular high level language, but my code generator injects additional flag check in every FP compare and in the production code I haven't seen any negative performance impacts compared to the case where I don't do the stated injection. That's how good the current branch prediction in CPUs can be.

So no, you don't need "hardware traps" you need somebody to first try to implement the given behavior in any HLL language before before we argue further. As soon as you have "wrappable" and "unwrappable" types in the language, you can have all the crypto primitives that need wrapping use the "wrappables" without any performance impact.

In fact "unwrappables" were interesting mostly for the calculations of the limits, practically wherever you'd use, for example, Microsoft's SafeInt classes.

The example from their header:

       void* AllocateMemForStructs(int StructSize, int HowMany) {
          SafeInt s(StructSize);
          s *= HowMany;
          return malloc(s);
       }
At least using MSFT's Visual C++ you can already have exceptions on integer overflows.

Re: We Need Hardware Traps for Integer Overflow

#100
post #70

Earlier quoted context omitted.

here's the best guide i could find on enabling those checks in gcc. it is unclear whether they take advantage of the carry bits, do you have a source for that information? http://www.pixelbeat.org/programming/gcc/integer_overflow.ht...

You can see the implementation in GCC here [1], for example addition starting on line 74. What machine code gets emitted for that obviously depends on the target architecture but it is reasonable to assume that the optimizer recognizes these patterns and uses hardware flags where available. [1] https://github.com/mirrors/gcc/blob/master/libgcc/libgcc2.c

http://www.emulators.com/docs/LazyOverflowDetect_Final.pdf This paper seems to imply that that high level languages can't access the carry bit, yet C#'s checked mechanism uses it.

I've been using -ftrapv with gcc for a long time, from here: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.

From the code you posted, and the assembly[1] emitted in the pdf above I can't see the optimiser taking advantage of the carry bit. No mention of CF, OF:

[1]

lea ebx, DWORD PTR [edi+eax]

cmp ebx, edi

jae SHORT $LN4@unsigned_c

cmp ebx, eax

jae SHORT $LN4@unsigned_c

mov ecx, 1

jmp SHORT $LN5@unsigned_c

xor ecx, ecx

The gcc flag ftapv only works for signed integers, not clear what the carry bit behaviour is for unsigned integers.

Post reply on HN