| Age | Commit message (Collapse) | Author | Files | Lines |
|
The SSA conversion works under the assumption that all the memory
operations on a given symbol always refer to the same object.
So, exclude the conversion of variables where:
* memory operations do not always match in size or offset
* there is an implicit integer/float conversion.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Packed bitfields are incompatible with the SSA conversion
which works on the assumption that memory operations are done
on the whole symbol.
So, directly exclude packed bitfields from the SSA conversion.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The SSA conversion is incorrect when the size or offset of the
memory operations doesn't match. It shouldn't be done at all.
So, add a few testcases for this.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The function dominates() needs to know if an OP_ASM instruction
may modify.
Use the information now available in the instruction to return
the answer.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Memory simplification is done with the help of the function
dominates() which determine when memory instructions interfere.
This function handles OP_CALLs, OP_LOADs and OP_STOREs but
memory can also be changed via OP_ASMs.
Add a testcase showing this.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The linearization step sometimes creates a lot of intermediate
basic blocks, often containing just a branch. Their presence often
make things more complicated than needed (more work to do in later
phases, visual clutter when inspection the IR 'by hand') and they
can sometimes, indirectly hinder some optimizations.
Happily, most of them can trivially be optimized away.
So, add a CFG simplification phase running very early and doing:
*) jump threading (eliminate jump to jump)
*) merge single-child/sinle-parents basic blocks.
These changes slightly decrease the number of 'context imbalance'
warnings (32 less on a total of 995 warnings) and the size of
the generated IR (only ~0.4% but this is very significant relatively
to most other simplifications).
They also seem to improve the kernel tests' running time:
before after
real 4m19.261s real 4m17.548s
user 72m03.634s user 71m34.642s
sys 29m05.573s sys 29m01.856s
but it's probably just noise.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
During SSA conversion, it is checked what can be promoted
and what cannot. Obviously, ints, longs, pointers can be
promoted, enums and bitfields can too. Complication arise
with unions and structs. Currently union are only accepted
if they contains integers of the same size. For structs
its even more complicated because we want to convert
simple bitfields. What should be accepted is structs
containing either:
* a single scalar
* only bitfields and only if the total size is < long
However the test was slightly more strict than that:
it dodn't allowed a struct with a total size bigger
than a long. As consequence, on IP32, a struct containing
a single double wasn't promoted.
Fix this by moving the test about the total size and
only if some bitfield was present.
Reported-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The test mem2reg/init-local.c succeeds on 64-bit but fails
on 32-bit.
Duplicate the test, one with -m64 and the other with -m32
and mark this one as known-to-fail.
Reported-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
This patch optimize the very simple implementation of the
phi-node renaming at the end of the SSA conversion.
It avoids the need to rescan the whole function to find the phi-nodes
by using a worklist to put the phi-nodes during the renaming
of non-phi nodes instructions.
This optimization avoids O(n^2) behaviour in some pathological cases.
Note: A lot of optimizations can be done for the renaming.
For the moment, things are kept as simplest as possible,
the goal being to have correctness first.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
This activate the new SSA conversion that will be used
to replace simplify_symbol_usage() which created invalid
SSA (phi-nodes were placed where the value was needed
instead of where the paths meet, also and partially related,
it was possible for a phi-node to have more operands/sources
than the BB it was in had parents).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
A few tests are added, some have been renamed to better
refect their purposes. Finally, some checks have been added
or tweaked.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In simplify_loads(), phisrcs are created in find_dominating_parents()
and are then supposed to be used in rewrite_load_instruction().
However, it may happen (quite often) that find_dominating_parents()
find a dominator for one of the branch, create a phi-source for it,
record it's usage and then doesn't find a dominator in one of other
parent branches. In this case, the function returns early and the
created phisrcs are simply ignored. These phisrcs can't be simplified
away as dead instructions because they still have their usage recorded.
Fix this by explicitly remove these ignored phisrcs.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
The function address_taken() check that the address of a variable
is not used for anything else than for doing a memory access.
If the function fails, it means that the address can escape and
thus can be used to modify the variable indirectly and the
memop simplification would then be unsafe.
The function do this check by assuming that any uses by an instruction
other than a load or a store can escape the address, which is true.
However it doesn't take in account that if the variable's address is
used, not as the address of a store, but as the value stored, then
this address also escape.
Fix this by adding a check that the use of the variable's address
is effectively done as the address of stores & loads and not as
the value stored by the memop.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Since the patterns in the testcases are evaluated in the shell
script, the backslash used to escape characters special to the
pattern need itself to be escaped. Theer is a few cases where
it wasn't done so, partly because 'format -l' gave a single
escape in its template.
Fix all occurences neededing this double-escape as well as the
'format -l' template.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
In some situations, loads and others instructions can be
unreachable already when linearized, for example in code like:
void foo(int *ptr)
{
return;
*ptr;
}
Such loads are detected in find_dominating_stores() and must
be discarded. This is done and the load have its opcode set
to OP_LNOP (wich is only useful for debugging) but it's
address is left as being used by the load.
Fix this by removing the address usage.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Instructions with a null ->bb are instructions which have
been killed. As such, they must thus always be ignored
but it's not always the case.
Fix this by adding a check for null ->bb where there is
some looping over all the instructions of a basic block.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
During simplify_one_symbol(), if possible, loads are replaced by
an OP_PHI and the corresponding OP_PHISOURCE. To simplify things
firther, If all the phisrcs correspond to an unique pseudo (often
because there is only a single phisrc), then it's useless to
create the OP_PHI: the created OP_PHISOURCEs can be removed and
the initial load can be converted to the unique pseudo.
However, if the unique pseudo was never used, the removal of
the OP_PHISOURCEs, done *before* the load conversion, will
kill the defining load (at this point the only user of the
pseudo was the OP_PHISOURCEs) which will then erroneously make
a VOID from the pseudo.
Fix this by doing the load conversion before removing the
unneeded OP_PHISOURCEs.
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
|