% This code is a cut down version of merge_key_ranges_2 in rl_key.m.
% It is a regression test; the 21 June 2004 version of the compiler got
% a compiler abort when compiling this code with deep profiling enabled.
%
% The problem had several causes that had all to be present.
%
% 1. The inlined code of less_or_equal contains a call. Deep profiling inserts
%    prepare_for_normal_call before that call, making it impure.
%
% 2. The body of less_or_equal isn't a complete switch in any argument, so
%    switch detection leaves a disjunction in it.
%
% 3. The inlining of less_or_equal in merge_key_ranges_2 *after* the initial
%    semantic checks causes the second run of simplify to modify the code,
%    removing the redundant check of the second argument of less_or_equal in
%    the second clause. This causes simplify to rerun determinism analysis.
%    (If the inlining is done in the source code, the simplification will have
%    been done in the first run of simplify, and simplify won't find any
%    improvements to do after the deep profiling transformation.)
%
% 4. When determinism analysis looks at the inlined disjunction, it disregards
%    the fact that it has no outputs because it is impure.
%
% The original symptom required -O5 to inline the relevant call in rl_key.m.
% We mark the predicate with pragma inline to force the problem, if present,
% to appear also at lower optimization levels.

:- module impure_detism.

:- interface.

:- import_module bool, list.

:- type bounding_tuple
	--->	infinity
	;	bound(list(int)).

:- pred merge_key_ranges_2(bounding_tuple::in,
	bounding_tuple::in, bool::out) is det.

:- implementation.

:- import_module std_util.

:- type upper_lower
	--->	upper
	;	lower.

merge_key_ranges_2(Lower1, Upper2, IsNeeded) :-
	( less_or_equal(Lower1, upper, Upper2) ->
		IsNeeded = no
	;
		IsNeeded = yes
	).

:- pragma inline(less_or_equal/3).

:- pred less_or_equal(bounding_tuple::in,
	upper_lower::in, bounding_tuple::in) is semidet.

less_or_equal(infinity, _, _).
less_or_equal(_, upper, infinity).
less_or_equal(bound(_), _, bound(_)) :-
	semidet_succeed.
