Skip to content

Commit ac731d4

Browse files
committed
Simplify pointer_offset using value set
When all candidates in the value set have the same offset we can replace a pointer_offset expression by the offset value found in the value set.
1 parent 4b88740 commit ac731d4

File tree

5 files changed

+75
-1
lines changed

5 files changed

+75
-1
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <stdlib.h>
2+
3+
int main()
4+
{
5+
int *p = malloc(sizeof(int));
6+
__CPROVER_assert(__CPROVER_POINTER_OFFSET(p) == 0, "");
7+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
--verbosity 8
4+
^Generated \d+ VCC\(s\), 0 remaining after simplification$
5+
^VERIFICATION SUCCESSFUL$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring

src/goto-symex/simplify_expr_with_value_set.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

src/goto-symex/simplify_expr_with_value_set.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ class simplify_expr_with_value_sett : public simplify_exprt
2626

2727
[[nodiscard]] resultt<>
2828
simplify_inequality(const binary_relation_exprt &) override;
29+
[[nodiscard]] resultt<>
30+
simplify_pointer_offset(const pointer_offset_exprt &) override;
2931

3032
protected:
3133
const value_sett &value_set;

src/util/simplify_expr_class.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ class simplify_exprt
202202
[[nodiscard]] resultt<>
203203
simplify_dereference_preorder(const dereference_exprt &);
204204
[[nodiscard]] resultt<> simplify_address_of(const address_of_exprt &);
205-
[[nodiscard]] resultt<> simplify_pointer_offset(const pointer_offset_exprt &);
205+
[[nodiscard]] virtual resultt<>
206+
simplify_pointer_offset(const pointer_offset_exprt &);
206207
[[nodiscard]] resultt<> simplify_bswap(const bswap_exprt &);
207208
[[nodiscard]] resultt<> simplify_isinf(const unary_exprt &);
208209
[[nodiscard]] resultt<> simplify_isnan(const unary_exprt &);

0 commit comments

Comments
 (0)