Skip to content

Commit b5562a7

Browse files
committed
Simplify typecast of zero-extension to a series of typecasts
The intervening zero-extension hinders the application of `skip_typecast`.
1 parent 66004dc commit b5562a7

File tree

4 files changed

+74
-1
lines changed

4 files changed

+74
-1
lines changed

regression/cbmc/Quantifiers-type2/main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ int main()
55

66
// clang-format off
77
// clang-format would rewrite the "==>" as "== >"
8-
__CPROVER_assume( __CPROVER_forall { char i; (i>=0 && i<2) ==> b[i]>=10 && b[i]<=10 } );
8+
__CPROVER_assume( __CPROVER_forall { signed char i; (i>=0 && i<2) ==> b[i]>=10 && b[i]<=10 } );
99
__CPROVER_assume( __CPROVER_forall { unsigned i; (i>=0 && i<2) ==> c[i]>=10 && c[i]<=10 } );
1010
// clang-format on
1111

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
int main()
2+
{
3+
int b[2];
4+
int c[2];
5+
6+
// clang-format off
7+
// clang-format would rewrite the "==>" as "== >"
8+
__CPROVER_assume( __CPROVER_forall { unsigned char i; (i>=0 && i<2) ==> b[i]>=10 && b[i]<=10 } );
9+
__CPROVER_assume( __CPROVER_forall { unsigned i; (i>=0 && i<2) ==> c[i]>=10 && c[i]<=10 } );
10+
// clang-format on
11+
12+
assert(b[0] == 10 && b[1] == 10);
13+
assert(c[0] == 10 && c[1] == 10);
14+
15+
return 0;
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE no-new-smt
2+
unsigned-char.c
3+
4+
^\*\* Results:$
5+
^\[main.assertion.1\] line 12 assertion b\[.*0\] == 10 && b\[.*1\] == 10: SUCCESS$
6+
^\[main.assertion.2\] line 13 assertion c\[.*0\] == 10 && c\[.*1\] == 10: SUCCESS$
7+
^VERIFICATION SUCCESSFUL$
8+
^EXIT=0$
9+
^SIGNAL=0$
10+
--
11+
^warning: ignoring

src/util/simplify_expr.cpp

+46
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,52 @@ simplify_exprt::simplify_typecast(const typecast_exprt &expr)
975975
else if(op_id==ID_ashr || op_id==ID_lshr || op_id==ID_shl)
976976
{
977977
}
978+
else if(op_id == ID_zero_extend)
979+
{
980+
const exprt &zero_extended_op = to_zero_extend_expr(expr.op());
981+
if(
982+
auto bv_type =
983+
type_try_dynamic_cast<bitvector_typet>(zero_extended_op.type()))
984+
{
985+
auto new_expr = expr;
986+
if(
987+
bv_type->id() == ID_signedbv &&
988+
bv_type->get_width() < to_bitvector_type(expr_type).get_width())
989+
{
990+
new_expr.op() =
991+
simplify_typecast(
992+
typecast_exprt{
993+
zero_extended_op, unsignedbv_typet{bv_type->get_width()}})
994+
.expr;
995+
}
996+
else
997+
new_expr.op() = zero_extended_op;
998+
return changed(simplify_typecast(new_expr)); // rec. call
999+
}
1000+
}
1001+
else if(op_id == ID_concatenation)
1002+
{
1003+
const auto &operands = expr.op().operands();
1004+
if(
1005+
operands.size() == 2 && operands.front().is_constant() &&
1006+
to_constant_expr(operands.front()).value_is_zero_string())
1007+
{
1008+
auto new_expr = expr;
1009+
const bitvector_typet &bv_type =
1010+
to_bitvector_type(operands.back().type());
1011+
if(bv_type.id() == ID_signedbv)
1012+
{
1013+
new_expr.op() =
1014+
simplify_typecast(
1015+
typecast_exprt{
1016+
operands.back(), unsignedbv_typet{bv_type.get_width()}})
1017+
.expr;
1018+
}
1019+
else
1020+
new_expr.op() = operands.back();
1021+
return changed(simplify_typecast(new_expr)); // rec. call
1022+
}
1023+
}
9781024
}
9791025
}
9801026

0 commit comments

Comments
 (0)