@@ -1858,17 +1858,19 @@ optionalt<std::reference_wrapper<const array_exprt>>
1858
1858
return optionalt<std::reference_wrapper<const array_exprt>>(char_seq);
1859
1859
}
1860
1860
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)
1862
1863
{
1863
1864
// lift up any ID_if on the object
1864
1865
if (expr.op ().id ()==ID_if)
1865
1866
{
1866
1867
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 ()));
1869
1872
simplify_if (if_expr);
1870
- expr.swap (if_expr);
1871
- return false ;
1873
+ return std::move (if_expr);
1872
1874
}
1873
1875
1874
1876
const auto el_size = pointer_offset_bits (expr.type (), ns);
@@ -1877,15 +1879,14 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
1877
1879
// byte_extract(root, offset1+offset2)
1878
1880
if (expr.op ().id ()==expr.id ())
1879
1881
{
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;
1884
1883
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 ());
1887
1887
1888
- return false ;
1888
+ tmp.op () = to_byte_extract_expr (expr.op ()).op ();
1889
+ return changed (simplify_byte_extract (tmp)); // recursive call
1889
1890
}
1890
1891
1891
1892
// byte_extract(byte_update(root, offset, value), offset) =>
@@ -1901,28 +1902,24 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
1901
1902
1902
1903
if (expr.type () == op_byte_update.value ().type ())
1903
1904
{
1904
- exprt tmp = op_byte_update.value ();
1905
- expr.swap (tmp);
1906
-
1907
- return false ;
1905
+ return op_byte_update.value ();
1908
1906
}
1909
1907
else if (
1910
1908
el_size.has_value () &&
1911
1909
*el_size <= pointer_offset_bits (op_byte_update.value ().type (), ns))
1912
1910
{
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 ());
1915
1914
1916
- simplify_byte_extract (expr);
1917
-
1918
- return false ;
1915
+ return changed (simplify_byte_extract (tmp)); // recursive call
1919
1916
}
1920
1917
}
1921
1918
1922
1919
// the following require a constant offset
1923
1920
auto offset = numeric_cast<mp_integer>(expr.offset ());
1924
1921
if (!offset.has_value () || *offset < 0 )
1925
- return true ;
1922
+ return unchanged (expr) ;
1926
1923
1927
1924
// don't do any of the following if endianness doesn't match, as
1928
1925
// bytes need to be swapped
@@ -1931,25 +1928,19 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
1931
1928
// byte extract of full object is object
1932
1929
if (expr.type () == expr.op ().type ())
1933
1930
{
1934
- exprt tmp = expr.op ();
1935
- expr.swap (tmp);
1936
-
1937
- return false ;
1931
+ return expr.op ();
1938
1932
}
1939
1933
else if (
1940
1934
expr.type ().id () == ID_pointer && expr.op ().type ().id () == ID_pointer)
1941
1935
{
1942
- typecast_exprt tc (expr.op (), expr.type ());
1943
- expr.swap (tc);
1944
-
1945
- return false ;
1936
+ return typecast_exprt (expr.op (), expr.type ());
1946
1937
}
1947
1938
}
1948
1939
1949
1940
// no proper simplification for expr.type()==void
1950
1941
// or types of unknown size
1951
1942
if (!el_size.has_value () || *el_size == 0 )
1952
- return true ;
1943
+ return unchanged (expr) ;
1953
1944
1954
1945
if (expr.op ().id ()==ID_array_of &&
1955
1946
to_array_of_expr (expr.op ()).op ().id ()==ID_constant)
@@ -1959,7 +1950,7 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
1959
1950
byte_extract_id ()==ID_byte_extract_little_endian);
1960
1951
1961
1952
if (!const_bits_opt.has_value ())
1962
- return true ;
1953
+ return unchanged (expr) ;
1963
1954
1964
1955
std::string const_bits=const_bits_opt.value ();
1965
1956
@@ -1978,22 +1969,20 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
1978
1969
el_bits, expr.type (), expr.id () == ID_byte_extract_little_endian);
1979
1970
1980
1971
if (tmp.has_value ())
1981
- {
1982
- expr.swap (*tmp);
1983
- return false ;
1984
- }
1972
+ return std::move (*tmp);
1985
1973
}
1986
1974
1987
1975
// in some cases we even handle non-const array_of
1988
1976
if (
1989
1977
expr.op ().id () == ID_array_of && (*offset * 8 ) % (*el_size) == 0 &&
1990
1978
*el_size <= pointer_offset_bits (expr.op ().op0 ().type (), ns))
1991
1979
{
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);
1995
1984
1996
- return false ;
1985
+ return std::move (tmp) ;
1997
1986
}
1998
1987
1999
1988
// extract bits of a constant
@@ -2030,42 +2019,37 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
2030
2019
bits_cut, expr.type (), expr.id () == ID_byte_extract_little_endian);
2031
2020
2032
2021
if (tmp.has_value ())
2033
- {
2034
- expr.swap (*tmp);
2035
-
2036
- return false ;
2037
- }
2022
+ return std::move (*tmp);
2038
2023
}
2039
2024
2040
2025
// try to refine it down to extracting from a member or an index in an array
2041
2026
auto subexpr =
2042
2027
get_subexpression_at_offset (expr.op (), *offset, expr.type (), ns);
2043
2028
if (!subexpr.has_value () || subexpr.value () == expr)
2044
- return true ;
2029
+ return unchanged (expr) ;
2045
2030
2046
2031
simplify_rec (subexpr.value ());
2047
- expr.swap (subexpr.value ());
2048
- return false ;
2032
+ return subexpr.value ();
2049
2033
}
2050
2034
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)
2052
2037
{
2053
- const byte_update_exprt &expr_const = expr;
2054
2038
// byte_update(byte_update(root, offset, value), offset, value2) =>
2055
2039
// byte_update(root, offset, value2)
2056
2040
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 ())
2061
2044
{
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);
2064
2048
}
2065
2049
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 ();
2069
2053
const auto val_size = pointer_offset_bits (value.type (), ns);
2070
2054
const auto root_size = pointer_offset_bits (root.type (), ns);
2071
2055
@@ -2080,10 +2064,7 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2080
2064
ID_byte_extract_big_endian,
2081
2065
value, offset, expr.type ());
2082
2066
2083
- simplify_byte_extract (be);
2084
- expr.swap (be);
2085
-
2086
- return false ;
2067
+ return changed (simplify_byte_extract (be));
2087
2068
}
2088
2069
2089
2070
/*
@@ -2095,7 +2076,7 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2095
2076
*/
2096
2077
2097
2078
if (expr.id ()!=ID_byte_update_little_endian)
2098
- return true ;
2079
+ return unchanged (expr) ;
2099
2080
2100
2081
if (value.id ()==ID_with)
2101
2082
{
@@ -2109,9 +2090,9 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2109
2090
root and offset of update and extract
2110
2091
are the same */
2111
2092
if (!(root==extract.op ()))
2112
- return true ;
2093
+ return unchanged (expr) ;
2113
2094
if (!(offset==extract.offset ()))
2114
- return true ;
2095
+ return unchanged (expr) ;
2115
2096
2116
2097
const typet &tp=ns.follow (with.type ());
2117
2098
if (tp.id ()==ID_struct)
@@ -2135,10 +2116,10 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2135
2116
plus_exprt new_offset (offset, compo_offset);
2136
2117
simplify_node (new_offset);
2137
2118
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
2142
2123
}
2143
2124
}
2144
2125
}
@@ -2162,10 +2143,10 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2162
2143
plus_exprt new_offset (offset, index_offset);
2163
2144
simplify_node (new_offset);
2164
2145
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
2169
2150
}
2170
2151
}
2171
2152
}
@@ -2174,13 +2155,13 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2174
2155
// the following require a constant offset
2175
2156
const auto offset_int = numeric_cast<mp_integer>(offset);
2176
2157
if (!offset_int.has_value () || *offset_int < 0 )
2177
- return true ;
2158
+ return unchanged (expr) ;
2178
2159
2179
2160
const typet &op_type=ns.follow (root.type ());
2180
2161
2181
2162
// size must be known
2182
2163
if (!val_size.has_value () || *val_size == 0 )
2183
- return true ;
2164
+ return unchanged (expr) ;
2184
2165
2185
2166
// Are we updating (parts of) a struct? Do individual member updates
2186
2167
// instead, unless there are non-byte-sized bit fields
@@ -2273,17 +2254,13 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2273
2254
if (result_expr.is_not_nil ())
2274
2255
{
2275
2256
simplify_rec (result_expr);
2276
- expr.swap (result_expr);
2277
-
2278
- return false ;
2257
+ return result_expr;
2279
2258
}
2280
2259
2281
2260
if (result_expr.is_not_nil ())
2282
2261
{
2283
2262
simplify_rec (result_expr);
2284
- expr.swap (result_expr);
2285
-
2286
- return false ;
2263
+ return result_expr;
2287
2264
}
2288
2265
}
2289
2266
@@ -2296,7 +2273,7 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2296
2273
if (!el_size.has_value () || *el_size == 0 ||
2297
2274
(*el_size) % 8 != 0 || (*val_size) % 8 != 0 )
2298
2275
{
2299
- return true ;
2276
+ return unchanged (expr) ;
2300
2277
}
2301
2278
2302
2279
exprt result=root;
@@ -2336,12 +2313,10 @@ bool simplify_exprt::simplify_byte_update(byte_update_exprt &expr)
2336
2313
m_offset_bits += *el_size;
2337
2314
}
2338
2315
2339
- expr.swap (result);
2340
-
2341
- return false ;
2316
+ return std::move (result);
2342
2317
}
2343
2318
2344
- return true ;
2319
+ return unchanged (expr) ;
2345
2320
}
2346
2321
2347
2322
bool simplify_exprt::simplify_complex (exprt &expr)
@@ -2437,10 +2412,24 @@ bool simplify_exprt::simplify_node(exprt &expr)
2437
2412
no_change = simplify_member (expr) && no_change;
2438
2413
else if (expr.id ()==ID_byte_update_little_endian ||
2439
2414
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
+ }
2441
2423
else if (expr.id ()==ID_byte_extract_little_endian ||
2442
2424
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
+ }
2444
2433
else if (expr.id ()==ID_pointer_object)
2445
2434
no_change = simplify_pointer_object (expr) && no_change;
2446
2435
else if (expr.id () == ID_is_dynamic_object)
0 commit comments