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

From c5979b0d6c491ae70e6866abaeeaba40d596b00f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Mon, 14 Aug 2023 05:36:41 +0200
Subject: [PATCH 6/6] Enhance range analysis for the * operator

Teach beam_bounds:bound/3 to determine a range for the `*` operator
when both factors have a non-negative lower bound. For example:

    m(A, B) when is_integer(A), A >= 2, is_integer(B), B >= 10 ->
        %% Range for A is 2..'+inf'; range for B is 10..'+inf'
        A * B < 100.            % Range for A * B is 20..'+inf'
---
 lib/compiler/src/beam_bounds.erl     |  3 +++
 lib/compiler/src/beam_call_types.erl | 18 ++++++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/lib/compiler/src/beam_bounds.erl b/lib/compiler/src/beam_bounds.erl
index dbe84c566f..cfa6e4d378 100644
--- a/lib/compiler/src/beam_bounds.erl
+++ b/lib/compiler/src/beam_bounds.erl
@@ -118,6 +118,9 @@ bounds('*', R1, R2) ->
             Min = lists:min(All),
             Max = lists:max(All),
             normalize({Min,Max});
+        {{A,'+inf'}, {C,'+inf'}} when abs(A) bsr ?NUM_BITS =:= 0, A >= 0,
+                                      abs(C) bsr ?NUM_BITS =:= 0, C >= 0 ->
+            {A*C,'+inf'};
         {{A,'+inf'}, {C,D}} when abs(A) bsr ?NUM_BITS =:= 0,
                                  abs(C) bsr ?NUM_BITS =:= 0,
                                  abs(D) bsr ?NUM_BITS =:= 0,
diff --git a/lib/compiler/src/beam_call_types.erl b/lib/compiler/src/beam_call_types.erl
index ca05d04d1d..222e586a79 100644
--- a/lib/compiler/src/beam_call_types.erl
+++ b/lib/compiler/src/beam_call_types.erl
@@ -484,6 +484,24 @@ types(erlang, Op, [LHS, RHS]) when Op =:= '+'; Op =:= '-' ->
             mixed_arith_types([LHS, RHS])
     end;
 
+types(erlang, '*', [LHS, RHS]) ->
+    case get_range(LHS, RHS, #t_number{}) of
+        {Type, {A,B}, {C,D}} ->
+            case beam_bounds:bounds('*', {A,B}, {C,D}) of
+                {Min,_Max} when is_integer(Min), Min >= 0 ->
+                    R = {Min,'+inf'},
+                    RetType = case Type of
+                                  integer -> #t_integer{elements=R};
+                                  number -> #t_number{elements=R}
+                              end,
+                    sub_unsafe(RetType, [#t_number{}, #t_number{}]);
+                _ ->
+                    mixed_arith_types([LHS, RHS])
+            end;
+        _ ->
+            mixed_arith_types([LHS, RHS])
+    end;
+
 types(erlang, abs, [Type]) ->
     case meet(Type, #t_number{}) of
         #t_float{} ->
-- 
2.35.3

openSUSE Build Service is sponsored by