[m-rev.] for review: float registers for higher order calls

Peter Wang novalazy at gmail.com
Mon Feb 6 16:49:03 AEDT 2012


On Mon, 30 Jan 2012 16:09:41 +1100 (EST), Julien Fischer <juliensf at csse.unimelb.edu.au> wrote:
> 
> 
> Hi Peter,
> 
> Here are some initial review comments for this.
> 
> On Fri, 14 Oct 2011, Peter Wang wrote:
> 
...
> > Note: Mercury code has a tendency to lose insts for higher-order terms, then
> > "recover" them by hacky means.  The float_regs pass depends on higher-order
> > insts; it is impossible to create a wrapper for a procedure without knowing
> > how to call it.  The float_regs pass will report errors which we otherwise
> > accepted, due to higher-order insts being unavailable.  It should be possible
> > for the user to adjust the code to satify the pass, though the user may not
> 
> s/satify/satisfy/

Fixed.

> > compiler/options.m:
> > compiler/handle_options.m:
> > 	Always enable float registers on low-level C grades when floats are
> > 	wider than a word.
> 
> s/on low-level/in low-level/
> 

Fixed.

> > compiler/check_typeclass.m:
> > 	In the pred_info of an instance method predicate, record the original
> > 	argument types before substiting the type variables for the instance.
> 
> s/substiting/substituting/
> 
> ...

Fixed.

> > diff --git a/compiler/float_regs.m b/compiler/float_regs.m
> > new file mode 100644
> > index 0000000..2779c6d
> > --- /dev/null
> > +++ b/compiler/float_regs.m
> 
> ...

> > +:- pred add_arg_regs_in_bound_inst(module_info::in, set(inst_name)::in,
> > +    mer_type::in, bound_inst::in, bound_inst::out) is det.
> > +
> > +add_arg_regs_in_bound_inst(ModuleInfo, Seen, Type, BoundInst0, BoundInst) :-
> > +    BoundInst0 = bound_functor(ConsId, ArgInsts0),
> > +    (
> > +        get_cons_id_non_existential_arg_types(ModuleInfo, Type, ConsId,
> > +            ArgTypes)
> > +    ->
> > +        (
> > +            ArgTypes = [],
> > +            % When a foreign type overrides a d.u. type, the inst may have
> > +            % arguments but the foreign type does not.
> > +            ArgInsts = ArgInsts0
> > +        ;
> > +            ArgTypes = [_ | _],
> > +            list.map_corresponding(add_arg_regs_in_inst(ModuleInfo, Seen),
> > +                ArgTypes, ArgInsts0, ArgInsts)
> > +        )
> > +    ;
> > +        % XXX handle existentially typed cons_ids
> > +        ArgInsts = ArgInsts0
> 
> Doesn't that XXX need to be fixed?  (Or is this also an issue with the XXX in
> the test case below?)
> 

I don't know how to reach there.  Probably because of bug #89.

