[m-rev.] for review: loop invariant hoisting bug

Peter Wang novalazy at gmail.com
Fri Oct 23 13:25:46 AEDT 2009


Branches: main

compiler/loop_inv.m:
        Fix a bug.  An `unused' variable in an invariant call was treated
        like an output variable and added to the invariant variables list,
        and hoisted.

tests/hard_coded/Mercury.options:
tests/hard_coded/loop_inv_test3.exp:
tests/hard_coded/loop_inv_test3.m:
        Add test case.

diff --git a/compiler/loop_inv.m b/compiler/loop_inv.m
index 9b13fad..7961854 100644
--- a/compiler/loop_inv.m
+++ b/compiler/loop_inv.m
@@ -232,7 +232,7 @@ hoist_loop_invariants(PredId, ProcId, PredInfo, !ProcInfo, !ModuleInfo) :-
             AuxPredInfo, AuxProcInfo, !ModuleInfo),
 
         % We update the body of AuxProc by replacing adding the set of
-        % computed invariant vars to the argument list, % replacing invariant
+        % computed invariant vars to the argument list, replacing invariant
         % goals in InProc with `true', and recursive calls at the end of
         % recursive paths with calls to the auxiliary procedure.
         gen_aux_proc(InvGoals, PredProcId,
@@ -1211,8 +1211,8 @@ input_arg(ModuleInfo, X, M) = X :-
 
 %-----------------------------------------------------------------------------%
 
-    % Find the list of vars for a goal that are free before the call.
-    % This only applies to calls and unifications.
+    % Find the list of vars for a goal that are free before the call and bound
+    % afterwards.  This only applies to calls and unifications.
     %
 :- func goal_outputs(module_info, hlds_goal) = prog_vars.
 
@@ -1269,13 +1269,12 @@ goal_outputs(ModuleInfo, Goal) = Outputs :-
 
 %-----------------------------------------------------------------------------%
 
-    % An output arg is one whose pre-call inst is free.
+    % An output arg is one whose pre-call inst is free and ground after.
     %
 :- func output_arg(module_info, prog_var, mer_mode) = prog_var is semidet.
 
 output_arg(ModuleInfo, X, M) = X :-
-    mode_get_insts(ModuleInfo, M, InInst, _OutInst),
-    inst_is_free(ModuleInfo, InInst).
+    mode_is_fully_output(ModuleInfo, M).
 
 %-----------------------------------------------------------------------------%
 
diff --git a/tests/hard_coded/Mercury.options b/tests/hard_coded/Mercury.options
index f3160e9..fe3d47b 100644
--- a/tests/hard_coded/Mercury.options
+++ b/tests/hard_coded/Mercury.options
@@ -60,6 +60,7 @@ MCFLAGS-loop_inv_test 	= 	--loop-invariants --trace-optimized
 MCFLAGS-loop_inv_test0 	= 	--loop-invariants --trace-optimized
 MCFLAGS-loop_inv_test1 	= 	--loop-invariants --trace-optimized
 MCFLAGS-loop_inv_test2 	= 	--loop-invariants --trace-optimized
+MCFLAGS-loop_inv_test3 	= 	--loop-invariants --trace-optimized
 MCFLAGS-prince_frameopt = 		--intermodule-optimization -O5
 MCFLAGS-prince_frameopt_css = 		--intermodule-optimization -O5
 MCFLAGS-prince_frameopt_css.style = 	--intermodule-optimization -O5
diff --git a/tests/hard_coded/loop_inv_test3.exp b/tests/hard_coded/loop_inv_test3.exp
new file mode 100644
index 0000000..6a2839f
--- /dev/null
+++ b/tests/hard_coded/loop_inv_test3.exp
@@ -0,0 +1 @@
+[100, 100, 100, 100, 100, 100, 100, 100, 100, 100]
diff --git a/tests/hard_coded/loop_inv_test3.m b/tests/hard_coded/loop_inv_test3.m
new file mode 100644
index 0000000..4b00f99
--- /dev/null
+++ b/tests/hard_coded/loop_inv_test3.m
@@ -0,0 +1,50 @@
+%-----------------------------------------------------------------------------%
+% Regression test.  Loop invariant hoisting incorrectly treated `unused'
+% arguments in calls like outputs.
+
+:- module loop_inv_test3.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module int.
+:- import_module list.
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+    loop(10, 10, [], L),
+    io.write(L, !IO),
+    io.nl(!IO).
+
+:- pred loop(int::in, int::in, list(int)::in, list(int)::out) is det.
+
+loop(Factor, N, L0, L) :-
+    Value = foo(Factor, N1),
+    bar(N, N1),
+    ( N1 = 0 ->
+        L = L0
+    ;
+        L1 = [Factor * Value | L0],
+        loop(Factor, N - 1, L1, L)
+    ).
+
+:- func foo(int::in, int::unused) = (int::out) is det.
+:- pragma no_inline(foo/2).
+
+foo(F, _) = F.
+
+:- pred bar(int::in, int::out) is det.
+:- pragma no_inline(bar/2).
+
+bar(N, N).
+
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=8 sts=4 sw=4 et

--------------------------------------------------------------------------
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