diff: inlining.m bug fix

Fergus Henderson fjh at hydra.cs.mu.oz.au
Wed Jul 9 18:20:15 AEST 1997


Hi,

Can someone (Andrew? Tom?) please review this one?

compiler/inlining.m:
	When inlining calls, use the goalinfo from the body of
	the callee rather than the goalinfo from the call.
	This avoids some bugs which resulted from mismatches
	between the goal and its goalinfo; for example, the
	old code could lead to nondet unifications, or to calls
	to error/1 that don't have instmap delta going to unreachable.

tests/hard_coded/Mmake:
tests/hard_coded/error_func.m:
tests/hard_coded/error_func.exp:
	Regression test for the above change.

Index: inlining.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/inlining.m,v
retrieving revision 1.66
diff -u -r1.66 inlining.m
--- inlining.m	1997/06/29 23:10:45	1.66
+++ inlining.m	1997/07/09 08:01:22
@@ -364,7 +364,10 @@
 	map__det_update(PredTable0, PredId, PredInfo, PredTable),
 	module_info_set_preds(ModuleInfo0, PredTable, ModuleInfo1),
 
-		% Re-run determinism analysis if we have to.
+		% If the determinism of some sub-goals has changed,
+		% then we re-run determinism analysis, because
+		% propagating the determinism information through
+		% the procedure may lead to more efficient code.
 	( DetChanged = yes,	
 		globals__io_get_globals(Globals, IoState0, IoState),
 		det_infer_proc(PredId, ProcId, ModuleInfo1, ModuleInfo,
@@ -380,41 +383,33 @@
 		inline_info).
 :- mode inlining__inlining_in_goal(in, out, in, out) is det.
 
-inlining__inlining_in_goal(Goal0 - GoalInfo, Goal - GoalInfo) -->
-	inlining__inlining_in_goal_2(Goal0, GoalInfo, Goal).
-
-%-----------------------------------------------------------------------------%
-
-:- pred inlining__inlining_in_goal_2(hlds_goal_expr, hlds_goal_info,
-		hlds_goal_expr, inline_info, inline_info).
-:- mode inlining__inlining_in_goal_2(in, in, out, in, out) is det.
-
-inlining__inlining_in_goal_2(conj(Goals0), _GoalInfo, conj(Goals)) -->
+inlining__inlining_in_goal(conj(Goals0) - GoalInfo, conj(Goals) - GoalInfo) -->
 	inlining__inlining_in_conj(Goals0, Goals).
 
-inlining__inlining_in_goal_2(disj(Goals0, SM), _GoalInfo, disj(Goals, SM)) -->
+inlining__inlining_in_goal(disj(Goals0, SM) - GoalInfo,
+		disj(Goals, SM) - GoalInfo) -->
 	inlining__inlining_in_disj(Goals0, Goals).
 
-inlining__inlining_in_goal_2(switch(Var, Det, Cases0, SM), _GoalInfo,
-		switch(Var, Det, Cases, SM)) -->
+inlining__inlining_in_goal(switch(Var, Det, Cases0, SM) - GoalInfo,
+		switch(Var, Det, Cases, SM) - GoalInfo) -->
 	inlining__inlining_in_cases(Cases0, Cases).
 
-inlining__inlining_in_goal_2(
-		if_then_else(Vars, Cond0, Then0, Else0, SM), _GoalInfo,
-		if_then_else(Vars, Cond, Then, Else, SM)) -->
+inlining__inlining_in_goal(
+		if_then_else(Vars, Cond0, Then0, Else0, SM) - GoalInfo,
+		if_then_else(Vars, Cond, Then, Else, SM) - GoalInfo) -->
 	inlining__inlining_in_goal(Cond0, Cond),
 	inlining__inlining_in_goal(Then0, Then),
 	inlining__inlining_in_goal(Else0, Else).
 
-inlining__inlining_in_goal_2(not(Goal0), _GoalInfo, not(Goal)) -->
+inlining__inlining_in_goal(not(Goal0) - GoalInfo, not(Goal) - GoalInfo) -->
 	inlining__inlining_in_goal(Goal0, Goal).
 
-inlining__inlining_in_goal_2(some(Vars, Goal0), _GoalInfo, some(Vars, Goal)) -->
+inlining__inlining_in_goal(some(Vars, Goal0) - GoalInfo,
+		some(Vars, Goal) - GoalInfo) -->
 	inlining__inlining_in_goal(Goal0, Goal).
 
-inlining__inlining_in_goal_2(
-		call(PredId, ProcId, ArgVars, Builtin, Context, Sym),
-		GoalInfo0, Goal, InlineInfo0, InlineInfo) :-
+inlining__inlining_in_goal(call(PredId, ProcId, ArgVars, Builtin, Context,
+		Sym) - GoalInfo0, Goal - GoalInfo, InlineInfo0, InlineInfo) :-
 
 	InlineInfo0 = inline_info(VarThresh, InlinedProcs, ModuleInfo,
 		VarSet0, VarTypes0, TypeVarSet0, TypeInfoVarMap0,
@@ -493,15 +488,15 @@
 			VarTypes0, Subn0, CalleeVarTypes, CalleeVarset,
 				VarSet, VarTypes, Subn),
 		goal_util__must_rename_vars_in_goal(CalledGoal, Subn,
-			Goal - GoalInfo1),
+			Goal - GoalInfo),
 
 			% If the inferred determinism of the called
 			% goal differs from the declared determinism,
-			% flag that we must re-run determinism checking
+			% flag that we should re-run determinism analysis
 			% on this proc.
 		goal_info_get_determinism(GoalInfo0, Determinism0),
