@@ -155,6 +155,78 @@ simplify_exprt::resultt<> simplify_expr_with_value_sett::simplify_inequality(
155155 return unchanged (expr);
156156}
157157
158+ simplify_exprt::resultt<>
159+ simplify_expr_with_value_sett::simplify_inequality_pointer_object (
160+ const binary_relation_exprt &expr)
161+ {
162+ PRECONDITION (expr.id () == ID_equal || expr.id () == ID_notequal);
163+ PRECONDITION (expr.is_boolean ());
164+
165+ auto collect_objects = [this ](const exprt &pointer)
166+ {
167+ std::set<exprt> objects;
168+ if (auto address_of = expr_try_dynamic_cast<address_of_exprt>(pointer))
169+ {
170+ objects.insert (
171+ object_descriptor_exprt::root_object (address_of->object ()));
172+ }
173+ else if (auto ssa_expr = expr_try_dynamic_cast<ssa_exprt>(pointer))
174+ {
175+ ssa_exprt l1_expr{*ssa_expr};
176+ l1_expr.remove_level_2 ();
177+ const std::vector<exprt> value_set_elements =
178+ value_set.get_value_set (l1_expr, ns);
179+
180+ for (const auto &value_set_element : value_set_elements)
181+ {
182+ if (
183+ value_set_element.id () == ID_unknown ||
184+ value_set_element.id () == ID_invalid ||
185+ is_failed_symbol (
186+ to_object_descriptor_expr (value_set_element).root_object ()))
187+ {
188+ objects.clear ();
189+ break ;
190+ }
191+
192+ objects.insert (
193+ to_object_descriptor_expr (value_set_element).root_object ());
194+ }
195+ }
196+ return objects;
197+ };
198+
199+ auto lhs_objects =
200+ collect_objects (to_pointer_object_expr (expr.lhs ()).pointer ());
201+ auto rhs_objects =
202+ collect_objects (to_pointer_object_expr (expr.rhs ()).pointer ());
203+
204+ if (lhs_objects.size () == 1 && lhs_objects == rhs_objects)
205+ {
206+ // there is exactly one pointed-to object on both left-hand and right-hand
207+ // side, and that object is the same
208+ return expr.id () == ID_equal ? changed (static_cast <exprt>(true_exprt{}))
209+ : changed (static_cast <exprt>(false_exprt{}));
210+ }
211+
212+ std::list<exprt> intersection;
213+ std::set_intersection (
214+ lhs_objects.begin (),
215+ lhs_objects.end (),
216+ rhs_objects.begin (),
217+ rhs_objects.end (),
218+ std::back_inserter (intersection));
219+ if (!lhs_objects.empty () && !rhs_objects.empty () && intersection.empty ())
220+ {
221+ // all pointed-to objects on the left-hand side are different from any of
222+ // the pointed-to objects on the right-hand side
223+ return expr.id () == ID_equal ? changed (static_cast <exprt>(false_exprt{}))
224+ : changed (static_cast <exprt>(true_exprt{}));
225+ }
226+
227+ return simplify_exprt::simplify_inequality_pointer_object (expr);
228+ }
229+
158230simplify_exprt::resultt<>
159231simplify_expr_with_value_sett::simplify_pointer_offset (
160232 const pointer_offset_exprt &expr)
0 commit comments