@@ -2105,35 +2105,37 @@ def __init__(self, options: HalmosConfig, fun_info: FunctionInfo) -> None:
21052105 def div_xy_y (self , w1 : Word , w2 : Word , signed : bool = False ) -> Word :
21062106 # return the number of bits required to represent the given value. default = 256
21072107 def bitsize (w : Word ) -> int :
2108+ z3w = w .as_z3 () if hasattr (w , "as_z3" ) else w
21082109 if (
2109- w .decl ().name () == "concat"
2110- and is_bv_value (w .arg (0 ))
2111- and int (str (w .arg (0 ))) == 0
2110+ z3w .decl ().name () == "concat"
2111+ and is_bv_value (z3w .arg (0 ))
2112+ and int (str (z3w .arg (0 ))) == 0
21122113 ):
2113- return 256 - w .arg (0 ).size ()
2114+ return 256 - z3w .arg (0 ).size ()
21142115 return 256
21152116
2116- w1 = normalize (w1 )
2117+ w1_z3 = w1 .as_z3 () if hasattr (w1 , "as_z3" ) else w1
2118+ w2_z3 = w2 .as_z3 () if hasattr (w2 , "as_z3" ) else w2
21172119
2118- if w1 .decl ().name () == "bvmul" and w1 .num_args () == 2 :
2119- x = w1 .arg (0 )
2120- y = w1 .arg (1 )
2121- if eq (w2 , x ) or eq (w2 , y ): # xy/x or xy/y
2120+ if w1_z3 .decl ().name () == "bvmul" and w1_z3 .num_args () == 2 :
2121+ x = w1_z3 .arg (0 )
2122+ y = w1_z3 .arg (1 )
2123+ if eq (w2_z3 , x ) or eq (w2_z3 , y ): # xy/x or xy/y
21222124 if signed :
21232125 # Signed division: safe to simplify if divisor exactly matches factor
2124- if eq (w2 , x ):
2125- return y
2126- elif eq (w2 , y ):
2127- return x
2126+ if eq (w2_z3 , x ):
2127+ return BV ( y , w1 . size ) # wrap back
2128+ elif eq (w2_z3 , y ):
2129+ return BV ( x , w1 . size )
21282130 else :
21292131 # Unsigned division: check for overflow
21302132 size_x = bitsize (x )
21312133 size_y = bitsize (y )
21322134 if size_x + size_y <= 256 :
2133- if eq (w2 , x ): # xy/x == y
2134- return y
2135+ if eq (w2_z3 , x ): # xy/x == y
2136+ return BV ( y , w1 . size ) # wrap back
21352137 else : # xy/y == x
2136- return x
2138+ return BV ( x , w1 . size )
21372139 return None
21382140
21392141 def mk_div (self , ex : Exec , x : Any , y : Any ) -> Any :
@@ -2178,7 +2180,7 @@ def arith(self, ex: Exec, op: int, w1: Word, w2: Word) -> Word:
21782180 return term
21792181
21802182 if op == OP_SDIV :
2181- # Try signed simplification
2183+ # Try signed simplification first
21822184 simplified_sdiv = self .div_xy_y (w1 , w2 , signed = True )
21832185 if simplified_sdiv is not None :
21842186 return simplified_sdiv
0 commit comments