http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48580

--- Comment #9 from joseph at codesourcery dot com <joseph at codesourcery dot 
com> 2011-04-13 12:45:35 UTC ---
On Wed, 13 Apr 2011, rguenth at gcc dot gnu.org wrote:

> For the latter reasons I think the builtins should be sth like
> __builtin_smul_ovfl_p (multiplication-result, op0, op1), thus pass
> in the multiplication result and keep the multiplication itself
> in the IL to also allow for regular optimizations to work on them.
> If the multiplication is just used as the builtin call argument
> expansion can get rid of it.

My inclination is that we probably want to separate the API for users from 
the built-in functions or other operations used internally - possibly 
providing a header gccarith.h with a supported API and saying the built-in 
functions are subject to change and should not be used directly in source 
code.  Maybe (inspired by the style used on C1X stdatomic.h) one could 
have operations like

arith_mul_signed (a, b, 32, ARITH_SAT)

that multiplies a and b (integers to infinite precision, producing an 
infinite precision result), saturates the result to 32-bit signed and 
returns an implementation-defined type (signed, two's complement, at least 
32 bits), or

arith_mul_signed_check (a, b, 32, ARITH_WRAP, &overflow_p)

that stores an overflow flag in the provided _Bool *.  Or the overflow 
handling (wrap, saturate, undefined, unspecified-value, trap) could be 
part of the macro/function name (putting it as a separate operand is 
inspired by the memory_order parameters in stdatomic.h).

The _check versions with explicit overflow flags could be used with any 
overflow handling other than "undefined behavior".  (So if you don't care 
about what the value is when the overflow flag is set - if you'll just 
call some error handler - then you'd use "unspecified-value" as the 
overflow handling.)  On divide by zero, both division and modulo 
operations would have undefined behavior except for the "trap" case - but 
modulo -1 would always be defined, unlike for C INT_MIN % -1 (I'm thinking 
of these operations as all being defined on their own by producing an 
infinite precision result first, but there might also be operations such 
as divmod producing multiple results).  It may also make sense to expose 
different variations of division/modulo (rounding to 0, -infinity or 
+infinity; a true modulo operation, rounding to -infinity, is one of those 
things C doesn't make easy; GCC has these as TRUNC_DIV_EXPR, 
FLOOR_DIV_EXPR, CEIL_DIV_EXPR and corresponding *_MOD_EXPR).  Starting 
with addition then increasing the set of operations gradually probably 
makes sense.

Along with all the arithmetic operations you get range check operations - 
take a value (in any integer type), and check whether it is in the 
signed/unsigned range with a given number of bits, wrapping/saturating 
etc. and setting overflow flags as needed.  These are just like the above 
but with one fewer operands.

The explicit number of bits (required to be an integer constant 
expression) is deliberate because it is sometimes useful e.g. to saturate 
to 16 bits, but integer promotions in C make it rather fragile to rely on 
16-bit operands remaining 16-bit rather than getting implicitly promoted 
to 32 bits.  A consequence is that operations with strange numbers of bits 
can be written without involving bit-field types (since the result is 
allowed to have more than the given number of bits).  I don't expect those 
to be very efficient in general, but note that ARM for example has SSAT 
and USAT instructions to saturate a value to a given number of bits (up to 
32) and set a flag if it was out of range.

Reply via email to