Skip to content

Add CIL instructions to detect arithmetic overflows without raising an exception #13026

@RobertBouillon

Description

@RobertBouillon

The current implementation of the CIL ISA runs counter to the design guidelines for .NET exception handling with respect to overflow handling. The only way to check for an overflow is to raise an exception, however overflows can occur as a normal condition; there is no way to check for an overflow without raising an exception.

The workaround is expensive arithmetic checking which involves up-casting the types or operation-specific legacy c-style checks. Both have their drawbacks and are pretty expensive, especially when you're checking for overflows in 64-bit integers.

It's pretty silly to have to jump through such elaborate hoops to determine if you've overflowed to avoid excessive exceptions when there's likely an overflow flag tripped somewhere on the hardware already to which we simply don't have access.

Since there are already instructions that have to check for an overflow (e.g. add.ovf), I think all that really needs to be done as far as implementation is to find the best way in the IL and languages to expose an overflow flag without raising an exception. The instruction (something like add.sovf for silent) could simply push a second value to the stack indicating whether or not the operation overflowed. Language support might be a bit trickier, but the IL instruction would be a great start since we could, at very least, emit it in code. Ultimately, I'd love to see support all the way through to expressions (e.g. Expression.AddSilentChecked).

Since this is really meant to address performance, I'd also like to make another suggestion. Typically, overflow flags are set after each operation. Checking this flag after every arithmetic operation essentially doubles the CPU work (best case) and can make for ugly (hard to maintain) code. Practically speaking, overflow checking doesn't NEED to occur after every arithmetic operation, and in my experience, rarely does. Typically, it only needs to be checked after a batch or an equation involving multiple operands (Think a SUM or FMA). A latch rather than a flag would be far more useful, since it can be cleared at the start of the operation and checked at the end of it, rather than after each instruction. That's O+2 rather than O2. AFAIK the VM doesn't have any persistent flags, but I think a latch and / or a flag would be better than putting the overflow result on the stack.

category:proposal
theme:msil
skill-level:expert
cost:extra-large

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIdesign-discussionOngoing discussion about design without consensus

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions