@@ -154,3 +154,58 @@ simplify_exprt::resultt<> simplify_expr_with_value_sett::simplify_inequality(
154
154
else
155
155
return unchanged (expr);
156
156
}
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