[m-rev.] for review: fix mantis bug 570
Peter Wang
novalazy at gmail.com
Thu Dec 14 12:01:46 AEDT 2023
On Wed, 13 Dec 2023 23:43:24 +1100 "Zoltan Somogyi" <zoltan.somogyi at runbox.com> wrote:
> Fix a bug in merging successive switches.
> diff --git a/compiler/simplify_goal_conj.m b/compiler/simplify_goal_conj.m
> index 725f0680e..747a083dc 100644
> --- a/compiler/simplify_goal_conj.m
> +++ b/compiler/simplify_goal_conj.m
...
> @@ -660,13 +706,67 @@ build_maps_second_switch([Case | Cases], CurCaseNum, FirstSwitchConsIdMap,
>
> build_maps_second_switch_cons_id(FirstSwitchConsIdMap, SecondSwitchCaseNum,
> ConsId, !CasesConsIdsMap) :-
> - map.lookup(FirstSwitchConsIdMap, ConsId, FirstSwitchCaseNum),
> - CaseNums = {FirstSwitchCaseNum, SecondSwitchCaseNum},
> - ( if map.search(!.CasesConsIdsMap, CaseNums, OldConsIds) then
> - NewConsIds = one_or_more.cons(ConsId, OldConsIds),
> - map.det_update(CaseNums, NewConsIds, !CasesConsIdsMap)
> + ( if map.search(FirstSwitchConsIdMap, ConsId, FirstSwitchCaseNum) then
> + CaseNums = {FirstSwitchCaseNum, SecondSwitchCaseNum},
> + ( if map.search(!.CasesConsIdsMap, CaseNums, OldConsIds) then
> + NewConsIds = one_or_more.cons(ConsId, OldConsIds),
> + map.det_update(CaseNums, NewConsIds, !CasesConsIdsMap)
> + else
> + map.det_insert(CaseNums, one_or_more(ConsId, []), !CasesConsIdsMap)
> + )
> else
> - map.det_insert(CaseNums, one_or_more(ConsId, []), !CasesConsIdsMap)
> + % This cons_id exists in the first switch, but not in the second.
It should be the other way around.
> + % This means one of two things.
> + %
> + % The first possibility is that the first switch is a can_fail switch.
> + % In such a situation, if the value of the switched-on variable
> + % is ConsId, then execution cannot reach the end of the first switch.
> + % Mode analysis will notice this fact before the compiler even
> + % discovers that the first switch *is* a switch, when it is still
> + % a disjunction. It will generate a warning about the unification
> + % of the same switched-on variable with ConsId in the disjunction
> + % that would turn into the second switch, and then delete that
> + % unification. So when switch detection gets around to that
> + % disjunction, it won't have a unification with ConsId to make
> + % ConsId one of the cons_ids of a switch arm. This means if execution
> + % gets here, then this possibility cannot actually have happened.
> + %
> + % For an example of this, have a look at the HLDS dumps of
> + % tests/hard_coded/bug570_can_fail.m from just before and just after
> + % the mode checking pass.
> + %
> + % The second possibility is that the first switch is a cannot_fail
> + % switch, but the inst of the switched-on variable at its start
> + % implies that the switched-on variable *cannot* be bound to ConsId
> + % there. Again, if the user writes code like this, the compiler will
> + % notice that the unification of the switched-on variable with ConsId
> + % in the disjunction that would turn into the second switch cannot
> + % succeed, generate a warning, and then delete that unification.
> + % This again would mean that execution cannot get here.
> + %
> + % However, there is a way in which execution *can* get here:
> + % if the code sequence containing the two switches, the first
> + % not having a ConsId arm but the second having such an arm,
> + % is constructed internally by the compiler *after* the mode analysis
> + % pass. This happens in tests/hard_coded/bug570, where this
> + % construction is done by the deforestation pass, which then
> + % invokes simplification on its output.
> + %
> + % The map.search above used to a map.lookup, but that test case showed
used to be
> + % that it must be a map.search. The make_headers predicate in
> + % bug570.m consists of three successive switches on the same variable,
> + % Prepare, all of which handle all the function symbols of Prepare's
> + % type. Deforestation moves copies of those switches into each arm
> + % of the previous switch. In their new positions in the arms of the
> + % first switch, some arms of the copied second switch become
> + % unreachable, and are pruned away. Mantis bug #570 happened when
> + % deforestation tried to move copies of the third switch, which had
> + % an arm for Prepare = prepare_edit, into each arm of the merged
> + % first/second switch, one of which occurred in a context in which
> + % Prepare could *not* be bound to prepare_edit, because it was derived
> + % from the arm of the first switch on Prepare which was *not*
> + % prepare_edit.
> + true
> ).
That's fine otherwise, thanks.
Peter
More information about the reviews
mailing list