On 08/11/2011 05:27, Hans-Peter Nilsson wrote:
On Sun, 6 Nov 2011, Joern Rennecke wrote:
Quoting David Brown<david.br...@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