@@ -154,3 +154,58 @@ simplify_exprt::resultt<> simplify_expr_with_value_sett::simplify_inequality(
154154 else
155155 return unchanged (expr);
156156}
157+
158+ simplify_exprt::resultt<>
159+ simplify_expr_with_value_sett::simplify_pointer_offset (
160+ const pointer_offset_exprt &expr)
161+ {
162+ const exprt &ptr = expr.pointer ();
163+
164+ if (ptr.type ().id () != ID_pointer)
165+ return unchanged (expr);
166+
167+ const ssa_exprt *ssa_symbol_expr = expr_try_dynamic_cast<ssa_exprt>(ptr);
168+
169+ if (!ssa_symbol_expr)
170+ return simplify_exprt::simplify_pointer_offset (expr);
171+
172+ ssa_exprt l1_expr{*ssa_symbol_expr};
173+ l1_expr.remove_level_2 ();
174+ const std::vector<exprt> value_set_elements =
175+ value_set.get_value_set (l1_expr, ns);
176+
177+ std::optional<exprt> offset;
178+
179+ for (const auto &value_set_element : value_set_elements)
180+ {
181+ if (
182+ value_set_element.id () == ID_unknown ||
183+ value_set_element.id () == ID_invalid ||
184+ is_failed_symbol (
185+ to_object_descriptor_expr (value_set_element).root_object ()) ||
186+ to_object_descriptor_expr (value_set_element).offset ().id () == ID_unknown)
187+ {
188+ offset.reset ();
189+ break ;
190+ }
191+
192+ exprt this_offset = to_object_descriptor_expr (value_set_element).offset ();
193+ if (
194+ this_offset.id () == ID_unknown ||
195+ (offset.has_value () && this_offset != *offset))
196+ {
197+ offset.reset ();
198+ break ;
199+ }
200+ else if (!offset.has_value ())
201+ {
202+ offset = this_offset;
203+ }
204+ }
205+
206+ if (!offset.has_value ())
207+ return simplify_exprt::simplify_pointer_offset (expr);
208+
209+ return changed (
210+ simplify_rec (typecast_exprt::conditional_cast (*offset, expr.type ())));
211+ }
0 commit comments