Skip to content

Commit ed168ac

Browse files
author
Daniel Kroening
authored
Merge pull request #4831 from diffblue/simplify_sig2
simplify_byte_extract and simplify_byte_update now have new interface
2 parents 536bce0 + b511a1a commit ed168ac

File tree

2 files changed

+80
-91
lines changed

2 files changed

+80
-91
lines changed

src/util/simplify_expr.cpp

Lines changed: 78 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,17 +1858,19 @@ optionalt<std::reference_wrapper<const array_exprt>>
18581858
return optionalt<std::reference_wrapper<const array_exprt>>(char_seq);
18591859
}
18601860

1861-
bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
1861+
simplify_exprt::resultt<>
1862+
simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
18621863
{
18631864
// lift up any ID_if on the object
18641865
if(expr.op().id()==ID_if)
18651866
{
18661867
if_exprt if_expr=lift_if(expr, 0);
1867-
simplify_byte_extract(to_byte_extract_expr(if_expr.true_case()));
1868-
simplify_byte_extract(to_byte_extract_expr(if_expr.false_case()));
1868+
if_expr.true_case() =
1869+
simplify_byte_extract(to_byte_extract_expr(if_expr.true_case()));
1870+
if_expr.false_case() =
1871+
simplify_byte_extract(to_byte_extract_expr(if_expr.false_case()));
18691872
simplify_if(if_expr);
1870-
expr.swap(if_expr);
1871-
return false;
1873+
return std::move(if_expr);
18721874
}
18731875

18741876
const auto el_size = pointer_offset_bits(expr.type(), ns);
@@ -1877,15 +1879,14 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
18771879
// byte_extract(root, offset1+offset2)
18781880
if(expr.op().id()==expr.id())
18791881
{
1880-
expr.offset()=plus_exprt(
1881-
to_byte_extract_expr(expr.op()).offset(),
1882-
expr.offset());
1883-
simplify_plus(expr.offset());
1882+
auto tmp = expr;
18841883

1885-
expr.op()=to_byte_extract_expr(expr.op()).op();
1886-
simplify_byte_extract(expr);
1884+
tmp.offset() =
1885+
plus_exprt(to_byte_extract_expr(expr.op()).offset(), expr.offset());
1886+
simplify_plus(tmp.offset());
18871887

1888-
return false;
1888+
tmp.op() = to_byte_extract_expr(expr.op()).op();
1889+
return changed(simplify_byte_extract(tmp)); // recursive call
18891890
}
18901891

18911892
// byte_extract(byte_update(root, offset, value), offset) =>
@@ -1901,28 +1902,24 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
19011902

19021903
if(expr.type() == op_byte_update.value().type())
19031904
{
1904-
exprt tmp = op_byte_update.value();
1905-
expr.swap(tmp);
1906-
1907-
return false;
1905+
return op_byte_update.value();
19081906
}
19091907
else if(
19101908
el_size.has_value() &&
19111909
*el_size <= pointer_offset_bits(op_byte_update.value().type(), ns))
19121910
{
1913-
expr.op() = op_byte_update.value();
1914-
expr.offset()=from_integer(0, expr.offset().type());
1911+
auto tmp = expr;
1912+
tmp.op() = op_byte_update.value();
1913+
tmp.offset() = from_integer(0, expr.offset().type());
19151914

1916-
simplify_byte_extract(expr);
1917-
1918-
return false;
1915+
return changed(simplify_byte_extract(tmp)); // recursive call
19191916
}
19201917
}
19211918

19221919
// the following require a constant offset
19231920
auto offset = numeric_cast<mp_integer>(expr.offset());
19241921
if(!offset.has_value() || *offset < 0)
1925-
return true;
1922+
return unchanged(expr);
19261923

19271924
// don't do any of the following if endianness doesn't match, as
19281925
// bytes need to be swapped
@@ -1931,25 +1928,19 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
19311928
// byte extract of full object is object
19321929
if(expr.type() == expr.op().type())
19331930
{
1934-
exprt tmp = expr.op();
1935-
expr.swap(tmp);
1936-
1937-
return false;
1931+
return expr.op();
19381932
}
19391933
else if(
19401934
expr.type().id() == ID_pointer && expr.op().type().id() == ID_pointer)
19411935
{
1942-
typecast_exprt tc(expr.op(), expr.type());
1943-
expr.swap(tc);
1944-
1945-
return false;
1936+
return typecast_exprt(expr.op(), expr.type());
19461937
}
19471938
}
19481939

19491940
// no proper simplification for expr.type()==void
19501941
// or types of unknown size
19511942
if(!el_size.has_value() || *el_size == 0)
1952-
return true;
1943+
return unchanged(expr);
19531944

19541945
if(expr.op().id()==ID_array_of &&
19551946
to_array_of_expr(expr.op()).op().id()==ID_constant)
@@ -1959,7 +1950,7 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
19591950
byte_extract_id()==ID_byte_extract_little_endian);
19601951

