mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-12 04:14:06 +00:00
In two places, we were using (pairs of) nondet calls to list.member
Estimated hours taken: 2 Branches: main compiler/inst_util.m: In two places, we were using (pairs of) nondet calls to list.member to iterate over all the insts included in a list of bound insts. For programs that build large terms, there could be many such insts, so many that they exhaust the nondet stack in low level C grades. This diff replaces that code with code to explicit traverse the lists of bound insts with det code. The new code is tail recursive to avoid simply transferring the problem to the det stack. I have also changed the code to use switches in det functions (which are checked for completeness) instead of switches in semidet predicates (which are not). I have also changed the code to use sets of inst_names instead of full insts to test for infinite recursion. The set of insts only ever contained insts that were wrappers around inst_names anyway.
This commit is contained in:
@@ -1761,58 +1761,92 @@ bound_inst_list_merge(Xs, Ys, MaybeType, Zs, !ModuleInfo) :-
|
||||
|
||||
inst_contains_nonstandard_func_mode(ModuleInfo, Inst) :-
|
||||
set.init(Expansions0),
|
||||
inst_contains_nonstandard_func_mode_2(ModuleInfo, Inst, Expansions0).
|
||||
inst_contains_nonstandard_func_mode_2(ModuleInfo, Inst, Expansions0) = yes.
|
||||
|
||||
:- pred inst_contains_nonstandard_func_mode_2(module_info::in, mer_inst::in,
|
||||
set(mer_inst)::in) is semidet.
|
||||
:- func inst_contains_nonstandard_func_mode_2(module_info, mer_inst,
|
||||
set(inst_name)) = bool.
|
||||
|
||||
inst_contains_nonstandard_func_mode_2(ModuleInfo, ground(_, HOInstInfo),
|
||||
_Expansions) :-
|
||||
ho_inst_info_is_nonstandard_func_mode(ModuleInfo, HOInstInfo).
|
||||
inst_contains_nonstandard_func_mode_2(ModuleInfo, bound(_, BoundInsts),
|
||||
Expansions) :-
|
||||
list.member(bound_functor(_, Insts), BoundInsts),
|
||||
list.member(Inst, Insts),
|
||||
inst_contains_nonstandard_func_mode_2(ModuleInfo, Inst, Expansions).
|
||||
inst_contains_nonstandard_func_mode_2(_, inst_var(_), _) :-
|
||||
unexpected($module, $pred, "uninstantiated inst parameter").
|
||||
inst_contains_nonstandard_func_mode_2(ModuleInfo, Inst, Expansions0) :-
|
||||
Inst = defined_inst(InstName),
|
||||
\+ set.member(Inst, Expansions0),
|
||||
set.insert(Inst, Expansions0, Expansions1),
|
||||
inst_lookup(ModuleInfo, InstName, Inst2),
|
||||
inst_contains_nonstandard_func_mode_2(ModuleInfo, Inst2, Expansions1).
|
||||
inst_contains_nonstandard_func_mode_2(ModuleInfo, Inst, !.Expansions)
|
||||
= ContainsNonstd :-
|
||||
(
|
||||
Inst = ground(_, HOInstInfo),
|
||||
( ho_inst_info_is_nonstandard_func_mode(ModuleInfo, HOInstInfo) ->
|
||||
ContainsNonstd = yes
|
||||
;
|
||||
ContainsNonstd = no
|
||||
)
|
||||
;
|
||||
Inst = bound(_, BoundInsts),
|
||||
ContainsNonstd = bound_inst_list_contains_nonstandard_func_mode(
|
||||
ModuleInfo, BoundInsts, !.Expansions)
|
||||
;
|
||||
Inst = inst_var(_),
|
||||
unexpected($module, $pred, "uninstantiated inst parameter")
|
||||
;
|
||||
Inst = defined_inst(InstName),
|
||||
( set.member(InstName, !.Expansions) ->
|
||||
ContainsNonstd = no
|
||||
;
|
||||
set.insert(InstName, !Expansions),
|
||||
inst_lookup(ModuleInfo, InstName, SubInst),
|
||||
ContainsNonstd = inst_contains_nonstandard_func_mode_2(ModuleInfo,
|
||||
SubInst, !.Expansions)
|
||||
)
|
||||
;
|
||||
Inst = constrained_inst_vars(_, SubInst),
|
||||
% ZZZ We used to fail for this case (the equivalent of returning `no').
|
||||
ContainsNonstd = inst_contains_nonstandard_func_mode_2(ModuleInfo,
|
||||
SubInst, !.Expansions)
|
||||
;
|
||||
( Inst = free
|
||||
; Inst = free(_)
|
||||
; Inst = not_reached
|
||||
; Inst = abstract_inst(_, _)
|
||||
),
|
||||
ContainsNonstd = no
|
||||
;
|
||||
Inst = any(_, _),
|
||||
% XXX This code preserves the old behavior of this predicate,
|
||||
% but it is arguably incorrect, since any/2 insts, like ground/2 insts,
|
||||
% contain a ho_inst_info.
|
||||
ContainsNonstd = no
|
||||
).
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
:- func inst_list_contains_nonstandard_func_mode(module_info, list(mer_inst),
|
||||
set(inst_name)) = bool.
|
||||
|
||||
inst_contains_any(ModuleInfo, Inst) :-
|
||||
set.init(Expansions),
|
||||
inst_contains_any_2(ModuleInfo, Inst, Expansions).
|
||||
inst_list_contains_nonstandard_func_mode(_ModuleInfo, [], _Expansions) = no.
|
||||
inst_list_contains_nonstandard_func_mode(ModuleInfo, [Inst | Insts],
|
||||
Expansions) = ContainsNonstd :-
|
||||
HeadContainsNonstd = inst_contains_nonstandard_func_mode_2(ModuleInfo,
|
||||
Inst, Expansions),
|
||||
(
|
||||
HeadContainsNonstd = yes,
|
||||
ContainsNonstd = yes
|
||||
;
|
||||
HeadContainsNonstd = no,
|
||||
ContainsNonstd = inst_list_contains_nonstandard_func_mode(ModuleInfo,
|
||||
Insts, Expansions)
|
||||
).
|
||||
|
||||
:- pred inst_contains_any_2(module_info::in, (mer_inst)::in,
|
||||
set(inst_name)::in) is semidet.
|
||||
:- func bound_inst_list_contains_nonstandard_func_mode(module_info,
|
||||
list(bound_inst), set(inst_name)) = bool.
|
||||
|
||||
inst_contains_any_2(_ModuleInfo, any(_, _), _Expansions).
|
||||
|
||||
inst_contains_any_2(ModuleInfo, bound(_, BoundInsts), Expansions) :-
|
||||
list.member(bound_functor(_, Insts), BoundInsts),
|
||||
list.member(Inst, Insts),
|
||||
inst_contains_any_2(ModuleInfo, Inst, Expansions).
|
||||
|
||||
inst_contains_any_2(_ModuleInfo, inst_var(_), _Expansions) :-
|
||||
unexpected($module, $pred, "uninstantiated inst parameter").
|
||||
|
||||
inst_contains_any_2(ModuleInfo, defined_inst(InstName), Expansions0) :-
|
||||
\+ set.member(InstName, Expansions0),
|
||||
Expansions = set.insert(Expansions0, InstName),
|
||||
inst_lookup(ModuleInfo, InstName, Inst),
|
||||
inst_contains_any_2(ModuleInfo, Inst, Expansions).
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
|
||||
var_inst_contains_any(ModuleInfo, Instmap, Var) :-
|
||||
instmap_lookup_var(Instmap, Var, Inst),
|
||||
inst_contains_any(ModuleInfo, Inst).
|
||||
bound_inst_list_contains_nonstandard_func_mode(_ModuleInfo, [], _Expansions)
|
||||
= no.
|
||||
bound_inst_list_contains_nonstandard_func_mode(ModuleInfo,
|
||||
[BoundInst | BoundInsts], Expansions) = ContainsNonstd :-
|
||||
BoundInst = bound_functor(_ConsId, ArgInsts),
|
||||
HeadContainsNonstd = inst_list_contains_nonstandard_func_mode(ModuleInfo,
|
||||
ArgInsts, Expansions),
|
||||
(
|
||||
HeadContainsNonstd = yes,
|
||||
ContainsNonstd = yes
|
||||
;
|
||||
HeadContainsNonstd = no,
|
||||
ContainsNonstd = bound_inst_list_contains_nonstandard_func_mode(
|
||||
ModuleInfo, BoundInsts, Expansions)
|
||||
).
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
|
||||
@@ -1835,6 +1869,87 @@ pred_inst_info_standard_func_mode(Arity) = PredInstInfo :-
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
|
||||
inst_contains_any(ModuleInfo, Inst) :-
|
||||
set.init(Expansions),
|
||||
inst_contains_any_2(ModuleInfo, Inst, Expansions) = yes.
|
||||
|
||||
:- func inst_contains_any_2(module_info, mer_inst, set(inst_name)) = bool.
|
||||
|
||||
inst_contains_any_2(ModuleInfo, Inst, !.Expansions) = ContainsAny :-
|
||||
(
|
||||
Inst = any(_, _),
|
||||
ContainsAny = yes
|
||||
;
|
||||
Inst = bound(_, BoundInsts),
|
||||
ContainsAny = bound_inst_list_contains_any(ModuleInfo, BoundInsts,
|
||||
!.Expansions)
|
||||
;
|
||||
Inst = inst_var(_),
|
||||
unexpected($module, $pred, "uninstantiated inst parameter")
|
||||
;
|
||||
Inst = defined_inst(InstName),
|
||||
( set.member(InstName, !.Expansions) ->
|
||||
ContainsAny = no
|
||||
;
|
||||
set.insert(InstName, !Expansions),
|
||||
inst_lookup(ModuleInfo, InstName, SubInst),
|
||||
ContainsAny =
|
||||
inst_contains_any_2(ModuleInfo, SubInst, !.Expansions)
|
||||
)
|
||||
;
|
||||
Inst = constrained_inst_vars(_, SubInst),
|
||||
% ZZZ We used to fail for this case (the equivalent of returning `no').
|
||||
ContainsAny = inst_contains_any_2(ModuleInfo, SubInst, !.Expansions)
|
||||
;
|
||||
( Inst = free
|
||||
; Inst = free(_)
|
||||
; Inst = not_reached
|
||||
; Inst = ground(_, _)
|
||||
; Inst = abstract_inst(_, _)
|
||||
),
|
||||
ContainsAny = no
|
||||
).
|
||||
|
||||
:- func inst_list_contains_any(module_info, list(mer_inst), set(inst_name))
|
||||
= bool.
|
||||
|
||||
inst_list_contains_any(_ModuleInfo, [], _Expansions) = no.
|
||||
inst_list_contains_any(ModuleInfo, [Inst | Insts], Expansions) = ContainsAny :-
|
||||
HeadContainsAny = inst_contains_any_2(ModuleInfo, Inst, Expansions),
|
||||
(
|
||||
HeadContainsAny = yes,
|
||||
ContainsAny = yes
|
||||
;
|
||||
HeadContainsAny = no,
|
||||
ContainsAny = inst_list_contains_any(ModuleInfo, Insts, Expansions)
|
||||
).
|
||||
|
||||
:- func bound_inst_list_contains_any(module_info, list(bound_inst),
|
||||
set(inst_name)) = bool.
|
||||
|
||||
bound_inst_list_contains_any(_ModuleInfo, [], _Expansions) = no.
|
||||
bound_inst_list_contains_any(ModuleInfo, [BoundInst | BoundInsts],
|
||||
Expansions) = ContainsAny :-
|
||||
BoundInst = bound_functor(_ConsId, ArgInsts),
|
||||
HeadContainsAny =
|
||||
inst_list_contains_any(ModuleInfo, ArgInsts, Expansions),
|
||||
(
|
||||
HeadContainsAny = yes,
|
||||
ContainsAny = yes
|
||||
;
|
||||
HeadContainsAny = no,
|
||||
ContainsAny = bound_inst_list_contains_any(ModuleInfo, BoundInsts,
|
||||
Expansions)
|
||||
).
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
|
||||
var_inst_contains_any(ModuleInfo, Instmap, Var) :-
|
||||
instmap_lookup_var(Instmap, Var, Inst),
|
||||
inst_contains_any(ModuleInfo, Inst).
|
||||
|
||||
%-----------------------------------------------------------------------------%
|
||||
|
||||
inst_may_restrict_cons_ids(ModuleInfo, Inst) = MayRestrict :-
|
||||
(
|
||||
Inst = any(_, _),
|
||||
|
||||
Reference in New Issue
Block a user