[m-rev.] diff: optimise single outputs in erlang backend

Peter Wang wangp at students.csse.unimelb.edu.au
Mon Jul 9 14:50:54 AEST 2007


Branches: main

Change the calling convention on the Erlang backend so that model_det
predicates/functions which have a single output variable directly return the
value of that variable, instead of a 1-tuple containing that value.

This change makes the compiler built with the Erlang backend, compiled to
native code, about 4% faster at compiling middle_rec.m.

compiler/elds.m:
	Add helper function tuple_or_single_expr.

compiler/erl_call_gen.m:
	Change the calling convention in make_det_call.

compiler/erl_code_gen.m:
	Change the calling convention in erl_gen_proc_body.

	Update the code generated for simplified unify/compare predicates
	for the new calling convention.

compiler/erl_rtti.m:
	Change the calling convention for method wrappers and unify/compare
	wrappers.

compiler/erl_unify_gen.m:
	Conform to the new calling convention when making closures.

library/erlang_rtti_implementation.m:
library/exception.m:
	Conform to the new calling convention in hand-written code.


Index: compiler/elds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/elds.m,v
retrieving revision 1.13
diff -u -r1.13 elds.m
--- compiler/elds.m	19 Jun 2007 01:10:52 -0000	1.13
+++ compiler/elds.m	9 Jul 2007 03:00:16 -0000
@@ -352,6 +352,12 @@
 
 :- func elds_clause_arity(elds_clause) = arity.
 
+    % tuple_or_single_expr(List)
+    % If List contains exactly one expression, return that expression.
+    % Otherwise return a tuple of the expressions in List.
+    %
+:- func tuple_or_single_expr(list(elds_expr)) = elds_expr.
+
     %
     % make_enum_alternative(F)
     %
@@ -444,6 +450,13 @@
 
 elds_clause_arity(elds_clause(Args, _Expr)) = list.length(Args).
 
+tuple_or_single_expr(List) =
+    ( List = [SingleExpr] ->
+        SingleExpr
+    ;
+        elds_term(elds_tuple(List))
+    ).
+
 make_enum_alternative(F) = elds_tuple([elds_term(elds_atom(unqualified(F)))]).
 
 %-----------------------------------------------------------------------------%
Index: compiler/erl_call_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/erl_call_gen.m,v
retrieving revision 1.8
diff -u -r1.8 erl_call_gen.m
--- compiler/erl_call_gen.m	2 Jul 2007 05:30:28 -0000	1.8
+++ compiler/erl_call_gen.m	9 Jul 2007 03:00:16 -0000
@@ -206,7 +206,7 @@
         )
     ;
         OutputVars = [_ | _],