-		goal_info_get_determinism(GoalInfo1, Determinism1),
-		( Determinism0 = Determinism1 ->
+		goal_info_get_determinism(GoalInfo, Determinism),
+		( Determinism0 = Determinism ->
 			DetChanged = DetChanged0
 		;
 			DetChanged = yes
@@ -513,6 +508,7 @@
 			TypeInfoVarMap)
 	;
 		Goal = call(PredId, ProcId, ArgVars, Builtin, Context, Sym),
+		GoalInfo = GoalInfo0,
 		VarSet = VarSet0,
 		VarTypes = VarTypes0,
 		TypeVarSet = TypeVarSet0,
@@ -522,14 +518,14 @@
 	InlineInfo = inline_info(VarThresh, InlinedProcs, ModuleInfo,
 		VarSet, VarTypes, TypeVarSet, TypeInfoVarMap, DetChanged).
 
-inlining__inlining_in_goal_2(higher_order_call(A, B, C, D, E), _GoalInfo,
-		higher_order_call(A, B, C, D, E)) --> [].
+inlining__inlining_in_goal(higher_order_call(A, B, C, D, E) - GoalInfo,
+		higher_order_call(A, B, C, D, E) - GoalInfo) --> [].
 
-inlining__inlining_in_goal_2(unify(A, B, C, D, E), _GoalInfo,
-		unify(A, B, C, D, E)) --> [].
+inlining__inlining_in_goal(unify(A, B, C, D, E) - GoalInfo,
+		unify(A, B, C, D, E) - GoalInfo) --> [].
 
-inlining__inlining_in_goal_2(pragma_c_code(A, B, C, D, E, F, G, H), _GoalInfo,
-		pragma_c_code(A, B, C, D, E, F, G, H)) --> [].
+inlining__inlining_in_goal(pragma_c_code(A, B, C, D, E, F, G, H) - GoalInfo,
+		pragma_c_code(A, B, C, D, E, F, G, H) - GoalInfo) --> [].
 
 %-----------------------------------------------------------------------------%
 
cvs diff: Diffing .
Index: Mmake
===================================================================
RCS file: /home/staff/zs/imp/tests/hard_coded/Mmake,v
retrieving revision 1.49
diff -u -r1.49 Mmake
--- Mmake	1997/07/09 05:45:34	1.49
+++ Mmake	1997/07/09 08:13:35
@@ -21,6 +21,7 @@
 	det_in_semidet_cntxt \
 	division_test \
 	elim_special_pred \
+	error_func \
 	expand \
 	float_reg \
 	float_rounding_bug \
Index: error_func.exp
===================================================================
RCS file: error_func.exp
diff -N error_func.exp
--- /dev/null	Tue Jan  1 15:00:00 1980
+++ error_func.exp	Wed Jul  9 18:16:16 1997
@@ -0,0 +1 @@
+Answer = 16472
Index: error_func.m
===================================================================
RCS file: error_func.m
diff -N error_func.m
--- /dev/null	Tue Jan  1 15:00:00 1980
+++ error_func.m	Wed Jul  9 18:16:46 1997
@@ -0,0 +1,74 @@
+/*
+$ mc bug2
+bug2.m:009: Warning: incorrect module name in `:- module' declaration.
+bug2.m:034: In `error(in) = out':
+bug2.m:034:   warning: determinism declaration could be tighter.
+bug2.m:034:   Declared `det', inferred `erroneous'.
+Software error: variable V_32 not found
+*/
+:- module error_func.
+:- interface.
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+:- import_module list, int, require, time, string.
+
+:- func first_denomination(int) = int.
+first_denomination(Kinds_of_coins) =
+  (if (Kinds_of_coins = 1) then
+    1
+  else if (Kinds_of_coins = 2) then
+    5
+  else if (Kinds_of_coins = 3) then
+    10
+  else if (Kinds_of_coins = 4) then
+    25
+  else if (Kinds_of_coins = 5) then
+    50
+  else
+    error("wrong kind of coin")
+  ).
+
+:- func error(string) = _.
+error(S) = _ :-
+  error(S).
+
+:- func cc_tail(int, int, int) = int.
+cc_tail(Amount, Kinds_of_coins, Count) =
+  (if (Amount = 0) then
+    Count + 1
+  else if (Amount < 0 ; Kinds_of_coins = 0) then
+    Count
+  else
+    cc_tail(Amount - first_denomination(Kinds_of_coins),
+                   Kinds_of_coins,
+                   cc_tail(Amount, Kinds_of_coins - 1, Count))
+  ).
+
+:- func count_change(int) = int.
+count_change(Amount) =
+  cc_tail(Amount, 5, 0).
+
+:- pred do_count_change(int::in, int::out) is det.
+do_count_change(Amount, Result) :- Result = count_change(Amount).
+
+main -->
+  io__command_line_arguments(Args),
+  (if { Args = [] } then
+      { N = 350 },
+      { do_count_change(N, Answer) },
+      io__format("Answer = %d\n", [i(Answer)])
+  else if { Args = [Num] } then
+    (if { string__to_int(Num, N), N >= 0 } then
+      { benchmark_det(do_count_change, N, Answer, 1, Time) },
+      { string__format("Answer = %d, Time = %d milliseconds\n",
+		[i(Answer),i(Time)], Message) },
+      io__write_string(Message)
+    else
+      io__write_string("invalid argument\n")
+    )
+  else
+    io__write_string("wrong number of arguments\n")
+  ).

-- 
Fergus Henderson <fjh at cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3         |     -- the last words of T. S. Garp.



More information about the developers mailing list