Skip to content

Commit c1336e4

Browse files
authored
Merge pull request #6703 from tautschnig/bugfixes/6702-ctz
Fix count-trailing-zeros lowering for value zero
2 parents a2e51b6 + e244103 commit c1336e4

File tree

3 files changed

+12
-13
lines changed

3 files changed

+12
-13
lines changed

regression/cbmc/__builtin_ctz-01/main.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ int main()
4343
[((unsigned)((u & -u) * 0x077CB531U)) >> 27] == __builtin_ctz(u));
4444

4545
// a failing assertion should be generated as __builtin_ctz is undefined for 0
46-
__builtin_ctz(0U);
46+
int r = __builtin_ctz(0U);
47+
__CPROVER_assert(
48+
r == sizeof(unsigned) * 8, "count trailing zeros of 0 is bit width");
4749

4850
return 0;
4951
}

regression/cbmc/__builtin_ctz-01/test.desc

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ CORE
22
main.c
33
--bounds-check
44
^\[main.bit_count.\d+\] line 46 count trailing zeros is undefined for value zero in __builtin_ctz\(0u\): FAILURE$
5+
^\[main.assertion.2\] line 47 count trailing zeros of 0 is bit width: SUCCESS$
56
^\*\* 1 of \d+ failed
67
^VERIFICATION FAILED$
78
^EXIT=10$

src/util/bitvector_expr.cpp

+8-12
Original file line numberDiff line numberDiff line change
@@ -129,18 +129,14 @@ exprt count_leading_zeros_exprt::lower() const
129129
exprt count_trailing_zeros_exprt::lower() const
130130
{
131131
exprt x = op();
132-
const auto int_width = to_bitvector_type(x.type()).get_width();
133-
CHECK_RETURN(int_width >= 1);
134-
135-
// popcount(x ^ ((unsigned)x - 1)) - 1
136-
const unsignedbv_typet ut{int_width};
137-
minus_exprt minus_one{typecast_exprt::conditional_cast(x, ut),
138-
from_integer(1, ut)};
139-
popcount_exprt popcount{
140-
bitxor_exprt{x, typecast_exprt::conditional_cast(minus_one, x.type())}};
141-
minus_exprt result{popcount.lower(), from_integer(1, x.type())};
142-
143-
return typecast_exprt::conditional_cast(result, type());
132+
133+
// popcount(~(x | (~x + 1)))
134+
// compute -x using two's complement
135+
plus_exprt minus_x{bitnot_exprt{x}, from_integer(1, x.type())};
136+
bitor_exprt x_or_minus_x{x, std::move(minus_x)};
137+
popcount_exprt popcount{bitnot_exprt{std::move(x_or_minus_x)}};
138+
139+
return typecast_exprt::conditional_cast(popcount.lower(), type());
144140
}
145141

146142
exprt bitreverse_exprt::lower() const

0 commit comments

Comments
 (0)