@@ -2047,6 +2047,117 @@ simplify_exprt::simplify_complex(const unary_exprt &expr)
20472047 return unchanged (expr);
20482048}
20492049
2050+ simplify_exprt::resultt<>
2051+ simplify_exprt::simplify_overflow_binary (const binary_exprt &expr)
2052+ {
2053+ // zero is a neutral element for all operations supported here
2054+ if (
2055+ expr.op1 ().is_zero () ||
2056+ (expr.op0 ().is_zero () && expr.id () != ID_overflow_minus))
2057+ {
2058+ return false_exprt{};
2059+ }
2060+
2061+ // we only handle the case of same operand types
2062+ if (expr.op0 ().type () != expr.op1 ().type ())
2063+ return unchanged (expr);
2064+
2065+ // catch some cases over mathematical types
2066+ const irep_idt &op_type_id = expr.op0 ().type ().id ();
2067+ if (
2068+ op_type_id == ID_integer || op_type_id == ID_rational ||
2069+ op_type_id == ID_real)
2070+ {
2071+ return false_exprt{};
2072+ }
2073+
2074+ if (op_type_id == ID_natural && expr.id () != ID_overflow_minus)
2075+ return false_exprt{};
2076+
2077+ // we only handle constants over signedbv/unsignedbv for the remaining cases
2078+ if (op_type_id != ID_signedbv && op_type_id != ID_unsignedbv)
2079+ return unchanged (expr);
2080+
2081+ if (!expr.op0 ().is_constant () || !expr.op1 ().is_constant ())
2082+ return unchanged (expr);
2083+
2084+ const auto op0_value = numeric_cast<mp_integer>(expr.op0 ());
2085+ const auto op1_value = numeric_cast<mp_integer>(expr.op1 ());
2086+ if (!op0_value.has_value () || !op1_value.has_value ())
2087+ return unchanged (expr);
2088+
2089+ mp_integer no_overflow_result;
2090+ if (expr.id () == ID_overflow_plus)
2091+ no_overflow_result = *op0_value + *op1_value;
2092+ else if (expr.id () == ID_overflow_minus)
2093+ no_overflow_result = *op0_value - *op1_value;
2094+ else if (expr.id () == ID_overflow_mult)
2095+ no_overflow_result = *op0_value * *op1_value;
2096+ else if (expr.id () == ID_overflow_shl)
2097+ no_overflow_result = *op0_value << *op1_value;
2098+ else
2099+ UNREACHABLE;
2100+
2101+ const std::size_t width = to_bitvector_type (expr.op0 ().type ()).get_width ();
2102+ const integer_bitvector_typet bv_type{op_type_id, width};
2103+ if (
2104+ no_overflow_result < bv_type.smallest () ||
2105+ no_overflow_result > bv_type.largest ())
2106+ {
2107+ return true_exprt{};
2108+ }
2109+ else
2110+ return false_exprt{};
2111+ }
2112+
2113+ simplify_exprt::resultt<>
2114+ simplify_exprt::simplify_overflow_unary (const unary_exprt &expr)
2115+ {
2116+ // zero is a neutral element for all operations supported here
2117+ if (expr.op ().is_zero ())
2118+ return false_exprt{};
2119+
2120+ // catch some cases over mathematical types
2121+ const irep_idt &op_type_id = expr.op ().type ().id ();
2122+ if (
2123+ op_type_id == ID_integer || op_type_id == ID_rational ||
2124+ op_type_id == ID_real)
2125+ {
2126+ return false_exprt{};
2127+ }
2128+
2129+ if (op_type_id == ID_natural)
2130+ return true_exprt{};
2131+
2132+ // we only handle constants over signedbv/unsignedbv for the remaining cases
2133+ if (op_type_id != ID_signedbv && op_type_id != ID_unsignedbv)
2134+ return unchanged (expr);
2135+
2136+ if (!expr.op ().is_constant ())
2137+ return unchanged (expr);
2138+
2139+ const auto op_value = numeric_cast<mp_integer>(expr.op ());
2140+ if (!op_value.has_value ())
2141+ return unchanged (expr);
2142+
2143+ mp_integer no_overflow_result;
2144+ if (expr.id () == ID_overflow_unary_minus)
2145+ no_overflow_result = -*op_value;
2146+ else
2147+ UNREACHABLE;
2148+
2149+ const std::size_t width = to_bitvector_type (expr.op ().type ()).get_width ();
2150+ const integer_bitvector_typet bv_type{op_type_id, width};
2151+ if (
2152+ no_overflow_result < bv_type.smallest () ||
2153+ no_overflow_result > bv_type.largest ())
2154+ {
2155+ return true_exprt{};
2156+ }
2157+ else
2158+ return false_exprt{};
2159+ }
2160+
20502161bool simplify_exprt::simplify_node_preorder (exprt &expr)
20512162{
20522163 bool result=true ;
@@ -2290,6 +2401,16 @@ simplify_exprt::resultt<> simplify_exprt::simplify_node(exprt node)
22902401 {
22912402 r = simplify_complex (to_unary_expr (expr));
22922403 }
2404+ else if (
2405+ expr.id () == ID_overflow_plus || expr.id () == ID_overflow_minus ||
2406+ expr.id () == ID_overflow_mult || expr.id () == ID_overflow_shl)
2407+ {
2408+ r = simplify_overflow_binary (to_binary_expr (expr));
2409+ }
2410+ else if (expr.id () == ID_overflow_unary_minus)
2411+ {
2412+ r = simplify_overflow_unary (to_unary_expr (expr));
2413+ }
22932414
22942415 if (!no_change_join_operands)
22952416 r = changed (r);
0 commit comments