Estimated hours taken: 20
vn_block:
Fix a typo which reflected a fundamental design error. When finding
cheaper copies of live lvals, for use in creating specialized copies
(parallels) of blocks jumped to from the current location, we used
to use the map reflecting the contents of lvals at the start of the
block, not at the point of the jump.
--pred-value-number, which uses the information computed by the
buggy predicate, actually bootstrapped some time ago despite
this fundamental bug!
value_number:
Fix a bug in the creation of parallel code sequences for computed
gotos. Add some more opprtunities for printing diagnostics.
Move code concerning final verification to vn_verify.
vn_verify:
Move the remaining code concerned with final verification from
value_number to vn_verify.
peephole:
Add a new pattern, which transforms the sequence
incr_sp N; goto L2; L1; incr_sp N; L2
into just
L1; incr_sp N; L2
The pattern is of course more broadly applicable, but I have seen
it only when it involves a single incr_sp between the two labels.
(The longer pattern can be introduced by frameopt.)
opt_util:
Look inside blocks when checking whether an instruction can fall
through. This improves the performance of labelopt.
vn_table:
Make the type vn_table abstract; add, export and use access functions.
vn_util:
Remove a noop predicate, since now it won't ever be made to do
anything.
vn_cost:
Refine debugging output.
vn_debug:
Add some more debugging routines.
opt_debug:
Add some more debugging routines.
det_analysis:
Remove an unused argument.
labelopt:
Formatting change.
A Constraint Solver Interface For Mercury
<thunderous applause>
Estimated hours taken: 1 summer studentship
This is the implementation of a fairly general constraint solver interface. If
using a library grade *.cnstr, we emit C instructions to keep track of the
solver's implicit state. This is done by storing and restoring 'tickets' -
abstract handles on the solver's state.
We emit a store_ticket() macro:
-when entering the first disjunct of a disjunction
-when entering the condition of an if-then-else
We emit a restore_ticket() macro:
-when entering a disjunct other than the first of a disjunction
-when entering the else part of an if-then-else
We emit a discard_ticket() macro:
-after the restore_ticket() in the final disjunct of a disjunction
-at the start of the 'then' part of an if-then-else
The rules for emitting the macros is slightly more complicated than that shown
above for if-then-elses (determinism of the parts must be taken into account).
compiler/code_info.m:
Get an llds store_ticket/restore_ticket etc. instruction
compiler/disj_gen.m:
Emit ticket macros in the appropriate places in a disjunction.
compiler/dupelim.m:
Handle the new llds instruction.
compiler/frameopt.m:
Handle the new llds instruction.
compiler/handle_options.m:
If the grade is *.cnstr, set the constraints option on.
compiler/ite_gen.m:
Emit ticket macros in the appopriate places in an if-then-else.
compiler/livemap.m:
Handle the new llds instruction.
compiler/llds.m:
Output the ticket macros.
compiler/make_hlds.m:
An irrelevant tidy-up.
compiler/mercury_compile.pp:
If the grade is *.cnstr, pass -DCONSTRAINTS to mgnuc
compiler/middle_rec.m:
Handle the new llds instruction.
compiler/opt_*.m:
Handle the new llds instruction.
compiler/options.m:
Introduce a new boolean option 'constraints'.
compiler/shapes.m:
Output a new shape - 'ticket'.
compiler/unify_proc.m:
Handle the new llds instruction.
compiler/v*.m:
Handle the new llds instruction.
Estimated hours taken: 1.5
Undo dylan's changes in the names of some library entities,
by applying the following sed script
s/term_atom/term__atom/g
s/term_string/term__string/g
s/term_integer/term__integer/g
s/term_float/term__float/g
s/term_context/term__context/g
s/term_functor/term__functor/g
s/term_variable/term__variable/g
s/_term__/_term_/g
s/std_util__bool_/bool__/g
to all the `.m' and `.pp' files in the compiler and library directories.
The reason for undoing these changes was to minimize incompatibilities
with 0.4 (and besides, the changes were not a really good idea in the first
place).
I also moved `bool' to a separate module.
The main reason for that change is to ensure that the `__' prefix is
only used when it genuinely represents a module qualifier.
(That's what dylan's changes were trying to acheive, but `term__'
does genuinely represent a module qualifier.)
compiler/*.m:
Apply sed script above;
where appropriate, add `bool' to the list of imported modules.
Estimated hours taken: _2___
Change names with badly placed double underscores (ie where the part of
a name before a double underscore is not the same as the module name.)
Reflect changes in the library interface.
compiler/*:
Use the newer, more correct form of the term and bool names.
Predicates "bool__" are now "std_util__bool" and labels of
the term ADT are now "term_" instead of "term__".
compiler/vn*.m:
change all names "vn__*" to a correct module prefix. All the
names remain qualified.
compiler/hlds.m:
s/\<is_builtin__/hlds__is_builtin_/g
s/\<dependency_info__/hlds__dependency_info_/g
compiler/unify_proc.m:
s/\<unify_proc_info__/unify_proc__info_/g
compiler/transform.m:
s/\<reschedule__conj/transform__reschedule_conj/g
code_exprn.m, modes.m:
Fix singleton variable warnings by deleting useless code.
shapes.m, typecheck.m:
Fix singleton variable warnings by renaming variables so that they
start with an underscore.
make_hlds.m:
Pass the context down into transform_goal_2, unravel_unification,
insert_arg_unifications, and append_arg_unifications, so that
the goal_info_context in the newly built HLDS is never empty.
This is needed because the new warn_singletons uses the context,
so it has to be valid.
unify_proc.m:
Pass a term__context to unravel_unification (as required by
above change).
quantification.m:
Rearrange some comments that got shifted a dozen
lines from the code they referred to.
vn_util.m:
Fix omission in Zoltan's changes with `succip(FramePointer)'
which caused "Software Error: unexpected lval in vn_...".
jumpopt:
Added last call optimization for nondet predicates.
llds:
Added a new lval type to represent the succip slot of nondet
stack frames.
other files:
Changes required by the change to llds (there is a minor unrelated
change in vn_cost as well).
Tyson: please check my changes to code_info__get_shape_num and
garbage_out__write_liveval.
instructions, and the last argument from local labels. All these were
placeholders for info put in there by prof.m and used when emitting C
code.
The set of labels that serve as return points are now calculated in llds.m
just before each procedure has its C code generated. This set is passed to
output_instruction along with the label at the start of the procedure.
This set of changes includes most of the work necessary for
mode and determinism checking of higher-order predicates.
prog_io.m:
Change the syntax for lambda expressions: they need
to have a determinism declaration. Lambda
expressions must now look like this:
lambda([X::in, Y::out] is det, ...goal...).
^^^^^^
Note that both the modes and the determinism are mandatory,
not optional.
hlds.m:
Insert a determinism field in the lambda_goal structure.
hlds_out.m, inlining.m, make_hlds.m, modes.m, polymorphism.m, quantification.m,
switch_detection.m, typecheck.m:
Modified to use lambda_goal/4 rather than lambda_goal/3.
prog_io.m:
Add a new field to the `ground' inst, of type `maybe(pred_inst_info)'.
We use this to store the modes and determinism of higher-order
predicate terms.
code_info.m, inst_match.m, mercury_to_mercury.m, mode_util.m, modes.m,
polymorphism.m, shapes.m, undef_modes.m:
Modified to handle higher-order pred modes:
use ground/2 rather than ground/1.
(Note that modes.m still requires a bit more work on this.)
llds.m:
Add a new field to the call_closure/3 instruction to hold the
caller address for use with profiling, since the C macros
require a caller address.
dup_elim.m, frame_opt.m, garbage_out.m, live_map.m, middle_rec.m, opt_debug.m,
opt_util.m, value_number.m, vn_*.m:
Modified to use call_closure/4 rather than call_closure/3.
mercury_to_mercury.m:
Export mercury_output_det for use by hlds_out.m.
frameopt:
Make the teardown map bidirectional, and export it.
peephole:
Add a new pattern to handle cases generated by fulljump optimization.
This pattern uses the teardownmap, but it is disabled for the moment.
optimize:
Pass the teardown map where it is needed, and make sure we do a
peephole pass immediately after frameopt to use the teardownmap
while it is still valid.
jumpopt:
Rename a variable.
labelopt:
A block being eliminated may have the last remaining reference
to the label starting another block. Therefore on the last invocation
of labelopt, we iterate to a fixpoint before returning.
opt_debug:
Add a predicate to help debug bidirectional teardown maps.
opt_util:
Liberalized some optimizations, but the changes are disabled for the
moment.
value_number:
Pass an empty teardown map to peephole. Loosen the sanity check on
tags a bit.
vn_order:
If the new value of a location depends on its old value,
avoid creating a circularity in the preferred order relation.
Such circularity may be broken arbitrarily, even though we have
a clear preference.
vn_flush:
Modify the criteria for saving the old value stored in a location
about to be overwritten, in an effort to eliminate useless copies
of old values.
vn_util:
Tighten the requirement for classifying a use as a "real" use,
also in the effort to eliminate useless saves of old values.
Recognize some more expression patterns as yieldsing known
results. Move some functionality from vn_flush to vn_util,
since it is needed by the other modification.
vn_flush, vn_util:
Tighten the definition of what it means for a use to be "real",
i.e. sufficient cause to keep around a value.
peephole:
Add a pattern that can be introduced by fulljump optimization.
-------------------------------------------------------
Implement unique modes. We do not handle local aliasing yet, so this
is still not very useful, except for io__state. Destructive update is
not yet implemented. Also note that this really only implements
"mostly unique" variables that may be non-unique on backtracking - we
don't check that you don't backtrack over I/O, for example.
prog_io.m, mode_util.m, modes.m, inst_match.m:
Major changes to Handle unique modes.
mercury_to_mercury.m, polymorphism.m, prog_out.m, undef_modes.m:
Use `ground(Uniqueness)' rather than just `ground'.
compiler/*.m:
Fix compile errors now that unique modes are enforced: add a
few calls to copy/2, and comment out lots of unique mode
declarations that caused problems.
typecheck.m, mode_info.m:
Hack around the use of unique modes, which doesn't work
because we don't allow local aliasing yet: make the insts
`uniq_type_info' and `uniq_mode_info' not unique at all,
and add a call to copy/2 when extracting the io_state from
type_info or mode_info.
-------------------------------------------------------
Plus a couple of unrelated changes:
hlds.m:
Change the modes for the special predicates from `ground -> ground'
to `in', so that any error messages that show those modes
come out looking nicer.
Add a new shared_inst_table for shared versions of user-defined
insts.
mercury_to_goedel.m:
Use string__is_alnum_or_underscore.
options, optimize:
Add a new option, --optimize-fulljumps, which defaults on.
jumpopt, opt_util:
If --optimize-fulljumps is set, replace unconditional gotos with
the instruction sequence they point to. This not only avoids a jump
at runtime, but also increases basic block length and makes value
numbering more effective.
peephole:
Fulljump optimization can replace a recursive tailcall with the
initial part of the code of the procedure. Therefore peephole now
looks for a decr_sp followed by an incr_sp, and removes such pairs
from the instruction sequence.
frameopt:
Do not consider a decr_sp followed by an incr_sp to be a fatal error
(just in case peephole is switched off).
vn_block:
Fix a big tickled by fulljump optimization: maxfr, curfr and succip
were not required to be made up to date before an if_val exited
the extended basic block.
vn_util:
Simplify some more patterns of vnrvals. The extra patterns are
involved in testing conditions that are known to be true or false.
These patterns can arise when fulljump optimization replaces a
recursive tailcall.
mercury_compile:
Sort the list of interface files before printing them to a .d file.
opt_util, peephole:
Fix a bug tickled by value numbering. Some sequences of code were
recognized as having no access to nondet stack control slots even
in the presence of such accesses, which lead to the incorrect
introduction of succeed_discards.
value_number:
Loosen the value correspondence sanity check, which was failing
needlessly, and tighten the tag sanity check, which was passing
incorrect code.
Do not try value numbering on blocks containing structures such as
"if (tag(x) == X && field(X, x, X) == X) goto X", since these will
definitely lead to tag sanity check violations.
vn_flush:
If a shared node has no uses left when flushed, leave it be.
When generating a mkframe, reflect its update of the top redoip slot
in the data structures.
vn_order:
Some hacks to get the relmaps partway to where I want them. This
code needs cleaning up.
vn_debug:
New debugging routines to support my changes to vn_order.
vn_type:
Deleted the vn_modframe vn_instr, since its role has been taken over
by assignments to redoip(maxfr).
opt_debug:
Reflect the change to vn_type, print address constants in vn_rvals,
and fix a typo.
vn_block, vn_util:
Reflect the change to vn_type.
code_gen.pp:
Put the comment about the contents of stack slots before the initial
label, since this way it will be preserved by optimizations.
cse_detection.m:
Extended the search to look for cses in if-then-elses and switches
as well as disjunctions. Removed InstmapDelta from preds in which it
was not being used.
det_analysis.m:
Make the diagnosis routines more robust. The changes here avoid the
Philip's problems with lexical.m.
jumpopt.m:
Minor formatting changes.
livemap.m:
Avoid duplicating livevals instructions when optimizations are
repeated, since this can confuse some optimizations.
llds.m:
Minor documentation change.
make_hlds.m:
Minor formatting change.
mercury_compile.pp:
Do not map arguments to registers if any semantic errors have been
found.
middle_rec.m and code_aux.m:
Apply middle recursion only if tail recursion is not possible,
since tail recursion yields more efficient code.
opt_util.m:
Added a predicate to recognize constant conditions in if_vals.
Modified a predicate to make it better suited for frameopt.
optimize.pp:
Changed the way optimizations were repeated to allow better control.
Repeat peephole once more after frameopt, since the new frameopt
can benefit from this.
options.m:
Removed the --compile-to-c option, which was obsolete. Added an
option for predicate-wide value numbering, which is off by default.
Changed some of the default values of optimization flags to reduce
compilation time while holding the loss of speed of generated code
to a minimum.
peephole.m:
Look for if_vals whose conditions are constants, and eliminate the
if_val or turn it into a goto depending on the value of the constant.
Generalized the condition for optimizing incr_sp/decr_sp pairs.
value_number.m:
Added a prepass to separate primary tag tests in if-then-elses from
the test of the secondary tag, which requires dereferencing the
pointer.
Added sanity check routines to test two aspects of the generated code.
First, whether it produces the same values for the live variables as
the original code, and second, whether it has moved any dereferences
of a pointer before a test of the tag of that pointer. If either test
fails, we use the old instruction sequence.
vn_debug.m:
New messages to announce the failure of the sanity checks. They are
enabled by default, but of course can only appear if value numbering
is turned on (it is still off by default).
vn_flush.m:
Threaded a list of forbidden lvals (lvals that may not be assigned to)
through the flushing routines. When saving the old value of an lval
that is being assigned to, we use this list to avoid modifying any of
the values used on the right hand side of the assignment, even if the
saving of an old value results in assignment that requires another
save, and so on recursively.
When the flushing of a node_lval referred to a shared vn, the uses of
the access vns of the node_lvals were not being adjusted properly.
Now they are.
vn_order.m:
The ctrl_vn phase of the ordering was designed to ensure that all
nodes that need not come before a control node come after it. However,
nodes were created after this phase operated, causing leakage of some
value nodes in front of control nodes. Some of these led to pointer
dereferences before tag tests, causing bus errors. The ctrl_vn phase
is now last to avoid this problem.
vn_table.m:
Added an extra interface predicate to support the sanity checks in
value_number.
vn_util.m:
The transformation of c1-e2 into (0-e2)+c1 during vnrval simplification
could lead to an infinite loop in the compiler if c1 was zero. A test
for this case now prevents the loop.
code_info.m:
Bug fix: change generate_pre_commit and generate_commit so that
the values which need to be saved and restored are always pushed
onto the det stack, even in nondet predicates. The reason is
that if the committed goal fails, curfr is not valid, so we
can't restore the fields from the nondet stack.
(This way may well be more efficient anyway.)
disj_gen.m, ite_gen.m:
Handle the case when the current failure continuation is unknown
on entry to the disjunction or nondet if-then-else by creating
a new frame on the nondet stack. (Originally we just aborted
in this case; recently we "fixed" this, but it turned out that
the fix was not correct, for the same reason as the above-mentioned
bug in pre_commit/commit.
llds.m:
Add succfr/1 and prevfr/1 to the rval type in llds.m,
since they were needed by the above bug fixes.
(This caused dozens of changes elsewhere to handle the
new types.)
Also fix a trivial bug that I recently introduced which
prevented --mod-comments from working.
live_vars.m:
Fix bug in allocation of stack slots for nondet code.
(This is the one that caused the bug that ksiew and I found
when writing a calculator program.)
peephole.m:
Disable the succeed_discard() optimization, since it
causes incorrect code to be generated. It was replacing
modframe(do_fail) ... succeed() with
modframe(do_fail) ... succeed_discard() even when there were
instructions such as mkframe() in between.
modes.m, hlds.m:
When modechecking switches, record the binding of the switch variable
as we enter each case, so that we get the determinism analysis
right.
mercury_compile.pp:
Make sure that we set the exit status to be non-zero if we
find any errors.
typecheck.m, modes.m, undef_types.m, undef_modes.m:
Don't invoke type-checking if there are undefined types.
Don't invoke mode-checking if there are undefined modes.
This avoids the problem of the compiler aborting with an
internal error if there are undefined types/modes.
frameopt:
fix the problem with destroying stack frames and creating
them again later, accessing detstackvars that were earlier
nominally destroyed.
vn_livemap:
renamed it to livemap since frameopt now uses it also.
value_number, vn_*:
Fixed some bugs. Reorganized the handling of blocks: they are now
put in at the last minute before llds writes out the code.
Made a start towards exploiting info about cheaper copies of
values.
optimize, options:
Made value_numbering an iterated optimization. Added a new
option to control how many times it is iterated together
with other the jumpopt, peephole and labelopt.
llds, call_gen, code_gen, code_info, middle_rec, opt_debug:
changed type of the argument of livevals to plain set.
Warning: in more than a week I haven't been able to fully test this change,
dur to kryten's flakiness and bugs upstream of the optimizer.
compiler/*:
Add copyright messages.
Change all occurences of *.nl in comments to *.m.
compiler/mercury_compile.pp:
Change the output to the .dep files to use *.m rather than *.nl.
(NOTE: this means that `mmake' will not work any more if you
call your files *.nl!!!)
unify_gen:
Whenever we do a test of a variable against a non-constant functor,
we now try to turn it into a negated test on a constant functor.
This is possible if these two functors are the only ones.
code_aux:
Added an extra predicate to look up type definitions to make the
previous change easier.
llds, code_gen, opt_util, opt_debug, frameopt, jumpopt, peephole:
Added a boolean argument to do_succeed to say whether the nondet
frame should be discarded on success or not. The default is no,
but peephole has an optimization that tries to turn on this flag.
optimize, value_number, vn*:
Restructured the top level of value numbering as part of an effort
to identify blocks that could be optimized further given our knowledge
that the contents of e.g. stackvars is also in registers when we
jump to those blocks. Redone the interface between value_number and
frameopt to allow value_number to be iterated, which is necessary
to take advantage of the previously mentioned capability. Threated
the I/O state through the relevant predicates; value numbering doesn't
use non-logical I/O any more.
llds.nl:
Introduced an extra argument to the LLDS goto. It is the label
address of the Caller and is used for the profiling of tailcall's.
*.nl and *.pp:
Propagated the extra argument to all the appropiate files.
llds, code_info, opt_*, vn*:
Replaced curredoip with redoip(rval) to make references to other
redoips more efficient. Also, by turning modframe(L) into
redoip(curfr) = const(address_const(L)), value_number can now
optimize hijacking code better.
vn*:
If a disagreement on the desired value of an lvalue prevents value
number, try again after skipping to the first control point, since
this may cure the problem.
peephole, opt_util:
Now looking for successive modframes to optimize out.
disj_gen:
Put deterministic alternatives before others, mainly to make
the back mode of append easier to explain in the paper. :-(
mode_util:
Fixed scope error.
garbage_out:
Fixed some spelling and formatting errors.
vn_*:
Got value numbering working. Isolated diagnostic messages in separate
file.
llds:
During output, transform x + -const into x - const, since some
compilers may not recognize the pattern and may use several
instructions to build up a negative constant.
atsort:
Added predicates for transitive closure.
frameopt:
Fixed a performance bug introduced by previous change.
value_number, vn_util, opt_util, opt_debug:
Fixed a bug with allowed incr_hp to overwrite its target without saving
it. Reorganized the handling of incr_sp and decr_sp to make sure they
never get reordered with respect to control flow instructions.
llds:
Fixed the output of temp declarations for blocks.
frameopt:
Generalized the set up patterns accepted as starting a det procedure.
labelopt:
Added a source-level option to remove eliminated instructions instead
of turning them into comments, and made it the default.
optimize:
After value numbering, perform jump optimization as well as peepholing
and label optimization.
mercury_compile:
Added back an old garbage collection point.
optimize:
Added some new garbage collection points, and made the file into .pp.
value_number, vn_util, opt_debug:
Changed the way access vns are counted. Pushed noop vnlvals towards
the front of the flush order; this can improve the speed of the
generated code.
middle_rec:
Clarified a bit of code.
Value_number, vn_util:
Multiple heap increments by 4 to compensate for the (Integer) cast
on hp.
frameopt:
Pull incr_sp instructions to the front of basic blocks.
value_number, vn_util:
Value numbering should now work with code that allocates memory.
frameopt:
Create a stack frame before an if_val if both continuations need one.
optimize, mercury_compile:
-V now prints a message for each optimization pass for each proc.
llds, call_gen, code_gen, middle_rec etc:
Change livevals/2 back into livevals1.
jumpopt:
Rename instmap to instrmap at fjh's request.
frameopt:
Now handles det/semidet procedures that refer to failure.
opt_util:
Moved some frameopt-specific stuff to frameopt.
vn_util:
Set up for better rval source selection.
value_number:
Fix references to mark_hp.
opt_debug:
An extra predicate for debugging value_number.
llds:
Minor change in formatting the output; diff --side-by-side should now
truncate fewer lines.
value_number, vn_util, atsort:
Value numbering now works for several examples. It does not yet
attempt to handlecode that manipulates the heap; that's for tomorrow.
opt_debug:
Much better facilities for debugging value numbering :-)
llds and others:
replaced the heap_alloc rval with two new instructions. The first
is incr_hp(lval, rval); it takes a size (the rval) and allocates
that much memory, returning its address in the lval. The idea is
that code sequences such as
r1 = hp;
incr_hp(4);
will now become
incr_hp(r1, 4)
The other instruction is restore_hp(rval). Incr_sp returns an rval
by putting it into the given lval; only rvals thus supplied should
be given as arguments to restore_hp. What used to be written as
hp = stackvar(5)
should now be
restore_hp(stackvar(5))
This scheme makes it possible to use gc_malloc instead of heap
discipline for memory allocation, preserves the referential
transparency of rvals, and still allows the efficient use of heap.
*.nl:
Replace all occurrences of `not(Vars, Goal)' with just
plain `not(Goal)'.
type_util.nl, switch_gen.nl:
Higher-order pred types are not user-defined types.
Add a `predtype' type category for them.
call_gen.nl:
Change call_closure/2 to call_closure/3 (with liveinfo).
Plus a little bit of random hacking.
value_number, vn_util:
Closer to working than before :-)
opt_util:
Moved all value_number-related functionality from there to vn_util.
llds and other files:
Renamed live_lvalues to liveinfo, and added a list of these as a
third argument to call_closure as well. Fergus and Tom, please generate
this third argument in call_gen.
llds.nl, *.nl:
Change field(int, rval, int) to field(int, rval, rval), so
that the field number can be calculated at runtime
(We need this for predicate closures).
Also, remove the incr_hp(int) instruction and replace it
with a heap_alloc(rval) rval.
(We need to determine the space allocated at runtime
for predicate closures, and also we want it to be an rval
not an instruction so we can get conservative garbage collection
to work.)
unify_gen.nl:
More work for higher-order predicate closures.
std_util.nl:
Recode `bool__and' and `bool__or' more elegantly.