@@ -1872,17 +1872,19 @@ optionalt<std::reference_wrapper<const array_exprt>>
1872
1872
return optionalt<std::reference_wrapper<const array_exprt>>(char_seq);
1873
1873
}
1874
1874
1875
- bool simplify_exprt::simplify_byte_extract (byte_extract_exprt &expr)
1875
+ simplify_exprt::resultt<>
1876
+ simplify_exprt::simplify_byte_extract (const byte_extract_exprt &expr)
1876
1877
{
1877
1878
// lift up any ID_if on the object
1878
1879
if (expr.op ().id ()==ID_if)
1879
1880
{
1880
1881
if_exprt if_expr=lift_if (expr, 0 );
1881
- simplify_byte_extract (to_byte_extract_expr (if_expr.true_case ()));
1882
- simplify_byte_extract (to_byte_extract_expr (if_expr.false_case ()));
1882
+ if_expr.true_case () =
1883
+ simplify_byte_extract (to_byte_extract_expr (if_expr.true_case ()));
1884
+ if_expr.false_case () =
1885
+ simplify_byte_extract (to_byte_extract_expr (if_expr.false_case ()));
1883
1886
simplify_if (if_expr);
1884
- expr.swap (if_expr);
1885
- return false ;
1887
+ return std::move (if_expr);
1886
1888
}
1887
1889
1888
1890
const auto el_size = pointer_offset_bits (expr.type (), ns);
@@ -1891,15 +1893,14 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
1891
1893
// byte_extract(root, offset1+offset2)
1892
1894
if (expr.op ().id ()==expr.id ())
1893
1895
{
1894
- expr.offset ()=plus_exprt (
1895
- to_byte_extract_expr (expr.op ()).offset (),
1896
- expr.offset ());
1897
- simplify_plus (expr.offset ());
1896
+ auto tmp = expr;
1898
1897
1899
- expr.op ()=to_byte_extract_expr (expr.op ()).op ();
1900
- simplify_byte_extract (expr);
1898
+ tmp.offset () =
1899
+ plus_exprt (to_byte_extract_expr (expr.op ()).offset (), expr.offset ());
1900
+ simplify_plus (tmp.offset ());
1901
1901
1902
- return false ;
1902
+ tmp.op () = to_byte_extract_expr (expr.op ()).op ();
1903
+ return changed (simplify_byte_extract (tmp)); // recursive call
1903
1904
}
1904
1905
1905
1906
// byte_extract(byte_update(root, offset, value), offset) =>
@@ -1915,28 +1916,24 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
1915
1916
1916
1917
if (expr.type () == op_byte_update.value ().type ())
1917
1918
{
1918
- exprt tmp = op_byte_update.value ();
1919
- expr.swap (tmp);
1920
-
1921
- return false ;
1919
+ return op_byte_update.value ();
1922
1920
}
1923
1921
else if (
1924
1922
el_size.has_value () &&
1925
1923
*el_size <= pointer_offset_bits (op_byte_update.value ().type (), ns))
1926
1924
{
1927
- expr.op () = op_byte_update.value ();
1928
- expr.offset ()=from_integer (0 , expr.offset ().type ());
1925
+ auto tmp = expr;
1926
+ tmp.op () = op_byte_update.value ();
1927
+ tmp.offset () = from_integer (0 , expr.offset ().type ());
1929
1928
1930
- simplify_byte_extract (expr);
1931
-
1932
- return false ;
1929
+ return changed (simplify_byte_extract (tmp)); // recursive call
1933
1930
}
1934
1931
}
1935
1932
1936
1933
// the following require a constant offset
1937
1934
auto offset = numeric_cast<mp_integer>(expr.offset ());
1938
1935
if (!offset.has_value () || *offset < 0 )
1939
- return true ;
1936
+ return unchanged (expr) ;
1940
1937
1941
1938
// don't do any of the following if endianness doesn't match, as
1942
1939
// bytes need to be swapped
@@ -1945,25 +1942,19 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
1945
1942
// byte extract of full object is object
1946
1943
if (expr.type () == expr.op ().type ())
1947
1944
{
1948
- exprt tmp = expr.op ();
1949
- expr.swap (tmp);
1950
-
1951
- return false ;
1945
+ return expr.op ();
1952
1946
}
1953
1947
else if (
1954
1948
expr.type ().id () == ID_pointer && expr.op ().type ().id () == ID_pointer)
1955
1949
{
1956
- typecast_exprt tc (expr.op (), expr.type ());
1957
- expr.swap (tc);
1958
-
1959
- return false ;
1950
+ return typecast_exprt (expr.op (), expr.type ());
1960
1951
}
1961
1952
}
1962
1953
1963
1954
// no proper simplification for expr.type()==void
1964
1955
// or types of unknown size
1965
1956
if (!el_size.has_value () || *el_size == 0 )
1966
- return true ;
1957
+ return unchanged (expr) ;
1967
1958
1968
1959
if (expr.op ().id ()==ID_array_of &&
1969
1960
to_array_of_expr (expr.op ()).op ().id ()==ID_constant)
@@ -1973,7 +1964,7 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
1973
1964
byte_extract_id ()==ID_byte_extract_little_endian);
1974
1965
1975
1966
if (!const_bits_opt.has_value ())
1976
- return true ;
1967
+ return unchanged (expr) ;
1977
1968
1978
1969
std::string const_bits=const_bits_opt.value ();
1979
1970
@@ -1992,22 +1983,20 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
1992
1983
el_bits, expr.type (), expr.id () == ID_byte_extract_little_endian);
1993
1984
1994
1985
if (tmp.has_value ())
1995
- {
1996
- expr.swap (*tmp);
1997
- return false ;
1998
- }
1986
+ return std::move (*tmp);
1999
1987
}
2000
1988
2001
1989
// in some cases we even handle non-const array_of
2002
1990
if (
2003
1991
expr.op ().id () == ID_array_of && (*offset * 8 ) % (*el_size) == 0 &&
2004
1992
*el_size <= pointer_offset_bits (expr.op ().op0 ().type (), ns))
2005
1993
{
2006
- expr.op ()=index_exprt (expr.op (), expr.offset ());
2007
- expr.offset ()=from_integer (0 , expr.offset ().type ());
2008
- simplify_rec (expr);
1994
+ auto tmp = expr;
1995
+ tmp.op () = index_exprt (expr.op (), expr.offset ());
1996
+ tmp.offset () = from_integer (0 , expr.offset ().type ());
1997
+ simplify_rec (tmp);
2009
1998
2010
- return false ;
1999
+ return std::move (tmp) ;
2011
2000
}
2012
2001
2013
2002
// extract bits of a constant
@@ -2044,42 +2033,37 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
2044
2033
bits_cut, expr.type (), expr.id () == ID_byte_extract_little_endian);
2045
2034
2046
2035
if (tmp.has_value ())
2047
- {
2048
- expr.swap (*tmp);
2049
-
2050
- return false ;
2051
- }
2036
+ return std::move (*tmp);
2052
2037
}
2053
2038
2054
2039
// try to refine it down to extracting from a member or an index in an array
2055
2040
auto subexpr =
2056
2041
get_subexpression_at_offset (expr.op (), *offset, expr.type (), ns);
2057
2042
if (!subexpr.has_value () || subexpr.value () == expr)
2058
- return true ;
2043
+ return unchanged (expr) ;
2059
2044
2060
2045
simplify_rec (subexpr.value ());
2061
- expr.swap (subexpr.value ());
2062
- return false ;
2046
+ return subexpr.value ();
2063
2047
}
2064
2048
2065
- bool simplify_exprt::simplify_byte_update (byte_update_exprt &expr)
2049
+ simplify_exprt::resultt<>
2050
+ simplify_exprt::simplify_byte_update (const byte_update_exprt &expr)
2066
2051
{
2067
- const byte_update_exprt &expr_const = expr;
2068
2052
// byte_update(byte_update(root, offset, value), offset, value2) =>
2069
2053
// byte_update(root, offset, value2)
2070
2054
if (
2071
- expr_const.id () == expr_const.op ().id () &&
2072
- expr_const.offset () == to_byte_update_expr (expr_const.op ()).offset () &&
2073
- expr_const.value ().type () ==
2074
- to_byte_update_expr (expr_const.op ()).value ().type ())
2055
+ expr.id () == expr.op ().id () &&
2056
+ expr.offset () == to_byte_update_expr (expr.op ()).offset () &&
2057
+ expr.value ().type () == to_byte_update_expr (expr.op ()).value ().type ())
2075
2058
{
2076
- expr.set_op (expr_const.op ().op0 ());
2077
- return false ;
2059
+ auto tmp = expr;
2060
+ tmp.set_op (expr.op ().op0 ());
2061
+ return std::move (tmp);
2078
2062
}
2079
2063
2080
- const exprt &root = expr_const .op ();
2081
- const exprt &offset = expr_const .offset ();
2082
- const exprt &value = expr_const .value ();
2064
+ const exprt &root = expr .op ();
2065
+ const exprt &offset = expr .offset ();
2066
+ const exprt &value = expr .value ();
2083
2067
const auto val_size = pointer_offset_bits (value.type (), ns);
2084
2068
const auto root_size = pointer_offset_bits (root.type (), ns);
2085
2069
@@ -2094,10 +2078,7 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2094
2078
ID_byte_extract_big_endian,
2095
2079
value, offset, expr.type ());
2096
2080
2097
- simplify_byte_extract (be);
2098
- expr.swap (be);
2099
-
2100
- return false ;
2081
+ return changed (simplify_byte_extract (be));
2101
2082
}
2102
2083
2103
2084
/*
@@ -2109,7 +2090,7 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2109
2090
*/
2110
2091
2111
2092
if (expr.id ()!=ID_byte_update_little_endian)
2112
- return true ;
2093
+ return unchanged (expr) ;
2113
2094
2114
2095
if (value.id ()==ID_with)
2115
2096
{
@@ -2123,9 +2104,9 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2123
2104
root and offset of update and extract
2124
2105
are the same */
2125
2106
if (!(root==extract.op ()))
2126
- return true ;
2107
+ return unchanged (expr) ;
2127
2108
if (!(offset==extract.offset ()))
2128
- return true ;
2109
+ return unchanged (expr) ;
2129
2110
2130
2111
const typet &tp=ns.follow (with.type ());
2131
2112
if (tp.id ()==ID_struct)
@@ -2149,10 +2130,10 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2149
2130
plus_exprt new_offset (offset, compo_offset);
2150
2131
simplify_node (new_offset);
2151
2132
exprt new_value (with.new_value ());
2152
- expr. set_offset ( std::move (new_offset)) ;
2153
- expr. set_value (std::move (new_value ));
2154
- simplify_byte_update (expr); // do this recursively
2155
- return false ;
2133
+ auto tmp = expr;
2134
+ tmp. set_offset (std::move (new_offset ));
2135
+ tmp. set_value ( std::move (new_value));
2136
+ return changed ( simplify_byte_update (tmp)); // recursive call
2156
2137
}
2157
2138
}
2158
2139
}
@@ -2176,10 +2157,10 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2176
2157
plus_exprt new_offset (offset, index_offset);
2177
2158
simplify_node (new_offset);
2178
2159
exprt new_value (with.new_value ());
2179
- expr. set_offset ( std::move (new_offset)) ;
2180
- expr. set_value (std::move (new_value ));
2181
- simplify_byte_update (expr); // do this recursively
2182
- return false ;
2160
+ auto tmp = expr;
2161
+ tmp. set_offset (std::move (new_offset ));
2162
+ tmp. set_value ( std::move (new_value));
2163
+ return changed ( simplify_byte_update (tmp)); // recursive call
2183
2164
}
2184
2165
}
2185
2166
}
@@ -2188,13 +2169,13 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2188
2169
// the following require a constant offset
2189
2170
const auto offset_int = numeric_cast<mp_integer>(offset);
2190
2171
if (!offset_int.has_value () || *offset_int < 0 )
2191
- return true ;
2172
+ return unchanged (expr) ;
2192
2173
2193
2174
const typet &op_type=ns.follow (root.type ());
2194
2175
2195
2176
// size must be known
2196
2177
if (!val_size.has_value () || *val_size == 0 )
2197
- return true ;
2178
+ return unchanged (expr) ;
2198
2179
2199
2180
// Are we updating (parts of) a struct? Do individual member updates
2200
2181
// instead, unless there are non-byte-sized bit fields
@@ -2287,17 +2268,13 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2287
2268
if (result_expr.is_not_nil ())
2288
2269
{
2289
2270
simplify_rec (result_expr);
2290
- expr.swap (result_expr);
2291
-
2292
- return false ;
2271
+ return result_expr;
2293
2272
}
2294
2273
2295
2274
if (result_expr.is_not_nil ())
2296
2275
{
2297
2276
simplify_rec (result_expr);
2298
- expr.swap (result_expr);
2299
-
2300
- return false ;
2277
+ return result_expr;
2301
2278
}
2302
2279
}
2303
2280
@@ -2310,7 +2287,7 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2310
2287
if (!el_size.has_value () || *el_size == 0 ||
2311
2288
(*el_size) % 8 != 0 || (*val_size) % 8 != 0 )
2312
2289
{
2313
- return true ;
2290
+ return unchanged (expr) ;
2314
2291
}
2315
2292
2316
2293
exprt result=root;
@@ -2350,12 +2327,10 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2350
2327
m_offset_bits += *el_size;
2351
2328
}
2352
2329
2353
- expr.swap (result);
2354
-
2355
- return false ;
2330
+ return std::move (result);
2356
2331
}
2357
2332
2358
- return true ;
2333
+ return unchanged (expr) ;
2359
2334
}
2360
2335
2361
2336
bool simplify_exprt::simplify_complex (exprt &expr)
@@ -2451,10 +2426,24 @@ bool simplify_exprt::simplify_node(exprt &expr)
2451
2426
no_change = simplify_member (expr) && no_change;
2452
2427
else if (expr.id ()==ID_byte_update_little_endian ||
2453
2428
expr.id ()==ID_byte_update_big_endian)
2454
- no_change = simplify_byte_update (to_byte_update_expr (expr)) && no_change;
2429
+ {
2430
+ auto r = simplify_byte_update (to_byte_update_expr (expr));
2431
+ if (r.has_changed ())
2432
+ {
2433
+ no_change = false ;
2434
+ expr = r.expr ;
2435
+ }
2436
+ }
2455
2437
else if (expr.id ()==ID_byte_extract_little_endian ||
2456
2438
expr.id ()==ID_byte_extract_big_endian)
2457
- no_change = simplify_byte_extract (to_byte_extract_expr (expr)) && no_change;
2439
+ {
2440
+ auto r = simplify_byte_extract (to_byte_extract_expr (expr));
2441
+ if (r.has_changed ())
2442
+ {
2443
+ no_change = false ;
2444
+ expr = r.expr ;
2445
+ }
2446
+ }
2458
2447
else if (expr.id ()==ID_pointer_object)
2459
2448
no_change = simplify_pointer_object (expr) && no_change;
2460
2449
else if (expr.id () == ID_is_dynamic_object)
0 commit comments