aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/test
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2016-09-15 16:33:57 +0200
committerBjörn Gustavsson <[email protected]>2016-11-18 11:58:34 +0100
commit348b5e6bee2f83d10642558d511cc904f5015ab3 (patch)
tree796175b689cfcf463fa854b2f306cfdf5f5d46bf /lib/compiler/test
parentcb4b1276acae0406344a24d4597c0d33a1d72ac7 (diff)
downloadotp-348b5e6bee2f83d10642558d511cc904f5015ab3.tar.gz
otp-348b5e6bee2f83d10642558d511cc904f5015ab3.tar.bz2
otp-348b5e6bee2f83d10642558d511cc904f5015ab3.zip
v3_kernel: Generate optimized code for guards
The compiler produces poor code for complex guard expressions with andalso/orelse. Here is an example from the filename module: -define(IS_DRIVELETTER(Letter),(((Letter >= $A) andalso (Letter =< $Z)) orelse ((Letter >= $a) andalso (Letter =< $z)))). skip_prefix(Name, false) -> Name; skip_prefix([L, DrvSep|Name], DrvSep) when ?IS_DRIVELETTER(L) -> Name; skip_prefix(Name, _) -> Name. beam_bool fails to simplify the code for the guard, leaving several 'bif' instructions: {function, skip_prefix, 2, 49}. {label,48}. {line,[{location,"filename.erl",187}]}. {func_info,{atom,filename},{atom,skip_prefix},2}. {label,49}. {test,is_ne_exact,{f,52},[{x,1},{atom,false}]}. {test,is_nonempty_list,{f,52},[{x,0}]}. {get_list,{x,0},{x,2},{x,3}}. {test,is_nonempty_list,{f,52},[{x,3}]}. {get_list,{x,3},{x,4},{x,5}}. {bif,'=:=',{f,52},[{x,1},{x,4}],{x,6}}. {test,is_ge,{f,50},[{x,2},{integer,65}]}. {bif,'=<',{f,52},[{x,2},{integer,90}],{x,7}}. {test,is_eq_exact,{f,51},[{x,7},{atom,false}]}. {test,is_ge,{f,50},[{x,2},{integer,97}]}. {bif,'=<',{f,52},[{x,2},{integer,122}],{x,7}}. {jump,{f,51}}. {label,50}. {move,{atom,false},{x,7}}. {label,51}. {bif,'=:=',{f,52},[{x,7},{atom,true}],{x,7}}. {test,is_eq_exact,{f,52},[{x,6},{atom,true}]}. {test,is_eq_exact,{f,52},[{x,7},{atom,true}]}. {move,{x,5},{x,0}}. return. {label,52}. return. We can add optimizations of guard tests to v3_kernel to achive a better result: {function, skip_prefix, 2, 49}. {label,48}. {line,[{location,"filename.erl",187}]}. {func_info,{atom,filename},{atom,skip_prefix},2}. {label,49}. {test,is_ne_exact,{f,51},[{x,1},{atom,false}]}. {test,is_nonempty_list,{f,51},[{x,0}]}. {get_list,{x,0},{x,2},{x,3}}. {test,is_nonempty_list,{f,51},[{x,3}]}. {get_list,{x,3},{x,4},{x,5}}. {test,is_eq_exact,{f,51},[{x,1},{x,4}]}. {test,is_ge,{f,51},[{x,2},{integer,65}]}. {test,is_lt,{f,50},[{integer,90},{x,2}]}. {test,is_ge,{f,51},[{x,2},{integer,97}]}. {test,is_ge,{f,51},[{integer,122},{x,2}]}. {label,50}. {move,{x,5},{x,0}}. return. {label,51}. return. Looking at the STDLIB application, there were 112 lines of BIF calls in guards that beam_bool failed to convert to test instructions. This commit eliminates all those BIF calls. Here is how I counted the instructions: $ PATH=$ERL_TOP/bin:$PATH erlc -I ../include -I ../../kernel/include -S *.erl $ grep "bif,'[=<>]" *.S | grep -v f,0 dets.S: {bif,'=:=',{f,547},[{x,4},{atom,read_write}],{x,4}}. dets.S: {bif,'=:=',{f,547},[{x,5},{atom,saved}],{x,5}}. dets.S: {bif,'=:=',{f,589},[{x,5},{atom,read}],{x,5}}. . . . $ grep "bif,'[=<>]" *.S | grep -v f,0 | wc 112 224 6765 $
Diffstat (limited to 'lib/compiler/test')
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl33
-rw-r--r--lib/compiler/test/core_SUITE.erl20
-rw-r--r--lib/compiler/test/core_SUITE_data/cover_v3_kernel_1.core147
-rw-r--r--lib/compiler/test/core_SUITE_data/cover_v3_kernel_2.core98
-rw-r--r--lib/compiler/test/core_SUITE_data/cover_v3_kernel_3.core98
-rw-r--r--lib/compiler/test/core_SUITE_data/cover_v3_kernel_4.core82
-rw-r--r--lib/compiler/test/core_SUITE_data/cover_v3_kernel_5.core98
7 files changed, 560 insertions, 16 deletions
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 6742571b86..89f851ac3b 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -887,28 +887,41 @@ matching_and_andalso(Config) when is_list(Config) ->
{'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, blurf)),
{'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, 19)),
- {"abc",<<"xyz">>} = matching_and_andalso_2("abc", <<"-xyz">>),
- {"abc",<<"">>} = matching_and_andalso_2("abc", <<($a-1)>>),
- {"abc",<<"">>} = matching_and_andalso_2("abc", <<($z+1)>>),
- {"abc",<<"">>} = matching_and_andalso_2("abc", <<($A-1)>>),
- {"abc",<<"">>} = matching_and_andalso_2("abc", <<($Z+1)>>),
- error = matching_and_andalso_2([], <<>>),
- error = matching_and_andalso_2([], <<$A>>),
- error = matching_and_andalso_2([], <<$Z>>),
- error = matching_and_andalso_2([], <<$a>>),
- error = matching_and_andalso_2([], <<$z>>),
+ {"abc",<<"xyz">>} = matching_and_andalso_23("abc", <<"-xyz">>),
+ {"abc",<<"">>} = matching_and_andalso_23("abc", <<($a-1)>>),
+ {"abc",<<"">>} = matching_and_andalso_23("abc", <<($z+1)>>),
+ {"abc",<<"">>} = matching_and_andalso_23("abc", <<($A-1)>>),
+ {"abc",<<"">>} = matching_and_andalso_23("abc", <<($Z+1)>>),
+ error = matching_and_andalso_23([], <<>>),
+ error = matching_and_andalso_23([], <<$A>>),
+ error = matching_and_andalso_23([], <<$Z>>),
+ error = matching_and_andalso_23([], <<$a>>),
+ error = matching_and_andalso_23([], <<$z>>),
ok.
matching_and_andalso_1(<<Bitmap/binary>>, K)
when is_integer(K) andalso size(Bitmap) >= K andalso 0 < K ->
ok.
+matching_and_andalso_23(Datetime, Bin) ->
+ Res = matching_and_andalso_2(Datetime, Bin),
+ Res = matching_and_andalso_3(Datetime, Bin),
+ Res.
+
matching_and_andalso_2(Datetime, <<H,T/binary>>)
when not ((H >= $a) andalso (H =< $z)) andalso
not ((H >= $A) andalso (H =< $Z)) ->
{Datetime,T};
matching_and_andalso_2(_, _) -> error.
+%% Contrived example to ensure we cover the handling of 'call' instructions
+%% in v3_codegen:bsm_rename_ctx/4.
+matching_and_andalso_3(Datetime, <<H,T/binary>>)
+ when not ((abs(H) >= $a) andalso (abs(H) =< $z)) andalso
+ not ((abs(H) >= $A) andalso (abs(H) =< $Z)) ->
+ {Datetime,T};
+matching_and_andalso_3(_, _) -> error.
+
%% Thanks to Tomas Stejskal.
otp_7188(Config) when is_list(Config) ->
MP3 = <<84,65,71,68,117,154,105,232,107,121,0,0,0,0,0,0,0,0,0,0,
diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl
index b768f49e2c..f8839da42f 100644
--- a/lib/compiler/test/core_SUITE.erl
+++ b/lib/compiler/test/core_SUITE.erl
@@ -26,8 +26,9 @@
seq_in_guard/1,make_effect_seq/1,eval_is_boolean/1,
unsafe_case/1,nomatch_shadow/1,reversed_annos/1,
map_core_test/1,eval_case/1,bad_boolean_guard/1,
- bs_shadowed_size_var/1
- ]).
+ bs_shadowed_size_var/1,
+ cover_v3_kernel_1/1,cover_v3_kernel_2/1,cover_v3_kernel_3/1,
+ cover_v3_kernel_4/1,cover_v3_kernel_5/1]).
-include_lib("common_test/include/ct.hrl").
@@ -53,8 +54,10 @@ groups() ->
[dehydrated_itracer,nested_tries,seq_in_guard,make_effect_seq,
eval_is_boolean,unsafe_case,nomatch_shadow,reversed_annos,
map_core_test,eval_case,bad_boolean_guard,
- bs_shadowed_size_var
- ]}].
+ bs_shadowed_size_var,
+ cover_v3_kernel_1,cover_v3_kernel_2,cover_v3_kernel_3,
+ cover_v3_kernel_4,cover_v3_kernel_5
+ ]}].
init_per_suite(Config) ->
@@ -64,10 +67,10 @@ end_per_suite(_Config) ->
ok.
init_per_group(_GroupName, Config) ->
- Config.
+ Config.
end_per_group(_GroupName, Config) ->
- Config.
+ Config.
?comp(dehydrated_itracer).
@@ -82,6 +85,11 @@ end_per_group(_GroupName, Config) ->
?comp(eval_case).
?comp(bad_boolean_guard).
?comp(bs_shadowed_size_var).
+?comp(cover_v3_kernel_1).
+?comp(cover_v3_kernel_2).
+?comp(cover_v3_kernel_3).
+?comp(cover_v3_kernel_4).
+?comp(cover_v3_kernel_5).
try_it(Mod, Conf) ->
diff --git a/lib/compiler/test/core_SUITE_data/cover_v3_kernel_1.core b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_1.core
new file mode 100644
index 0000000000..9e5788796f
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_1.core
@@ -0,0 +1,147 @@
+module 'cover_v3_kernel_1' ['cover_v3_kernel_1'/0,
+ 'module_info'/0,
+ 'module_info'/1]
+ attributes []
+'cover_v3_kernel_1'/0 =
+ %% Line 4
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ %% Line 5
+ case apply 'bad_and_args'/1
+ ('x') of
+ <'error'> when 'true' ->
+ %% Line 7
+ case apply 'bad_and_args'/2
+ (1, 2) of
+ <'error'> when 'true' ->
+ %% Line 8
+ case apply 'bad_and_args'/2
+ (1, 'true') of
+ <'error'> when 'true' ->
+ %% Line 9
+ case apply 'bad_and_args'/2
+ ('true', 42) of
+ <'error'> when 'true' ->
+ %% Line 10
+ case apply 'bad_and_args'/2
+ ('true', 'false') of
+ <'error'> when 'true' ->
+ %% Line 11
+ case apply 'bad_and_args'/2
+ ('false', 'true') of
+ <'error'> when 'true' ->
+ %% Line 12
+ case apply 'bad_and_args'/2
+ ('true', 'true') of
+ <'ok'> when 'true' ->
+ %% Line 14
+ 'ok'
+ ( <_@c6> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_@c6})
+ -| ['compiler_generated'] )
+ end
+ ( <_@c5> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_@c5})
+ -| ['compiler_generated'] )
+ end
+ ( <_@c4> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_@c4})
+ -| ['compiler_generated'] )
+ end
+ ( <_@c3> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_@c3})
+ -| ['compiler_generated'] )
+ end
+ ( <_@c2> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_@c2})
+ -| ['compiler_generated'] )
+ end
+ ( <_@c1> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_@c1})
+ -| ['compiler_generated'] )
+ end
+ ( <_@c0> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_@c0})
+ -| ['compiler_generated'] )
+ end
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'cover_v3_kernel_1',0}}] )
+ -| ['compiler_generated'] )
+ end
+'bad_and_args'/1 =
+ %% Line 16
+ fun (_@c0) ->
+ case _@c0 of
+ <A>
+ when try
+ call 'erlang':'and'(A, 42)
+ of <Try> ->
+ Try
+ catch <T,R> ->
+ 'false' ->
+ 'ok'
+ %% Line 17
+ <_@c4> when 'true' ->
+ 'error'
+ ( <_@c3> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_@c3})
+ -| [{'function_name',{'bad_and_args',1}}] )
+ -| ['compiler_generated'] )
+ end
+'bad_and_args'/2 =
+ %% Line 19
+ fun (_@c1,_@c0) ->
+ case <_@c1,_@c0> of
+ <X,Y>
+ when try
+ call 'erlang':'and'(X, Y)
+ of <Try> ->
+ Try
+ catch <T,R> ->
+ 'false' ->
+ 'ok'
+ %% Line 20
+ <_@c6,_@c7> when 'true' ->
+ 'error'
+ ( <_@c5,_@c4> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_@c5,_@c4})
+ -| [{'function_name',{'bad_and_args',2}}] )
+ -| ['compiler_generated'] )
+ end
+'module_info'/0 =
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ call 'erlang':'get_module_info'
+ ('cover_v3_kernel_1')
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'module_info',0}}] )
+ -| ['compiler_generated'] )
+ end
+'module_info'/1 =
+ fun (_@c0) ->
+ case _@c0 of
+ <X> when 'true' ->
+ call 'erlang':'get_module_info'
+ ('cover_v3_kernel_1', X)
+ ( <_@c1> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_@c1})
+ -| [{'function_name',{'module_info',1}}] )
+ -| ['compiler_generated'] )
+ end
+end
diff --git a/lib/compiler/test/core_SUITE_data/cover_v3_kernel_2.core b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_2.core
new file mode 100644
index 0000000000..165aacd691
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_2.core
@@ -0,0 +1,98 @@
+module 'cover_v3_kernel_2' ['cover_v3_kernel_2'/0,
+ 'module_info'/0,
+ 'module_info'/1]
+ attributes []
+'cover_v3_kernel_2'/0 =
+ %% Line 4
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ %% Line 5
+ case apply 'strange_case'/1
+ ('a') of
+ <'ok'> when 'true' ->
+ %% Line 6
+ case apply 'strange_case'/1
+ ('b') of
+ <'ok'> when 'true' ->
+ %% Line 7
+ case apply 'strange_case'/1
+ ('c') of
+ <'error'> when 'true' ->
+ %% Line 8
+ case apply 'strange_case'/1
+ (42) of
+ <'error'> when 'true' ->
+ %% Line 9
+ 'ok'
+ ( <_cor3> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor3})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor2> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor2})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor1> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor1})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor0> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor0})
+ -| ['compiler_generated'] )
+ end
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'cover_v3_kernel_2',0}}] )
+ -| ['compiler_generated'] )
+ end
+'strange_case'/1 =
+ %% Line 12
+ fun (_cor0) ->
+ case _cor0 of
+ <X> when
+ case X of
+ <'a'> when 'true' -> 'true'
+ <'b'> when 'true' -> 'true'
+ <Other> when 'true' -> 'false'
+ end ->
+ 'ok'
+ %% Line 13
+ <_cor4> when 'true' ->
+ 'error'
+ ( <_cor3> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_cor3})
+ -| [{'function_name',{'strange_case',1}}] )
+ -| ['compiler_generated'] )
+ end
+'module_info'/0 =
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ call 'erlang':'get_module_info'
+ ('cover_v3_kernel_2')
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'module_info',0}}] )
+ -| ['compiler_generated'] )
+ end
+'module_info'/1 =
+ fun (_cor0) ->
+ case _cor0 of
+ <X> when 'true' ->
+ call 'erlang':'get_module_info'
+ ('cover_v3_kernel_2', X)
+ ( <_cor1> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_cor1})
+ -| [{'function_name',{'module_info',1}}] )
+ -| ['compiler_generated'] )
+ end
+end
diff --git a/lib/compiler/test/core_SUITE_data/cover_v3_kernel_3.core b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_3.core
new file mode 100644
index 0000000000..88a9edc354
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_3.core
@@ -0,0 +1,98 @@
+module 'cover_v3_kernel_3' ['cover_v3_kernel_3'/0,
+ 'module_info'/0,
+ 'module_info'/1]
+ attributes []
+'cover_v3_kernel_3'/0 =
+ %% Line 4
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ %% Line 5
+ case apply 'strange_case'/1
+ (1) of
+ <'ok'> when 'true' ->
+ %% Line 6
+ case apply 'strange_case'/1
+ (2) of
+ <'ok'> when 'true' ->
+ %% Line 7
+ case apply 'strange_case'/1
+ (42) of
+ <'error'> when 'true' ->
+ %% Line 8
+ case apply 'strange_case'/1
+ ('atom') of
+ <'error'> when 'true' ->
+ %% Line 9
+ 'ok'
+ ( <_cor3> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor3})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor2> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor2})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor1> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor1})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor0> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor0})
+ -| ['compiler_generated'] )
+ end
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'cover_v3_kernel_3',0}}] )
+ -| ['compiler_generated'] )
+ end
+'strange_case'/1 =
+ %% Line 12
+ fun (_cor0) ->
+ case _cor0 of
+ <X> when
+ case X of
+ <1> when 'true' -> 'true'
+ <2> when 'true' -> 'true'
+ <Other> when 'true' -> 'false'
+ end ->
+ 'ok'
+ %% Line 13
+ <_cor4> when 'true' ->
+ 'error'
+ ( <_cor3> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_cor3})
+ -| [{'function_name',{'strange_case',1}}] )
+ -| ['compiler_generated'] )
+ end
+'module_info'/0 =
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ call 'erlang':'get_module_info'
+ ('cover_v3_kernel_3')
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'module_info',0}}] )
+ -| ['compiler_generated'] )
+ end
+'module_info'/1 =
+ fun (_cor0) ->
+ case _cor0 of
+ <X> when 'true' ->
+ call 'erlang':'get_module_info'
+ ('cover_v3_kernel_3', X)
+ ( <_cor1> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_cor1})
+ -| [{'function_name',{'module_info',1}}] )
+ -| ['compiler_generated'] )
+ end
+end
diff --git a/lib/compiler/test/core_SUITE_data/cover_v3_kernel_4.core b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_4.core
new file mode 100644
index 0000000000..905e236f26
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_4.core
@@ -0,0 +1,82 @@
+module 'cover_v3_kernel_4' ['cover_v3_kernel_4'/0,
+ 'module_info'/0,
+ 'module_info'/1]
+ attributes []
+'cover_v3_kernel_4'/0 =
+ %% Line 4
+ fun () ->
+ %% Line 5
+ case apply 'turned_case'/1
+ (20) of
+ <'ok'> when 'true' ->
+ %% Line 6
+ case apply 'turned_case'/1
+ (0) of
+ <'error'> when 'true' ->
+ %% Line 7
+ 'ok'
+ ( <_@c1> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_@c1})
+ -| ['compiler_generated'] )
+ end
+ ( <_@c0> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_@c0})
+ -| ['compiler_generated'] )
+ end
+'turned_case'/1 =
+ %% Line 9
+ fun (_@c0) ->
+ let <True> =
+ apply %% Line 10
+ 'id'/1
+ (%% Line 10
+ 'true')
+ in %% Line 11
+ case <> of
+ %% Line 12
+ <>
+ when try
+ ( let <_@c4> =
+ case call 'erlang':'<'
+ (_@c0, 10) of
+ ( <( 'false'
+ -| ['compiler_generated'] )> when 'true' ->
+ True
+ -| ['compiler_generated'] )
+ ( <( 'true'
+ -| ['compiler_generated'] )> when 'true' ->
+ 'false'
+ -| ['compiler_generated'] )
+ ( <_@c2> when 'true' ->
+ _@c2
+ -| ['compiler_generated'] )
+ end
+ in ( call 'erlang':'=:='
+ (( _@c4
+ -| ['compiler_generated'] ), 'true')
+ -| ['compiler_generated'] )
+ -| ['compiler_generated'] )
+ of <Try> ->
+ Try
+ catch <T,R> ->
+ 'false' ->
+ 'ok'
+ %% Line 13
+ <> when 'true' ->
+ 'error'
+ end
+'id'/1 =
+ %% Line 16
+ fun (_@c0) ->
+ _@c0
+'module_info'/0 =
+ fun () ->
+ call 'erlang':'get_module_info'
+ ('cover_v3_kernel_4')
+'module_info'/1 =
+ fun (_@c0) ->
+ call 'erlang':'get_module_info'
+ ('cover_v3_kernel_4', _@c0)
+end \ No newline at end of file
diff --git a/lib/compiler/test/core_SUITE_data/cover_v3_kernel_5.core b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_5.core
new file mode 100644
index 0000000000..48c1bb84e6
--- /dev/null
+++ b/lib/compiler/test/core_SUITE_data/cover_v3_kernel_5.core
@@ -0,0 +1,98 @@
+module 'cover_v3_kernel_5' ['cover_v3_kernel_5'/0,
+ 'module_info'/0,
+ 'module_info'/1]
+ attributes []
+'cover_v3_kernel_5'/0 =
+ %% Line 4
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ %% Line 5
+ case apply 'strange_case'/1
+ (1) of
+ <'ok'> when 'true' ->
+ %% Line 6
+ case apply 'strange_case'/1
+ (2) of
+ <'ok'> when 'true' ->
+ %% Line 7
+ case apply 'strange_case'/1
+ (42) of
+ <'error'> when 'true' ->
+ %% Line 8
+ case apply 'strange_case'/1
+ ('atom') of
+ <'error'> when 'true' ->
+ %% Line 9
+ 'ok'
+ ( <_cor3> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor3})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor2> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor2})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor1> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor1})
+ -| ['compiler_generated'] )
+ end
+ ( <_cor0> when 'true' ->
+ primop 'match_fail'
+ ({'badmatch',_cor0})
+ -| ['compiler_generated'] )
+ end
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'cover_v3_kernel_5',0}}] )
+ -| ['compiler_generated'] )
+ end
+'strange_case'/1 =
+ %% Line 12
+ fun (_cor0) ->
+ case _cor0 of
+ <X> when
+ case X of
+ <1> when 'true' -> 'true'
+ <2> when 'true' -> 'true'
+ <Other> when 'true' -> X
+ end ->
+ 'ok'
+ %% Line 13
+ <_cor4> when 'true' ->
+ 'error'
+ ( <_cor3> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_cor3})
+ -| [{'function_name',{'strange_case',1}}] )
+ -| ['compiler_generated'] )
+ end
+'module_info'/0 =
+ fun () ->
+ case <> of
+ <> when 'true' ->
+ call 'erlang':'get_module_info'
+ ('cover_v3_kernel_5')
+ ( <> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause'})
+ -| [{'function_name',{'module_info',0}}] )
+ -| ['compiler_generated'] )
+ end
+'module_info'/1 =
+ fun (_cor0) ->
+ case _cor0 of
+ <X> when 'true' ->
+ call 'erlang':'get_module_info'
+ ('cover_v3_kernel_5', X)
+ ( <_cor1> when 'true' ->
+ ( primop 'match_fail'
+ ({'function_clause',_cor1})
+ -| [{'function_name',{'module_info',1}}] )
+ -| ['compiler_generated'] )
+ end
+end