@@ -8,12 +8,15 @@ Author: Daniel Kroening, kroening@kroening.com
88
99#include " simplify_expr_class.h"
1010
11- #include < unordered_set >
12-
11+ #include " arith_tools.h "
12+ # include " c_types.h "
1313#include " expr_util.h"
1414#include " mathematical_expr.h"
15+ #include " namespace.h"
1516#include " std_expr.h"
1617
18+ #include < unordered_set>
19+
1720simplify_exprt::resultt<> simplify_exprt::simplify_boolean (const exprt &expr)
1821{
1922 if (!expr.has_operands ())
@@ -96,6 +99,8 @@ simplify_exprt::resultt<> simplify_exprt::simplify_boolean(const exprt &expr)
9699 std::unordered_set<exprt, irep_hash> expr_set;
97100
98101 bool no_change = true ;
102+ bool may_be_reducible_to_interval =
103+ expr.id () == ID_or && expr.operands ().size () > 2 ;
99104
100105 exprt::operandst new_operands = expr.operands ();
101106
@@ -127,7 +132,70 @@ simplify_exprt::resultt<> simplify_exprt::simplify_boolean(const exprt &expr)
127132 no_change = false ;
128133 }
129134 else
135+ {
136+ if (may_be_reducible_to_interval)
137+ may_be_reducible_to_interval = it->id () == ID_equal;
130138 it++;
139+ }
140+ }
141+
142+ if (may_be_reducible_to_interval)
143+ {
144+ optionalt<symbol_exprt> symbol_opt;
145+ std::set<mp_integer> values;
146+ for (const exprt &op : new_operands)
147+ {
148+ equal_exprt eq = to_equal_expr (op);
149+ if (eq.lhs ().is_constant ())
150+ std::swap (eq.lhs (), eq.rhs ());
151+ if (auto s = expr_try_dynamic_cast<symbol_exprt>(eq.lhs ()))
152+ {
153+ if (!symbol_opt.has_value ())
154+ symbol_opt = *s;
155+
156+ if (*s == *symbol_opt)
157+ {
158+ if (auto c = expr_try_dynamic_cast<constant_exprt>(eq.rhs ()))
159+ {
160+ constant_exprt c_tmp = *c;
161+ if (c_tmp.type ().id () == ID_c_enum_tag)
162+ c_tmp.type () = ns.follow_tag (to_c_enum_tag_type (c_tmp.type ()));
163+ if (auto int_opt = numeric_cast<mp_integer>(c_tmp))
164+ {
165+ values.insert (*int_opt);
166+ continue ;
167+ }
168+ }
169+ }
170+ }
171+
172+ symbol_opt.reset ();
173+ break ;
174+ }
175+
176+ if (symbol_opt.has_value () && values.size () >= 3 )
177+ {
178+ mp_integer lower = *values.begin ();
179+ mp_integer upper = *std::prev (values.end ());
180+ if (upper - lower + 1 == mp_integer{values.size ()})
181+ {
182+ typet type = symbol_opt->type ();
183+ if (symbol_opt->type ().id () == ID_c_enum_tag)
184+ {
185+ type = ns.follow_tag (to_c_enum_tag_type (symbol_opt->type ()))
186+ .underlying_type ();
187+ }
188+
189+ less_than_or_equal_exprt lb{
190+ from_integer (lower, type),
191+ typecast_exprt::conditional_cast (*symbol_opt, type)};
192+ less_than_or_equal_exprt ub{
193+ typecast_exprt::conditional_cast (*symbol_opt, type),
194+ from_integer (upper, type)};
195+
196+ return and_exprt{lb, ub};
197+ }
198+ }
131199 }
132200
133201 // search for a and !a
0 commit comments