Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

For the same reason we trap on integer division by zero.

> It is _trivial_ to detect integer overflow

I think if we counted the number of + operations in a typical C program and multiplied that by the instruction(s) needed to implement a conditional branch path (often never taken dead code), it would be nontrivial. This overhead should be easily measurable on benchmarks.

> Furthermore, there are many cases where integer overflow is actually desired.

I'm not arguing against the ability to do that, but I think those cases are far less common.

> My question is would be why would a cpu trap be a better solution than what we already have?

To allow compilers (not just C) to emit safer code by default by removing the small but measurable instruction penalty.



> For the same reason we trap on integer division by zero.

The thing is I can hardly imagine a situation where a division by zero would be normal and expected, while having integers overflow as a normal part of a calculation is business as usual in many cases. Having to handle a trap (or disabling/enabling it dynamically) would slow things down way too much. Many crypto ciphers for instance specify operations "modulo 32" in order to take advantage of this "feature".

> To allow compilers (not just C) to emit safer code by default by removing the small but measurable instruction penalty.

Detecting overflow in asm is just testing the carry bit of the processor. A trap would be orders of magnitude slower on any modern architecture. You seem to be assuming that overflows are rare in C programs. I'm not sure this is true, but I have no hard data on that so who knows...


> Many crypto ciphers for instance specify operations "modulo 32" in order to take advantage of this "feature".

Which is one reason I'm specifically not advocating for doing away with nonsignaling modulo-2^2^n addition.

However, of all the addition operations in the gigabytes of object code on my hard drive, what percentage of them do you think actually encode the true desire of an application developer to perform wrapping arithmetic?


> For the same reason we trap on integer division by zero.

We trap on division because it is objectively a programmer error that has no obvious right answer. Division is also a relatively expensive and much less common operation for the cpu. The overhead of adding trapping is much smaller compared to addition. Furthermore, integer overflow has an easy solution: widen the computation. Divide by 0 has no quick answer.

> I think if we counted the number of + operations in a typical C program and multiplied that by the instruction(s) needed to implement a conditional branch path (often never taken dead code), it would be nontrivial. This overhead should be easily measurable on benchmarks.

A consistently not taken branch has very, very close to 0 overhead in a modern processor. Not to mention that adding trapping to addition would hinder things like instruction reordering and speculative execution, which adds an overhead that can't be disabled when overflow can provably not occur or not matter. The cpu would also have to treat unsigned and signed addition differently, which means an additional opcode, which adds complexity to the control logic and decreases code density. Finally, there are plenty of languages and libraries which do almost exactly what you propose and automatically widen variables when they overflow and do not experience significant slowdown.

>I'm not arguing against the ability to do that, but I think those cases are far less common.

You are wrong. Consider the pointer arithmetic expression "ptr += x;" on a cpu that has two trapping add instructions (add unsigned and add signed) and ptr is a pointer and x is a signed value. Note that this is extreamly common for things like array access. Suppose the compiler generated an unsigned add. If the ptr value was 0x1 and x was -1 that would generate an overflow because 0x00000001 + 0xFFFFFFFF results in an unsigned overflow. Suppose it instead generated a signed add. If the ptr value was 0x7FFFFFFF and x was 1 this would also generate an overflow because 0x00000001 + 0x7FFFFFFF results in signed overflow. To resolve this you would need 4 different instructions, which would only get worse as you add various operand lengths to the mix. Now I wouldn't say this is a problem for a majority of add instructions, but adding a signed and unsigned number is a very common operation. In addition, if you actually look at generated assembly code, many of the add instructions do not correspond to a '+' but instead do things like stack management or pointer offset adjustment which do not care about overflow because they can be proved to not occur.

> To allow compilers (not just C) to emit safer code by default by removing the small but measurable instruction penalty.

Again, there is virtually no overhead on a modern out of order, branch predicting processor. And adding trapping does have an overhead, a significant one, that cannot be removed when overflow can be proved to not occur or isn't important.

As a final argument, consider this: of all the major cpu architectures I've studied (MIPS, x86, ARM) not a single one has a trapping add instruction. Very smart people have also considered this problem and have come to the same conclusion: trapping is bad and should only be used in truly exceptional circumstances where no recovery is obvious. I agree with you that integer overflow is a big problem in languages like C that do not have a good way to detect it. However, this is truly a language only problem NOT a cpu one.


> We trap on division because it is objectively a programmer error that has no obvious right answer.

Defining (2^31 - 1) + 1 = -2^31 is no more of an "obvious right answer" than defining N/0 = 42 for all N. It's just one that we computer engineers have been trained to accept because it is occasionally useful.

But it's still madness which discourages us from using tools that emit more correct code.

> A consistently not taken branch has very, very close to 0 overhead in a modern processor.

Except the half a dozen or so bytes it consumes in the cache.

Nevertheless, I concede that others have thought about this a lot more than I have and done so with hard data in front of them.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: