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