> > +insert_reg_wrappers_goal_2(Goal0, Goal, !InstMap, !Info, !Specs) :-
> > +    Goal0 = hlds_goal(GoalExpr0, GoalInfo0),
> > +    (
> > +        GoalExpr0 = unify(_LHS, _RHS, _Mode, _Unification, _Context),
> > +        insert_reg_wrappers_unify_goal(GoalExpr0, GoalInfo0, Goal, !InstMap,
> > +            !Info, !Specs)
> > +    ;
> > +        GoalExpr0 = conj(ConjType, Goals0),
> > +        (
> > +            ConjType = plain_conj,
> > +            insert_reg_wrappers_conj(Goals0, Goals, !InstMap, !Info, !Specs)
> > +        ;
> > +            ConjType = parallel_conj,
> > +            list.map_foldl3(insert_reg_wrappers_goal, Goals0, Goals,
> > +                !InstMap, !Info, !Specs)
> > +        ),
> > +        GoalExpr = conj(ConjType, Goals),
> > +        Goal = hlds_goal(GoalExpr, GoalInfo0),
> > +        % For some reason, the instmap delta for the conjunction as a whole may
> > +        % be unreachable even though all of the conjuncts are reachable.
> > +        % If we leave the instmap reachable that leads to problems when we
> > +        % try to fix up at the end of branching goals.
> > +        % XXX figure out why
> 
> Do you have an example where this occurs?
> 

Turns out to be imported procedures with an empty conjunction for a
body.

> 
> > +:- pred insert_reg_wrappers_unify_goal(hlds_goal_expr::in(goal_expr_unify),
> > +    hlds_goal_info::in, hlds_goal::out, instmap::in, instmap::out,
> > +    lambda_info::in, lambda_info::out,
> > +    list(error_spec)::in, list(error_spec)::out) is det.
> > +
> > +insert_reg_wrappers_unify_goal(GoalExpr0, GoalInfo0, Goal, !InstMap, !Info,
> > +        !Specs) :-
> > +    GoalExpr0 = unify(LHS, RHS0, Mode, Unification0, Context),
> > +    (
> > +        Unification0 = construct(CellVar, ConsId, Args0, UniModes0,
> > +            HowToConstruct, IsUnique, SubInfo),
> > +        (
> > +            RHS0 = rhs_functor(_, IsExistConstruct, _)
> > +        ;
> > +            RHS0 = rhs_var(_),
> > +            unexpected($module, $pred, "construct rhs_var")
> > +        ;
> > +            RHS0 = rhs_lambda_goal(_, _, _, _, _, _, _, _, _),
> > +            unexpected($module, $pred, "construct rhs_lambda_goal")
> > +        ),
> > +        (
> > +            Args0 = [],
> > +            ModuleInfo = !.Info ^ li_module_info,
> > +            update_construct_goal_instmap_delta(ModuleInfo, CellVar, ConsId,
> > +                Args0, GoalInfo0, GoalInfo, !InstMap),
> > +            Goal = hlds_goal(GoalExpr0, GoalInfo)
> > +        ;
> > +            Args0 = [_ | _],
> > +            GoalContext = goal_info_get_context(GoalInfo0),
> > +            insert_reg_wrappers_construct(CellVar, ConsId, Args0, Args,
> > +                UniModes0, UniModes, Maybe, !.InstMap, GoalContext,
> > +                !Info, !Specs),
> 
> s/Maybe/MaybeWrappedGoals/ there and below (and in the body of
> insert_reg_wrappers_construct).

Fixed.

> > +:- pred rebuild_cell_inst(module_info::in, instmap::in, cons_id::in,
> > +    list(prog_var)::in, mer_inst::in, mer_inst::out) is det.
> > +
> > +rebuild_cell_inst(ModuleInfo, InstMap, ConsId, Args, Inst0, Inst) :-
> > +    (
> > +        Inst0 = bound(Uniq, BoundInsts0),
> > +        list.map(rebuild_cell_bound_inst(InstMap, ConsId, Args),
> > +            BoundInsts0, BoundInsts),
> > +        Inst = bound(Uniq, BoundInsts)
> > +    ;
> > +        Inst0 = ground(Uniq, higher_order(PredInstInfo0)),
> > +        PredInstInfo0 = pred_inst_info(PredOrFunc, Modes, _, Determinism),
> > +        ( ConsId = closure_cons(ShroudedPredProcId, _EvalMethod) ->
> > +            proc(PredId, _) = unshroud_pred_proc_id(ShroudedPredProcId),
> > +            module_info_pred_info(ModuleInfo, PredId, PredInfo),
> > +            pred_info_get_arg_types(PredInfo, ArgTypes),
> > +            list.length(Args, NumArgs),
> > +            list.det_drop(NumArgs, ArgTypes, MissingArgTypes),
> > +            list.map(ho_arg_reg_for_type, MissingArgTypes, ArgRegs),
> > +            PredInstInfo = pred_inst_info(PredOrFunc, Modes, yes(ArgRegs),
> > +                Determinism),
> > +            Inst = ground(Uniq, higher_order(PredInstInfo))
> > +        ;
> > +            Inst = Inst0
> > +        )
> > +    ;
> > +        % XXX do we need to handle any of these other cases?
> 
> Yes, you also need to apply it to the any(Uniq, higher_order(_)) case.
> It should do the same thing as the ground case.

Done.

> 
> I think you also need to handle insts nested inside the constrained_inst_vars/2
> case.  (And maybe elsewhere as well.)

Done.

> > diff --git a/compiler/hlds_goal.m b/compiler/hlds_goal.m
> > index bc07c7f..a1ee238 100644
> > --- a/compiler/hlds_goal.m
> > +++ b/compiler/hlds_goal.m
> > @@ -123,6 +123,12 @@
> >                 % this field is junk until after mode analysis.
> >                 gcall_modes         :: list(mer_mode),
> >
> > +                gcall_reg_types     :: maybe(list(ho_arg_reg)),
> > +                                    % The register type to use for each of the
> > +                                    % arguments. This is only needed when float
> > +                                    % registers exist, and is only set after
> > +                                    % the float reg wrappers pass.
> > +
> >                 % The determinism of the call.
> >                 gcall_detism        :: determinism
> 
> 
> I suggest defining a purpose-specific type rather than using maybe(list(ho_arg_regs)
> there, something like:
> 
> :- type reg_type_info
>  	---> 	reg_types_not_needed
>  	;	reg_types(list(ho_arg_reg)).
> 
> You should also use the purpose specific type in prog_data.m.
> 

Done.

> 
> > diff --git a/compiler/hlds_pred.m b/compiler/hlds_pred.m
> > index 1d533fc..e5a873c 100644
> > --- a/compiler/hlds_pred.m
> > +++ b/compiler/hlds_pred.m
> 
> ...
> 
> > @@ -2335,6 +2353,11 @@ attribute_list_to_attributes(Attributes, Attributes).
> >                 % Allocation of variables to stack slots.
> >                 stack_slots                 :: stack_slots,
> >
> > +                % The head variables which must be forced to use regular
> > +                % registers in the calling convention, despite having type
> 
>   ... by the calling convention

Fixed.

> > diff --git a/compiler/inst_match.m b/compiler/inst_match.m
> > index 998526a..d57f479 100644
> > --- a/compiler/inst_match.m
> > +++ b/compiler/inst_match.m
> > @@ -799,7 +799,7 @@ ho_inst_info_matches_initial(HOInstInfoA, none, _, _, !Info) :-
> >     \+ ho_inst_info_is_nonstandard_func_mode(!.Info ^ imi_module_info,
> >         HOInstInfoA).
> > ho_inst_info_matches_initial(none, higher_order(PredInstB), _, Type, !Info) :-
> > -    PredInstB = pred_inst_info(pf_function, ArgModes, _Det),
> > +    PredInstB = pred_inst_info(pf_function, ArgModes, _, _Det),
> >     Arity = list.length(ArgModes),
> >     PredInstA = pred_inst_info_standard_func_mode(Arity),
> >     pred_inst_matches_2(PredInstA, PredInstB, Type, !Info).
> > @@ -827,11 +827,13 @@ pred_inst_matches_1(PredInstA, PredInstB, MaybeType, ModuleInfo) :-
> > :- pred pred_inst_matches_2(pred_inst_info::in, pred_inst_info::in,
> >     maybe(mer_type)::in, inst_match_info::in, inst_match_info::out) is semidet.
> >
> > -pred_inst_matches_2(pred_inst_info(PredOrFunc, ModesA, Det),
> > -        pred_inst_info(PredOrFunc, ModesB, Det), MaybeType, !Info) :-
> > +pred_inst_matches_2(PredInstA, PredInstB, MaybeType, !Info) :-
> > +    PredInstA = pred_inst_info(PredOrFunc, ModesA, _MaybeArgRegsA, Det),
> > +    PredInstB = pred_inst_info(PredOrFunc, ModesB, _MaybeArgRegsB, Det),
> >     maybe_get_higher_order_arg_types(MaybeType, length(ModesA),
> >         MaybeTypes),
> >     pred_inst_argmodes_matches(ModesA, ModesB, MaybeTypes, !Info).
> > +    % XXX do we need to match the arg reg lists? I don't know how.
> 
> Is this ever going to be called after stage 213?  (If not, then you can certainly
> ignore them.)
> 

Actually, during 213 we must NOT match the arg reg lists.
Replaced the XXX with a comment.

> > diff --git a/compiler/lambda.m b/compiler/lambda.m
> > index adac13d..cf3691c 100644
> > --- a/compiler/lambda.m
> > +++ b/compiler/lambda.m
...
> > @@ -80,6 +88,39 @@
> >     is det.
> >
> > %-----------------------------------------------------------------------------%
> > +
> > +:- interface.
> > +
> > +% The following is exported for float_reg.m
> 
> Is it really necessary to export it all?  Can lambda_info/0 not be abstract exported,
> along with any access predicates required?

Done.

> > @@ -385,15 +397,12 @@ expand_lambda(Purity, _Groundness, PredOrFunc, EvalMethod, Vars, Modes,
> >
> >     (
> >         Unification0 = construct(Var, _, OrigNonLocals1, UniModes0, _, _, _),
> > -        % We use to use OrigVars = OrigNonLocals0 (from rhs_lambda_goal) but
> > -        % the order of the variables does not necessarily match UniModes0.
> > +        % We use to use OrigVars = OrigNonLocals0 (from the outer
> > +        % rhs_lambda_goal) but OrigNonLocals0 may be a reordered version of
> > +        % OrigNonLocals1.
> 
> The comment should explain *why* OrigNonLocals0 may be reordered, i.e. because
> the use of float registers requires that.
> 
> >         OrigVars = OrigNonLocals1,
> > -        trace [compiletime(flag("lambda_var_order"))] (
> > -            list.sort(OrigNonLocals0, SortedOrigNonLocals0),
> > -            list.sort(OrigNonLocals1, SortedOrigNonLocals1),
> > -            expect(unify(SortedOrigNonLocals0, SortedOrigNonLocals1),
> > -                $module, $pred, "OrigNonLocals0 != OrigNonLocals1")
> > -        )
> > +        expect(unify(sort(OrigNonLocals0), sort(OrigNonLocals1) : list(_)),
> > +            $module, $pred, "ConstructArgs != OrigVars")

These changes are not supposed to be here.  They reflect an earlier
version of fix that was previously reviewed and committed.

> > diff --git a/compiler/mercury_compile_middle_passes.m b/compiler/mercury_compile_middle_passes.m
> > index 3062904..78e7815 100644
> > --- a/compiler/mercury_compile_middle_passes.m
> > +++ b/compiler/mercury_compile_middle_passes.m
...
> > @@ -240,6 +241,9 @@ middle_pass(ModuleName, !HLDS, !DumpInfo, !IO) :-
> >     maybe_lco(Verbose, Stats, !HLDS, !IO),
> >     maybe_dump_hlds(!.HLDS, 210, "lco", !DumpInfo, !IO),
> >
> > +    maybe_float_reg_wrapper(Verbose, Stats, !HLDS, !IO),
> > +    maybe_dump_hlds(!.HLDS, 213, "float_reg_wrapper", !DumpInfo, !IO),
> 
> Does this have to be done here, or could it be done later, for example
> around stages 300-310?  (Doing it later would mean that the passes between now
> and 300 don't need to deal with the extra information you are attaching to insts.)
> 
> If there are constraints on when the float_regs pass must occur then it would be
> as well to document them here so that the pass isn't accidently shifted around.
> 

The comments for 220-term_size_prof and 225-deep_profiling suggest that
I should run the pass before them.  213 is basically the last pass
before them.

Also, it has to come after lco.  When Paul moved lco to 210 I had to
move the float_reg_wrapper pass to follow.  If I remember correctly,
it's because after lco may transform the code such that a reg_f
argument becomes a reg_r argument (float becomes pointer to float).

> > diff --git a/compiler/prog_data.m b/compiler/prog_data.m
> > index d8033cf..d935f43 100644
> > --- a/compiler/prog_data.m
> > +++ b/compiler/prog_data.m
> > @@ -2073,10 +2073,21 @@ get_type_kind(kinded_type(_, Kind)) = Kind.
> >                                     % of the return value as the last element
> >                                     % of the list.
> >
> > +                maybe(list(ho_arg_reg)),
> > +                                    % The register type to use for each of the
> > +                                    % additional arguments of the pred. This
> > +                                    % field is only needed when float registers
> > +                                    % exist, and is only set after the float
> > +                                    % reg wrappers pass.
> > +
> >                 determinism         % The determinism of the predicate or
> >                                     % function.
> >             ).
> 
> See my comments in hlds_goal.m.
> 

Fixed.

> > diff --git a/compiler/prog_type.m b/compiler/prog_type.m
> > index a310df6..db27c6e 100644
> > --- a/compiler/prog_type.m
> > +++ b/compiler/prog_type.m
> > @@ -66,6 +66,10 @@
> >     pred_or_func::out, lambda_eval_method::out, list(mer_type)::out)
> >     is semidet.
> >
> > +:- pred type_is_higher_order_details_det(mer_type::in, purity::out,
> > +    pred_or_func::out, lambda_eval_method::out, list(mer_type)::out)
> > +    is det.
> 
> I suggest following the convention used in the stdlib and calling that
> predicate: det_type_is_higher_order_details.

The module contains several other predicates with the _det suffix.
I'm leaving it as-is.

> > diff --git a/runtime/mercury_ho_call.c b/runtime/mercury_ho_call.c
> > index 3cb8e63..a2e517e 100644
> > --- a/runtime/mercury_ho_call.c
> > +++ b/runtime/mercury_ho_call.c
> > @@ -334,8 +334,12 @@ static  MR_Word MR_compare_closures_representation(MR_Closure *x,
> > ** returned in registers MR_r1, MR_r2, etc for det and nondet calls or
> > ** registers MR_r2, MR_r3, etc for semidet calls.
> > **
> > -** The placement of the extra input arguments into MR_r3, MR_r4 etc is done by
> > -** the code generator, as is the movement of the output arguments to their
> > +** When float registers are in effect, float input arguments are passed
> 
> s/in effect/enabled/

Done.

> > +%-----------------------------------------------------------------------------%
> > +
> > +:- type existstruct(T)
> > +    --->    some [U] existstruct(pred(T, T), U).
> > +
> > +:- inst existstruct
> > +    --->    existstruct(pred(in, out) is det, ground).
> > +
> > +% XXX mode checking fails
> > +%
> > +% :- pred docall_existstruct(existstruct(T)::in(existstruct), T::in, T::out)
> > +%     is det.
> > +% :- pragma no_inline(docall_existstruct/3).
> > +%
> > +% docall_existstruct(existstruct(P, _), X, Y) :-
> > +%     P(X, Y).
> 
> Presumably, because of bug #89 or is this something else?

Yes, looks like the same.

Interdiff follows.

Peter

diff --git a/compiler/add_pred.m b/compiler/add_pred.m
index 6de4ef2..fc1d792 100644
--- a/compiler/add_pred.m
+++ b/compiler/add_pred.m
@@ -295,7 +295,8 @@ add_builtin(PredId, Types, CompilationTarget, !PredInfo) :-
         AssignGoal = hlds_goal(AssignExpr, GoalInfoWithZero),
 
         CastExpr = generic_call(cast(unsafe_type_inst_cast),
-            [ZeroVar] ++ HeadVarList, [in_mode, uo_mode], no, detism_det),
+            [ZeroVar] ++ HeadVarList, [in_mode, uo_mode], arg_reg_types_unset,
+            detism_det),
         goal_info_set_nonlocals(
             set_of_var.list_to_set([ZeroVar | HeadVarList]),
             GoalInfo0, GoalInfoWithZeroHeadVars),
diff --git a/compiler/arg_info.m b/compiler/arg_info.m
index 4d0d63d..4d1acd4 100644
--- a/compiler/arg_info.m
+++ b/compiler/arg_info.m
@@ -35,7 +35,6 @@
 
 :- import_module assoc_list.
 :- import_module list.
-:- import_module maybe.
 :- import_module set.
 
 %-----------------------------------------------------------------------------%
@@ -70,7 +69,7 @@
     % Return the register type to use for each argument of a generic call.
     %
 :- pred generic_call_arg_reg_types(module_info::in, vartypes::in,
-    generic_call::in, list(prog_var)::in, maybe(list(ho_arg_reg))::in,
+    generic_call::in, list(prog_var)::in, arg_reg_type_info::in,
     list(reg_type)::out) is det.
 
     % Divide the given list of arguments into those treated as inputs
@@ -346,11 +345,11 @@ generic_call_arg_reg_types(ModuleInfo, _VarTypes, GenericCall, ArgVars,
             list.duplicate(length(ArgVars), reg_r, ArgRegTypes)
         ;
             UseFloatRegs = yes,
-            MaybeArgRegs = yes(ArgRegs),
+            MaybeArgRegs = arg_reg_types(ArgRegs),
             ArgRegTypes = list.map(arg_reg_to_reg_type, ArgRegs)
         ;
             UseFloatRegs = yes,
-            MaybeArgRegs = no,
+            MaybeArgRegs = arg_reg_types_unset,
             % This should have been set by the float register wrapper pass.
             unexpected($module, $pred, "missing ho_arg_regs")
         )
diff --git a/compiler/call_gen.m b/compiler/call_gen.m
index da5f7a0..f805b4e 100644
--- a/compiler/call_gen.m
+++ b/compiler/call_gen.m
@@ -27,7 +27,6 @@
 
 :- import_module assoc_list.
 :- import_module list.
-:- import_module maybe.
 
 %---------------------------------------------------------------------------%
 
@@ -36,7 +35,7 @@
     code_info::in, code_info::out) is det.
 
 :- pred generate_generic_call(code_model::in, generic_call::in,
-    list(prog_var)::in, list(mer_mode)::in, maybe(list(ho_arg_reg))::in,
+    list(prog_var)::in, list(mer_mode)::in, arg_reg_type_info::in,
     determinism::in, hlds_goal_info::in, llds_code::out,
     code_info::in, code_info::out) is det.
 
@@ -191,7 +190,7 @@ generate_generic_call(OuterCodeModel, GenericCall, Args, Modes,
     ).
 
 :- pred generate_main_generic_call(code_model::in, generic_call::in,
-    list(prog_var)::in, list(mer_mode)::in, maybe(list(ho_arg_reg))::in,
+    list(prog_var)::in, list(mer_mode)::in, arg_reg_type_info::in,
     determinism::in, hlds_goal_info::in, llds_code::out,
     code_info::in, code_info::out) is det.
 
diff --git a/compiler/common.m b/compiler/common.m
index 70fce93..7202cad 100644
--- a/compiler/common.m
+++ b/compiler/common.m
@@ -793,7 +793,7 @@ generate_assign(ToVar, FromVar, UniMode, OldGoalInfo, GoalExpr, GoalInfo,
         % equivalence of the input and output.
         Modes = [(ToVarInst -> ToVarInst), (free -> ToVarInst)],
         GoalExpr = generic_call(cast(unsafe_type_cast), [FromVar, ToVar],
-            Modes, no, detism_det)
+            Modes, arg_reg_types_unset, detism_det)
     ),
 
     % `ToVar' may not appear in the original instmap_delta, so we can't just
diff --git a/compiler/float_regs.m b/compiler/float_regs.m
index 2779c6d..a2af908 100644
--- a/compiler/float_regs.m
+++ b/compiler/float_regs.m
@@ -356,6 +356,10 @@ add_arg_regs_in_inst(ModuleInfo, Seen0, Type, Inst0, Inst) :-
             BoundInsts0, BoundInsts),
         Inst = bound(Uniq, BoundInsts)
     ;
+        Inst0 = constrained_inst_vars(InstVarSet, SpecInst0),
+        add_arg_regs_in_inst(ModuleInfo, Seen0, Type, SpecInst0, SpecInst),
+        Inst = constrained_inst_vars(InstVarSet, SpecInst)
+    ;
         Inst0 = defined_inst(InstName),
         % XXX is this correct?
         ( set.contains(Seen0, InstName) ->
@@ -378,7 +382,6 @@ add_arg_regs_in_inst(ModuleInfo, Seen0, Type, Inst0, Inst) :-
         ; Inst0 = free(_)
         ; Inst0 = not_reached
         ; Inst0 = inst_var(_)
-        ; Inst0 = constrained_inst_vars(_, _)
         ; Inst0 = abstract_inst(_, _)
         ),
         Inst = Inst0
@@ -393,7 +396,8 @@ add_arg_regs_in_pred_inst_info(ModuleInfo, Seen, ArgTypes, PredInstInfo0,
     list.map_corresponding(add_arg_regs_in_mode_2(ModuleInfo, Seen),
         ArgTypes, Modes0, Modes),
     list.map(ho_arg_reg_for_type, ArgTypes, ArgRegs),
-    PredInstInfo = pred_inst_info(PredOrFunc, Modes, yes(ArgRegs), Det).
+    PredInstInfo = pred_inst_info(PredOrFunc, Modes, arg_reg_types(ArgRegs),
+        Det).
 
 :- pred add_arg_regs_in_bound_inst(module_info::in, set(inst_name)::in,
     mer_type::in, bound_inst::in, bound_inst::out) is det.
@@ -416,6 +420,9 @@ add_arg_regs_in_bound_inst(ModuleInfo, Seen, Type, BoundInst0, BoundInst) :-
         )
     ;
         % XXX handle existentially typed cons_ids
+        trace [compile_time(flag("debug_float_regs"))] (
+            sorry($module, $pred, "existentially typed cons_id")
+        ),
         ArgInsts = ArgInsts0
     ),
     BoundInst = bound_functor(ConsId, ArgInsts).
@@ -480,18 +487,18 @@ insert_reg_wrappers_proc_2(!ProcInfo, !PredInfo, !ModuleInfo, !Specs) :-
     proc_info_get_rtti_varmaps(!.ProcInfo, RttiVarMaps0),
     proc_info_get_inst_varset(!.ProcInfo, InstVarSet0),
     proc_info_get_has_parallel_conj(!.ProcInfo, HasParallelConj),
-    MustRecomputeNonLocals0 = no,
-    HaveExpandedLambdas0 = no,
 
     % Process the goal.
-    Info0 = lambda_info(VarSet0, VarTypes0, TypeVarSet0, InstVarSet0,
-        RttiVarMaps0, HasParallelConj, !.PredInfo, !.ModuleInfo,
-        MustRecomputeNonLocals0, HaveExpandedLambdas0),
+    init_lambda_info(VarSet0, VarTypes0, TypeVarSet0, InstVarSet0,
+        RttiVarMaps0, HasParallelConj, !.PredInfo, !.ModuleInfo, Info0),
     insert_reg_wrappers_proc_body(HeadVars, ArgModes, Goal0, Goal1, InstMap0,
         Info0, Info1, !Specs),
-    Info1 = lambda_info(VarSet1, VarTypes1, TypeVarSet, _InstVarSet,
-        RttiVarMaps1, _, _PredInfo, !:ModuleInfo, MustRecomputeNonLocals,
-        _HaveExpandedLambdas),
+    lambda_info_get_varset(Info1, VarSet1),
+    lambda_info_get_vartypes(Info1, VarTypes1),
+    lambda_info_get_tvarset(Info1, TypeVarSet),
+    lambda_info_get_rtti_varmaps(Info1, RttiVarMaps1),
+    lambda_info_get_module_info(Info1, !:ModuleInfo),
+    lambda_info_get_recompute_nonlocals(Info1, MustRecomputeNonLocals),
 
     % Check if we need to requantify.
     (
@@ -534,7 +541,7 @@ insert_reg_wrappers_proc_body(HeadVars, ArgModes, Goal0, Goal, InstMap0,
         !Info, !Specs) :-
     insert_reg_wrappers_goal(Goal0, Goal1, InstMap0, InstMap1, !Info, !Specs),
     % Ensure that all arguments match their final insts.
-    ModuleInfo = !.Info ^ li_module_info,
+    lambda_info_get_module_info(!.Info, ModuleInfo),
     mode_list_get_final_insts(ModuleInfo, ArgModes, FinalInsts),
     assoc_list.from_corresponding_lists(HeadVars, FinalInsts,
         VarsExpectInsts),
@@ -576,11 +583,10 @@ insert_reg_wrappers_goal_2(Goal0, Goal, !InstMap, !Info, !Specs) :-
         ),
         GoalExpr = conj(ConjType, Goals),
         Goal = hlds_goal(GoalExpr, GoalInfo0),
-        % For some reason, the instmap delta for the conjunction as a whole may
-        % be unreachable even though all of the conjuncts are reachable.
-        % If we leave the instmap reachable that leads to problems when we
-        % try to fix up at the end of branching goals.
-        % XXX figure out why
+        % Imported procedures may have a body consisting of an empty
+        % conjunction, yet have an `unreachable' instmap delta.
+        % Then we must make !:InstMap `unreachable' as well otherwise
+        % we will run into problems at fix_branching_goal.
         update_instmap_if_unreachable(Goal, !InstMap)
     ;
         GoalExpr0 = disj(Goals0),
@@ -640,8 +646,8 @@ insert_reg_wrappers_goal_2(Goal0, Goal, !InstMap, !Info, !Specs) :-
             Context = goal_info_get_context(GoalInfo0),
             insert_reg_wrappers_higher_order_call(CallVar, Args0, Args, Modes,
                 ArgsRegs, WrapGoals, !.InstMap, Context, !Info, !Specs),
-            GoalExpr1 = generic_call(GenericCall, Args, Modes, yes(ArgsRegs),
-                Determinism),
+            GoalExpr1 = generic_call(GenericCall, Args, Modes,
+                arg_reg_types(ArgsRegs), Determinism),
             finish_call_goal(WrapGoals, GoalExpr1, GoalInfo0, Goal, !InstMap,
                 !Info)
         ;
@@ -650,9 +656,8 @@ insert_reg_wrappers_goal_2(Goal0, Goal, !InstMap, !Info, !Specs) :-
             insert_reg_wrappers_method_call(ClassId, MethodNum, Args0, Args,
                 Modes0, Modes, WrapGoals, !.InstMap, Context, !Info, !Specs),
             % Currently we don't use float registers for method calls.
-            MaybeArgRegs = no,
-            GoalExpr1 = generic_call(GenericCall, Args, Modes, MaybeArgRegs,
-                Determinism),
+            GoalExpr1 = generic_call(GenericCall, Args, Modes,
+                arg_reg_types_unset, Determinism),
             finish_call_goal(WrapGoals, GoalExpr1, GoalInfo0, Goal, !InstMap,
                 !Info)
         ;
@@ -696,12 +701,12 @@ finish_call_goal(WrapGoals, CallGoalExpr0, CallGoalInfo0, Goal,
     instmap::in, lambda_info::in, lambda_info::out) is det.
 
 do_recompute_atomic_instmap_delta(Goal0, Goal, InstMap, !Info) :-
-    VarTypes = !.Info ^ li_vartypes,
-    InstVarSet = !.Info ^ li_inst_varset,
-    ModuleInfo0 = !.Info ^ li_module_info,
+    lambda_info_get_vartypes(!.Info, VarTypes),
+    lambda_info_get_inst_varset(!.Info, InstVarSet),
+    lambda_info_get_module_info(!.Info, ModuleInfo0),
     recompute_instmap_delta(recompute_atomic_instmap_deltas, Goal0, Goal,
         VarTypes, InstVarSet, InstMap, ModuleInfo0, ModuleInfo),
-    !Info ^ li_module_info := ModuleInfo.
+    lambda_info_set_module_info(ModuleInfo, !Info).
 
 :- pred update_instmap_if_unreachable(hlds_goal::in, instmap::in, instmap::out)
     is det.
@@ -739,7 +744,7 @@ insert_reg_wrappers_unify_goal(GoalExpr0, GoalInfo0, Goal, !InstMap, !Info,
         ),
         (
             Args0 = [],
-            ModuleInfo = !.Info ^ li_module_info,
+            lambda_info_get_module_info(!.Info, ModuleInfo),
             update_construct_goal_instmap_delta(ModuleInfo, CellVar, ConsId,
                 Args0, GoalInfo0, GoalInfo, !InstMap),
             Goal = hlds_goal(GoalExpr0, GoalInfo)
@@ -747,12 +752,12 @@ insert_reg_wrappers_unify_goal(GoalExpr0, GoalInfo0, Goal, !InstMap, !Info,
             Args0 = [_ | _],
             GoalContext = goal_info_get_context(GoalInfo0),
             insert_reg_wrappers_construct(CellVar, ConsId, Args0, Args,
-                UniModes0, UniModes, Maybe, !.InstMap, GoalContext,
+                UniModes0, UniModes, MaybeWrappedGoals, !.InstMap, GoalContext,
                 !Info, !Specs),
             (
-                Maybe = yes(WrapGoals),
+                MaybeWrappedGoals = yes(WrapGoals),
                 list.foldl(update_instmap, WrapGoals, !InstMap),
-                ModuleInfo = !.Info ^ li_module_info,
+                lambda_info_get_module_info(!.Info, ModuleInfo),
                 update_construct_goal_instmap_delta(ModuleInfo, CellVar,
                     ConsId, Args, GoalInfo0, GoalInfo1, !InstMap),
                 RHS = rhs_functor(ConsId, IsExistConstruct, Args),
@@ -762,8 +767,8 @@ insert_reg_wrappers_unify_goal(GoalExpr0, GoalInfo0, Goal, !InstMap, !Info,
                 Goal1 = hlds_goal(GoalExpr1, GoalInfo1),
                 conj_list_to_goal(WrapGoals ++ [Goal1], GoalInfo1, Goal)
             ;
-                Maybe = no,
-                ModuleInfo = !.Info ^ li_module_info,
+                MaybeWrappedGoals = no,
+                lambda_info_get_module_info(!.Info, ModuleInfo),
                 update_construct_goal_instmap_delta(ModuleInfo, CellVar,
                     ConsId, Args0, GoalInfo0, GoalInfo, !InstMap),
                 Goal = hlds_goal(GoalExpr0, GoalInfo)
@@ -775,7 +780,7 @@ insert_reg_wrappers_unify_goal(GoalExpr0, GoalInfo0, Goal, !InstMap, !Info,
         % Update the uni_modes of the deconstruction using the current inst of
         % the deconstructed var. Recompute the instmap delta from the new
         % uni_modes if changed.
-        ModuleInfo = !.Info ^ li_module_info,
+        lambda_info_get_module_info(!.Info, ModuleInfo),
         list.length(Args, Arity),
         instmap_lookup_var(!.InstMap, CellVar, CellVarInst0),
         inst_expand(ModuleInfo, CellVarInst0, CellVarInst),
@@ -818,9 +823,10 @@ insert_reg_wrappers_unify_goal(GoalExpr0, GoalInfo0, Goal, !InstMap, !Info,
     list(error_spec)::in, list(error_spec)::out) is det.
 
 insert_reg_wrappers_construct(CellVar, ConsId, OrigVars, Vars,
-        UniModes0, UniModes, Maybe, InstMap0, Context, !Info, !Specs) :-
-    ModuleInfo = !.Info ^ li_module_info,
-    VarTypes = !.Info ^ li_vartypes,
+        UniModes0, UniModes, MaybeWrappedGoals, InstMap0, Context,
+        !Info, !Specs) :-
+    lambda_info_get_module_info(!.Info, ModuleInfo),
+    lambda_info_get_vartypes(!.Info, VarTypes),
     map.lookup(VarTypes, CellVar, CellType),
     (
         % Replace all type parameters by phony type variables.
@@ -844,11 +850,11 @@ insert_reg_wrappers_construct(CellVar, ConsId, OrigVars, Vars,
         mode_list_get_initial_insts(ModuleInfo, RhsModes, ArgInitialInsts),
         match_args(InstMap0, Context, PhonyArgTypes, ArgInitialInsts,
             OrigVars, Vars, [], WrapGoals, !Info, !Specs),
-        Maybe = yes(WrapGoals)
+        MaybeWrappedGoals = yes(WrapGoals)
     ;
         Vars = OrigVars,
         UniModes = UniModes0,
-        Maybe = no
+        MaybeWrappedGoals = no
     ).
 
 :- pred replace_type_params_by_dummy_vars(mer_type::in, mer_type::out,
@@ -906,7 +912,11 @@ rebuild_cell_inst(ModuleInfo, InstMap, ConsId, Args, Inst0, Inst) :-
             BoundInsts0, BoundInsts),
         Inst = bound(Uniq, BoundInsts)
     ;
-        Inst0 = ground(Uniq, higher_order(PredInstInfo0)),
+        (
+            Inst0 = ground(Uniq, higher_order(PredInstInfo0))
+        ;
+            Inst0 = any(Uniq, higher_order(PredInstInfo0))
+        ),
         PredInstInfo0 = pred_inst_info(PredOrFunc, Modes, _, Determinism),
         ( ConsId = closure_cons(ShroudedPredProcId, _EvalMethod) ->
             proc(PredId, _) = unshroud_pred_proc_id(ShroudedPredProcId),
@@ -915,20 +925,30 @@ rebuild_cell_inst(ModuleInfo, InstMap, ConsId, Args, Inst0, Inst) :-
             list.length(Args, NumArgs),
             list.det_drop(NumArgs, ArgTypes, MissingArgTypes),
             list.map(ho_arg_reg_for_type, MissingArgTypes, ArgRegs),
-            PredInstInfo = pred_inst_info(PredOrFunc, Modes, yes(ArgRegs),
-                Determinism),
-            Inst = ground(Uniq, higher_order(PredInstInfo))
+            PredInstInfo = pred_inst_info(PredOrFunc, Modes,
+                arg_reg_types(ArgRegs), Determinism),
+            (
+                Inst0 = ground(_, _),
+                Inst = ground(Uniq, higher_order(PredInstInfo))
+            ;
+                Inst0 = any(_, _),
+                Inst = any(Uniq, higher_order(PredInstInfo))
+            )
         ;
             Inst = Inst0
         )
     ;
+        Inst0 = constrained_inst_vars(InstVarSet, SpecInst0),
+        rebuild_cell_inst(ModuleInfo, InstMap, ConsId, Args,
+            SpecInst0, SpecInst),
+        Inst = constrained_inst_vars(InstVarSet, SpecInst)
+    ;
         % XXX do we need to handle any of these other cases?
         ( Inst0 = free
         ; Inst0 = free(_)
-        ; Inst0 = any(_, _)
+        ; Inst0 = any(_, none)
         ; Inst0 = ground(_, none)
         ; Inst0 = not_reached
-        ; Inst0 = constrained_inst_vars(_, _)
         ; Inst0 = defined_inst(_)
         ),
         Inst = Inst0
@@ -1024,7 +1044,7 @@ insert_reg_wrappers_disjunct(InstMap0, Goal0, Goal, InstMap, !Info, !Specs) :-
 
 insert_reg_wrappers_switch(Var, Cases0, Cases, NonLocals, InstMap0, InstMap,
         !Info, !Specs) :-
-    VarTypes = !.Info ^ li_vartypes,
+    lambda_info_get_vartypes(!.Info, VarTypes),
     map.lookup(VarTypes, Var, Type),
     list.map2_foldl2(insert_reg_wrappers_case(Var, Type, InstMap0),
         Cases0, Cases1, InstMaps1, !Info, !Specs),
@@ -1045,10 +1065,10 @@ insert_reg_wrappers_switch(Var, Cases0, Cases, NonLocals, InstMap0, InstMap,
 insert_reg_wrappers_case(Var, Type, InstMap0, Case0, Case, InstMap, !Info,
         !Specs) :-
     Case0 = case(MainConsId, OtherConsIds, Goal0),
-    ModuleInfo0 = !.Info ^ li_module_info,
+    lambda_info_get_module_info(!.Info, ModuleInfo0),
     bind_var_to_functors(Var, Type, MainConsId, OtherConsIds,
         InstMap0, InstMap1, ModuleInfo0, ModuleInfo1),
-    !Info ^ li_module_info := ModuleInfo1,
+    lambda_info_set_module_info(ModuleInfo1, !Info),
     insert_reg_wrappers_goal(Goal0, Goal, InstMap1, InstMap, !Info, !Specs),
     Case = case(MainConsId, OtherConsIds, Goal).
 
@@ -1093,7 +1113,7 @@ insert_reg_wrappers_ite(NonLocals, GoalExpr0, GoalExpr, InstMap0, InstMap,
 
 insert_reg_wrappers_plain_call(PredId, ProcId, Vars0, Vars, WrapGoals,
         InstMap0, Context, !Info, !Specs) :-
-    ModuleInfo = !.Info ^ li_module_info,
+    lambda_info_get_module_info(!.Info, ModuleInfo),
     module_info_pred_proc_info(ModuleInfo, PredId, ProcId, PredInfo, ProcInfo),
     pred_info_get_arg_types(PredInfo, ArgTypes),
     proc_info_get_argmodes(ProcInfo, ArgModes),
@@ -1108,8 +1128,8 @@ insert_reg_wrappers_plain_call(PredId, ProcId, Vars0, Vars, WrapGoals,
 
 insert_reg_wrappers_higher_order_call(CallVar, Vars0, Vars, ArgModes, ArgRegs,
         WrapGoals, InstMap0, Context, !Info, !Specs) :-
-    ModuleInfo = !.Info ^ li_module_info,
-    VarTypes = !.Info ^ li_vartypes,
+    lambda_info_get_module_info(!.Info, ModuleInfo),
+    lambda_info_get_vartypes(!.Info, VarTypes),
     map.lookup(VarTypes, CallVar, CallVarType),
     instmap_lookup_var(InstMap0, CallVar, CallVarInst),
     type_is_higher_order_details_det(CallVarType, _, PredOrFunc, _, ArgTypes),
@@ -1129,7 +1149,7 @@ insert_reg_wrappers_higher_order_call(CallVar, Vars0, Vars, ArgModes, ArgRegs,
 
 insert_reg_wrappers_method_call(ClassId, MethodNum, Vars0, Vars,
         Modes0, Modes, WrapGoals, InstMap0, Context, !Info, !Specs) :-
-    ModuleInfo = !.Info ^ li_module_info,
+    lambda_info_get_module_info(!.Info, ModuleInfo),
     module_info_get_class_table(ModuleInfo, Classes),
     map.lookup(Classes, ClassId, ClassDefn),
     ClassInterface = ClassDefn ^ class_hlds_interface,
@@ -1208,7 +1228,7 @@ set_foreign_arg_var(Var, !ForeignArg) :-
 
 match_args_for_call(InstMap0, Context, ArgTypes, ArgModes, OrigVars, Vars,
         WrapGoals, !Info, !Specs) :-
-    ModuleInfo = !.Info ^ li_module_info,
+    lambda_info_get_module_info(!.Info, ModuleInfo),
     mode_list_get_initial_insts(ModuleInfo, ArgModes, InitialInsts),
     match_args(InstMap0, Context, ArgTypes, InitialInsts, OrigVars, Vars,
         [], WrapGoals, !Info, !Specs).
@@ -1247,8 +1267,8 @@ match_args(InstMap0, Context, ArgTypes, Insts, OrigVars, Vars, !WrapGoals,
 
 match_arg(InstMapBefore, Context, ArgType, ExpectInst, OrigVar, Var,
         !WrapGoals, !Info, !Specs) :-
-    ModuleInfo = !.Info ^ li_module_info,
-    VarTypes = !.Info ^ li_vartypes,
+    lambda_info_get_module_info(!.Info, ModuleInfo),
+    lambda_info_get_vartypes(!.Info, VarTypes),
     (
         inst_is_bound(ModuleInfo, ExpectInst),
         type_is_higher_order_details(ArgType, _, PredOrFunc, _,
@@ -1278,8 +1298,8 @@ match_arg(InstMapBefore, Context, ArgType, ExpectInst, OrigVar, Var,
                 list.cons(UnifyGoal, !WrapGoals)
             )
         ;
-            PredInfo = !.Info ^ li_pred_info,
-            VarSet = !.Info ^ li_varset,
+            lambda_info_get_pred_info(!.Info, PredInfo),
+            lambda_info_get_varset(!.Info, VarSet),
             maybe_report_missing_pred_inst(PredInfo, VarSet, OrigVar, Context,
                 OrigPredArgTypes, ArgPredArgTypes, !Specs),
             Var = OrigVar
@@ -1332,9 +1352,9 @@ search_pred_inst_info_2(ModuleInfo, Inst, PredInstInfo) :-
 get_ho_arg_regs(PredInstInfo, ArgTypes, ArgRegs) :-
     PredInstInfo = pred_inst_info(_, _, MaybeArgRegs, _),
     (
-        MaybeArgRegs = yes(ArgRegs)
+        MaybeArgRegs = arg_reg_types(ArgRegs)
     ;
-        MaybeArgRegs = no,
+        MaybeArgRegs = arg_reg_types_unset,
         list.map(ho_arg_reg_for_type, ArgTypes, ArgRegs)
     ).
 
@@ -1414,11 +1434,11 @@ common_instmap_delta(InstMap0, NonLocals, InstMaps, CommonDelta, !Info) :-
         instmap_delta_init_unreachable(CommonDelta)
     ;
         InstMapDeltas = [_ | _],
-        VarTypes = !.Info ^ li_vartypes,
-        ModuleInfo0 = !.Info ^ li_module_info,
+        lambda_info_get_vartypes(!.Info, VarTypes),
+        lambda_info_get_module_info(!.Info, ModuleInfo0),
         merge_instmap_deltas(InstMap0, NonLocals, VarTypes, InstMapDeltas,
             CommonDelta, ModuleInfo0, ModuleInfo),
-        !Info ^ li_module_info := ModuleInfo
+        lambda_info_set_module_info(ModuleInfo, !Info)
     ).
 
 :- pred fix_branching_goal(assoc_list(prog_var, mer_inst)::in,
@@ -1482,8 +1502,8 @@ match_vars_insts(VarsExpectInsts, InstMap0, Context, !Renaming, !WrapGoals,
 
 match_var_inst(Var, ExpectInst, InstMap0, Context, !Renaming, !WrapGoals,
         !Info, !Specs) :-
-    ModuleInfo = !.Info ^ li_module_info,
-    VarTypes = !.Info ^ li_vartypes,
+    lambda_info_get_module_info(!.Info, ModuleInfo),
+    lambda_info_get_vartypes(!.Info, VarTypes),
     ( inst_is_free(ModuleInfo, ExpectInst) ->
         true
     ;
@@ -1507,9 +1527,9 @@ match_var_inst(Var, ExpectInst, InstMap0, Context, !Renaming, !WrapGoals,
 
 create_reg_wrapper(OrigVar, OrigVarPredInstInfo, OuterArgRegs, InnerArgRegs,
         Context, Var, UnifyGoal, !Info) :-
-    VarSet0 = !.Info ^ li_varset,
-    VarTypes0 = !.Info ^ li_vartypes,
-    ModuleInfo0 = !.Info ^ li_module_info,
+    lambda_info_get_varset(!.Info, VarSet0),
+    lambda_info_get_vartypes(!.Info, VarTypes0),
+    lambda_info_get_module_info(!.Info, ModuleInfo0),
 
     map.lookup(VarTypes0, OrigVar, OrigVarType),
     type_is_higher_order_details_det(OrigVarType, Purity, PredOrFunc,
@@ -1526,7 +1546,7 @@ create_reg_wrapper(OrigVar, OrigVarPredInstInfo, OuterArgRegs, InnerArgRegs,
     OrigVarPredInstInfo = pred_inst_info(_, ArgModes, _, Determinism),
     GenericCall = higher_order(CallVar, Purity, PredOrFunc, Arity),
     CallGoalExpr = generic_call(GenericCall, CallVars, ArgModes,
-        yes(InnerArgRegs), Determinism),
+        arg_reg_types(InnerArgRegs), Determinism),
     CallNonLocals = set_of_var.list_to_set([CallVar | CallVars]),
     instmap_delta_from_mode_list(CallVars, ArgModes, ModuleInfo0,
         CallInstMapDelta),
@@ -1537,8 +1557,8 @@ create_reg_wrapper(OrigVar, OrigVarPredInstInfo, OuterArgRegs, InnerArgRegs,
     % Create the replacement variable Var.
     varset.new_var(Var, VarSet1, VarSet),
     map.det_insert(Var, OrigVarType, VarTypes1, VarTypes),
-    !Info ^ li_varset := VarSet,
-    !Info ^ li_vartypes := VarTypes,
+    lambda_info_set_varset(VarSet, !Info),
+    lambda_info_set_vartypes(VarTypes, !Info),
 
     % RegR_HeadVars are the wrapper procedure's headvars which must use regular
     % registers.
@@ -1564,8 +1584,8 @@ create_reg_wrapper(OrigVar, OrigVarPredInstInfo, OuterArgRegs, InnerArgRegs,
     UnifyContext = unify_context(MainContext, []),
     UnifyGoalExpr = unify(Var, Functor, UnifyMode, Unification, UnifyContext),
     UnifyNonLocals = set_of_var.make_singleton(Var),
-    UnifyPredInstInfo = pred_inst_info(PredOrFunc, ArgModes, yes(OuterArgRegs),
-        Determinism),
+    UnifyPredInstInfo = pred_inst_info(PredOrFunc, ArgModes,
+        arg_reg_types(OuterArgRegs), Determinism),
     UnifyPredVarInst = ground(shared, higher_order(UnifyPredInstInfo)),
     UnifyInstMapDelta = instmap_delta_from_assoc_list([
         Var - UnifyPredVarInst]),
@@ -1573,7 +1593,7 @@ create_reg_wrapper(OrigVar, OrigVarPredInstInfo, OuterArgRegs, InnerArgRegs,
         purity_pure, UnifyGoalInfo),
     UnifyGoal = hlds_goal(UnifyGoalExpr, UnifyGoalInfo),
 
-    !Info ^ li_recompute_nonlocals := yes.
+    lambda_info_set_recompute_nonlocals(yes, !Info).
 
 :- pred create_fresh_vars(list(mer_type)::in, list(prog_var)::out,
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
diff --git a/compiler/goal_expr_to_goal.m b/compiler/goal_expr_to_goal.m
index 471507f..e0ad5f6 100644
--- a/compiler/goal_expr_to_goal.m
+++ b/compiler/goal_expr_to_goal.m
@@ -484,7 +484,8 @@ transform_goal_expr_to_goal(LocKind, Expr, Context, Renaming, Goal, !:NumAdded,
         list.duplicate(Arity, in_mode, Modes),
         goal_info_init(Context, GoalInfo),
         Details = event_call(EventName),
-        GoalExpr0 = generic_call(Details, HeadVars, Modes, no, detism_det),
+        GoalExpr0 = generic_call(Details, HeadVars, Modes, arg_reg_types_unset,
+            detism_det),
         Goal0 = hlds_goal(GoalExpr0, GoalInfo),
         CallId = generic_call_id(gcid_event_call(EventName)),
         insert_arg_unifications(HeadVars, Args, Context, ac_call(CallId),
@@ -551,7 +552,7 @@ transform_goal_expr_to_goal(LocKind, Expr, Context, Renaming, Goal, !:NumAdded,
             ->
                 % Initialize some fields to junk.
                 Modes = [],
-                MaybeArgRegs = no,
+                MaybeArgRegs = arg_reg_types_unset,
                 Det = detism_erroneous,
 
                 GenericCall = higher_order(PredVar, Purity, pf_predicate,
diff --git a/compiler/goal_util.m b/compiler/goal_util.m
index d4abc49..18ba997 100644
--- a/compiler/goal_util.m
+++ b/compiler/goal_util.m
@@ -1734,7 +1734,7 @@ generate_cast_with_insts(CastType, InArg, OutArg, InInst, OutInst, Context,
     goal_info_init(NonLocals, InstMapDelta, detism_det, purity_pure, Context,
         GoalInfo),
     GoalExpr = generic_call(cast(CastType), [InArg, OutArg],
-        [in_mode(InInst), out_mode(OutInst)], no, detism_det),
+        [in_mode(InInst), out_mode(OutInst)], arg_reg_types_unset, detism_det),
     Goal = hlds_goal(GoalExpr, GoalInfo).
 
 %-----------------------------------------------------------------------------%
diff --git a/compiler/higher_order.m b/compiler/higher_order.m
index 001f6b3..3b74bdc 100644
--- a/compiler/higher_order.m
+++ b/compiler/higher_order.m
@@ -3138,7 +3138,7 @@ construct_higher_order_terms(ModuleInfo, HeadVars0, NewHeadVars, ArgModes0,
 
         proc_info_interface_determinism(CalledProcInfo, ProcDetism),
         GroundInstInfo = higher_order(pred_inst_info(PredOrFunc,
-            NonCurriedArgModes, no, ProcDetism))
+            NonCurriedArgModes, arg_reg_types_unset, ProcDetism))
     ;
         in_mode(InMode),
         GroundInstInfo = none,
diff --git a/compiler/hlds_goal.m b/compiler/hlds_goal.m
index 8e74df3..0e3e96c 100644
--- a/compiler/hlds_goal.m
+++ b/compiler/hlds_goal.m
@@ -123,11 +123,10 @@
                 % this field is junk until after mode analysis.
                 gcall_modes         :: list(mer_mode),
 
-                gcall_reg_types     :: maybe(list(ho_arg_reg)),
-                                    % The register type to use for each of the
-                                    % arguments. This is only needed when float
-                                    % registers exist, and is only set after
-                                    % the float reg wrappers pass.
+                % The register type to use for each of the arguments. This is
+                % only needed when float registers exist, and is only set after
+                % the float reg wrappers pass.
+                gcall_reg_types     :: arg_reg_type_info,
 
                 % The determinism of the call.
                 gcall_detism        :: determinism
diff --git a/compiler/hlds_out_goal.m b/compiler/hlds_out_goal.m
index 13d3ec1..843c45a 100644
--- a/compiler/hlds_out_goal.m
+++ b/compiler/hlds_out_goal.m
@@ -1443,18 +1443,18 @@ write_goal_generic_call(Info, GoalExpr, _ModuleInfo, VarSet,
         io.write_string(Follow, !IO)
     ).
 
-:- pred write_ho_arg_regs(int::in, maybe(list(ho_arg_reg))::in,
+:- pred write_ho_arg_regs(int::in, arg_reg_type_info::in,
     io::di, io::uo) is det.
 
 write_ho_arg_regs(Indent, MaybeArgRegs, !IO) :-
     (
-        MaybeArgRegs = yes(ArgRegs),
+        MaybeArgRegs = arg_reg_types(ArgRegs),
         write_indent(Indent, !IO),
         io.write_string("% arg regs: ", !IO),
         io.write_list(ArgRegs, ", ", write_ho_arg_reg, !IO),
         io.nl(!IO)
     ;
-        MaybeArgRegs = no
+        MaybeArgRegs = arg_reg_types_unset
     ).
 
 :- pred write_ho_arg_reg(ho_arg_reg::in, io::di, io::uo) is det.
diff --git a/compiler/hlds_pred.m b/compiler/hlds_pred.m
index 03bc9a6..496e136 100644
--- a/compiler/hlds_pred.m
+++ b/compiler/hlds_pred.m
@@ -2356,7 +2356,7 @@ attribute_list_to_attributes(Attributes, Attributes).
                 stack_slots                 :: stack_slots,
 
                 % The head variables which must be forced to use regular
-                % registers in the calling convention, despite having type
+                % registers by the calling convention, despite having type
                 % float. This is only meaningful with float registers.
                 reg_r_headvars              :: set_of_progvar,
 
diff --git a/compiler/inst_match.m b/compiler/inst_match.m
index d57f479..c0aa337 100644
--- a/compiler/inst_match.m
+++ b/compiler/inst_match.m
@@ -828,12 +828,13 @@ pred_inst_matches_1(PredInstA, PredInstB, MaybeType, ModuleInfo) :-
     maybe(mer_type)::in, inst_match_info::in, inst_match_info::out) is semidet.
 
 pred_inst_matches_2(PredInstA, PredInstB, MaybeType, !Info) :-
+    % In the float_regs.m pass a variable may take on pred insts which differ
+    % only in the arg reg lists in different branches. They should be allowed
+    % to match here.
     PredInstA = pred_inst_info(PredOrFunc, ModesA, _MaybeArgRegsA, Det),
     PredInstB = pred_inst_info(PredOrFunc, ModesB, _MaybeArgRegsB, Det),
-    maybe_get_higher_order_arg_types(MaybeType, length(ModesA),
-        MaybeTypes),
+    maybe_get_higher_order_arg_types(MaybeType, length(ModesA), MaybeTypes),
     pred_inst_argmodes_matches(ModesA, ModesB, MaybeTypes, !Info).
-    % XXX do we need to match the arg reg lists? I don't know how.
 
     % pred_inst_argmodes_matches(ModesA, ModesB, !Info):
     %
diff --git a/compiler/inst_util.m b/compiler/inst_util.m
index 09654fd..7552a7a 100644
--- a/compiler/inst_util.m
+++ b/compiler/inst_util.m
@@ -1826,11 +1826,12 @@ ho_inst_info_is_nonstandard_func_mode(ModuleInfo, HOInstInfo) :-
     HOInstInfo = higher_order(PredInstInfo),
     pred_inst_info_is_nonstandard_func_mode(ModuleInfo, PredInstInfo).
 
-pred_inst_info_standard_func_mode(Arity) =
-        pred_inst_info(pf_function, ArgModes, no, detism_det) :-
+pred_inst_info_standard_func_mode(Arity) = PredInstInfo :-
     in_mode(InMode),
     out_mode(OutMode),
-    ArgModes = list.duplicate(Arity - 1, InMode) ++ [OutMode].
+    ArgModes = list.duplicate(Arity - 1, InMode) ++ [OutMode],
+    PredInstInfo = pred_inst_info(pf_function, ArgModes, arg_reg_types_unset,
+        detism_det).
 
 %-----------------------------------------------------------------------------%
 
diff --git a/compiler/lambda.m b/compiler/lambda.m
index f116ca6..19826c7 100644
--- a/compiler/lambda.m
+++ b/compiler/lambda.m
@@ -89,30 +89,37 @@
 
 %-----------------------------------------------------------------------------%
 
-:- interface.
+% The following are exported for float_reg.m
 
-% The following is exported for float_reg.m
-
-:- type lambda_info
-    --->    lambda_info(
-                li_varset               :: prog_varset,
-                li_vartypes             :: vartypes,
-                li_tvarset              :: tvarset,
-                li_inst_varset          :: inst_varset,
-                li_rtti_varmaps         :: rtti_varmaps,
-                li_has_parallel_conj    :: bool,
-                li_pred_info            :: pred_info,
-                li_module_info          :: module_info,
-                % True iff we need to recompute the nonlocals.
-                li_recompute_nonlocals  :: bool,
-                % True if we expanded some lambda expressions.
-                li_have_expanded_lambda :: bool
-            ).
+:- type lambda_info.
 
 :- type reg_wrapper_proc
     --->    reg_wrapper_proc(set_of_progvar)
     ;       not_reg_wrapper_proc.
 
+:- pred init_lambda_info(prog_varset::in, vartypes::in, tvarset::in,
+    inst_varset::in, rtti_varmaps::in, bool::in, pred_info::in,
+    module_info::in, lambda_info::out) is det.
+
+:- pred lambda_info_get_varset(lambda_info::in, prog_varset::out) is det.
+:- pred lambda_info_get_vartypes(lambda_info::in, vartypes::out) is det.
+:- pred lambda_info_get_tvarset(lambda_info::in, tvarset::out) is det.
+:- pred lambda_info_get_rtti_varmaps(lambda_info::in, rtti_varmaps::out)
+    is det.
+:- pred lambda_info_get_inst_varset(lambda_info::in, inst_varset::out) is det.
+:- pred lambda_info_get_pred_info(lambda_info::in, pred_info::out) is det.
+:- pred lambda_info_get_module_info(lambda_info::in, module_info::out) is det.
+:- pred lambda_info_get_recompute_nonlocals(lambda_info::in, bool::out) is det.
+
+:- pred lambda_info_set_varset(prog_varset::in,
+    lambda_info::in, lambda_info::out) is det.
+:- pred lambda_info_set_vartypes(vartypes::in,
+    lambda_info::in, lambda_info::out) is det.
+:- pred lambda_info_set_module_info(module_info::in,
+    lambda_info::in, lambda_info::out) is det.
+:- pred lambda_info_set_recompute_nonlocals(bool::in,
+    lambda_info::in, lambda_info::out) is det.
+
 :- pred expand_lambda(purity::in, ho_groundness::in,
     pred_or_func::in, lambda_eval_method::in, reg_wrapper_proc::in,
     list(prog_var)::in, list(mer_mode)::in, determinism::in,
@@ -129,24 +136,18 @@
 :- import_module hlds.code_model.
 :- import_module hlds.goal_util.
 :- import_module hlds.hlds_data.
-:- import_module hlds.hlds_goal.
-:- import_module hlds.hlds_rtti.
 :- import_module hlds.pred_table.
 :- import_module hlds.quantification.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
-:- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_mode.
 :- import_module parse_tree.prog_type.
 :- import_module parse_tree.prog_util.
-:- import_module parse_tree.set_of_var.
 
 :- import_module assoc_list.
 :- import_module array.
-:- import_module bool.
 :- import_module int.
-:- import_module list.
 :- import_module map.
 :- import_module maybe.
 :- import_module pair.
@@ -156,6 +157,50 @@
 :- import_module varset.
 
 %-----------------------------------------------------------------------------%
+
+:- type lambda_info
+    --->    lambda_info(
+                li_varset               :: prog_varset,
+                li_vartypes             :: vartypes,
+                li_tvarset              :: tvarset,
+                li_inst_varset          :: inst_varset,
+                li_rtti_varmaps         :: rtti_varmaps,
+                li_has_parallel_conj    :: bool,
+                li_pred_info            :: pred_info,
+                li_module_info          :: module_info,
+                % True iff we need to recompute the nonlocals.
+                li_recompute_nonlocals  :: bool,
+                % True if we expanded some lambda expressions.
+                li_have_expanded_lambda :: bool
+            ).
+
+init_lambda_info(VarSet, VarTypes, TypeVarSet, InstVarSet, RttiVarMaps,
+        HasParallelConj, PredInfo, ModuleInfo, Info) :-
+    MustRecomputeNonLocals = no,
+    HaveExpandedLambdas = no,
+    Info = lambda_info(VarSet, VarTypes, TypeVarSet, InstVarSet,
+        RttiVarMaps, HasParallelConj, PredInfo, ModuleInfo,
+        MustRecomputeNonLocals, HaveExpandedLambdas).
+
+lambda_info_get_varset(Info, Info ^ li_varset).
+lambda_info_get_vartypes(Info, Info ^ li_vartypes).
+lambda_info_get_tvarset(Info, Info ^ li_tvarset).
+lambda_info_get_rtti_varmaps(Info, Info ^ li_rtti_varmaps).
+lambda_info_get_inst_varset(Info, Info ^ li_inst_varset).
+lambda_info_get_pred_info(Info, Info ^ li_pred_info).
+lambda_info_get_module_info(Info, Info ^ li_module_info).
+lambda_info_get_recompute_nonlocals(Info, Info ^ li_recompute_nonlocals).
+
+lambda_info_set_varset(VarSet, !Info) :-
+    !Info ^ li_varset := VarSet.
+lambda_info_set_vartypes(VarTypes, !Info) :-
+    !Info ^ li_vartypes := VarTypes.
+lambda_info_set_module_info(ModuleInfo, !Info) :-
+    !Info ^ li_module_info := ModuleInfo.
+lambda_info_set_recompute_nonlocals(Recompute, !Info) :-
+    !Info ^ li_recompute_nonlocals := Recompute.
+
+%-----------------------------------------------------------------------------%
 %
 % This whole section just traverses the module structure
 %
diff --git a/compiler/mercury_to_mercury.m b/compiler/mercury_to_mercury.m
index 477c61c..9450b4c 100644
--- a/compiler/mercury_to_mercury.m
+++ b/compiler/mercury_to_mercury.m
@@ -1357,12 +1357,12 @@ mercury_format_ground_pred_inst_info(Uniq, PredInstInfo, VarSet, !U) :-
         add_string(")", !U)
     ),
     (
-        MaybeArgRegs = yes(ArgRegs),
+        MaybeArgRegs = arg_reg_types(ArgRegs),
         add_string(" /* arg regs: [", !U),
         mercury_format_arg_reg_list(ArgRegs, !U),
         add_string("] */", !U)
     ;
-        MaybeArgRegs = no
+        MaybeArgRegs = arg_reg_types_unset
     ).
 
 :- pred mercury_format_any_pred_inst_info(uniqueness::in, pred_inst_info::in,
@@ -1416,12 +1416,12 @@ mercury_format_any_pred_inst_info(Uniq, PredInstInfo, VarSet, !U) :-
         add_string(")", !U)
     ),
     (
-        MaybeArgRegs = yes(ArgRegs),
+        MaybeArgRegs = arg_reg_types(ArgRegs),
         add_string(" /* arg regs: [", !U),
         mercury_format_arg_reg_list(ArgRegs, !U),
         add_string("] */", !U)
     ;
-        MaybeArgRegs = no
+        MaybeArgRegs = arg_reg_types_unset
     ).
 
 :- pred mercury_format_arg_reg_list(list(ho_arg_reg)::in, U::di, U::uo) is det
diff --git a/compiler/mode_util.m b/compiler/mode_util.m
index 5541bcd..e61fc71 100644
--- a/compiler/mode_util.m
+++ b/compiler/mode_util.m
@@ -856,7 +856,8 @@ default_higher_order_func_inst(ModuleInfo, PredArgTypes, PredInstInfo) :-
     list.append(FuncArgModes, [FuncRetMode], PredArgModes0),
     propagate_types_into_mode_list(ModuleInfo, PredArgTypes,
         PredArgModes0, PredArgModes),
-    PredInstInfo = pred_inst_info(pf_function, PredArgModes, no, detism_det).
+    PredInstInfo = pred_inst_info(pf_function, PredArgModes,
+        arg_reg_types_unset, detism_det).
 
 constructors_to_bound_insts(ModuleInfo, Uniq, TypeCtor, Constructors,
         BoundInsts) :-
@@ -1624,7 +1625,7 @@ cons_id_to_shared_inst(ModuleInfo, ConsId, NumArgs) = MaybeInst :-
             unexpected($module, $pred, "list.drop failed")
         ),
         Inst = ground(shared, higher_order(pred_inst_info(PorF, Modes,
-            no, Det))),
+            arg_reg_types_unset, Det))),
         MaybeInst = yes(Inst)
     ;
         ( ConsId = type_ctor_info_const(_, _, _)
diff --git a/compiler/modecheck_goal.m b/compiler/modecheck_goal.m
index bf0eea7..87bc976 100644
--- a/compiler/modecheck_goal.m
+++ b/compiler/modecheck_goal.m
@@ -1323,7 +1323,8 @@ modecheck_goal_generic_call(GenericCall, Args0, Modes0, GoalInfo0, GoalExpr,
         GenericCall = higher_order(PredVar, _, PredOrFunc, _),
         modecheck_higher_order_call(PredOrFunc, PredVar,
             Args0, Args, Modes, Det, ExtraGoals, !ModeInfo),
-        GoalExpr1 = generic_call(GenericCall, Args, Modes, no, Det),
+        GoalExpr1 = generic_call(GenericCall, Args, Modes, arg_reg_types_unset,
+            Det),
         AllArgs0 = [PredVar | Args0],
         AllArgs = [PredVar | Args],
         handle_extra_goals(GoalExpr1, ExtraGoals, GoalInfo0, AllArgs0, AllArgs,
@@ -1347,7 +1348,8 @@ modecheck_goal_generic_call(GenericCall, Args0, Modes0, GoalInfo0, GoalExpr,
             unexpected($module, $pred, "unknown event")
         ),
         modecheck_event_call(Modes, Args0, Args, !ModeInfo),
-        GoalExpr = generic_call(GenericCall, Args, Modes, no, detism_det)
+        GoalExpr = generic_call(GenericCall, Args, Modes, arg_reg_types_unset,
+            detism_det)
     ;
         GenericCall = cast(_CastType),
         (
@@ -1385,7 +1387,8 @@ modecheck_goal_generic_call(GenericCall, Args0, Modes0, GoalInfo0, GoalExpr,
             Modes = Modes0
         ),
         modecheck_builtin_cast(Modes, Args0, Args, Det, ExtraGoals, !ModeInfo),
-        GoalExpr1 = generic_call(GenericCall, Args, Modes, no, Det),
+        GoalExpr1 = generic_call(GenericCall, Args, Modes, arg_reg_types_unset,
+            Det),
         handle_extra_goals(GoalExpr1, ExtraGoals, GoalInfo0, Args0, Args,
             InstMap0, GoalExpr, !ModeInfo)
     ),
diff --git a/compiler/modecheck_unify.m b/compiler/modecheck_unify.m
index 1869be2..72801e4 100644
--- a/compiler/modecheck_unify.m
+++ b/compiler/modecheck_unify.m
@@ -492,7 +492,8 @@ modecheck_unify_lambda(X, PredOrFunc, ArgVars, LambdaModes, LambdaDet,
     mode_info_get_instmap(!.ModeInfo, InstMap0),
     instmap_lookup_var(InstMap0, X, InstOfX),
     InstOfY = ground(unique, higher_order(LambdaPredInfo)),
-    LambdaPredInfo = pred_inst_info(PredOrFunc, LambdaModes, no, LambdaDet),
+    LambdaPredInfo = pred_inst_info(PredOrFunc, LambdaModes,
+        arg_reg_types_unset, LambdaDet),
     (
         abstractly_unify_inst(is_dead, InstOfX, InstOfY, real_unify,
             UnifyInst, _Det, ModuleInfo0, ModuleInfo1)
diff --git a/compiler/polymorphism.m b/compiler/polymorphism.m
index a370dcd..4b0cb9c 100644
--- a/compiler/polymorphism.m
+++ b/compiler/polymorphism.m
@@ -3629,7 +3629,7 @@ expand_class_method_body(hlds_class_proc(PredId, ProcId), !ProcNum,
     BodyGoalExpr = generic_call(
         class_method(TypeClassInfoVar, !.ProcNum,
             class_id(ClassName, InstanceArity), CallId),
-        HeadVars, Modes, no, Detism),
+        HeadVars, Modes, arg_reg_types_unset, Detism),
 
     % Make the goal info for the call.
     set_of_var.list_to_set(HeadVars0, NonLocals),
diff --git a/compiler/post_typecheck.m b/compiler/post_typecheck.m
index 3aef772..8cd3fd0 100644
--- a/compiler/post_typecheck.m
+++ b/compiler/post_typecheck.m
@@ -1054,7 +1054,7 @@ resolve_unify_functor(X0, ConsId0, ArgVars0, Mode0, Unification0, UnifyContext,
         adjust_func_arity(pf_function, Arity, FullArity),
         HOCall = generic_call(
             higher_order(FuncVar, Purity, pf_function, FullArity),
-            ArgVars, Modes, no, Det),
+            ArgVars, Modes, arg_reg_types_unset, Det),
         Goal = hlds_goal(HOCall, GoalInfo0),
         IsPlainUnify = is_not_plain_unify
     ;
diff --git a/compiler/prog_data.m b/compiler/prog_data.m
index 56ebb52..f17e9e0 100644
--- a/compiler/prog_data.m
+++ b/compiler/prog_data.m
@@ -2073,7 +2073,7 @@ get_type_kind(kinded_type(_, Kind)) = Kind.
                                     % of the return value as the last element
                                     % of the list.
 
-                maybe(list(ho_arg_reg)),
+                arg_reg_type_info,
                                     % The register type to use for each of the
                                     % additional arguments of the pred. This
                                     % field is only needed when float registers
@@ -2084,6 +2084,10 @@ get_type_kind(kinded_type(_, Kind)) = Kind.
                                     % function.
             ).
 
+:- type arg_reg_type_info
+    --->    arg_reg_types_unset     % Unneeded or simply unset yet.
+    ;       arg_reg_types(list(ho_arg_reg)).
+
 :- type ho_arg_reg
     --->    ho_arg_reg_r
     ;       ho_arg_reg_f.
diff --git a/compiler/prog_io_util.m b/compiler/prog_io_util.m
index f7015dd..c16b0ab 100644
--- a/compiler/prog_io_util.m
+++ b/compiler/prog_io_util.m
@@ -543,7 +543,8 @@ convert_mode(AllowConstrainedInstVar, Term, Mode) :-
         DetTerm = term.functor(term.atom(DetString), [], _),
         standard_det(DetString, Detism),
         convert_mode_list(AllowConstrainedInstVar, ArgModesTerms, ArgModes),
-        PredInstInfo = pred_inst_info(pf_predicate, ArgModes, no, Detism),
+        PredInstInfo = pred_inst_info(pf_predicate, ArgModes,
+            arg_reg_types_unset, Detism),
         Inst = ground(shared, higher_order(PredInstInfo)),
         Mode = (Inst -> Inst)
     ;
@@ -564,7 +565,8 @@ convert_mode(AllowConstrainedInstVar, Term, Mode) :-
         convert_mode_list(AllowConstrainedInstVar, ArgModesTerms, ArgModes0),
         convert_mode(AllowConstrainedInstVar, RetModeTerm, RetMode),
         list.append(ArgModes0, [RetMode], ArgModes),
-        FuncInstInfo = pred_inst_info(pf_function, ArgModes, no, Detism),
+        FuncInstInfo = pred_inst_info(pf_function, ArgModes,
+            arg_reg_types_unset, Detism),
         Inst = ground(shared, higher_order(FuncInstInfo)),
         Mode = (Inst -> Inst)
     ;
@@ -582,7 +584,8 @@ convert_mode(AllowConstrainedInstVar, Term, Mode) :-
         DetTerm = term.functor(term.atom(DetString), [], _),
         standard_det(DetString, Detism),
         convert_mode_list(AllowConstrainedInstVar, ArgModesTerms, ArgModes),
-        PredInstInfo = pred_inst_info(pf_predicate, ArgModes, no, Detism),
+        PredInstInfo = pred_inst_info(pf_predicate, ArgModes,
+            arg_reg_types_unset, Detism),
         Inst = any(shared, higher_order(PredInstInfo)),
         Mode = (Inst -> Inst)
     ;
@@ -603,7 +606,8 @@ convert_mode(AllowConstrainedInstVar, Term, Mode) :-
         convert_mode_list(AllowConstrainedInstVar, ArgModesTerms, ArgModes0),
         convert_mode(AllowConstrainedInstVar, RetModeTerm, RetMode),
         list.append(ArgModes0, [RetMode], ArgModes),
-        FuncInstInfo = pred_inst_info(pf_function, ArgModes, no, Detism),
+        FuncInstInfo = pred_inst_info(pf_function, ArgModes,
+            arg_reg_types_unset, Detism),
         Inst = any(shared, higher_order(FuncInstInfo)),
         Mode = (Inst -> Inst)
     ;
@@ -641,7 +645,8 @@ convert_inst(AllowConstrainedInstVar, Term, Result) :-
         DetTerm = term.functor(term.atom(DetString), [], _),
         standard_det(DetString, Detism),
         convert_mode_list(AllowConstrainedInstVar, ArgModesTerm, ArgModes),
-        PredInst = pred_inst_info(pf_predicate, ArgModes, no, Detism),
+        PredInst = pred_inst_info(pf_predicate, ArgModes,
+            arg_reg_types_unset, Detism),
         Result = ground(shared, higher_order(PredInst))
     ;
         % The syntax for a ground higher-order func inst is
@@ -660,7 +665,8 @@ convert_inst(AllowConstrainedInstVar, Term, Result) :-
         convert_mode_list(AllowConstrainedInstVar, ArgModesTerm, ArgModes0),
         convert_mode(AllowConstrainedInstVar, RetModeTerm, RetMode),
         list.append(ArgModes0, [RetMode], ArgModes),
-        FuncInst = pred_inst_info(pf_function, ArgModes, no, Detism),
+        FuncInst = pred_inst_info(pf_function, ArgModes,
+            arg_reg_types_unset, Detism),
         Result = ground(shared, higher_order(FuncInst))
     ;
         % The syntax for an `any' higher-order pred inst is
@@ -676,7 +682,8 @@ convert_inst(AllowConstrainedInstVar, Term, Result) :-
         DetTerm = term.functor(term.atom(DetString), [], _),
         standard_det(DetString, Detism),
         convert_mode_list(AllowConstrainedInstVar, ArgModesTerm, ArgModes),
-        PredInst = pred_inst_info(pf_predicate, ArgModes, no, Detism),
+        PredInst = pred_inst_info(pf_predicate, ArgModes,
+            arg_reg_types_unset, Detism),
         Result = any(shared, higher_order(PredInst))
     ;
         % The syntax for an `any' higher-order func inst is
@@ -695,7 +702,8 @@ convert_inst(AllowConstrainedInstVar, Term, Result) :-
         convert_mode_list(AllowConstrainedInstVar, ArgModesTerm, ArgModes0),
         convert_mode(AllowConstrainedInstVar, RetModeTerm, RetMode),
         list.append(ArgModes0, [RetMode], ArgModes),
-        FuncInst = pred_inst_info(pf_function, ArgModes, no, Detism),
+        FuncInst = pred_inst_info(pf_function, ArgModes,
+            arg_reg_types_unset, Detism),
         Result = any(shared, higher_order(FuncInst))
 
     ; Name = "bound", Args0 = [Disj] ->
diff --git a/compiler/purity.m b/compiler/purity.m
index 016f65d..d035946 100644
--- a/compiler/purity.m
+++ b/compiler/purity.m
@@ -517,7 +517,8 @@ compute_expr_purity(GoalExpr0, GoalExpr, GoalInfo, Purity, ContainsTrace,
                 ArgVars = [InputArg, OutputArg]
             ->
                 GoalExpr = generic_call(cast(unsafe_type_cast),
-                    [InputArg, OutputArg], [in_mode, out_mode], no, detism_det)
+                    [InputArg, OutputArg], [in_mode, out_mode],
+                    arg_reg_types_unset, detism_det)
             ;
                 GoalExpr = plain_call(PredId, ProcId, ArgVars, Status,
                     MaybeUnifyContext, SymName)
diff --git a/compiler/stm_expand.m b/compiler/stm_expand.m
index 0c8c156..1a6139f 100644
--- a/compiler/stm_expand.m
+++ b/compiler/stm_expand.m
@@ -2278,7 +2278,7 @@ create_closure(PredProcID, Args, ArgTypes, ArgModes, ClosureVar,
 
     ClosureAssignInstmapDeltaList = assoc_list.from_corresponding_lists(
         [ClosureVar], [ground(shared, higher_order(pred_inst_info(
-        pf_predicate, ArgModes, no, detism_det)))]),
+        pf_predicate, ArgModes, arg_reg_types_unset, detism_det)))]),
     ClosureAssignInstmapDelta =
         instmap_delta_from_assoc_list(ClosureAssignInstmapDeltaList),
 
diff --git a/compiler/unique_modes.m b/compiler/unique_modes.m
index 16f92c8..53d1a2e 100644
--- a/compiler/unique_modes.m
+++ b/compiler/unique_modes.m
@@ -577,7 +577,7 @@ unique_modes_check_goal_scope(Reason, SubGoal0, GoalInfo0, GoalExpr,
     ).
 
 :- pred unique_modes_check_goal_generic_call(generic_call::in,
-    list(prog_var)::in, list(mer_mode)::in, maybe(list(ho_arg_reg))::in,
+    list(prog_var)::in, list(mer_mode)::in, arg_reg_type_info::in,
     determinism::in, hlds_goal_expr::out, mode_info::in, mode_info::out)
     is det.
 
diff --git a/runtime/mercury_ho_call.c b/runtime/mercury_ho_call.c
index a2e517e..f528925 100644
--- a/runtime/mercury_ho_call.c
+++ b/runtime/mercury_ho_call.c
@@ -334,7 +334,7 @@ static  MR_Word MR_compare_closures_representation(MR_Closure *x,
 ** returned in registers MR_r1, MR_r2, etc for det and nondet calls or
 ** registers MR_r2, MR_r3, etc for semidet calls.
 **
-** When float registers are in effect, float input arguments are passed
+** When float registers are enabled, float input arguments are passed
 ** in MR_f1, MR_f2, etc. Float output arguments are returned in registers
 ** MR_f1, MR_f2, etc.
 **

--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list