| Age | Commit message (Collapse) | Author | Files | Lines |
|
OP_BR instructions exist in two flavours, relatively much
differentiated: conditional & non-conditional. One has an
operand (and thus its usage need to be cared for, must be
handled in liveness analysis, ..) the other has not; one has
two BB target, the other only one.
There is essentially no places in the code where both flavours
are handled the same. Sometimes they both must be handled but
each with their specificities but in most cases only one of
them is concerned and we need to filter out the other one.
In both cases it means that we need to check what kind we're
dealing with.
There is already a problem with this because there is
several ways to test which kind an OP_BR is and they
are not exactly equivalent:
1) testing if insn->cond is NULL
2) testing if one of insn->bb_true or ->bb_false is NULL.
There exist also an helper (is_branch_goto()) which does
the second tests but which is never used.
It appears that the first test should not be used because
in some cases an conditional OP_BR is changed into
a non-conditional one by (amongst others things) setting
it's ->cond to VOID. We should thus always use the seconds
test (which need two compares with NULL).
This could be corrected in several ways (like changing all
the places wheer the first test is used, use the helper
everywhere or never set ->cond to VOID) but the simplest
is to simply split them in two separated instructions:
OP_BR & OP_CBR, especailly given the fact that in most cases
the OP_BR was first selected by a switch (opcode).
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Signed-off-by: David Given <dg@cowlark.com>
[negative value division fixed by alexey.zaytsev@gmal.com]
Signed-off-by: Alexey Zaytsev <alexey.zaytsev@gmail.com>
|
|
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
Expose the FORMAT_ATTR portability macro in lib.h, and use it on the various
printf-like functions in sparse.
Add a new SENTINEL_ATTR portability macro for the GCC sentinel attribute, and
use it on match_idents in parse.c.
match_oplist in expression.c should use SENTINEL_ATTR, but GCC does not accept
an integer 0 as a sentinel, only a pointer 0 like NULL.
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
The liveness instruction takes up about 10% of the bytecode bloat file.
It is not very useful, it is duplicate information that can be obtained
from the def/user chain.
This change disables the liveness instruction by default.
The caller can track_pseudo_death() if needed.
Signed-Off-By: Christopher Li <sparse@chrisli.org>
|
|
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
The sparse interface is a kind of snaky that it change the input argument
array. The function sparse() does the same hack just to skip the files.
This patch add the ptr list for string. So sparse_initialize will
return list of file to compile. The string pointer is not aligned
at word boundary. This patch introduce non taged version of the ptr
list iteration function.
Signed-off-by: Christopher Li <sparse@chrisli.org>
|
|
Signed-off-by: Pavel Roskin <proski@gnu.org>
Signed-off-by: Josh Triplett <josh@freedesktop.org>
|
|
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@looxix.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
Toto, I have a feeling We're not in SSA land any more.
(Not that it really helps. The example compiler not only had SSA
assumptions, it also depended on liveness information and insn->def
state, both of which are destroyed by the un-ssa phase. So this is
really a small bandage around a much larger problem, and doesn't really
fix anything fundamental).
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
Yeah, this probably breaks the example in a totally _different_ way than
it was broken before ;)
But it's certainly no worse than before. At least not much.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
Noted by Mitesh Shah
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
|
|
Start off with
sparse_initialize(argc, argv);
which will return the number of filenames found. You can then use that,
or just check if *argv is NULL in a loop like
while (*argv)
list = sparse(argv);
where you get the declaration list for each file in turn.
|
|
|
|
to the return register state.
|
|
value that is contained within.
|
|
about addresses of local variables.
|
|
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.
|
|
doing unnecessary register->sameregister moves.
|
|
address of a symbol.
Not quite there..
|
|
it meant "contains a pseudo".
|
|
Take argument type into account (somewhat), and do a first
(broken, but it's a good example) cut at having different
calling conventions for different kinds of functions.
|
|
register right now.
Change users that just wanted to test for "empty" to check that
"reg->contains" is NULL instead.
|
|
using static strings.
If we ever want to generate more abstract output (and we do), we
can't just have strings.
|
|
(symbol addresses).
They are pretty different. Symbol addresses have special meaning during
various phases, from symbol simplification to CSE.
|
|
by a parent as outputs as unavailable as an input register.
The parent won't be able to write two different pseudos to the
same register..
|
|
We could make the internal per-bb allocations be
local, though. That would require some more care.
|
|
the outgoing pseudos.
This caused us to then possibly double-allocate that register
later for another pseudo..
|
|
to the outputs.
|
|
I totally botch the constraints handling, but hey, it's just
an example.
|
|
|
|
return NULL from find_pseudo_storage().
That way the caller won't bother to move the register to
itself - it sees that it has no separate storage.
|
|
We could make it deeper if we wanted to combine conditionals,
but one-deep is good enough to catch the common "setXX + brcc"
thing, and thus makes the conditional branches MUCH more readable.
This also moves things around a bit to help organization.
|
|
They otherwise get drowned out by the _real_ comments.
|
|
Just the infrastructure.
|
|
|
|
In particular, casts to a smaller type doesn't need to do anything.
|
|
It can select the order based on whether one of the sources
is dead, or on the target register choice.
|
|
This allows us to mark a register dead when we load it from dead
backing store.
NOTE! This all sounds nonsensical, but we mark things "dead" _before_
the last use, not after. So dead means not that it's gone, it means
that this use is the last one.
|
|
rather than the storage itself.
I'll want to mark the hash entry dead when marking the pseudo
dead, and this allows me to use the common helper routine.
|
|
pseudo into a routine of its own.
Cleaner and more readable.
This also allows us to be a lot better at the "generic"
inputs (aka gcc "g" specifier), since it can now just look
up the storage instead of having to load it into a register.
|
|
issues:
- argument passign setup
- return value storage
- silly switch register hack.
|
|
That allows us to re-use the sources if they have died.
|
|
This makes it much easier to look at the real state of a register:
- busy == 0 means no users
- busy == dead means all users are dead
- dead != 0 means that we should clean it
|
|
|
|
You know the drill by now. It's not so much correct, as it is
"kind of looks right".
|
|
Yeah, yeah, it's still pretty stupid.
|
|
No sign extension, no nuffink. My opcode generation gets
worse and worse.
|
|
Just real enough to make it look good.
|
|
We get those when encountering unimplemented instructions, since
then we'll have bad register contents. Let's just silently ignore
it for now.
|
|
than as comments.
This makes them visible even without having to make
the output verbose (and verbose is _really_ verbose
these days).
|
|
new register if one is available.
Use a few symbolic macros to make some of the logic more readable,
and split up the "try to flush" logic into a function of its own.
|
|
|
|
be so eager to flush to memory. If we can find the proper
target register for the existing pseudo, just turn it
into a simple reg-reg move instead.
Also, don't worry about dead pseudos - they don't need
flushing anyway.
|
|
Keep the busy count valid.
|
|
example output. Very informational.
|
|
through a phi-node.
|
|
and labels. And comments, for that matter.
This eventually allows us to buffer them up, rather than print
them out directly. Which we'll need to do if we want to fix up
frame offsets etc (for register save areas). And other post-
processing.
Also, for comments, make "show_instruction()" return the string
rather than print it out.
|
|
We used to be lazy and just assume that if a value was in a
register when we exited, we could just use that register. Not
so, since now a register can contain multiple pseudos, that
may all need different output storages.
|
|
Remove hardreg dirty bit, it really is per-pseudo.
|
|
We can often just re-generate it (from its source, or from
an earlier flush).
|
|
make "busy" be a counter of non-dead pseudos.
|
|
|
|
Now that we let several pseudos be associated with one hardreg,
it may not be totally empty any more by the writeback phase.
|
|
by the hardreg.
We often have more than one pseudo with the same value, notably
when generating a phi source. Use the new list tagging to tag
which ones are dead (and which ones need writeback).
|
|
Avoid a few silly reg-reg moves.
|
|
We don't want to always start from the same reg at each bb
entry.
|
|
|
|
Our binops are destructive, but maybe we should try to copy
the destroyed register if it's still live.
|
|
This actually makes some trivial cases come out almost right.
|
|
|
|
something. If we can try to go for a register, all the better.
|
|
You can kind of start seeing what it's trying to do.
Kind of.
|
|
It ain't pretty, but that's not the aim right now.
|
|
the example.
And by "totally ridiculous", I mean "do one instruction,
and do it badly".
|
|
I dunno if this will ever get anywhere.
|
|
the "example output" program from it.
|
|
Start by renaming.
|
|
Next step: start generating x86-like code for simple
instructions.
|
|
This one links up the inter-bb usage pseudos to each other
with "storage" structures, which should make it possible to
write a simple code generator that doesn't need to worry
about any global state - all the decisions are local.
There are probably cases where this simply doesn't work, but
I want to try to start generating _some_ code at least.
|