avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

AW: [avr-libc-dev] Improved optimizer for mixed 32 / 16 / 8 bit expressi


From: Björn Haase
Subject: AW: [avr-libc-dev] Improved optimizer for mixed 32 / 16 / 8 bit expressions
Date: Tue, 7 Dec 2004 22:07:29 +0100

Hi,

> Paul Schlie wrote
>
>Very nice, out of curiosity, whas this done entirely with .md rtl
>optimization, or improving the minimal type size representation
>within the compiler's front/middle end? (or a little of both?)

sorry for replying a bit late. The changes that I have implemented so-far
are restricted to
the machine definition.

What I have been doing is something rather tedious. I have made use of a
well-known
principle. The people that wrote the avr-port already have made use of it.


1.) The idea is to teach the compiler better to deal with 32 bit and 16 bit
variables.
E.g., when the compiler encounters an instruction pattern of type

a = a + b;

with a being an int32_t register variable and b being an int8_t register
variable,
the compiler did not know how to do this directly.
For this reason, he generates a temporary register variable c of int32_t and
uses
the instruction sequence

c = sign_extend (b);
a = a + c;

. He already knew both, how to sign-extend 8-bit values and how to add two
32 bit values. Similarly, when storing an 8-Bit value to memory also a
temporary 32-Bit
register variable was allocated, filled with the sign-extension and stored
into memory.

What I have been doing is:

Writing *lots* of additional "combined" patterns telling the compiler to do
sign-extension
and diverse other operations simultaneously without requiring the entire
32-Bit value to be
contained in a register. There is a whole bunch of possible combinations!

This is nothing very new. Already in the present .md file there exist
patterns for
combining zero-extending values and arithmetic operations. These, however,
mostly
treat combinations of 16 bit values and 8 bit values. What I did is, make
the
number of cases treated explicitly more complete, e.g. by adding stores to
memory
the sign-extensions and comparisons.

2.)
In order to be able to treat also moves of constants to memory better, I
have
implemented a single second change. When encountering moves of constants to
memory, e.g. one variable a in memory of 32 bit width and a constant b that
would fit e.g. into 8 bits, the compiler so far has generated code requiring
a temporary
register variable of the width of the memory target, e.g. 32 bits.
These registers are then filled by the constant which is afterwords written
to memory.
This code is contained in the movsi and movhi "define_expand" patterns.

I have changed these "define_expand"s so, that in case that one of the move
operands happen to be a "const_int", the compiler first looks more closely
at the constant value.
If the constant value happens to fit into 8 or 16 bits only, the compiler
allocates a register variable of the required size only and issues a
sign-extend or zero-extend pattern for creating the remaining byte values
on-line.
Since with the additional patterns (1.)) the compiler now nows better, how
to
work with such sign-extended values, it could generate more efficient
assembler code.


The combined instructions for zero-extension, in my opinion, are allways a
win.
For the sign-extension patterns, however, I could imagine that existence of
these
patterns could eventually provoke that the sign-extension is determined
more frequently than would be required. Generally, I have the impression
that they
generate considerably better code. I, however, also have observed one case
when
dealing with 16 bit target sizes, where a bit worse code came out.

This is, why I asked for ideas concerning other real-world test cases in my
last mail.
Possibly my own application code is fairly specific.

I have rechecked the changes for some days and I will post my suggestions in
the .md this evening.

Yours,

Björn





reply via email to

[Prev in Thread] Current Thread [Next in Thread]