@@ -113,15 +113,7 @@ void constant_propagator_domaint::transform(
113113 if (g.is_false ())
114114 values.set_to_bottom ();
115115 else
116- {
117116 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- }
125117 }
126118 else if (from->is_dead ())
127119 {
@@ -222,7 +214,7 @@ void constant_propagator_domaint::transform(
222214
223215
224216// / handles equalities and conjunctions containing equalities
225- bool constant_propagator_domaint::two_way_propagate_rec (
217+ void constant_propagator_domaint::two_way_propagate_rec (
226218 const exprt &expr,
227219 const namespacet &ns,
228220 const constant_propagator_ait *cp)
@@ -231,42 +223,79 @@ bool constant_propagator_domaint::two_way_propagate_rec(
231223 std::cout << " two_way_propagate_rec: " << format (expr) << ' \n ' ;
232224#endif
233225
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.
235229
236- // this seems to be buggy at present
237- #if 0
238230 if (expr.id ()==ID_and)
239231 {
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)
242238 {
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);
248247 }
249- while(change);
250248 }
251- else if(expr.id()==ID_equal )
249+ else if (expr.id () == ID_symbol )
252250 {
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+ }
262256 }
263- #endif
257+ else if (expr.id () == ID_equal || expr.id () == ID_notequal)
258+ {
259+ exprt lhs = expr.op0 ();
260+ exprt rhs = expr.op1 ();
264261
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 ;
268267
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+ }
270299}
271300
272301// / Simplify the condition given context-sensitive knowledge from the abstract
0 commit comments