Skip to content

Commit 3d23ab4

Browse files
author
Daniel Kroening
authored
Merge pull request #3105 from diffblue/hex-bitvectors6
simplify_exprt::simplify_bitwise is now independent of bitvector representation
2 parents 8ecbec9 + 3db8644 commit 3d23ab4

File tree

3 files changed

+71
-28
lines changed

3 files changed

+71
-28
lines changed

src/util/arith_tools.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,51 @@ bool get_bitvector_bit(const irep_idt &src, std::size_t bit_index)
273273
PRECONDITION(bit_index < src.size());
274274
return src[src.size() - 1 - bit_index] == '1';
275275
}
276+
277+
/// construct a bit-vector representation from a functor
278+
/// \param width: the width of the bit-vector
279+
/// \param f: the functor -- the parameter is the bit index
280+
/// \returns new bitvector representation
281+
irep_idt
282+
make_bvrep(const std::size_t width, const std::function<bool(std::size_t)> f)
283+
{
284+
std::string result(width, ' ');
285+
286+
for(std::size_t i = 0; i < width; i++)
287+
result[width - 1 - i] = f(i) ? '1' : '0';
288+
289+
return result;
290+
}
291+
292+
/// perform a binary bit-wise operation, given as a functor,
293+
/// on a bit-vector representation
294+
/// \param a: the representation of the first bit vector
295+
/// \param b: the representation of the second bit vector
296+
/// \param width: the width of the bit-vector
297+
/// \param f: the functor
298+
/// \returns new bitvector representation
299+
irep_idt bitvector_bitwise_op(
300+
const irep_idt &a,
301+
const irep_idt &b,
302+
const std::size_t width,
303+
const std::function<bool(bool, bool)> f)
304+
{
305+
return make_bvrep(width, [&a, &b, f](std::size_t i) {
306+
return f(get_bitvector_bit(a, i), get_bitvector_bit(b, i));
307+
});
308+
}
309+
310+
/// perform a unary bit-wise operation, given as a functor,
311+
/// on a bit-vector representation
312+
/// \param a: the bit-vector representation
313+
/// \param width: the width of the bit-vector
314+
/// \param f: the functor
315+
/// \returns new bitvector representation
316+
irep_idt bitvector_bitwise_op(
317+
const irep_idt &a,
318+
const std::size_t width,
319+
const std::function<bool(bool)> f)
320+
{
321+
return make_bvrep(
322+
width, [&a, f](std::size_t i) { return f(get_bitvector_bit(a, i)); });
323+
}

src/util/arith_tools.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,7 @@ void mp_max(mp_integer &a, const mp_integer &b);
166166

167167
bool get_bitvector_bit(const irep_idt &src, std::size_t bit_index);
168168

169+
irep_idt
170+
make_bvrep(const std::size_t width, const std::function<bool(std::size_t)> f);
171+
169172
#endif // CPROVER_UTIL_ARITH_TOOLS_H

src/util/simplify_expr_int.cpp

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -713,13 +713,10 @@ bool simplify_exprt::simplify_bitwise(exprt &expr)
713713

714714
// try to merge constants
715715

716-
std::size_t width=to_bitvector_type(expr.type()).get_width();
716+
const std::size_t width = to_bitvector_type(expr.type()).get_width();
717717

718718
while(expr.operands().size()>=2)
719719
{
720-
const irep_idt &a_str=expr.op0().get(ID_value);
721-
const irep_idt &b_str=expr.op1().get(ID_value);
722-
723720
if(!expr.op0().is_constant())
724721
break;
725722

@@ -732,30 +729,24 @@ bool simplify_exprt::simplify_bitwise(exprt &expr)
732729
if(expr.op1().type()!=expr.type())
733730
break;
734731

735-
INVARIANT(
736-
a_str.size() == b_str.size(),
737-
"bitvectors of the same type have the same size");
732+
const auto &a_val = to_constant_expr(expr.op0()).get_value();
733+
const auto &b_val = to_constant_expr(expr.op1()).get_value();
738734

739-
std::string new_value;
740-
new_value.resize(width);
735+
std::function<bool(bool, bool)> f;
741736

742737
if(expr.id()==ID_bitand)
743-
{
744-
for(std::size_t i=0; i<width; i++)
745-
new_value[i]=(a_str[i]=='1' && b_str[i]=='1')?'1':'0';
746-
}
738+
f = [](bool a, bool b) { return a & b; };
747739
else if(expr.id()==ID_bitor)
748-
{
749-
for(std::size_t i=0; i<width; i++)
750-
new_value[i]=(a_str[i]=='1' || b_str[i]=='1')?'1':'0';
751-
}
740+
f = [](bool a, bool b) { return a | b; };
752741
else if(expr.id()==ID_bitxor)
753-
{
754-
for(std::size_t i=0; i<width; i++)
755-
new_value[i]=((a_str[i]=='1')!=(b_str[i]=='1'))?'1':'0';
756-
}
742+
f = [](bool a, bool b) { return a ^ b; };
757743
else
758-
break;
744+
UNREACHABLE;
745+
746+
const irep_idt new_value =
747+
make_bvrep(width, [&a_val, &b_val, &f](std::size_t i) {
748+
return f(get_bitvector_bit(a_val, i), get_bitvector_bit(b_val, i));
749+
});
759750

760751
constant_exprt new_op(new_value, expr.type());
761752

@@ -1280,16 +1271,17 @@ bool simplify_exprt::simplify_bitnot(exprt &expr)
12801271
expr.type().id()==ID_unsignedbv ||
12811272
expr.type().id()==ID_signedbv)
12821273
{
1274+
const auto width = to_bitvector_type(expr.type()).get_width();
1275+
12831276
if(op.type()==expr.type())
12841277
{
12851278
if(op.id()==ID_constant)
12861279
{
1287-
std::string value=op.get_string(ID_value);
1288-
1289-
for(auto &ch : value)
1290-
ch=(ch=='0')?'1':'0';
1291-
1292-
expr = constant_exprt(value, op.type());
1280+
const auto &value = to_constant_expr(op).get_value();
1281+
const auto new_value = make_bvrep(width, [&value](std::size_t i) {
1282+
return !get_bitvector_bit(value, i);
1283+
});
1284+
expr = constant_exprt(new_value, op.type());
12931285
return false;
12941286
}
12951287
}

0 commit comments

Comments
 (0)