-        UnpackTerm = elds_term(elds_tuple(elds.exprs_from_vars(OutputVars))),
+        UnpackTerm = tuple_or_single_expr(exprs_from_vars(OutputVars)),
         (if
             MaybeSuccessExpr = yes(UnpackTerm)
         then
@@ -627,17 +627,20 @@
     OutputVarsNames = list.map(foreign_arg_name, OutputForeignArgs),
 
     ForeignCodeExpr = elds_foreign_code(ForeignCode),
-    OutputTuple = elds_term(elds_tuple(
-        exprs_from_fixed_vars(OutputVarsNames))),
 
     % Create the inner lambda function.
     (
         CodeModel = model_det,
         %
         %   <ForeignCodeExpr>,
+        %   SingleOutput
+        % or
+        %   <ForeignCodeExpr>,
         %   {Outputs, ...}
         %
-        InnerFunStatement = join_exprs(ForeignCodeExpr, OutputTuple)
+        OutputExpr = tuple_or_single_expr(
+            exprs_from_fixed_vars(OutputVarsNames)),
+        InnerFunStatement = join_exprs(ForeignCodeExpr, OutputExpr)
     ;
         CodeModel = model_semi,
         %
@@ -648,6 +651,8 @@
         %   end
         %
         InnerFunStatement = join_exprs(ForeignCodeExpr, MaybePlaceOutputs),
+        OutputTuple = elds_term(elds_tuple(
+            exprs_from_fixed_vars(OutputVarsNames))),
         MaybePlaceOutputs = elds_case_expr(SuccessInd, [OnTrue, OnFalse]),
         SuccessInd = elds_term(elds_fixed_name_var("SUCCESS_INDICATOR")),
         OnTrue = elds_case(elds_true, OutputTuple),
Index: compiler/erl_code_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/erl_code_gen.m,v
retrieving revision 1.18
diff -u -r1.18 erl_code_gen.m
--- compiler/erl_code_gen.m	3 Jul 2007 04:48:28 -0000	1.18
+++ compiler/erl_code_gen.m	9 Jul 2007 03:00:16 -0000
@@ -278,11 +278,11 @@
 
     %   '__Compare__'(X, Y) ->
     %       case X =:= Y of
-    %           true -> {{'='}};
+    %           true -> {'='};
     %           false ->
     %               case X < Y of
-    %                   true -> {{'<'}};
-    %                   false -> {{'>'}};
+    %                   true -> {'<'};
+    %                   false -> {'>'};
     %               end
     %       end.
     %
@@ -290,23 +290,18 @@
     ClauseExpr = elds_case_expr(CondEq, [IsEq, IsNotEq]),
 
     CondEq = elds_binop((=:=), XExpr, YExpr),
-    IsEq = elds_case(elds_true, enum_in_tuple("=")),
+    IsEq = elds_case(elds_true, elds_term(make_enum_alternative("="))),
     IsNotEq = elds_case(elds_false, elds_case_expr(CondLt, [IsLt, IsGt])),
 
     CondLt = elds_binop((<), XExpr, YExpr),
-    IsLt = elds_case(elds_true, enum_in_tuple("<")),
-    IsGt = elds_case(elds_false, enum_in_tuple(">")),
+    IsLt = elds_case(elds_true, elds_term(make_enum_alternative("<"))),
+    IsGt = elds_case(elds_false, elds_term(make_enum_alternative(">"))),
 
     erl_gen_info_get_varset(Info, ProcVarSet),
     erl_gen_info_get_env_vars(Info, EnvVarNames),
     ProcDefn = elds_defn(proc(PredId, ProcId), ProcVarSet,
         body_defined_here(Clause), EnvVarNames).
 
-:- func enum_in_tuple(string) = elds_expr.
-
-enum_in_tuple(X) = 
-    elds_term(elds_tuple([elds_term(make_enum_alternative(X))])).
-
 %-----------------------------------------------------------------------------%
 %
 % Code for handling individual procedures
@@ -381,9 +376,18 @@
     erl_gen_info_get_output_vars(!.Info, OutputVars),
     OutputVarsExprs = exprs_from_vars(OutputVars),
     (
-        ( CodeModel = model_det
-        ; CodeModel = model_semi
-        ),
+        CodeModel = model_det,
+        InputVarsTerms = terms_from_vars(InputVars),
+        %
+        % On success, the procedure returns either:
+        % - the single output variable, or
+        % - a tuple of its output variables if there are zero or two or more
+        %   output variables.
+        % 
+        SuccessExpr = tuple_or_single_expr(OutputVarsExprs),
+        InstMap = InstMap0
+    ;
+        CodeModel = model_semi,
         InputVarsTerms = terms_from_vars(InputVars),
         %
         % On success, the procedure returns a tuple of its output variables.
Index: compiler/erl_rtti.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/erl_rtti.m,v
retrieving revision 1.13
diff -u -r1.13 erl_rtti.m
--- compiler/erl_rtti.m	14 Jun 2007 04:43:50 -0000	1.13
+++ compiler/erl_rtti.m	9 Jul 2007 03:00:16 -0000
@@ -318,11 +318,16 @@
     determinism_to_code_model(Detism, CodeModel),
     WrapperOutputVarsExprs = exprs_from_vars(WrapperOutputVars),
     (
-        ( CodeModel = model_det
-        ; CodeModel = model_semi
-        ),
+        CodeModel = model_det,
         AllWrapperInputVars = [TCIVar | WrapperInputVars],
-        % On success we return a tuple of the output arguments of the call.
+        % On success we either return a tuple of the output variables of the
+        % call, or if there is exactly one output variable, just that output
+        % variable.
+        SuccessExpr0 = tuple_or_single_expr(WrapperOutputVarsExprs)
+    ;
+        CodeModel = model_semi,
+        AllWrapperInputVars = [TCIVar | WrapperInputVars],
+        % On success we return a tuple of the output variables of the call.
         SuccessExpr0 = elds_term(elds_tuple(WrapperOutputVarsExprs))
     ;
         CodeModel = model_non,
@@ -675,9 +680,13 @@
     determinism_to_code_model(Detism, CodeModel),
     WrapperOutputVarsExprs = exprs_from_vars(WrapperOutputVars),
     (
-        ( CodeModel = model_det
-        ; CodeModel = model_semi
-        ),
+        CodeModel = model_det,
+        % On success we either return a tuple of the output variables of the
+        % call, or if there is exactly one output variable, just that output
+        % variable.
+        SuccessExpr0 = tuple_or_single_expr(WrapperOutputVarsExprs)
+    ;
+        CodeModel = model_semi,
         % On success we return a tuple of the output arguments of the call.
         SuccessExpr0 = elds_term(elds_tuple(WrapperOutputVarsExprs))
     ;
Index: compiler/erl_unify_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/erl_unify_gen.m,v
retrieving revision 1.7
diff -u -r1.7 erl_unify_gen.m
--- compiler/erl_unify_gen.m	14 Jun 2007 03:52:48 -0000	1.7
+++ compiler/erl_unify_gen.m	9 Jul 2007 03:00:16 -0000
@@ -363,9 +363,11 @@
 
     OutputVarsInclDummyExprs = exprs_from_vars(OutputVarsInclDummy),
     (
-        ( CodeModel = model_det
-        ; CodeModel = model_semi
-        ),
+        CodeModel = model_det,
+        ClosureInputArgs = InputExtraVars,
+        SuccessExpr0 = tuple_or_single_expr(OutputVarsInclDummyExprs)
+    ;
+        CodeModel = model_semi,
         ClosureInputArgs = InputExtraVars,
         SuccessExpr0 = elds_term(elds_tuple(OutputVarsInclDummyExprs))
     ;
Index: library/erlang_rtti_implementation.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/erlang_rtti_implementation.m,v
retrieving revision 1.11
diff -u -r1.11 erlang_rtti_implementation.m
--- library/erlang_rtti_implementation.m	5 Jul 2007 02:53:49 -0000	1.11
+++ library/erlang_rtti_implementation.m	9 Jul 2007 03:00:16 -0000
@@ -1060,39 +1060,39 @@
     result_call_4(Pred::in, Res::out, X::in, Y::in),
     [will_not_call_mercury, promise_pure, thread_safe],
 "
-    {Res} = Pred(X, Y)
+    Res = Pred(X, Y)
 ").
 
 :- pragma foreign_proc("Erlang",
     result_call_5(Pred::in, Res::out, A::in, X::in, Y::in),
     [will_not_call_mercury, promise_pure, thread_safe],
 "
-    {Res} = Pred(A, X, Y)
+    Res = Pred(A, X, Y)
 ").
 :- pragma foreign_proc("Erlang",
     result_call_6(Pred::in, Res::out, A::in, B::in, X::in, Y::in),
     [will_not_call_mercury, promise_pure, thread_safe],
 "
-    {Res} = Pred(A, B, X, Y)
+    Res = Pred(A, B, X, Y)
 ").
 :- pragma foreign_proc("Erlang",
     result_call_7(Pred::in, Res::out, A::in, B::in, C::in, X::in, Y::in),
     [will_not_call_mercury, promise_pure, thread_safe],
 "
-    {Res} = Pred(A, B, C, X, Y)
+    Res = Pred(A, B, C, X, Y)
 ").
 :- pragma foreign_proc("Erlang",
     result_call_8(Pred::in, Res::out, A::in, B::in, C::in, D::in, X::in, Y::in),
     [will_not_call_mercury, promise_pure, thread_safe],
 "
-    {Res} = Pred(A, B, C, D, X, Y)
+    Res = Pred(A, B, C, D, X, Y)
 ").
 :- pragma foreign_proc("Erlang",
     result_call_9(Pred::in, Res::out, A::in, B::in, C::in, D::in, E::in,
         X::in, Y::in),
     [will_not_call_mercury, promise_pure, thread_safe],
 "
-    {Res} = Pred(A, B, C, D, E, X, Y)
+    Res = Pred(A, B, C, D, E, X, Y)
 ").
 
 %-----------------------------------------------------------------------------%
Index: library/exception.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/exception.m,v
retrieving revision 1.126
diff -u -r1.126 exception.m
--- library/exception.m	6 Jun 2007 01:26:26 -0000	1.126
+++ library/exception.m	9 Jul 2007 03:00:16 -0000
@@ -1401,7 +1401,7 @@
     catch_impl(Pred::pred(out) is det, Handler::in(handler), T::out),
     [will_not_call_mercury, promise_pure],
 "
-    {T} = try
+    T = try
         Pred()
     catch
         throw: {'ML_exception', Excp} ->
@@ -1421,11 +1421,11 @@
                 Handler(Excp)
         end
     of
-        {T} ->
-            SUCCESS_INDICATOR = true;
-        _ ->
+        fail ->
             SUCCESS_INDICATOR = false,
-            T = null
+            T = null;
+        T ->
+            SUCCESS_INDICATOR = true
     end
 ").
 
@@ -1444,7 +1444,7 @@
             Pred(Succeed)
         catch
             throw: {'ML_exception', Excp} ->
-                {Result} = Handler(Excp),
+                Result = Handler(Excp),
                 Succeed(Result)
         end.
 
@@ -1453,7 +1453,7 @@
             Pred(Succeed)
         catch
             throw: {'ML_exception', Excp} ->
-                {Result} = Handler(Excp),
+                Result = Handler(Excp),
                 Succeed(Result)
         end.
 ").
--------------------------------------------------------------------------
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