Skip to content

Commit 81943f2

Browse files
committed
Split ID_and/ID_or vs ID_xor simplification
The code paths are vastly different, and splitting thus enables optimisations.
1 parent 77236cc commit 81943f2

File tree

1 file changed

+60
-61
lines changed

1 file changed

+60
-61
lines changed

src/util/simplify_expr_boolean.cpp

+60-61
Original file line numberDiff line numberDiff line change
@@ -72,21 +72,60 @@ bool simplify_exprt::simplify_boolean(exprt &expr)
7272
return false;
7373
}
7474
}
75-
else if(expr.id()==ID_or ||
76-
expr.id()==ID_and ||
77-
expr.id()==ID_xor)
75+
else if(expr.id()==ID_xor)
7876
{
79-
if(operands.empty())
80-
return true;
81-
8277
bool result=true;
8378

84-
exprt::operandst::const_iterator last;
85-
bool last_set=false;
86-
8779
bool negate=false;
8880

89-
for(exprt::operandst::iterator it=operands.begin();
81+
for(exprt::operandst::const_iterator it=operands.begin();
82+
it!=operands.end();)
83+
{
84+
if(it->type().id()!=ID_bool)
85+
return true;
86+
87+
bool erase;
88+
89+
if(it->is_true())
90+
{
91+
erase=true;
92+
negate=!negate;
93+
}
94+
else
95+
erase=it->is_false();
96+
97+
if(erase)
98+
{
99+
it=operands.erase(it);
100+
result=false;
101+
}
102+
else
103+
it++;
104+
}
105+
106+
if(operands.empty())
107+
{
108+
expr.make_bool(negate);
109+
return false;
110+
}
111+
else if(operands.size()==1)
112+
{
113+
exprt tmp(operands.front());
114+
if(negate)
115+
tmp.make_not();
116+
expr.swap(tmp);
117+
return false;
118+
}
119+
120+
return result;
121+
}
122+
else if(expr.id()==ID_and || expr.id()==ID_or)
123+
{
124+
std::unordered_set<exprt, irep_hash> expr_set;
125+
126+
bool result=true;
127+
128+
for(exprt::operandst::const_iterator it=operands.begin();
90129
it!=operands.end();)
91130
{
92131
if(it->type().id()!=ID_bool)
@@ -106,77 +145,37 @@ bool simplify_exprt::simplify_boolean(exprt &expr)
106145
return false;
107146
}
108147

109-
bool erase;
110-
111-
if(expr.id()==ID_and)
112-
erase=is_true;
113-
else if(is_true && expr.id()==ID_xor)
114-
{
115-
erase=true;
116-
negate=!negate;
117-
}
118-
else
119-
erase=is_false;
120-
121-
if(last_set && *it==*last &&
122-
(expr.id()==ID_or || expr.id()==ID_and))
123-
erase=true; // erase duplicate operands
148+
bool erase=
149+
(expr.id()==ID_and ? is_true : is_false) ||
150+
!expr_set.insert(*it).second;
124151

125152
if(erase)
126153
{
127154
it=operands.erase(it);
128155
result=false;
129156
}
130157
else
131-
{
132-
last=it;
133-
last_set=true;
134158
it++;
135-
}
136159
}
137160

138161
// search for a and !a
139-
if(expr.id()==ID_and || expr.id()==ID_or)
140-
{
141-
// first gather all the a's with !a
142-
143-
std::unordered_set<exprt, irep_hash> expr_set;
144-
145-
forall_operands(it, expr)
146-
if(it->id()==ID_not &&
147-
it->operands().size()==1 &&
148-
it->type().id()==ID_bool)
149-
expr_set.insert(it->op0());
150-
151-
// now search for a
152-
153-
if(!expr_set.empty())
162+
for(const exprt &op : operands)
163+
if(op.id()==ID_not &&
164+
op.operands().size()==1 &&
165+
op.type().id()==ID_bool &&
166+
expr_set.find(op.op0())!=expr_set.end())
154167
{
155-
forall_operands(it, expr)
156-
{
157-
if(it->id()!=ID_not &&
158-
expr_set.find(*it)!=expr_set.end())
159-
{
160-
expr.make_bool(expr.id()==ID_or);
161-
return false;
162-
}
163-
}
168+
expr.make_bool(expr.id()==ID_or);
169+
return false;
164170
}
165-
}
166171

167172
if(operands.empty())
168173
{
169-
if(expr.id()==ID_and || negate)
170-
expr=true_exprt();
171-
else
172-
expr=false_exprt();
173-
174+
expr.make_bool(expr.id()==ID_and);
174175
return false;
175176
}
176177
else if(operands.size()==1)
177178
{
178-
if(negate)
179-
expr.op0().make_not();
180179
exprt tmp(operands.front());
181180
expr.swap(tmp);
182181
return false;

0 commit comments

Comments
 (0)