[m-rev.] for review: pragma input_spec
Julien Fischer
juliensf at gmail.com
Mon Aug 17 21:27:23 AEST 2026
On Sun, 16 Aug 2026 at 17:13, Zoltan Somogyi <zoltan.somogyi at runbox.com> wrote:
> On Fri, 14 Aug 2026 17:56:27 +1000, Julien Fischer <jfischer at opturion.com> wrote:
...
> > > +rebuild_proc_table_loop(_, [], !ProcTable).
> > > +rebuild_proc_table_loop(ProcNum, [ProcInfo | ProcInfos], !ProcTable) :-
> > > + proc_id_to_int(ProcId, ProcNum),
> > > + map.det_insert(ProcId, ProcInfo, !ProcTable),
> > > + rebuild_proc_table_loop(ProcNum + 1, ProcInfos, !ProcTable).
> >
> > This seems suspicious. The HLDS has a lot of references to proc_ids.
> > Why does this renumbering not invalidate the ones in, for example,
> > the list of pragma exported procs? At least, had a comment giving
> > a correctness argument.
>
> This is a much more complex issue, or rather set of different issues.
> The attached file contains my proposals for addressing them.
Here are my comment on that:
> Proposal to fix the interaction of input_spec pragmas
> with other pragmas that refer to specific procedures
>
> ------------------------------------------------------------------
>
> These other pragmas can be put into these groups:
>
> group 1:
> termination
> termination2
> require_tail_rec
Termination analysis has three:
terminates
termination_info
termination2_info
(We do allow the latter two outside of .opt and .trans_opt files, although I
can't remember anyone actually ever doing that.)
> group 2:
> obsolete_proc
>
> group 3:
> tabling method pragmas such as memo and minimal
>
> group 4:
> structure sharing
> structure reuse
>
> group 5:
> type_spec
>
> group 6:
> the gen pragmas that record analysis results
>
> For groups 1, 2, 3 and 4, adding the pragma to the HLDS looks up
> the specified procedure in the HLDS, and adds a notation to its proc_info.
> When input specialization duplicates a procedure, this automatically
> duplicates the notation as well.
We also have:
:- pragma promise_pure
:- pramga promise_semipure
:- pragma format_call
:- pragma consider_used
:- pragma inline
:- pragma no_inline
:- pragma no_determinism_warning
And as mentioned earlier in this thread :- pragma foreign_export.
> ------------------------------------------------------------------
>
> GROUP 1
>
> The pragmas in group 1 each call for some diagnostic about the procedure
> if some condition is not met. Duplicating the procedure will indirectly
> cause the duplication of these diagnostics as well, but this is not an
> issue if the diagnostics for each duplicate proc are identical to the
> diagnostics for the original procedure. However, the diagnostic text
> may include the argument modes, and these WILL differ in the duplicated
> copies.
>
> The way I propose to fix this is as follows.
>
> - When input specialization duplicates a procedure, mark the duplicate
> proc_info as being a duplicate created by input specialization.
>
> - When compiler passes that the generate diagnostics called for by
> the pragmas in group 1, simply to do not process the procedures
> marked in that way.
>
> - To ensure that all called-for diagnostics are in fact generated,
> keep the original procedure in its pred_info's proc_table EVEN WITH
> REPLACE_IN_MODE.
>
> - To ensure the absence of calls to any procedures that replace_in_mode
> logically deletes, mark each original procedure that input specialization
> creates duplicates of as either "original, logically deleted" (with
> replace_in_mode) or as "original, logically kept" (with add_to_in_mode),
> and
>
> - have simplification generate an error for each call to an "original,
> logically deleted" procedure, in roughly the same way as we generate
> warnings for calls to obsolete predicates.
>
> In general, this new notation could be a new field in proc_infos,
> whose type is something like this:
>
> :- type maybe_input_spec_proc
> ---> not_involved_in_input_spec(proc_id)
> ; input_spec_original_proc_kept(proc_id)
> ; input_spec_original_proc_deleted(proc_id)
> ; input_specialized_proc(proc_id).
>
> The proc_id fields would each id the *original* procedure
> that the annotated procedure is a (possibly modified) copy of.
...
> ------------------------------------------------------------------
>
> GROUP 2
>
> obsolete_proc pragmas differ from group 1 pragmas in that they call for
> diagnostics not for some property of the body of the procedure they name,
> but for *calls* to the procedure they name from other predicates.
>
> The only issue here is that input specialization may redirect a call
> to an obsolete proc to one of its input specialized variants, which
> would cause the diagnostic to refer to the specialized mode of the
> callee. The code that generates the diagnostic would use the
> maybe_input_spec_proc field on the call to map it back to the
> procedure that the obsolete_proc pragma is for.
>
> ------------------------------------------------------------------
>
> GROUP 3
...
> The way I propose to handle this is to simply consider any change
> by input specialization to any predicate that contains a tabled procedure
> to be an error.
Ok.
> The only raised by this decision is: what can a programmer do
> whose module contains both an input_spec and a tabling pragmas,
> and they clash? Deleting one or the other will work. Is this good
> enough, or do we need to add a flag to input_spec pragmas that says
> "if applying this input specialization to a predicate clashes with
> a tabling pragma for that predicate, then forget input specialization
> for that predicate"?
>
> I would say no, since the absence of input_specs is the current condition.
I think that's fine for now.
> ------------------------------------------------------------------
>
> GROUP 4
>
> It has been a *very* long time since I looked at the code that
> implements structure sharing/reuse pragmas. I don't know enough
> to say how they should be handled. I don't even know whether
> they work well enough for it to be worth worrying about
> how they would be affected.
It has been a very long time since *anyone* looked at it.
I suggest simply disabling input specialization if --ctgc is enabled.
(That should be sufficient for anyone who picks up the work CTGC.
If that work is ever picked up, then we can worry about its
interaction with input specialization.)
...
> GROUP 5
>
> I think that logically, input specialization in its current form
> and type specialization are orthogonal, because
>
> - input specialization applies to args whose types are ground
> (at least for now), while
> - type specialization replaces type variables in argument types.
>
> I don't yet know whether the implementations are orthogonal,
> mostly because the existing implementation of type specialization
> is (I think) unnecessarily roundabout. By that I mean that
> creating a new predicate containing a type-specializable call
> just so that a later traversal of the module_info will find it
> and add an entry to a table is much more complicated than
> simply adding that same entry to a table. The roundabout way
> may have some advantage I don't know about, but it would be nice
> if it was documented somehere obvious.
>
> For now, I propose to generate an error if we are about to apply
> type specialization to predicate that was modified by input
> specialization. The justification for this is the same
> as for group 3: requiring users to delete the input_spec pragma
> would just get them back to the current condition.
Agreed.
Julien.
More information about the reviews
mailing list