[m-rev.] diff: fix --optimize-higher-order bug

Simon Taylor stayl at cs.mu.OZ.AU
Thu Jan 16 22:59:01 AEDT 2003


On 16-Jan-2003, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> On 16-Jan-2003, Simon Taylor <stayl at cs.mu.OZ.AU> wrote:
> > On 16-Jan-2003, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> > > On 15-Jan-2003, Simon Taylor <stayl at cs.mu.OZ.AU> wrote:
> > > > 
> > > > Estimated hours taken: 5
> > > > Branches: main, release
> > > > 
> > > > compiler/higher_order.m:
> > > > 	Fix a bug in `--optimize-higher-order' which caused compilation of 
> > > > 	analysis/analysis.file.m to fail with inter-module optimization.
> > > > 	The problem was that type-infos for curried arguments of a higher-order
> > > > 	term were not being added to the typeinfo_varmap for the specialized
> > > > 	procedure.
> > > 
> > > This change seems to have broken the hlc.agc grade.
> > > 
> > > The compiler now generates invalid C code for library/relation.m in grade
> > > hlc.agc at -O3 or higher.  The generated C code refers to an undeclared
> > > type_info variable.
> > > 
> > > The problem seems to be that the HLDS generated by higher_order.m is no
> > > longer meeting an invariant which the accurate GC code is assuming.
> > > In particular, the invariant that it assumes is this: for every
> > > polymorphically typed variable which occurs in a procedure call,
> > > the corresponding type_info variable for that type will also be
> > > an argument of the procedure call.
> > > 
> > > The reason that this invariant is being broken is that the higher order
> > > specialization pass is introducing a procedure that has *more than one
> > > type_info argument corresponding to the same type variable*, and in the
> > > body of the procedure there is a call which passes a variable of type
> > > T, and a type_info that is a type_info for T, but the type_info passed
> > > is not the type_info for T that was recorded in the type_info varmap.
> >
> > I think any code that relies on an invariant as subtle as this
> > is broken anyway, and should be fixed.  I couldn't give a guarantee
> > that other optimization passes don't introduce the same sort of code.
> > It could happen for any optimization which causes types to be substituted
> > (type specialization, inlining, deforestation, any others?).
> 
> The invariant is basically just that for each variable X whose type
> contains a polymorphic type variable T, the type_info variable for T
> is around whenever X is around.  IMHO that is not an unreasonable thing
> to assume!  That's basically the definition of type-info liveness,
> which is used extensively throughout the compiler.
> 
> The only time that maintaining this invariant would be difficult is if 
> there is more than one type_info variable for a single type variable.
> I don't think there is *ever* a good reason to have that.
> If type specialization, inlining, or deforestation don't maintain
> the invariant that there is only one type_info variable for each
> type variable, then IMHO they should be fixed too.
> 
> Furthermore, the definition of the type_info_varmap type assumes that
> there is only one type_info for each type variable.  If you're going to
> break that assumption, then type_info_varmap would need to be changed
> to map each type variable to a set of type_info vars.

That would not be necessary. At the point where accurate garbage
collection needs the type-info, the type-info in the typeinfo_varmap
is guaranteed to be live, and it is also guaranteed that you are
passed a type-info for the type variable (not necessarily the
one in the typeinfo_varmap). It should be trivial to substitute
so that the variable in the typeinfo_varmap is passed.

It's more robust to do this once where the invariant is needed,
rather than in every place where invariant could possibly be broken.

> Inlining preserves the invariant that there is only one type_info variable
> for each type variable, I'm pretty sure. 

It doesn't (although for some reason this example compiles without problems).

:- module agcbug.

:- interface.

:- pred p(T::in) is semidet.

:- implementation.

:- import_module std_util.

p(A) :-
	q(A, B, C),
	r(B),
	r(C).

:- some [U, V] pred q(T::in, U::out, V::out) is det.
:- pragma inline(q/3).

q(X, X, X).

:- pred r(U::in) is semidet.
:- pragma no_inline(r/1).

r(_) :- semidet_succeed.

Simon.
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list