File 1181-Simplify-range-check-for-element-2-on-a-known-litera.patch of Package erlang

From 8faccec0379e4e40177985cc853c3ae4b1af7314 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Mon, 26 Aug 2024 07:36:33 +0200
Subject: [PATCH] Simplify range check for element/2 on a known literal tuple

This will improve code in the `json` and `base64` modules.
---
 .../beam/jit/arm/instr_guard_bifs.cpp         | 17 ++++-------
 .../beam/jit/x86/instr_guard_bifs.cpp         | 18 ++++-------
 erts/emulator/test/guard_SUITE.erl            | 30 +++++++++++++++++++
 3 files changed, 41 insertions(+), 24 deletions(-)

diff --git a/erts/emulator/beam/jit/arm/instr_guard_bifs.cpp b/erts/emulator/beam/jit/arm/instr_guard_bifs.cpp
index 7f986daf09..0e66523d39 100644
--- a/erts/emulator/beam/jit/arm/instr_guard_bifs.cpp
+++ b/erts/emulator/beam/jit/arm/instr_guard_bifs.cpp
@@ -609,19 +609,12 @@ void BeamModuleAssembler::emit_bif_element(const ArgLabel &Fail,
 
             a.asr(TMP3, pos.reg, imm(_TAG_IMMED1_SIZE));
 
-            if (min >= 1) {
-                comment("skipped check for position >= 1");
+            if (1 <= min && max <= size) {
+                comment("skipped check for known safe position");
             } else {
-                a.cmp(TMP3, imm(1));
-                a.b_mi(fail);
-            }
-
-            if (size >= max) {
-                comment("skipped check for position beyond tuple");
-            } else {
-                mov_imm(TMP2, size);
-                a.cmp(TMP2, TMP3);
-                a.b_lo(fail);
+                a.sub(TMP2, TMP3, imm(1));
+                cmp(TMP2, size);
+                a.b_hs(fail);
             }
 
             a.ldr(dst.reg, arm::Mem(TMP1, TMP3, arm::lsl(3)));
diff --git a/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp b/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp
index 3898068237..c95bfcf69a 100644
--- a/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp
+++ b/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp
@@ -380,19 +380,13 @@ void BeamModuleAssembler::emit_bif_element(const ArgLabel &Fail,
 
             a.mov(RET, ARG1);
             a.sar(RET, imm(_TAG_IMMED1_SIZE));
-            if (min >= 1) {
-                comment("skipped check for position =:= 0 since it is always "
-                        ">= 1");
-            } else {
-                a.short_().jz(error);
-            }
-            if (min >= 0 && size >= max) {
-                comment("skipped check for negative position and position "
-                        "beyond tuple");
+
+            if (1 <= min && max <= size) {
+                comment("skipped check for known safe position");
             } else {
-                /* Note: Also checks for negative size. */
-                a.cmp(RET, imm(size));
-                a.short_().ja(error);
+                a.lea(ARG3, x86::qword_ptr(RET, -1));
+                cmp(ARG3, size, ARG5);
+                a.short_().jae(error);
             }
 
             a.mov(RET, x86::qword_ptr(ARG4, RET, 3));
diff --git a/erts/emulator/test/guard_SUITE.erl b/erts/emulator/test/guard_SUITE.erl
index 5bf6871f8c..29a716f50d 100644
--- a/erts/emulator/test/guard_SUITE.erl
+++ b/erts/emulator/test/guard_SUITE.erl
@@ -26,6 +26,7 @@
 	 type_tests/1,guard_bif_binary_part/1]).
 
 -include_lib("common_test/include/ct.hrl").
+-include_lib("stdlib/include/assert.hrl").
 
 -export([init/3]).
 -import(lists, [member/2]).
@@ -55,6 +56,19 @@ bad_tuple(Config) when is_list(Config) ->
     error = bad_tuple1({a, b}),
     x = bad_tuple1({x, b}),
     y = bad_tuple1({a, b, y}),
+
+    ?assertError(badarg, int_to_atom_1(-1)),
+    ?assertError(badarg, int_to_atom_1(0)),
+    ?assertError(badarg, int_to_atom_1(4)),
+    ?assertError(badarg, int_to_atom_1(4.2)),
+    ?assertError(badarg, int_to_atom_1(x)),
+
+    ?assertError(badarg, int_to_atom_2(-1)),
+    ?assertError(badarg, int_to_atom_2(0)),
+    ?assertError(badarg, int_to_atom_2(4)),
+    ?assertError(badarg, int_to_atom_2(3.0)),
+    ?assertError(badarg, int_to_atom_2(x)),
+
     ok.
 
 bad_tuple1(T) when element(1, T) == x ->
@@ -64,6 +78,22 @@ bad_tuple1(T) when element(3, T) == y ->
 bad_tuple1(_) ->
     error.
 
+int_to_atom_1(N) ->
+    if
+        is_integer(N) ->
+            element(N, {a,b,c});
+        true ->
+            element(N, {a,b,c})
+    end.
+
+int_to_atom_2(N0) ->
+    case id(N0) of
+        N when is_integer(N) ->
+            element(N, {a,b,c});
+        Other ->
+            element(Other, {a,b,c})
+    end.
+
 test_heap_guards(Config) when is_list(Config) ->
     ct:timetrap({minutes, 2}),
     
-- 
2.43.0

openSUSE Build Service is sponsored by