File 3135-Enhance-range-analysis-for-the-bor-operator.patch of Package erlang

From 7e33bac60cd7ac8a3f3929d3e976c503407958d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Sun, 13 Aug 2023 07:32:58 +0200
Subject: [PATCH 5/6] Enhance range analysis for the bor operator

Teach beam_bounds:bounds/3 to calculate a range for the `bor` operator
for negative or partly unbounded arguments. For example:

    bor0(A) when is_integer(A), -10 =< A, A =< 10 ->
        %% Range for A is -10..10
        A bor 1.                % Range is '-inf'..11

    bor1(A, B) when is_integer(A), A < 0, is_integer(B), B < 0 ->
        %% Range for A and B is '-inf'..-1
        A bor B.                % Range is '-inf'..-1

    bor2(A, B) when is_integer(A), A >= 1, is_integer(B), B >= 10 ->
        %% Range for A is 1..'+inf'; range for B is 10..'+inf'
        A bor B.                % Range is 10..'+inf'
---
 lib/compiler/src/beam_bounds.erl        | 39 ++++++++++++++++++-------
 lib/compiler/test/beam_bounds_SUITE.erl | 14 +++++++--
 2 files changed, 41 insertions(+), 12 deletions(-)

diff --git a/lib/compiler/src/beam_bounds.erl b/lib/compiler/src/beam_bounds.erl
index 034aded4b8..dbe84c566f 100644
--- a/lib/compiler/src/beam_bounds.erl
+++ b/lib/compiler/src/beam_bounds.erl
@@ -156,12 +156,13 @@ bounds('band', R1, R2) ->
     end;
 bounds('bor', R1, R2) ->
     case {R1,R2} of
-        {{A,B}, {C,D}} when A bsr ?NUM_BITS =:= 0, A >= 0,
-                            C bsr ?NUM_BITS =:= 0, C >= 0,
-                            is_integer(B), is_integer(D) ->
+        {{A,B}, {C,D}} when A =:= '-inf' orelse abs(A) bsr ?NUM_BITS =:= 0,
+                            C =:= '-inf' orelse abs(C) bsr ?NUM_BITS =:= 0,
+                            B =:= '+inf' orelse abs(B) bsr ?NUM_BITS =:= 0,
+                            D =:= '+inf' orelse abs(D) bsr ?NUM_BITS =:= 0 ->
             Min = min_bor(A, B, C, D),
             Max = max_bor(A, B, C, D),
-            {Min,Max};
+            normalize({Min,Max});
         {_, _} ->
             any
     end;
@@ -379,8 +380,13 @@ max_band(A, B, C, D, M) ->
     end.
 
 min_bor(A, B, C, D) ->
-    M = 1 bsl upper_bit(A bxor C),
-    min_bor(A, B, C, D, M).
+    case inf_lt(inf_min(A, C), 0) of
+        true ->
+            '-inf';
+        false ->
+            M = 1 bsl upper_bit(A bxor C),
+            min_bor(A, B, C, D, M)
+    end.
 
 min_bor(A, _B, C, _D, 0) ->
     A bor C;
@@ -404,10 +410,23 @@ min_bor(A, B, C, D, M) ->
             min_bor(A, B, C, D, M bsr 1)
     end.
 
-max_bor(A, B, C, D) ->
-    Intersection = B band D,
-    M = 1 bsl upper_bit(Intersection),
-    max_bor(Intersection, A, B, C, D, M).
+max_bor(A0, B, C0, D) ->
+    A = inf_max(A0, 0),
+    C = inf_max(C0, 0),
+    case inf_max(B, D) of
+        '+inf' ->
+            '+inf';
+        Max when Max < 0 ->
+            %% Both B and D are negative. The intersection would be
+            %% infinite.
+            -1;
+        _ ->
+            %% At least one of B and D are positive. The intersection
+            %% has a finite size.
+            Intersection = B band D,
+            M = 1 bsl upper_bit(Intersection),
+            max_bor(Intersection, A, B, C, D, M)
+    end.
 
 max_bor(_Intersection, _A, B, _C, D, 0) ->
     B bor D;
diff --git a/lib/compiler/test/beam_bounds_SUITE.erl b/lib/compiler/test/beam_bounds_SUITE.erl
index 5f5d2441f1..bee79533b9 100644
--- a/lib/compiler/test/beam_bounds_SUITE.erl
+++ b/lib/compiler/test/beam_bounds_SUITE.erl
@@ -181,8 +181,18 @@ band_bounds(_Config) ->
 bor_bounds(_Config) ->
     test_commutative('bor'),
 
-    any = beam_bounds:bounds('bor', {-10,0},{-1,10}),
-    any = beam_bounds:bounds('bor', {-20,-10}, {-1,10}),
+    {'-inf',15} = beam_bounds:bounds('bor', {-10,7},{3,10}),
+    {'-inf',11} = beam_bounds:bounds('bor', {-10,1},{-1,10}),
+    {'-inf',-1} = beam_bounds:bounds('bor', {-20,-10}, {-2,10}),
+
+    {'-inf',15} = beam_bounds:bounds('bor', {'-inf',10}, {3,5}),
+    {'-inf',-1} = beam_bounds:bounds('bor', {-20,-10}, {-100,-50}),
+
+    any = beam_bounds:bounds('bor', {-20,-10}, {-2,'+inf'}),
+    any = beam_bounds:bounds('bor', {-20,'+inf'}, {-7,-3}),
+
+    {16,'+inf'} = beam_bounds:bounds('bor', {0,8}, {16,'+inf'}),
+    {16,'+inf'} = beam_bounds:bounds('bor', {3,'+inf'}, {16,'+inf'}),
 
     ok.
 
-- 
2.35.3

openSUSE Build Service is sponsored by