19611952
if(!const_bits_opt.has_value())
1962-
return true;
1953+
return unchanged(expr);
19631954

19641955
std::string const_bits=const_bits_opt.value();
19651956

@@ -1978,22 +1969,20 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
19781969
el_bits, expr.type(), expr.id() == ID_byte_extract_little_endian);
19791970

19801971
if(tmp.has_value())
1981-
{
1982-
expr.swap(*tmp);
1983-
return false;
1984-
}
1972+
return std::move(*tmp);
19851973
}
19861974

19871975
// in some cases we even handle non-const array_of
19881976
if(
19891977
expr.op().id() == ID_array_of && (*offset * 8) % (*el_size) == 0 &&
19901978
*el_size <= pointer_offset_bits(expr.op().op0().type(), ns))
19911979
{
1992-
expr.op()=index_exprt(expr.op(), expr.offset());
1993-
expr.offset()=from_integer(0, expr.offset().type());
1994-
simplify_rec(expr);
1980+
auto tmp = expr;
1981+
tmp.op() = index_exprt(expr.op(), expr.offset());
1982+
tmp.offset() = from_integer(0, expr.offset().type());
1983+
simplify_rec(tmp);
19951984

1996-
return false;
1985+
return std::move(tmp);
19971986
}
19981987

19991988
// extract bits of a constant
@@ -2030,42 +2019,37 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
20302019
bits_cut, expr.type(), expr.id() == ID_byte_extract_little_endian);
20312020

20322021
if(tmp.has_value())
2033-
{
2034-
expr.swap(*tmp);
2035-
2036-
return false;
2037-
}
2022+
return std::move(*tmp);
20382023
}
20392024

20402025
// try to refine it down to extracting from a member or an index in an array
20412026
auto subexpr =
20422027
get_subexpression_at_offset(expr.op(), *offset, expr.type(), ns);
20432028
if(!subexpr.has_value() || subexpr.value() == expr)
2044-
return true;
2029+
return unchanged(expr);
20452030

20462031
simplify_rec(subexpr.value());
2047-
expr.swap(subexpr.value());
2048-
return false;
2032+
return subexpr.value();
20492033
}
20502034

2051-
bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2035+
simplify_exprt::resultt<>
2036+
simplify_exprt::simplify_byte_update(const byte_update_exprt &expr)
20522037
{
2053-
const byte_update_exprt &expr_const = expr;
20542038
// byte_update(byte_update(root, offset, value), offset, value2) =>
20552039
// byte_update(root, offset, value2)
20562040
if(
2057-
expr_const.id() == expr_const.op().id() &&
2058-
expr_const.offset() == to_byte_update_expr(expr_const.op()).offset() &&
2059-
expr_const.value().type() ==
2060-
to_byte_update_expr(expr_const.op()).value().type())
2041+
expr.id() == expr.op().id() &&
2042+
expr.offset() == to_byte_update_expr(expr.op()).offset() &&
2043+
expr.value().type() == to_byte_update_expr(expr.op()).value().type())
20612044
{
2062-
expr.set_op(expr_const.op().op0());
2063-
return false;
2045+
auto tmp = expr;
2046+
tmp.set_op(expr.op().op0());
2047+
return std::move(tmp);
20642048
}
20652049

2066-
const exprt &root = expr_const.op();
2067-
const exprt &offset = expr_const.offset();
2068-
const exprt &value = expr_const.value();
2050+
const exprt &root = expr.op();
2051+
const exprt &offset = expr.offset();
2052+
const exprt &value = expr.value();
20692053
const auto val_size = pointer_offset_bits(value.type(), ns);
20702054
const auto root_size = pointer_offset_bits(root.type(), ns);
20712055

@@ -2080,10 +2064,7 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
20802064
ID_byte_extract_big_endian,
20812065
value, offset, expr.type());
20822066

2083-
simplify_byte_extract(be);
2084-
expr.swap(be);
2085-
2086-
return false;
2067+
return changed(simplify_byte_extract(be));
20872068
}
20882069

20892070
/*
@@ -2095,7 +2076,7 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
20952076
*/
20962077

20972078
if(expr.id()!=ID_byte_update_little_endian)
2098-
return true;
2079+
return unchanged(expr);
20992080

