diff options
author | Erlang/OTP <[email protected]> | 2019-06-12 09:51:19 +0200 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2019-06-12 09:51:19 +0200 |
commit | fc375a6d56ecd706db43173d8347f086be233188 (patch) | |
tree | ad859c7e4e7a86fd6ac3f063475a87fcd0e94182 | |
parent | 024c51bf0cd9050bf7171e0b3560c7c4ef846301 (diff) | |
parent | 5ee02a07b5c31aea4dd464060fa626d6e6ab8ceb (diff) | |
download | otp-fc375a6d56ecd706db43173d8347f086be233188.tar.gz otp-fc375a6d56ecd706db43173d8347f086be233188.tar.bz2 otp-fc375a6d56ecd706db43173d8347f086be233188.zip |
Merge branch 'john/erts/fix-bad-get_tuple_element-opt/OTP-15871/ERIERL-374' into maint-22
* john/erts/fix-bad-get_tuple_element-opt/OTP-15871/ERIERL-374:
erts: Fix bad loader optimization of get_tuple_element
-rw-r--r-- | erts/emulator/beam/ops.tab | 19 | ||||
-rw-r--r-- | lib/compiler/test/match_SUITE.erl | 26 |
2 files changed, 35 insertions, 10 deletions
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab index 10ca74cd60..e9107933f9 100644 --- a/erts/emulator/beam/ops.tab +++ b/erts/emulator/beam/ops.tab @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2018. All Rights Reserved. +# Copyright Ericsson AB 1997-2019. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -699,13 +699,18 @@ is_tuple NotTupleFail Tuple=x | is_tagged_tuple WrongRecordFail Tuple Arity Atom is_tagged_tuple_ff f? f? rx A a -get_tuple_element Reg=x P1 D1=x | get_tuple_element Reg=x P2 D2=x | \ +get_tuple_element Reg=x P1 D1=x | \ + get_tuple_element Reg=x P2 D2=x | \ get_tuple_element Reg=x P3 D3=x | \ - succ(P1, P2) | succ(P2, P3) | \ - succ(D1, D2) | succ(D2, D3) => i_get_tuple_element3 Reg P1 D1 - -get_tuple_element Reg=x P1 D1=x | get_tuple_element Reg=x P2 D2=x | \ - succ(P1, P2) | succ(D1, D2) => i_get_tuple_element2 Reg P1 D1 + succ(P1, P2) | succ(P2, P3) | succ(D1, D2) | succ(D2, D3) | \ + distinct(D1, Reg) | distinct(D2, Reg) | distinct(D3, Reg) => \ + i_get_tuple_element3 Reg P1 D1 + +get_tuple_element Reg=x P1 D1=x | \ + get_tuple_element Reg=x P2 D2=x | \ + succ(P1, P2) | succ(D1, D2) | \ + distinct(D1, Reg) => \ + i_get_tuple_element2 Reg P1 D1 get_tuple_element Reg=x P1 D1=x | get_tuple_element Reg=x P2 D2=x | \ succ(P1, P2) | distinct(D1, Reg) => i_get_tuple_element2_dst Reg P1 D1 D2 diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl index 94bfbb0efe..aac9de278d 100644 --- a/lib/compiler/test/match_SUITE.erl +++ b/lib/compiler/test/match_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2018. All Rights Reserved. +%% Copyright Ericsson AB 2004-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ match_in_call/1,untuplify/1,shortcut_boolean/1,letify_guard/1, selectify/1,deselectify/1,underscore/1,match_map/1,map_vars_used/1, coverage/1,grab_bag/1,literal_binary/1, - unary_op/1,eq_types/1,match_after_return/1]). + unary_op/1,eq_types/1,match_after_return/1,match_right_tuple/1]). -include_lib("common_test/include/ct.hrl"). @@ -41,7 +41,7 @@ groups() -> shortcut_boolean,letify_guard,selectify,deselectify, underscore,match_map,map_vars_used,coverage, grab_bag,literal_binary,unary_op,eq_types, - match_after_return]}]. + match_after_return,match_right_tuple]}]. init_per_suite(Config) -> @@ -902,4 +902,24 @@ match_after_return(Config) when is_list(Config) -> mar_test_tuple(I) -> {gurka, I}. +match_right_tuple(Config) when is_list(Config) -> + %% The loader wrongly coalesced certain get_tuple_element sequences, fusing + %% the code below into a single i_get_tuple_element2 operating on {x,0} + %% even though the first one overwrites it. + %% + %% {get_tuple_element,{x,0},0,{x,0}}. + %% {get_tuple_element,{x,0},1,{x,1}}. + + Inner = {id(wrong_element), id(ok)}, + Outer = {Inner, id(wrong_tuple)}, + ok = match_right_tuple_1(Outer). + +match_right_tuple_1(T) -> + {A, _} = T, + {_, B} = A, + %% The call ensures that A is in {x,0} and B is in {x,1} + id(force_succ_regs(A, B)). + +force_succ_regs(_A, B) -> B. + id(I) -> I. |