18 #include <unordered_set>
25 if(expr.
type().
id()!=ID_bool)
28 if(expr.
id()==ID_implies)
33 implies_expr.op0().type().id() != ID_bool ||
34 implies_expr.op1().type().id() != ID_bool)
46 else if(expr.
id()==ID_xor)
48 bool no_change =
true;
53 for(exprt::operandst::const_iterator it = new_operands.begin();
54 it != new_operands.end();)
56 if(it->type().id()!=ID_bool)
71 it = new_operands.erase(it);
78 if(new_operands.empty())
82 else if(new_operands.size() == 1)
87 return std::move(new_operands.front());
93 tmp.
operands() = std::move(new_operands);
94 return std::move(tmp);
97 else if(expr.
id()==ID_and || expr.
id()==ID_or)
99 std::unordered_set<exprt, irep_hash> expr_set;
101 bool no_change =
true;
102 bool may_be_reducible_to_interval =
103 expr.
id() == ID_or && expr.
operands().size() > 2;
107 for(exprt::operandst::const_iterator it = new_operands.begin();
108 it != new_operands.end();)
110 if(it->type().id()!=ID_bool)
127 !expr_set.insert(*it).second;
131 it = new_operands.erase(it);
136 if(may_be_reducible_to_interval)
137 may_be_reducible_to_interval = it->id() == ID_equal;
142 if(may_be_reducible_to_interval)
145 std::set<mp_integer> values;
146 for(
const exprt &op : new_operands)
150 std::swap(eq.
lhs(), eq.
rhs());
151 if(
auto s = expr_try_dynamic_cast<symbol_exprt>(eq.
lhs()))
153 if(!symbol_opt.has_value())
156 if(*s == *symbol_opt)
158 if(
auto c = expr_try_dynamic_cast<constant_exprt>(eq.
rhs()))
161 if(c_tmp.
type().
id() == ID_c_enum_tag)
163 if(
auto int_opt = numeric_cast<mp_integer>(c_tmp))
165 values.insert(*int_opt);
176 if(symbol_opt.has_value() && values.size() >= 3)
180 if(upper - lower + 1 ==
mp_integer{values.size()})
182 typet type = symbol_opt->type();
183 if(symbol_opt->type().id() == ID_c_enum_tag)
202 for(
const exprt &op : new_operands)
204 op.id() == ID_not && op.type().id() == ID_bool &&
205 expr_set.find(
to_not_expr(op).op()) != expr_set.end())
210 if(new_operands.empty())
214 else if(new_operands.size() == 1)
216 return std::move(new_operands.front());
222 tmp.
operands() = std::move(new_operands);
223 return std::move(tmp);
234 if(expr.
type().
id()!=ID_bool ||
252 else if(op.
id()==ID_and ||
262 tmp.
id(tmp.
id() == ID_and ? ID_or : ID_and);
264 return std::move(tmp);
266 else if(op.
id()==ID_notequal)
270 return std::move(tmp);
272 else if(op.
id()==ID_exists)
278 else if(op.
id() == ID_forall)