From 1127a7463b86db021a08123f792084ea00788349 Mon Sep 17 00:00:00 2001 From: Frej Drejhammar Date: Wed, 24 Jul 2024 09:37:55 +0200 Subject: [PATCH] compiler: Avoid reuse hint for update_record with > 1 update Take care to not produce a reuse hint when more than one update exists. There is no point in attempting the reuse optimization when more than one element is updated, as checking more than one element at runtime is known to be slower than just copying the tuple in most cases. Additionally, using a copy hint occasionally allows the alias analysis pass to do a better job. --- lib/compiler/src/beam_ssa_type.erl | 18 ++++++++++++++++-- .../test/beam_ssa_check_SUITE_data/alias.erl | 4 ++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl index fdc5d06dd9b9..f34dd1cb51f4 100644 --- a/lib/compiler/src/beam_ssa_type.erl +++ b/lib/compiler/src/beam_ssa_type.erl @@ -1561,12 +1561,26 @@ will_succeed_1(#b_set{op=wait_timeout}, _Src, _Ts) -> will_succeed_1(#b_set{}, _Src, _Ts) -> 'maybe'. +%% Take care to not produce a reuse hint when more than one update +%% exists. There is no point in attempting the reuse optimization when +%% more than one element is updated, as checking more than one element +%% at runtime is known to be slower than just copying the tuple in +%% most cases. Additionally, using a copy hint occasionally allows the +%% alias analysis pass to do a better job. simplify_update_record(Src, Hint0, Updates, Ts) -> case sur_1(Updates, concrete_type(Src, Ts), Ts, Hint0, []) of + {#b_literal{val=reuse}, []} when length(Updates) > 2 -> + {changed, #b_literal{val=copy}, Updates}; {Hint0, []} -> unchanged; - {Hint, Skipped} -> - {changed, Hint, sur_skip(Updates, Skipped)} + {Hint1, Skipped} -> + Updates1 = sur_skip(Updates, Skipped), + Hint = if length(Updates1) > 2 -> + #b_literal{val=copy}; + true -> + Hint1 + end, + {changed, Hint, Updates1} end. sur_1([Index, Arg | Updates], RecordType, Ts, Hint, Skipped) -> diff --git a/lib/compiler/test/beam_ssa_check_SUITE_data/alias.erl b/lib/compiler/test/beam_ssa_check_SUITE_data/alias.erl index 22c2ee89a7f1..55400ccd9d27 100644 --- a/lib/compiler/test/beam_ssa_check_SUITE_data/alias.erl +++ b/lib/compiler/test/beam_ssa_check_SUITE_data/alias.erl @@ -1077,7 +1077,7 @@ update_record0() -> update_record0([Val|Ls], Acc=#r0{not_aliased=N}) -> %ssa% (_, Rec) when post_ssa_opt -> -%ssa% _ = update_record(reuse, 3, Rec, 3, A, 2, NA) {unique => [Rec, NA], aliased => [A]}. +%ssa% _ = update_record(copy, 3, Rec, 3, A, 2, NA) {unique => [Rec, NA], aliased => [A]}. R = Acc#r0{not_aliased=N+1,aliased=Val}, update_record0(Ls, R); update_record0([], Acc) -> @@ -1090,7 +1090,7 @@ update_record1() -> update_record1([Val|Ls], Acc=#r1{not_aliased0=N0,not_aliased1=N1}) -> %ssa% (_, Rec) when post_ssa_opt -> -%ssa% _ = update_record(reuse, 3, Rec, 3, NA0, 2, NA1) {unique => [Rec, NA1, NA0], source_dies => true}. +%ssa% _ = update_record(copy, 3, Rec, 3, NA0, 2, NA1) {unique => [Rec, NA1, NA0], source_dies => true}. R = Acc#r1{not_aliased0=N0+1,not_aliased1=[Val|N1]}, update_record1(Ls, R); update_record1([], Acc) ->