Age | Commit message (Collapse) | Author |
|
While I was at it I also refreshed some bits
in the instruction selection.
|
|
|
|
|
|
|
|
Compiling languages with closures often requires passing
an extra environment parameter to the called function.
One solution is to use a convention, and reserve, say,
the first argument for that purpose. However, that
makes binding to C a little less smooth.
Alternatively, QBE now provides a way to remain fully
ABI compatible with C by having a "hidden" environment
argument (marked with the keyword 'env'). Calling a
function expecting an environment from C will make the
contents of the environment undefined, but the normal
arguments will be passed without alteration. Conversely,
calling a C function like it is a closure by passing
it an environemnt will work smoothly.
|
|
|
|
We conservatively assume all functions have
variable argument lists.
|
|
|
|
This change is backward compatible, calls to
"variadic" functions (like printf) must now be
annotated (with ...).
|
|
|
|
|
|
When an edge is deleted, the phis and predecessors of the
destination block have to be updated. This is what blkdel()
was doing, but at a level too coarse. The new function
edgedel() allows to remove a single edge (and takes care of
multiple edges).
|
|
This makes it possible to call it several times in a row.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This also provides a violent fix to a bug causing an invalid
addressing to be generated when indexing into a global variable.
The fix is not satisfactory, though, as bad code is generated
(instead of invalid code before).
|
|
|
|
The assertion was invalid, I was assuming il->blk was
b when writing it. The new assertion should be right:
If the loop level were to decrease we would get out of
a cycle in cfg, this should not be possible unless we
go through a block with more than 1 predecessor.
|
|
|
|
The assertion fails incorrectly on a block right
after the end of a loop.
|
|
|
|
|
|
|
|
|
|
|
|
This was not necessary as temporaries were never freed
and returned from an array zero initialized. But in the
coming load optimization, we sometimes free temporaries
by resetting fn->ntmp.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The casting to uint32_t made the code for comparing
two signed words invalid. Interestingly, this can
be fixed by casting to int32_t instead. Because
sign extension is monotonic, all the unsigned
comparisons remain valid.
CVC4 can even check that for us:
x, y : BITVECTOR(32);
QUERY BVLT(SX(x, 64), SX(y, 64)) <=> BVLT(x, y);
QUERY BVLE(SX(x, 64), SX(y, 64)) <=> BVLE(x, y);
QUERY BVGT(SX(x, 64), SX(y, 64)) <=> BVGT(x, y);
QUERY BVGE(SX(x, 64), SX(y, 64)) <=> BVGE(x, y);
|
|
The pass was not doing anything incorrect, but
it missed some opportunities to optimize. On
a copy heavy example I observed that, in the
output of the pass a phi of the following shape
remained:
%a =w phi @A %c, @B %a
Originally the phi for %a was:
%a =w phi @A %b, @B %a
Since %b was discovered a copy of %c, %a should
have been eliminated and replaced with %c.
I think the problem is that knowledge on the
first argument of the phi %a changes as the
algorithm progresses, a more detailed walk-
through follows.
In the first round of the algoritm, %a is
discovered to be a copy of its first argument
%b.
phi(%b, %a) -> %b
In the second round, %a is computed as the phi
of %c (since the first argument changed) and %b
(the result of the first iteration), in our
lattice, the glb of those two is bottom.
phi(%c, %b) -> %a (Bottom)
Finally, there is a third round in which we
compute %a as the phi of %a and %c, which again,
gives bottom.
phi(%c, %a) -> %a (Bottom)
The bug is not tied to a phi of a copy, for
example, if the first argument is speculated
to be a copy of 0 and then, this knowledge is
retracted; we will compute in sequence:
phi(0, %a) -> 0
phi(%b, 0) -> %a (Bottom)
phi(%b, %a) -> %a (Bottom)
The way I fixed this is by ignoring arguments
of the phi that were discovered to be copies of
the phi node itself. This will make the last
rounds above do the correct thing.
|