[m-rev.] for review: fix simplification of multi-arm switch

Peter Wang novalazy at gmail.com
Fri Jun 26 15:23:39 AEST 2009


Branches: main

Fix a simplification bug which was introduced with multi-cons_id switch arms.
Previously a singleton switch could be replaced by the case goal, possibly
with a functor test beforehand, but that's only true if the case arm is
applicable to only a single functor.

compiler/simplify.m:
        As above.

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

diff --git a/compiler/simplify.m b/compiler/simplify.m
index 7c101fa..47eeedd 100644
--- a/compiler/simplify.m
+++ b/compiler/simplify.m
@@ -1071,19 +1071,21 @@ simplify_goal_switch(GoalExpr0, GoalExpr,
GoalInfo0, GoalInfo, !Info) :-
         SwitchCanFail0, SwitchCanFail, !.Info, !Info),
     list.reverse(RevCases, Cases),
     (
-        Cases = [],
+        Cases = []
+    ->
         % An empty switch always fails.
         simplify_info_incr_cost_delta(cost_of_eliminate_switch, !Info),
         Context = goal_info_get_context(GoalInfo0),
         hlds_goal(GoalExpr, GoalInfo) = fail_goal_with_context(Context)
     ;
         Cases = [case(MainConsId, OtherConsIds, SingleGoal)],
+        OtherConsIds = []
+    ->
         % A singleton switch is equivalent to the goal itself with a
         % possibly can_fail unification with the functor on the front.
         MainConsIdArity = cons_id_arity(MainConsId),
         (
             SwitchCanFail = can_fail,
-            OtherConsIds = [],
             MaybeConsIds \= yes([MainConsId])
         ->
             % Don't optimize in the case of an existentially typed constructor
@@ -1135,7 +1137,6 @@ simplify_goal_switch(GoalExpr0, GoalExpr,
GoalInfo0, GoalInfo, !Info) :-
         ),
         simplify_info_incr_cost_delta(cost_of_eliminate_switch, !Info)
     ;
-        Cases = [_, _ | _],
         GoalExpr = switch(Var, SwitchCanFail, Cases),
         (
             ( goal_info_has_feature(GoalInfo0, feature_mode_check_clauses_goal)
diff --git a/tests/hard_coded/Mercury.options b/tests/hard_coded/Mercury.options
index a2cd8e7..91c64dd 100644
--- a/tests/hard_coded/Mercury.options
+++ b/tests/hard_coded/Mercury.options
@@ -42,6 +42,7 @@ 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-simplify_multi_arm_switch = -O3
 MCFLAGS-uncond_reuse	    =	--ctgc
 MCFLAGS-uncond_reuse_bad    =	--ctgc

diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 6271558..5c2dbd4 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -206,6 +206,7 @@ ORDINARY_PROGS=	\
 	semi_disj \
 	setjmp_test \
 	shift_test \
+	simplify_multi_arm_switch \
 	solve_quadratic \
 	space \
 	stable_sort \
diff --git a/tests/hard_coded/simplify_multi_arm_switch.exp
b/tests/hard_coded/simplify_multi_arm_switch.exp
new file mode 100644
index 0000000..9766475
--- /dev/null
+++ b/tests/hard_coded/simplify_multi_arm_switch.exp
@@ -0,0 +1 @@
+ok
diff --git a/tests/hard_coded/simplify_multi_arm_switch.m
b/tests/hard_coded/simplify_multi_arm_switch.m
new file mode 100644
index 0000000..cbdeaa4
--- /dev/null
+++ b/tests/hard_coded/simplify_multi_arm_switch.m
@@ -0,0 +1,51 @@
+% Regression test.
+% Previously a singleton switch could be replaced by the case goal, possibly
+% with a functor test beforehand, but that's only true if the case arm is
+% applicable to only a single functor.
+
+:- module simplify_multi_arm_switch.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module bool.
+
+:- type fruit
+    --->    apple
+    ;       pear
+    ;       banana
+    ;       plum.
+
+:- pred squishy(fruit::in) is semidet.
+:- pragma no_inline(squishy/1).
+
+squishy(Fruit) :-
+    (
+        ( Fruit = apple
+        ; Fruit = pear
+        ),
+        IsSquishy = no
+    ;
+        ( Fruit = banana
+        ; Fruit = plum
+        ),
+        IsSquishy = yes
+    ),
+    IsSquishy = yes.
+
+main(!IO) :-
+    ( squishy(apple) ->
+        io.write_string("bug!\n", !IO)
+    ;
+        io.write_string("ok\n", !IO)
+    ).
+
+%-----------------------------------------------------------------------------%
+% 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