21002081
if(value.id()==ID_with)
21012082
{
@@ -2109,9 +2090,9 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
21092090
root and offset of update and extract
21102091
are the same */
21112092
if(!(root==extract.op()))
2112-
return true;
2093+
return unchanged(expr);
21132094
if(!(offset==extract.offset()))
2114-
return true;
2095+
return unchanged(expr);
21152096

21162097
const typet &tp=ns.follow(with.type());
21172098
if(tp.id()==ID_struct)
@@ -2135,10 +2116,10 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
21352116
plus_exprt new_offset(offset, compo_offset);
21362117
simplify_node(new_offset);
21372118
exprt new_value(with.new_value());
2138-
expr.set_offset(std::move(new_offset));
2139-
expr.set_value(std::move(new_value));
2140-
simplify_byte_update(expr); // do this recursively
2141-
return false;
2119+
auto tmp = expr;
2120+
tmp.set_offset(std::move(new_offset));
2121+
tmp.set_value(std::move(new_value));
2122+
return changed(simplify_byte_update(tmp)); // recursive call
21422123
}
21432124
}
21442125
}
@@ -2162,10 +2143,10 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
21622143
plus_exprt new_offset(offset, index_offset);
21632144
simplify_node(new_offset);
21642145
exprt new_value(with.new_value());
2165-
expr.set_offset(std::move(new_offset));
2166-
expr.set_value(std::move(new_value));
2167-
simplify_byte_update(expr); // do this recursively
2168-
return false;
2146+
auto tmp = expr;
2147+
tmp.set_offset(std::move(new_offset));
2148+
tmp.set_value(std::move(new_value));
2149+
return changed(simplify_byte_update(tmp)); // recursive call
21692150
}
21702151
}
21712152
}
@@ -2174,13 +2155,13 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
21742155
// the following require a constant offset
21752156
const auto offset_int = numeric_cast<mp_integer>(offset);
21762157
if(!offset_int.has_value() || *offset_int < 0)
2177-
return true;
2158+
return unchanged(expr);
21782159

21792160
const typet &op_type=ns.follow(root.type());
21802161

21812162
// size must be known
21822163
if(!val_size.has_value() || *val_size == 0)
2183-
return true;
2164+
return unchanged(expr);
21842165

21852166
// Are we updating (parts of) a struct? Do individual member updates
21862167
// instead, unless there are non-byte-sized bit fields
@@ -2273,17 +2254,13 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
22732254
if(result_expr.is_not_nil())
22742255
{
22752256
simplify_rec(result_expr);
2276-
expr.swap(result_expr);
2277-
2278-
return false;
2257+
return result_expr;
22792258
}
22802259

22812260
if(result_expr.is_not_nil())
22822261
{
22832262
simplify_rec(result_expr);
2284-
expr.swap(result_expr);
2285-
2286-
return false;
2263+
return result_expr;
22872264
}
22882265
}
22892266

@@ -2296,7 +2273,7 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
22962273
if(!el_size.has_value() || *el_size == 0 ||
22972274
(*el_size) % 8 != 0 || (*val_size) % 8 != 0)
22982275
{
2299-
return true;
2276+
return unchanged(expr);
23002277
}
23012278

23022279
exprt result=root;
@@ -2336,12 +2313,10 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
23362313
m_offset_bits += *el_size;
23372314
}
23382315

2339-
expr.swap(result);
2340-
2341-
return false;
2316+
return std::move(result);
23422317
}
23432318

2344-
return true;
2319+
return unchanged(expr);
23452320
}
23462321

23472322
bool simplify_exprt::simplify_complex(exprt &expr)
@@ -2437,10 +2412,24 @@ bool simplify_exprt::simplify_node(exprt &expr)
24372412
no_change = simplify_member(expr) && no_change;
24382413
else if(expr.id()==ID_byte_update_little_endian ||
24392414
expr.id()==ID_byte_update_big_endian)
2440-
no_change = simplify_byte_update(to_byte_update_expr(expr)) && no_change;
2415+
{
2416+
auto r = simplify_byte_update(to_byte_update_expr(expr));
2417+
if(r.has_changed())
2418+
{
2419+
no_change = false;
2420+
expr = r.expr;
2421+
}
2422+
}
24412423
else if(expr.id()==ID_byte_extract_little_endian ||
24422424
expr.id()==ID_byte_extract_big_endian)
2443-
no_change = simplify_byte_extract(to_byte_extract_expr(expr)) && no_change;
2425+
{
2426+
auto r = simplify_byte_extract(to_byte_extract_expr(expr));
2427+
if(r.has_changed())
2428+
{
2429+
no_change = false;
2430+
expr = r.expr;
2431+
}
2432+
}
24442433
else if(expr.id()==ID_pointer_object)
24452434
no_change = simplify_pointer_object(expr) && no_change;
24462435
else if(expr.id() == ID_is_dynamic_object)

src/util/simplify_expr_class.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ class simplify_exprt
143143
bool simplify_update(exprt &expr);
144144
bool simplify_index(exprt &expr);
145145
bool simplify_member(exprt &expr);
146-
bool simplify_byte_update(byte_update_exprt &expr);
147-
bool simplify_byte_extract(byte_extract_exprt &expr);
146+
resultt<> simplify_byte_update(const byte_update_exprt &);
147+
resultt<> simplify_byte_extract(const byte_extract_exprt &);
148148
bool simplify_pointer_object(exprt &expr);
149149
bool simplify_object_size(exprt &expr);
150150
bool simplify_dynamic_size(exprt &expr);

0 commit comments

Comments
 (0)