Skip to content

Commit c57ab77

Browse files
committed
simplify_byte_extract: avoid unnecessary calls to has_subtype
This is a performance-improving refactoring: We only need the result of a `has_subtype` call under conditions that are infrequently met. On the benchmark of #7357, this avoids 443214 calls of `has_subtype`, which previously was the most costly part of `simplify_byte_extract`.
1 parent 8c152bc commit c57ab77

File tree

1 file changed

+33
-31
lines changed

1 file changed

+33
-31
lines changed

src/util/simplify_expr.cpp

+33-31
Original file line numberDiff line numberDiff line change
@@ -1831,41 +1831,43 @@ simplify_exprt::simplify_byte_extract(const byte_extract_exprt &expr)
18311831
const auto bits =
18321832
expr2bits(expr.op(), expr.id() == ID_byte_extract_little_endian, ns);
18331833

1834-
// make sure we don't lose bits with structs containing flexible array members
1835-
const bool struct_has_flexible_array_member = has_subtype(
1836-
expr.type(),
1837-
[&](const typet &type) {
1838-
if(type.id() != ID_struct && type.id() != ID_struct_tag)
1839-
return false;
1840-
1841-
const struct_typet &st = to_struct_type(ns.follow(type));
1842-
const auto &comps = st.components();
1843-
if(comps.empty() || comps.back().type().id() != ID_array)
1844-
return false;
1845-
1846-
if(comps.back().type().get_bool(ID_C_flexible_array_member))
1847-
return true;
1848-
1849-
const auto size =
1850-
numeric_cast<mp_integer>(to_array_type(comps.back().type()).size());
1851-
return !size.has_value() || *size <= 1;
1852-
},
1853-
ns);
18541834
if(
18551835
bits.has_value() &&
1856-
mp_integer(bits->size()) >= *el_size + *offset * expr.get_bits_per_byte() &&
1857-
!struct_has_flexible_array_member)
1858-
{
1859-
std::string bits_cut = std::string(
1860-
bits.value(),
1861-
numeric_cast_v<std::size_t>(*offset * expr.get_bits_per_byte()),
1862-
numeric_cast_v<std::size_t>(*el_size));
1836+
mp_integer(bits->size()) >= *el_size + *offset * expr.get_bits_per_byte())
1837+
{
1838+
// make sure we don't lose bits with structs containing flexible array members
1839+
const bool struct_has_flexible_array_member = has_subtype(
1840+
expr.type(),
1841+
[&](const typet &type) {
1842+
if(type.id() != ID_struct && type.id() != ID_struct_tag)
1843+
return false;
1844+
1845+
const struct_typet &st = to_struct_type(ns.follow(type));
1846+
const auto &comps = st.components();
1847+
if(comps.empty() || comps.back().type().id() != ID_array)
1848+
return false;
1849+
1850+
if(comps.back().type().get_bool(ID_C_flexible_array_member))
1851+
return true;
1852+
1853+
const auto size =
1854+
numeric_cast<mp_integer>(to_array_type(comps.back().type()).size());
1855+
return !size.has_value() || *size <= 1;
1856+
},
1857+
ns);
1858+
if(!struct_has_flexible_array_member)
1859+
{
1860+
std::string bits_cut = std::string(
1861+
bits.value(),
1862+
numeric_cast_v<std::size_t>(*offset * expr.get_bits_per_byte()),
1863+
numeric_cast_v<std::size_t>(*el_size));
18631864

1864-
auto tmp = bits2expr(
1865-
bits_cut, expr.type(), expr.id() == ID_byte_extract_little_endian, ns);
1865+
auto tmp = bits2expr(
1866+
bits_cut, expr.type(), expr.id() == ID_byte_extract_little_endian, ns);
18661867

1867-
if(tmp.has_value())
1868-
return std::move(*tmp);
1868+
if(tmp.has_value())
1869+
return std::move(*tmp);
1870+
}
18691871
}
18701872

18711873
// push byte extracts into struct or union expressions, just like

0 commit comments

Comments
 (0)