This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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

On 08/11/2011 05:27, Hans-Peter Nilsson wrote:
On Sun, 6 Nov 2011, Joern Rennecke wrote:

Quoting David Brown<>:

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.

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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]