| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
| |
Profiling showed that Sparse spent much of its time doing CSE, which involved
traversing every bucket of insn_hash_table repeatedly. insn_hash_table had
64K buckets, but never more than a few dozen entries. Shrink insn_hash_table
to 256 entries. This makes Sparse 2-4 times faster for me.
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
|
|
| |
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
|
|
|
|
|
|
|
|
|
|
| |
It's better than nothing, but I need to re-do cast linearization some
day. Right now we squirrell away the whole original type, but the fact
is, we only need to save away a few bits of "type of cast".
We need to know if it's sign-extending, and whether the source or
destination are floating point values. And the source size, of course.
But we don't really need to know the detailed original type.
Oh, well. This makes at least trivial things look much better.
|
|
|
|
|
|
|
|
|
|
| |
This trivial patch remove the warning when I try to compile sparse
in with sparse.
Another warning I did not fix is:
../pre-process.c:554:18: warning: bad constant expression
The offending line is:
struct arg args[nargs];
|
|
|
|
| |
error reporting.
|
|
|
|
|
|
|
| |
This is OP_MUL/OP_DIV/OP_MOD/OP_SHR.
We actually do the constant simplifications still wrong, but
now the information is all there.
|
|
|
|
|
|
|
| |
(symbol addresses).
They are pretty different. Symbol addresses have special meaning during
various phases, from symbol simplification to CSE.
|
|
|
|
|
| |
It looked good on paper. Not so good when actually trying
to generate code.
|
|
|
|
| |
We already did this, we just didn't have a visible prototype.
|
|
|
|
|
|
|
|
|
|
|
|
| |
We don't care _where_ a PHI-node is, since the real location
is at the phi sources. So unlike other instructions, we do not
bother with any dominance analysis - we can just combine them
blindly across basic block borders.
It might make sense to totally disconnect the PHI nodes from
the flow graph to make this lack of positional information
even more explicit. That might also allow us to combine more
basic blocks.
|
|
|
|
|
|
|
|
| |
This allows us to always see which pseudos are nonlocally affected
by the phi source.
We can only do this after the instruction flow is fixed, together
with the OP_DEATHNOTE phase.
|
|
|
|
|
| |
Umm. The compiler even warned about it, I don't see how I
could miss it. I'm a maroon.
|
|
|
|
|
|
|
| |
This was originally done so that "struct instruction" would be
smaller, but it has since grown anyway (for the memops), so splitting
OP_SEL into two instructions no longer makes sense, and makes it
harder on CSE.
|
|
|
|
|
|
|
|
| |
regular CSE.
The CSE case is totally different: since both children use the same
pseudos, there can be no question that a common parent wouldn't
have that pseudo live.
|
|
|
|
|
|
|
|
|
|
| |
We should drop symbol types by now, and base things on just raw
sizes. Anything else just doesn't work from a CSE standpoint.
Some things may care about actual types later, notably the type-
based alias analysis. Those types still exist in the cast nodes.
Also, make the printout be more readable.
|
|
|
|
| |
CSE it together with the OP_SETCC that goes with it ;)
|
|
|
|
| |
Hey, it's simple, and it happens.
|
|
|
|
|
|
| |
...but we can't merge phi-sources after packing. Or rather, we
could, but we'll have to be more careful about not re-ordering
them, which we aren't. Sort it out later.
|
|
|
|
|
|
|
|
|
|
|
| |
It's a bit more simple-minded than the symbol simplification,
and it can be more costly. So we start off with the (cheap)
symbol simplification algorithm, and then use this new more
generic phase later.
This allows us to remove extra loads (and, in theory, stores,
but the dead store elimination is so simple-minded right now
that it's effectively useless).
|
|
|
|
|
|
|
| |
Make sure to clear them when turning operations into NOP's. And when
doing OP_LOAD->OP_PHI conversion, just re-use the target pseudo,
which means that we don't need to unnecessarily move all the uses
over.
|
|
|
|
|
|
|
|
| |
repeating CSE itself.
In particular, some symbol address simplifications imply that
we should repeat symbol simplification, since things may have
improved.
|
|
|
|
|
|
|
|
|
|
| |
Also, allow marking a pseudo unused by setting it to VOID,
which just disables further renaming of that use. This is
needed to make phi-source instructions (that can be shared
among multiple phi-nodes thanks to CSE) be collectable.
We used to just mark the phi source dead, but that was
wrong, since _another_ phi node might be using it.
|
| |
|
|
|
|
|
| |
It may be a nice readability thing, but with the usage lists
we really mustn't change a location that may be on a list.
|
|
|
|
|
|
|
|
|
|
| |
that we keep track of usage notes.
The usage trackign tracks the address of the phi pseudo, so
sorting the list would need to update that too.
This sucks, because it means we can't turn the phi-nodes into
canonical format, and thus not CSE phi-nodes as effectively.
|
|
|
|
|
|
|
| |
They's _slightly_ special in that they depend on their bb,
so we can only combine them within one basic block, but that's
easily handled by making the bb be part of the hashing and
comparison.
|
| |
|
|
|
|
|
| |
The "half-way" point was making the phi be an instruction,
and some of that half-way stuff remained.
|
|
|
|
|
|
|
|
|
|
|
| |
The instruction contains everything "struct phi" had, namely
source bb and pseudo. And generating a new pseudo means that
we not only have the pointer to the instruction that defines
the phi-node (in pseudo->def), we also end up with automatic
phi-node usage tracking (pseudo->users).
The changes may look large, but almost all of this is just
direct search-and-replace of the old phi-node usage.
|
|
|
|
|
|
|
|
|
| |
We can turn trivial phi-nodes into OP_SEL instructions instead,
and generally improve code flow.
This doesn't remove the empty blocks this results in yet, so
it's not quite as dramatic as it could be, but it does the hard
work. Empty block removal is trivial.
|
| |
|
|
|
|
| |
instruction.
|
| |
|
| |
|
|
|
|
| |
That is - simple instructions with no users.
|
|
|
|
| |
Show the source that the thing was replaced with.
|
|
|
|
|
| |
Instead of using the "convert_load_insn()" that converts them to
OP_LNOP's, which ends up confusing instruction printout horribly.
|
|
|
|
|
|
|
|
| |
This makes us able to CSE stuff where one subexpression
directly dominates another.
But we still don't do any fancy code motion in the non-
dominance case.
|
| |
|
|
It ain't very smart yet, but give it time.
In particular, right now it gathers information for the
whole function, but it only does the actual replacement
if the instructions are in the same basic block.
|