@@ -113,15 +113,7 @@ void constant_propagator_domaint::transform(
113
113
if (g.is_false ())
114
114
values.set_to_bottom ();
115
115
else
116
- {
117
116
two_way_propagate_rec (g, ns, cp);
118
- // If two way propagate is enabled then it may be possible to detect
119
- // that the branch condition is infeasible and thus the domain should
120
- // be set to bottom. Without it the domain will only be set to bottom
121
- // if the guard expression is trivially (i.e. without context) false.
122
- INVARIANT (!values.is_bottom ,
123
- " Without two-way propagation this should be impossible." );
124
- }
125
117
}
126
118
else if (from->is_dead ())
127
119
{
@@ -222,7 +214,7 @@ void constant_propagator_domaint::transform(
222
214
223
215
224
216
// / handles equalities and conjunctions containing equalities
225
- bool constant_propagator_domaint::two_way_propagate_rec (
217
+ void constant_propagator_domaint::two_way_propagate_rec (
226
218
const exprt &expr,
227
219
const namespacet &ns,
228
220
const constant_propagator_ait *cp)
@@ -231,42 +223,79 @@ bool constant_propagator_domaint::two_way_propagate_rec(
231
223
std::cout << " two_way_propagate_rec: " << format (expr) << ' \n ' ;
232
224
#endif
233
225
234
- bool change=false ;
226
+ // This used to attempt to propagate equalities both ways, but the original
227
+ // author noted it is "buggy at the moment," so I only propagate constants
228
+ // onto non-constants.
235
229
236
- // this seems to be buggy at present
237
- #if 0
238
230
if (expr.id ()==ID_and)
239
231
{
240
- // need a fixed point here to get the most out of it
241
- do
232
+ forall_operands (it, expr)
233
+ two_way_propagate_rec (*it, ns, cp);
234
+ }
235
+ else if (expr.id () == ID_not)
236
+ {
237
+ if (expr.op0 ().id () == ID_equal || expr.op0 ().id () == ID_notequal)
242
238
{
243
- change = false;
244
-
245
- forall_operands(it, expr)
246
- if(two_way_propagate_rec(*it, ns, cp))
247
- change=true;
239
+ exprt subexpr = expr.op0 ();
240
+ subexpr.id (subexpr.id () == ID_equal ? ID_notequal : ID_equal);
241
+ two_way_propagate_rec (subexpr, ns, cp);
242
+ }
243
+ else if (expr.op0 ().id () == ID_symbol && expr.type () == bool_typet ())
244
+ {
245
+ // Treat `IF !x` like `IF x == FALSE`:
246
+ two_way_propagate_rec (equal_exprt (expr.op0 (), false_exprt ()), ns, cp);
248
247
}
249
- while(change);
250
248
}
251
- else if(expr.id()==ID_equal )
249
+ else if (expr.id () == ID_symbol )
252
250
{
253
- const exprt &lhs=expr.op0();
254
- const exprt &rhs=expr.op1();
255
-
256
- // two-way propagation
257
- valuest copy_values=values;
258
- assign_rec(copy_values, lhs, rhs, ns);
259
- if(!values.is_constant(rhs) || values.is_constant(lhs))
260
- assign_rec(values, rhs, lhs, ns);
261
- change=values.meet(copy_values);
251
+ if (expr.type () == bool_typet ())
252
+ {
253
+ // Treat `IF x` like `IF x == TRUE`:
254
+ two_way_propagate_rec (equal_exprt (expr, true_exprt ()), ns, cp);
255
+ }
262
256
}
263
- #endif
257
+ else if (expr.id () == ID_equal || expr.id () == ID_notequal)
258
+ {
259
+ exprt lhs = expr.op0 ();
260
+ exprt rhs = expr.op1 ();
264
261
265
- #ifdef DEBUG
266
- std::cout << " two_way_propagate_rec: " << change << ' \n ' ;
267
- #endif
262
+ if (lhs.is_constant () && !rhs.is_constant ())
263
+ std::swap (lhs, rhs);
264
+
265
+ if (lhs.is_constant () || !rhs.is_constant ())
266
+ return ;
268
267
269
- return change;
268
+ // (int)var xx 0 ==> var xx (_Bool)0 or similar
269
+ // Note this is restricted to bools because in general turning a widening
270
+ // into a narrowing typecast is not correct.
271
+ if (lhs.id () == ID_typecast
272
+ (lhs.op0 ().type ().id () == ID_bool || lhs.op0 ().type ().id () == ID_c_bool))
273
+ {
274
+ rhs = typecast_exprt (rhs, lhs.op0 ().type ());
275
+ simplify (rhs, ns);
276
+
277
+ lhs = lhs.op0 ();
278
+ }
279
+
280
+ if (expr.id () == ID_notequal)
281
+ {
282
+ if (lhs.type ().id () != ID_bool && lhs.type ().id () != ID_c_bool)
283
+ return ;
284
+
285
+ // x != FALSE ==> x == TRUE
286
+
287
+ if (rhs.is_zero () || rhs.is_false ())
288
+ rhs = from_integer (1 , rhs.type ());
289
+ else
290
+ rhs = from_integer (0 , rhs.type ());
291
+
292
+ two_way_propagate_rec (equal_exprt (lhs, rhs), ns, cp);
293
+ }
294
+ else // expr.id() == ID_equal
295
+ {
296
+ assign_rec (values, lhs, rhs, ns, cp);
297
+ }
298
+ }
270
299
}
271
300
272
301
// / Simplify the condition given context-sensitive knowledge from the abstract
0 commit comments