[C++11] Reclaiming fixed-point suffixes for user-defined literals.

David Brown david@westcontrol.com
Tue Nov 8 14:56:00 GMT 2011


On 08/11/2011 05:27, Hans-Peter Nilsson wrote:
> On Sun, 6 Nov 2011, Joern Rennecke wrote:
>
>> Quoting David Brown<david.brown@hesbynett.no>:
>>
>>> Take an example using a processor I know well, the AVR (it is an 8-bit
>>> device, which is a little unusual for gcc).  It has an instruction will
>>> multiply two "1.7" signed 8-bit integers to get a single 1.15 signed
>>> 16-bit integer - basically combining an 8-bit x 8-bit to 16-bit
>>> multiply with a left shift.  So to do a "signed short _Fract" multiply,
>>> you have a single instruction and discard the least significant byte.
>>>
>>> Simulating the same operation in generic C would be something like :
>>>
>>> int8_t multShortFract(int8_t a, int8_t b) {
>>> 	int16_t c = (int16_t) a * b;
>>> 	return (c>>  7);
>>> }
>>
>> If you can make up your mind if the result is 8 or 16 bit, generating the
>> instruction should be standard fare for the combiner pass.
>

If the compiler can generate fractional arithmetic code directly from 
such expressions, then it is indeed a good step towards implementing 
such types as a pure C++ class without needing to use compiler extensions.

However, this is a simple case.  It gets a lot more complicated with 
"_Accum" types, with saturating types, and especially when mixing them. 
  It also gets more complicated when you start to have series of 
expressions, constant folding, etc.  I am not saying the compiler 
couldn't generate optimal code (on a target with hardware support for 
these operations) out from carefully written generic C++ code - but I do 
think it would be easier to get good code if the compiler views these 
types as "native".

The guts of gcc already know about types like "signed short _Fract", and 
can handle them well (at least for some targets).  It is always easier 
for the compiler when it has more knowledge than if it has to guess 
based on code patterns - so using "signed short _Fract" means it can see 
the real type early in the process rather than in a later "combine" pass.

> Looks like a pretty typical Q7 (or Q1.7) multiplication to me
> unless I miss something...  Would be a nice thing to have those
> Q1.<N-1>  formats as native GCC-extension types including
> vectorized versions.  No, not planning it.
>

Yes, it is Q1.7 multiplication.  And there is already a type for it in 
C, though gcc doesn't (yet) support it for all targets (I haven't 
checked recent versions).  It is "signed short _Fract" from TR 18037.
<http://gcc.gnu.org/onlinedocs/gcc/Fixed_002dPoint.html>

> And having intermediate calculations in a wider mode does not
> constituate lack of making ones mind up. :)

Correct - the return type is clearly int8_t.  The wider intermediate 
mode is a necessity of C.

> Though I believe that cast of "a" is ineffective, IIUC.
>

Also correct - "a" will be promoted automatically to an "int" (which is 
always at least 16-bit).  From long habit in embedded programming, I 
tend to be a bit more explicit about such conversions.  A real-world 
library would be written somewhat differently, of course (at the very 
least, it would use "int_fast16_t").

> brgds, H-P
>




More information about the Gcc mailing list