1- /* $NetBSD: tree.c,v 1.668 2025/01/02 18:36:51 rillig Exp $ */
1+ /* $NetBSD: tree.c,v 1.669 2025/01/02 20:02:59 rillig Exp $ */
22
33/*
44 * Copyright (c) 1994, 1995 Jochen Pohl
3737
3838#include <sys/cdefs.h>
3939#if defined(__RCSID )
40- __RCSID ("$NetBSD: tree.c,v 1.668 2025/01/02 18:36:51 rillig Exp $" );
40+ __RCSID ("$NetBSD: tree.c,v 1.669 2025/01/02 20:02:59 rillig Exp $" );
4141#endif
4242
4343#include <float.h>
@@ -146,6 +146,22 @@ si_min_value(const type_t *tp)
146146 return - si_max_value (tp ) - 1 ;
147147}
148148
149+ static int64_t
150+ si_mult_sat (const type_t * tp , int64_t l , int64_t r )
151+ {
152+ uint64_t al = s64_abs (l );
153+ uint64_t ar = s64_abs (r );
154+ bool neg = (l >= 0 ) != (r >= 0 );
155+ uint64_t max = ui_max_value (tp );
156+ uint64_t max_prod = (uint64_t )max + (neg ? 1 : 0 );
157+ if (al == 0 || ar <= max_prod / al )
158+ return l * r ;
159+ else if (neg )
160+ return -1 - (int64_t )(max >> 1 );
161+ else
162+ return (int64_t )(max >> 1 );
163+ }
164+
149165static int64_t
150166si_plus_sat (const type_t * tp , int64_t a , int64_t b )
151167{
@@ -211,8 +227,21 @@ ic_mult(const type_t *tp, integer_constraints a, integer_constraints b)
211227{
212228 integer_constraints c ;
213229
214- if (ic_maybe_signed_binary (tp , a , b )
215- || (a .umax > 0 && b .umax > ic_any (tp ).umax / a .umax ))
230+ if (ic_maybe_signed_binary (tp , a , b )) {
231+ int64_t ll = si_mult_sat (tp , a .smin , b .smin );
232+ int64_t lu = si_mult_sat (tp , a .smin , b .smax );
233+ int64_t ul = si_mult_sat (tp , a .smax , b .smin );
234+ int64_t uu = si_mult_sat (tp , a .smax , b .smax );
235+
236+ c .smin = s64_min (ll , s64_min (lu , s64_min (ul , uu )));
237+ c .smax = s64_max (ll , s64_max (lu , s64_max (ul , uu )));
238+ c .umin = c .smin >= 0 ? (uint64_t )c .smin : 0 ;
239+ c .umax = c .smin >= 0 ? (uint64_t )c .smax : UINT64_MAX ;
240+ c .bclr = ~u64_fill_right (c .umax );
241+ return c ;
242+ }
243+
244+ if (a .umax > 0 && b .umax > ic_any (tp ).umax / a .umax )
216245 return ic_any (tp );
217246
218247 c .smin = INT64_MIN ;
@@ -226,8 +255,11 @@ ic_mult(const type_t *tp, integer_constraints a, integer_constraints b)
226255static integer_constraints
227256ic_div (const type_t * tp , integer_constraints a , integer_constraints b )
228257{
229- if (ic_maybe_signed_binary (tp , a , b ))
258+ if (ic_maybe_signed_binary (tp , a , b )) {
259+ if (b .smin >= 0 )
260+ return a ;
230261 return ic_any (tp );
262+ }
231263
232264 integer_constraints c ;
233265 c .smin = INT64_MIN ;
@@ -1102,8 +1134,8 @@ fold_signed_integer(op_t op, int64_t l, int64_t r,
11021134 * overflow = l == min_value ;
11031135 return * overflow ? l : - l ;
11041136 case MULT :;
1105- uint64_t al = l >= 0 ? ( uint64_t ) l : - ( uint64_t ) l ;
1106- uint64_t ar = r >= 0 ? ( uint64_t ) r : - ( uint64_t ) r ;
1137+ uint64_t al = s64_abs ( l ) ;
1138+ uint64_t ar = s64_abs ( r ) ;
11071139 bool neg = (l >= 0 ) != (r >= 0 );
11081140 uint64_t max_prod = (uint64_t )max_value + (neg ? 1 : 0 );
11091141 if (al > 0 && ar > max_prod / al ) {
0 commit comments