From f79afb23fbd469bed88616784f757707f9985a06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Wed, 4 Feb 2015 15:47:07 +0100 Subject: Correct unsafe optimization of '==' and '/=' Since '=:=' is cheaper than '==', the compiler tries to replace '==' with '=:=' if the result of comparison will be the same. As an example: V == {a,b} can be rewritten to: V =:= {a,b} since the literal on the right side contains no numeric values that '==' would compare differently to '=:='. With the introduction of maps, we will need to take them into account. Since the comparison of maps is planned to change in 18.0, we will be very conservative and only do the optimization if both keys and values are non-numeric. --- lib/compiler/src/sys_core_fold.erl | 5 +++++ lib/compiler/test/core_fold_SUITE.erl | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index f4f5c3f361..ed8f609082 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -1229,6 +1229,11 @@ is_non_numeric([H|T]) -> is_non_numeric(H) andalso is_non_numeric(T); is_non_numeric(Tuple) when is_tuple(Tuple) -> is_non_numeric_tuple(Tuple, tuple_size(Tuple)); +is_non_numeric(Map) when is_map(Map) -> + %% Note that 17.x and 18.x compare keys in different ways. + %% Be very conservative -- require that both keys and values + %% are non-numeric. + is_non_numeric(maps:to_list(Map)); is_non_numeric(Num) when is_number(Num) -> false; is_non_numeric(_) -> true. diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl index 9c7e97a1bf..2de17e7653 100644 --- a/lib/compiler/test/core_fold_SUITE.erl +++ b/lib/compiler/test/core_fold_SUITE.erl @@ -210,6 +210,16 @@ eq(Config) when is_list(Config) -> ?line ?CMP_DIFF(a, [a]), ?line ?CMP_DIFF(a, {1,2,3}), + ?CMP_SAME(#{a=>1.0,b=>2}, #{b=>2.0,a=>1}), + ?CMP_SAME(#{a=>[1.0],b=>[2]}, #{b=>[2.0],a=>[1]}), + + %% The rule for comparing keys are different in 17.x and 18.x. + %% Just test that the results are consistent. + Bool = id(#{1=>a}) == id(#{1.0=>a}), %Unoptimizable. + Bool = id(#{1=>a}) == #{1.0=>a}, %Optimizable. + Bool = #{1=>a} == #{1.0=>a}, %Optimizable. + io:format("Bool = ~p\n", [Bool]), + ok. %% OTP-7117. -- cgit v1.2.3 From f3a8efa2e4fa6f3f64ee38939103bfd55e78bc51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 5 Feb 2015 09:38:45 +0100 Subject: Update primary bootstrap --- bootstrap/lib/compiler/ebin/sys_core_fold.beam | Bin 50428 -> 50468 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/bootstrap/lib/compiler/ebin/sys_core_fold.beam b/bootstrap/lib/compiler/ebin/sys_core_fold.beam index 0001adc5ad..64477ec574 100644 Binary files a/bootstrap/lib/compiler/ebin/sys_core_fold.beam and b/bootstrap/lib/compiler/ebin/sys_core_fold.beam differ -- cgit v1.2.3