Skip to content

Commit dc34d50

Browse files
alobakinYuryNorov
authored andcommitted
lib: test_bitmap: add compile-time optimization/evaluations assertions
Add a function to the bitmap test suite, which will ensure that compilers are able to evaluate operations performed by the bitops/bitmap helpers to compile-time constants when all of the arguments are compile-time constants as well, or trigger a build bug otherwise. This should work on all architectures and all the optimization levels supported by Kbuild. The function doesn't perform any runtime tests and gets optimized out to nothing after passing the build assertions. Unfortunately, Clang for s390 is currently broken (up to the latest Git snapshots) -- see the comment in the code -- so for now there's a small workaround for it which doesn't alter the logics. Hope we'll be able to remove it one day (bugreport is on its way). Suggested-by: Yury Norov <yury.norov@gmail.com> Signed-off-by: Alexander Lobakin <alexandr.lobakin@intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Yury Norov <yury.norov@gmail.com>
1 parent 3e7e5ba commit dc34d50

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

lib/test_bitmap.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,67 @@ static void __init test_bitmap_print_buf(void)
869869
}
870870
}
871871

872+
static void __init test_bitmap_const_eval(void)
873+
{
874+
DECLARE_BITMAP(bitmap, BITS_PER_LONG);
875+
unsigned long initvar = BIT(2);
876+
unsigned long bitopvar = 0;
877+
unsigned long var = 0;
878+
int res;
879+
880+
/*
881+
* Compilers must be able to optimize all of those to compile-time
882+
* constants on any supported optimization level (-O2, -Os) and any
883+
* architecture. Otherwise, trigger a build bug.
884+
* The whole function gets optimized out then, there's nothing to do
885+
* in runtime.
886+
*/
887+
888+
/*
889+
* Equals to `unsigned long bitmap[1] = { GENMASK(6, 5), }`.
890+
* Clang on s390 optimizes bitops at compile-time as intended, but at
891+
* the same time stops treating @bitmap and @bitopvar as compile-time
892+
* constants after regular test_bit() is executed, thus triggering the
893+
* build bugs below. So, call const_test_bit() there directly until
894+
* the compiler is fixed.
895+
*/
896+
bitmap_clear(bitmap, 0, BITS_PER_LONG);
897+
#if defined(__s390__) && defined(__clang__)
898+
if (!const_test_bit(7, bitmap))
899+
#else
900+
if (!test_bit(7, bitmap))
901+
#endif
902+
bitmap_set(bitmap, 5, 2);
903+
904+
/* Equals to `unsigned long bitopvar = BIT(20)` */
905+
__change_bit(31, &bitopvar);
906+
bitmap_shift_right(&bitopvar, &bitopvar, 11, BITS_PER_LONG);
907+
908+
/* Equals to `unsigned long var = BIT(25)` */
909+
var |= BIT(25);
910+
if (var & BIT(0))
911+
var ^= GENMASK(9, 6);
912+
913+
/* __const_hweight<32|64>(GENMASK(6, 5)) == 2 */
914+
res = bitmap_weight(bitmap, 20);
915+
BUILD_BUG_ON(!__builtin_constant_p(res));
916+
BUILD_BUG_ON(res != 2);
917+
918+
/* !(BIT(31) & BIT(18)) == 1 */
919+
res = !test_bit(18, &bitopvar);
920+
BUILD_BUG_ON(!__builtin_constant_p(res));
921+
BUILD_BUG_ON(!res);
922+
923+
/* BIT(2) & GENMASK(14, 8) == 0 */
924+
res = initvar & GENMASK(14, 8);
925+
BUILD_BUG_ON(!__builtin_constant_p(res));
926+
BUILD_BUG_ON(res);
927+
928+
/* ~BIT(25) */
929+
BUILD_BUG_ON(!__builtin_constant_p(~var));
930+
BUILD_BUG_ON(~var != ~BIT(25));
931+
}
932+
872933
static void __init selftest(void)
873934
{
874935
test_zero_clear();
@@ -884,6 +945,7 @@ static void __init selftest(void)
884945
test_for_each_set_clump8();
885946
test_bitmap_cut();
886947
test_bitmap_print_buf();
948+
test_bitmap_const_eval();
887949
}
888950

889951
KSTM_MODULE_LOADERS(test_bitmap);

0 commit comments

Comments
 (0)