[m-rev.] for review: make private_builtin.store_at_ref impure
Peter Wang
novalazy at gmail.com
Mon Sep 8 17:55:55 AEST 2008
These would be committed over some period of time.
=============================================================================
Branches: main
`private_builtin.store_at_ref' is currently pure but should be impure.
There would be bootstrapping problems if we just made it impure, as it is
a builtin that the compiler needs to recognise. Instead, we will add a
new predicate `store_at_ref_impure' to take its place. This needs to be
done in three steps:
1. Get the compiler to recognise `store_at_ref_impure' as a builtin.
2. After step 1 has bootstrapped, add the predicate declaration for
`store_at_ref_impure'. Change generated code to call it.
3. After step 2 has bootstrapped, delete `store_at_ref'. The stage1
compiler in step 2 could be built by a compiler that still generates
references to `store_at_ref' so we couldn't just delete it at step 2.
This is also part of fixing Mantis bug #42. The bug there is that we
didn't generate a valid definition for `store_at_ref'; the procedure
existed but had an empty body. Calls to `store_at_ref' introduced by the
LCMC optimisation are normally replaced by inline code, but with
`--no-inlining-builtins' we would call the procedure, which did nothing.
compiler/builtin_ops.m:
Add a builtin translation for `store_at_ref_impure'.
library/private_builtin.m:
Add the declaration of `store_at_ref_impure', commented out for now.
compiler/add_pred.m:
Generate non-no-op procedures for `private_builtin.store_at_ref'
and `private_builtin.store_at_ref_impure'.
compiler/term_constr_initial.m:
mdbcomp/program_representation.m:
Handle `store_at_ref_impure' in a couple of spots.
compiler/options.m:
Add a option that we can use to check if the bootstrap compiler
recognises `store_at_ref_impure'.
diff --git a/compiler/add_pred.m b/compiler/add_pred.m
index fe2309c..14d4259 100644
--- a/compiler/add_pred.m
+++ b/compiler/add_pred.m
@@ -240,13 +240,10 @@ add_builtin(PredId, Types, !PredInfo) :-
goal_info_init(Context, GoalInfo0),
NonLocals = proc_arg_vector_to_set(HeadVars),
- goal_info_set_nonlocals(NonLocals, GoalInfo0, GoalInfo),
+ goal_info_set_nonlocals(NonLocals, GoalInfo0, GoalInfo1),
(
Module = mercury_private_builtin_module,
(
- Name = "store_at_ref",
- StubPrime = no
- ;
( Name = "builtin_compound_eq"
; Name = "builtin_compound_lt"
),
@@ -254,6 +251,7 @@ add_builtin(PredId, Types, !PredInfo) :-
)
->
GoalExpr = conj(plain_conj, []),
+ GoalInfo = GoalInfo1,
ExtraVars = [],
ExtraTypes = [],
VarSet = VarSet0,
@@ -292,6 +290,7 @@ add_builtin(PredId, Types, !PredInfo) :-
Reason = promise_purity(dont_make_implicit_promises, purity_semipure),
GoalExpr = scope(Reason, ConjGoal),
+ GoalInfo = GoalInfo1,
Stub = no
;
Module = mercury_private_builtin_module,
@@ -301,6 +300,7 @@ add_builtin(PredId, Types, !PredInfo) :-
ConjGoal = hlds_goal(ConjExpr, GoalInfo),
Reason = promise_purity(dont_make_implicit_promises, purity_impure),
GoalExpr = scope(Reason, ConjGoal),
+ GoalInfo = GoalInfo1,
ExtraVars = [],
ExtraTypes = [],
VarSet = VarSet0,
@@ -314,6 +314,8 @@ add_builtin(PredId, Types, !PredInfo) :-
% XXX ARGVEC
GoalExpr = plain_call(PredId, ModeId, HeadVarList, inline_builtin,
MaybeUnifyContext, SymName),
+ pred_info_get_purity(!.PredInfo, Purity),
+ goal_info_set_purity(Purity, GoalInfo1, GoalInfo),
ExtraVars = [],
ExtraTypes = [],
VarSet = VarSet0,
diff --git a/compiler/builtin_ops.m b/compiler/builtin_ops.m
index 82d099b..4080468 100644
--- a/compiler/builtin_ops.m
+++ b/compiler/builtin_ops.m
@@ -181,6 +181,8 @@ builtin_translation("private_builtin", "trace_set_io_state", 0, [_X],
builtin_translation("private_builtin", "store_at_ref", 0, [X, Y],
ref_assign(X, Y)).
+builtin_translation("private_builtin", "store_at_ref_impure", 0, [X, Y],
+ ref_assign(X, Y)).
% Note that the code we generate for unsafe_type_cast is not type-correct.
% Back-ends that require type-correct intermediate code (e.g. the MLDS
diff --git a/compiler/options.m b/compiler/options.m
index cdef083..028c6c3 100644
--- a/compiler/options.m
+++ b/compiler/options.m
@@ -2615,6 +2615,8 @@ long_option("foreign-enum-switch-fix",
compiler_sufficiently_recent).
long_option("failing-disjunct-in-switch-dup-fix",
compiler_sufficiently_recent).
+long_option("store-at-ref-impure-2008-09-04",
+ compiler_sufficiently_recent).
long_option("experiment", experiment).
long_option("feedback-file", feedback_file).
diff --git a/compiler/term_constr_initial.m b/compiler/term_constr_initial.m
index 2494e08..77cf632 100644
--- a/compiler/term_constr_initial.m
+++ b/compiler/term_constr_initial.m
@@ -558,6 +558,7 @@ process_no_type_info_builtin(PredName, HeadVars, SizeVarMap) = Constraints :-
ConstraintsPrime = [make_vars_eq_constraint(SizeVar1, SizeVar2)]
;
( PredName = "store_at_ref"
+ ; PredName = "store_at_ref_impure"
; PredName = "builtin_compound_eq"
; PredName = "builtin_compound_lt"
)
diff --git a/library/private_builtin.m b/library/private_builtin.m
index d6dedd7..3c9c3ec 100644
--- a/library/private_builtin.m
+++ b/library/private_builtin.m
@@ -1450,6 +1450,7 @@ const MR_FA_TypeInfo_Struct1 ML_type_info_for_list_of_pseudo_type_info = {
% will happen if this is used in programs.
%
:- pred store_at_ref(store_at_ref_type(T)::in, T::in) is det.
+% :- impure pred store_at_ref_impure(store_at_ref_type(T)::in, T::in) is det.
% This type should be used only by the program transformation that
% introduces calls to store_at_ref. Any other use is will cause bad things
diff --git a/mdbcomp/program_representation.m b/mdbcomp/program_representation.m
index e4fa56c..7e533a4 100644
--- a/mdbcomp/program_representation.m
+++ b/mdbcomp/program_representation.m
@@ -1558,6 +1558,7 @@ no_type_info_builtin(ModuleName, PredName, Arity) :-
is semidet.
no_type_info_builtin_2(private_builtin, "store_at_ref", 2).
+no_type_info_builtin_2(private_builtin, "store_at_ref_impure", 2).
no_type_info_builtin_2(private_builtin, "unsafe_type_cast", 2).
no_type_info_builtin_2(builtin, "unsafe_promise_unique", 2).
no_type_info_builtin_2(private_builtin,
=============================================================================
Branches: main
Step 2 in replacing `private_builtin.store_at_ref' by an impure
`private_builtin.store_at_ref_impure' predicate.
configure.in:
Check that the bootstrap compiler recognises `store_at_ref_impure'.
library/private_builtin.m:
Add the predicate declaration for `store_at_ref_impure'.
compiler/lco.m:
Make generated code call `store_at_ref_impure'.
tests/hard_coded/Mercury.options:
tests/hard_coded/Mmakefile:
tests/hard_coded/lco_no_inline.exp:
tests/hard_coded/lco_no_inline.m:
Add test case for Mantis bug #42.
diff --git a/compiler/lco.m b/compiler/lco.m
index a8a9918..508eb3a 100644
--- a/compiler/lco.m
+++ b/compiler/lco.m
@@ -1021,17 +1021,9 @@ is_grounding(ModuleInfo, InstMap0, InstMap, Var - _AddrVar) :-
hlds_goal::out) is det.
make_store_goal(ModuleInfo, Var - AddrVar, Goal) :-
- generate_simple_call(mercury_private_builtin_module, "store_at_ref",
- pf_predicate, only_mode, detism_det, purity_pure, [AddrVar, Var],
- [], [], ModuleInfo, term.context_init, Goal0),
- %
- % XXX the following hack is used to stop simplify from trying to
- % optimise the introduced call away. store_at_ref/2 should
- % really be declared to be impure.
- %
- Goal0 = hlds_goal(GoalExpr, GoalInfo0),
- goal_info_set_purity(purity_impure, GoalInfo0, GoalInfo),
- Goal = hlds_goal(GoalExpr, GoalInfo).
+ generate_simple_call(mercury_private_builtin_module, "store_at_ref_impure",
+ pf_predicate, only_mode, detism_det, purity_impure, [AddrVar, Var],
+ [], [], ModuleInfo, term.context_init, Goal).
%-----------------------------------------------------------------------------%
diff --git a/configure.in b/configure.in
index e2ed501..b490fa0 100644
--- a/configure.in
+++ b/configure.in
@@ -347,6 +347,7 @@ EOF
--no-no-det-warning-compound-compare-2007-07-17 \
--foreign-enum-switch-fix \
--no-ssdb \
+ --store-at-ref-impure-2008-09-04 \
</dev/null >&AC_FD_CC 2>&1 &&
test "`./conftest 2>&1 | tr -d '\015'`" = "Hello, world" &&
# Test for the --record-term-sizes-as-words option.
diff --git a/library/private_builtin.m b/library/private_builtin.m
index 3c9c3ec..73f1e2f 100644
--- a/library/private_builtin.m
+++ b/library/private_builtin.m
@@ -1446,11 +1446,15 @@ const MR_FA_TypeInfo_Struct1 ML_type_info_for_list_of_pseudo_type_info = {
:- pred unsafe_type_cast(T1::in, T2::out) is det.
- % store_at_ref/2 is used internally by the compiler. Bad things
+ % store_at_ref_impure/2 is used internally by the compiler. Bad things
% will happen if this is used in programs.
%
+:- impure pred store_at_ref_impure(store_at_ref_type(T)::in, T::in) is det.
+
+ % This is deprecated. The compiler should now generate calls to
+ % store_at_ref_impure.
+ %
:- pred store_at_ref(store_at_ref_type(T)::in, T::in) is det.
-% :- impure pred store_at_ref_impure(store_at_ref_type(T)::in, T::in) is det.
% This type should be used only by the program transformation that
% introduces calls to store_at_ref. Any other use is will cause bad things
diff --git a/tests/hard_coded/Mercury.options b/tests/hard_coded/Mercury.options
index f08bc36..9b84734 100644
--- a/tests/hard_coded/Mercury.options
+++ b/tests/hard_coded/Mercury.options
@@ -38,6 +38,7 @@ MCFLAGS-intermod_type_qual = --intermodule-optimization
MCFLAGS-intermod_type_qual2 = --intermodule-optimization
MCFLAGS-intermod_multimode = --intermodule-optimization
MCFLAGS-intermod_multimode_main = --intermodule-optimization
+MCFLAGS-lco_no_inline = --optimize-constructor-last-call --no-inline-builtins
MCFLAGS-reuse_ho = --ctgc --no-optimise-higher-order
MCFLAGS-sharing_comb = --ctgc --structure-sharing-widening 2
MCFLAGS-uncond_reuse = --ctgc
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index df68298..b79487a 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -137,6 +137,7 @@ ORDINARY_PROGS= \
intermod_type_qual \
intermod_unused_args \
join_list \
+ lco_no_inline \
list_series_int \
loop_inv_test \
loop_inv_test1 \
diff --git a/tests/hard_coded/lco_no_inline.exp b/tests/hard_coded/lco_no_inline.exp
new file mode 100644
index 0000000..4cb83cb
--- /dev/null
+++ b/tests/hard_coded/lco_no_inline.exp
@@ -0,0 +1 @@
+["one", "two", "two"]
diff --git a/tests/hard_coded/lco_no_inline.m b/tests/hard_coded/lco_no_inline.m
new file mode 100644
index 0000000..f24f380
--- /dev/null
+++ b/tests/hard_coded/lco_no_inline.m
@@ -0,0 +1,42 @@
+% Regression test. There was no out-of-line definition of
+% private_builtin.store_at_ref which is required for
+% --optimise-constructor-last-call and --no-inline-builtins to work together.
+
+%-----------------------------------------------------------------------------%
+
+:- module lco_no_inline.
+:- interface.
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module int.
+:- import_module list.
+:- import_module pair.
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+ AL = ["one" - 1, "two" - 2],
+ to_list_2(AL, L),
+ io.write(L, !IO),
+ io.nl(!IO).
+
+:- pred to_list_2(list(pair(string, int))::in, list(string)::out) is det.
+
+to_list_2([], []).
+to_list_2([X - Int | Xs], Out) :-
+ ( Int =< 0 ->
+ to_list_2(Xs, Out)
+ ;
+ NewInt = Int - 1,
+ to_list_2([X - NewInt | Xs], Out0),
+ Out = [X | Out0]
+ ).
+
+%-----------------------------------------------------------------------------%
=============================================================================
Branches: main
Step 3 in replacing `private_builtin.store_at_ref' by an impure
`private_builtin.store_at_ref_impure' predicate.
compiler/builtin_ops.m:
compiler/term_constr_initial.m:
library/private_builtin.m:
mdbcomp/program_representation.m:
Delete references to `private_builtin.store_at_ref'.
diff --git a/compiler/builtin_ops.m b/compiler/builtin_ops.m
index 4080468..714295a 100644
--- a/compiler/builtin_ops.m
+++ b/compiler/builtin_ops.m
@@ -179,8 +179,6 @@ builtin_translation("private_builtin", "trace_get_io_state", 0, [X],
builtin_translation("private_builtin", "trace_set_io_state", 0, [_X],
noop([])).
-builtin_translation("private_builtin", "store_at_ref", 0, [X, Y],
- ref_assign(X, Y)).
builtin_translation("private_builtin", "store_at_ref_impure", 0, [X, Y],
ref_assign(X, Y)).
diff --git a/compiler/term_constr_initial.m b/compiler/term_constr_initial.m
index 77cf632..faf0dfc 100644
--- a/compiler/term_constr_initial.m
+++ b/compiler/term_constr_initial.m
@@ -557,8 +557,7 @@ process_no_type_info_builtin(PredName, HeadVars, SizeVarMap) = Constraints :-
SizeVar2 = prog_var_to_size_var(SizeVarMap, HVar2),
ConstraintsPrime = [make_vars_eq_constraint(SizeVar1, SizeVar2)]
;
- ( PredName = "store_at_ref"
- ; PredName = "store_at_ref_impure"
+ ( PredName = "store_at_ref_impure"
; PredName = "builtin_compound_eq"
; PredName = "builtin_compound_lt"
)
diff --git a/library/private_builtin.m b/library/private_builtin.m
index 73f1e2f..5ae56de 100644
--- a/library/private_builtin.m
+++ b/library/private_builtin.m
@@ -1451,14 +1451,9 @@ const MR_FA_TypeInfo_Struct1 ML_type_info_for_list_of_pseudo_type_info = {
%
:- impure pred store_at_ref_impure(store_at_ref_type(T)::in, T::in) is det.
- % This is deprecated. The compiler should now generate calls to
- % store_at_ref_impure.
- %
-:- pred store_at_ref(store_at_ref_type(T)::in, T::in) is det.
-
% This type should be used only by the program transformation that
- % introduces calls to store_at_ref. Any other use is will cause bad things
- % to happen.
+ % introduces calls to store_at_ref_impure. Any other use will cause bad
+ % things to happen.
:- type store_at_ref_type(T)
---> store_at_ref_type(int).
diff --git a/mdbcomp/program_representation.m b/mdbcomp/program_representation.m
index 7e533a4..419c451 100644
--- a/mdbcomp/program_representation.m
+++ b/mdbcomp/program_representation.m
@@ -1557,7 +1557,6 @@ no_type_info_builtin(ModuleName, PredName, Arity) :-
:- pred no_type_info_builtin_2(builtin_mod::out, string::in, int::in)
is semidet.
-no_type_info_builtin_2(private_builtin, "store_at_ref", 2).
no_type_info_builtin_2(private_builtin, "store_at_ref_impure", 2).
no_type_info_builtin_2(private_builtin, "unsafe_type_cast", 2).
no_type_info_builtin_2(builtin, "unsafe_promise_unique", 2).
--------------------------------------------------------------------------
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