[erlang-questions] naive execution of guards

Kostis Sagonas kostis@REDACTED
Tue Dec 12 18:26:30 CET 2006


Ulf Wiger (TN/EAB) wrote:
> 
> I was curious to see whether the compiler would optimize away repeated
> use of the length/1 guard, e.g in the following code:
> 
> check_arity(_, L, Min, Max)
>   when is_list(L), length(L) =< Min, length(L) >= Max ->
>     true;
> 
> but compiling with erlc -S indicates that it doesn't:
> 
> {function, check_arity, 4, 8}.
>   {label,7}.
>     {func_info,{atom,test},{atom,check_arity},4}.
>   {label,8}.
>     {bif,is_list,{f,9},[{x,1}],{x,4}}.
>     {gc_bif,length,{f,9},5,[{x,1}],{x,5}}.
>     {bif,'=<',{f,9},[{x,5},{x,2}],{x,5}}.
>     {gc_bif,length,{f,9},6,[{x,1}],{x,6}}.
>     {bif,'>=',{f,9},[{x,6},{x,3}],{x,6}}.
>     {bif,'and',{f,9},[{x,5},{x,6}],{x,5}}.
>     {bif,'and',{f,9},[{x,4},{x,5}],{x,4}}.
>     {test,is_eq_exact,{f,9},[{x,4},{atom,true}]}.
>     {move,{atom,true},{x,0}}.
>     return.
> 
> I guess there are two reasons for doing the optimization:
> - one less register to handle
> - length/1 is an O(N) bif
> 
> I'm sure it's tricky, and I don't know if the above reasons are strong
> enough.

The 2nd reason IS strong enough.

Even some of the OTP code would benefit from it.

lib/compiler/src/sys_expand_pmod.erl:  when length(As0) == 0;
length(As0) == 1 ->
lib/megaco/src/text/megaco_text_mini_parser.hrl:  when length(Hex4) =<
4, length(Hex4) > 0 ->
lib/megaco/src/text/megaco_text_parser_prev3a.hrl:  when length(Hex4) =<
4, length(Hex4) > 0 ->
lib/megaco/src/text/megaco_text_parser_prev3b.hrl:  when length(Hex4) =<
4, length(Hex4) > 0 ->
lib/megaco/src/text/megaco_text_parser_prev3c.hrl:  when length(Hex4) =<
4, length(Hex4) > 0 ->
lib/megaco/src/text/megaco_text_parser_v1.hrl:  when length(Hex4) =< 4,
length(Hex4) > 0 ->
lib/megaco/src/text/megaco_text_parser_v2.hrl:  when length(Hex4) =< 4,
length(Hex4) > 0 ->
lib/megaco/src/text/megaco_text_parser_v3.hrl:  when length(Hex4) =< 4,
length(Hex4) > 0 ->
lib/megaco/test/megaco_test_msg_prev3b_lib.erl:  when list(L), Min =<
length(L), length(L) =< Max ->
lib/megaco/test/megaco_test_msg_prev3c_lib.erl:  when list(L), Min =<
length(L), length(L) =< Max ->
lib/megaco/test/megaco_test_msg_v2_lib.erl:  when list(L), Min =<
length(L), length(L) =< Max ->


This should be optimized away by the compiler.


On a slightly unrelated topic: About a month ago, I suggested to OTP a
new guard (or possibly a family of guards, if open intervals are also
needed) tailored to integer ranges.  Using these guards instead of writing:

 ... when Min =< N, N =< Max ->

would simply be written as:

 ... when in_range(Min, N, Max) ->

One immediate side effect, which admittedly I had not thought of when I
made the proposal, would be that when N was an expression such as e.g.
length(L), this expression would only appear once.


Kostis



More information about the erlang-questions mailing list