diff options
| author | Björn Gustavsson <[email protected]> | 2017-12-31 17:01:58 +0100 | 
|---|---|---|
| committer | Björn Gustavsson <[email protected]> | 2018-01-11 12:00:07 +0100 | 
| commit | b1615cb1159cc1c9a5fa67992fa92a6d0da36b3c (patch) | |
| tree | d41a0fb1bf29984ad1c0feebd2c2a66e991544eb /lib/runtime_tools/examples/messages.systemtap | |
| parent | e21e95536d7fe2ebd1bb1772266a5ccd39b074f2 (diff) | |
| download | otp-b1615cb1159cc1c9a5fa67992fa92a6d0da36b3c.tar.gz otp-b1615cb1159cc1c9a5fa67992fa92a6d0da36b3c.tar.bz2 otp-b1615cb1159cc1c9a5fa67992fa92a6d0da36b3c.zip | |
Improve code generation for a 'case' with exported variables
Consider a 'case' that exports variables and whose return
value is ignored:
foo(N) ->
    case N of
        1 ->
            Res = one;
        2 ->
            Res = two
    end,
    {ok,Res}.
That code will be translated to the following Core Erlang code:
'foo'/1 =
    fun (_@c0) ->
        let <_@c5,Res> =
           case _@c0 of
	      <1> when 'true' ->
                  <'one','one'>
	      <2> when 'true' ->
                  <'two','two'>
	      <_@c3> when 'true' ->
                  primop 'match_fail'({'case_clause',_@c3})
           end
	in
           {'ok',Res}
The exported variables has been rewritten to explicit return
values. Note that the original return value from the 'case' is bound to
the variable _@c5, which is unused.
The corresponding BEAM assembly code looks like this:
{function, foo, 1, 2}.
  {label,1}.
    {line,[...]}.
    {func_info,{atom,t},{atom,foo},1}.
  {label,2}.
    {test,is_integer,{f,6},[{x,0}]}.
    {select_val,{x,0},{f,6},{list,[{integer,2},{f,3},{integer,1},{f,4}]}}.
  {label,3}.
    {move,{atom,two},{x,1}}.
    {move,{atom,two},{x,0}}.
    {jump,{f,5}}.
  {label,4}.
    {move,{atom,one},{x,1}}.
    {move,{atom,one},{x,0}}.
  {label,5}.
    {test_heap,3,2}.
    {put_tuple,2,{x,0}}.
    {put,{atom,ok}}.
    {put,{x,1}}.
    return.
  {label,6}.
    {line,[...]}.
    {case_end,{x,0}}.
Because of the test_heap instruction following label 5, the assignment
to {x,0} cannot be optimized away by the passes that optimize BEAM assembly
code.
Refactor the optimizations of 'let' in sys_core_fold to eliminate the
unused variable. Thus:
'foo'/1 =
    fun (_@c0) ->
       let <Res> =
           case _@c0 of
              <1> when 'true' ->
                 'one'
              <2> when 'true' ->
                 'two'
              <_@c3> when 'true' ->
                  primop 'match_fail'({'case_clause',_@c3})
           end
       in
           {'ok',Res}
The resulting BEAM code will look like:
{function, foo, 1, 2}.
  {label,1}.
    {line,[...]}.
    {func_info,{atom,t},{atom,foo},1}.
  {label,2}.
    {test,is_integer,{f,6},[{x,0}]}.
    {select_val,{x,0},{f,6},{list,[{integer,2},{f,3},{integer,1},{f,4}]}}.
  {label,3}.
    {move,{atom,two},{x,0}}.
    {jump,{f,5}}.
  {label,4}.
    {move,{atom,one},{x,0}}.
  {label,5}.
    {test_heap,3,1}.
    {put_tuple,2,{x,1}}.
    {put,{atom,ok}}.
    {put,{x,0}}.
    {move,{x,1},{x,0}}.
    return.
  {label,6}.
    {line,[...]}.
    {case_end,{x,0}}.
Diffstat (limited to 'lib/runtime_tools/examples/messages.systemtap')
0 files changed, 0 insertions, 0 deletions
