18 #include <unordered_set>
28 if(expr.
id()==ID_implies)
32 if(!implies_expr.op0().is_boolean() || !implies_expr.op1().is_boolean())
44 else if(expr.
id()==ID_xor)
46 bool no_change =
true;
51 for(exprt::operandst::const_iterator it = new_operands.begin();
52 it != new_operands.end();)
69 it = new_operands.erase(it);
76 if(new_operands.empty())
80 else if(new_operands.size() == 1)
85 return std::move(new_operands.front());
91 tmp.
operands() = std::move(new_operands);
92 return std::move(tmp);
95 else if(expr.
id()==ID_and || expr.
id()==ID_or)
97 std::unordered_set<exprt, irep_hash> expr_set;
99 bool no_change =
true;
100 bool may_be_reducible_to_interval =
101 expr.
id() == ID_or && expr.
operands().size() > 2;
102 bool may_be_reducible_to_singleton_interval =
103 expr.
id() == ID_and && expr.
operands().size() == 2;
107 for(exprt::operandst::const_iterator it = new_operands.begin();
108 it != new_operands.end();)
110 if(!it->is_boolean())
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;
148 if(may_be_reducible_to_singleton_interval && new_operands.size() == 2)
154 exprt non_const_value;
167 auto const match_first_operand = [&bounds](
const exprt &op) ->
bool {
170 expr_try_dynamic_cast<greater_than_or_equal_exprt>(op))
175 if(!ge_expr->rhs().is_constant())
181 bounds.non_const_value = ge_expr->lhs();
182 bounds.lower = *int_opt;
191 auto const match_second_operand = [&bounds](
const exprt &op) ->
bool {
192 if(
const auto not_expr = expr_try_dynamic_cast<not_exprt>(op))
197 expr_try_dynamic_cast<greater_than_or_equal_exprt>(
202 if(!ge_expr->rhs().is_constant())
204 if(ge_expr->lhs() != bounds.non_const_value)
210 bounds.higher = *int_opt - 1;
221 bool structure_matched = match_first_operand(new_operands[0]) &&
222 match_second_operand(new_operands[1]);
224 if(structure_matched && bounds.lower == bounds.higher)
230 expr_dynamic_cast<greater_than_or_equal_exprt>(new_operands[0]);
236 if(may_be_reducible_to_interval)
238 std::optional<symbol_exprt> symbol_opt;
239 std::set<mp_integer> values;
240 for(
const exprt &op : new_operands)
244 std::swap(eq.
lhs(), eq.
rhs());
245 if(
auto s = expr_try_dynamic_cast<symbol_exprt>(eq.
lhs()))
247 if(!symbol_opt.has_value())
250 if(*s == *symbol_opt)
252 if(
auto c = expr_try_dynamic_cast<constant_exprt>(eq.
rhs()))
255 if(c_tmp.
type().
id() == ID_c_enum_tag)
257 if(
auto int_opt = numeric_cast<mp_integer>(c_tmp))
259 values.insert(*int_opt);
270 if(symbol_opt.has_value() && values.size() >= 3)
274 if(upper - lower + 1 ==
mp_integer{values.size()})
276 typet type = symbol_opt->type();
277 if(symbol_opt->type().id() == ID_c_enum_tag)
296 for(
const exprt &op : new_operands)
298 op.id() == ID_not && op.is_boolean() &&
299 expr_set.find(
to_not_expr(op).op()) != expr_set.end())
304 if(new_operands.empty())
308 else if(new_operands.size() == 1)
310 return std::move(new_operands.front());
316 tmp.
operands() = std::move(new_operands);
317 return std::move(tmp);
345 else if(op.
id()==ID_and ||
355 tmp.
id(tmp.
id() == ID_and ? ID_or : ID_and);
357 return std::move(tmp);
359 else if(op.
id()==ID_notequal)
363 return std::move(tmp);
365 else if(op.
id()==ID_exists)
371 else if(op.
id() == ID_forall)
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
A base class for binary expressions.
A constant literal expression.
Base class for all expressions.
std::vector< exprt > operandst
bool has_operands() const
Return true if there is at least one operand.
bool is_true() const
Return whether the expression is a constant representing true.
bool is_boolean() const
Return whether the expression represents a Boolean.
bool is_false() const
Return whether the expression is a constant representing false.
typet & type()
Return the type of the expression.
bool is_constant() const
Return whether the expression is a constant.
The Boolean constant false.
const irep_idt & id() const
Binary less than or equal operator expression.
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
static resultt changed(resultt<> result)
resultt simplify_boolean(const exprt &)
resultt simplify_not(const not_exprt &)
static resultt unchanged(exprt expr)
The Boolean constant true.
static exprt conditional_cast(const exprt &expr, const typet &type)
The type of an expression, extends irept.
#define Forall_operands(it, expr)
constant_exprt make_boolean_expr(bool value)
returns true_exprt if given true and false_exprt otherwise
Deprecated expression utility functions.
bool is_false(const literalt &l)
bool is_true(const literalt &l)
API to expression classes for 'mathematical' expressions.
const exists_exprt & to_exists_expr(const exprt &expr)
const forall_exprt & to_forall_expr(const exprt &expr)
#define PRECONDITION(CONDITION)
API to expression classes.
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
const not_exprt & to_not_expr(const exprt &expr)
Cast an exprt to an not_exprt.
const equal_exprt & to_equal_expr(const exprt &expr)
Cast an exprt to an equal_exprt.
const implies_exprt & to_implies_expr(const exprt &expr)
Cast an exprt to a implies_exprt.