]> git.baikalelectronics.ru Git - kernel.git/commitdiff
lib: test_bitmap: add compile-time optimization/evaluations assertions
authorAlexander Lobakin <alexandr.lobakin@intel.com>
Fri, 24 Jun 2022 12:13:13 +0000 (14:13 +0200)
committerYury Norov <yury.norov@gmail.com>
Fri, 1 Jul 2022 02:52:42 +0000 (19:52 -0700)
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>
lib/test_bitmap.c

index d5923a640457d01a40fba3cc9d1daf31a928e765..25967cfa4ab2d7224a14609953332477cc427144 100644 (file)
@@ -869,6 +869,67 @@ static void __init test_bitmap_print_buf(void)
        }
 }
 
+static void __init test_bitmap_const_eval(void)
+{
+       DECLARE_BITMAP(bitmap, BITS_PER_LONG);
+       unsigned long initvar = BIT(2);
+       unsigned long bitopvar = 0;
+       unsigned long var = 0;
+       int res;
+
+       /*
+        * Compilers must be able to optimize all of those to compile-time
+        * constants on any supported optimization level (-O2, -Os) and any
+        * architecture. Otherwise, trigger a build bug.
+        * The whole function gets optimized out then, there's nothing to do
+        * in runtime.
+        */
+
+       /*
+        * Equals to `unsigned long bitmap[1] = { GENMASK(6, 5), }`.
+        * Clang on s390 optimizes bitops at compile-time as intended, but at
+        * the same time stops treating @bitmap and @bitopvar as compile-time
+        * constants after regular test_bit() is executed, thus triggering the
+        * build bugs below. So, call const_test_bit() there directly until
+        * the compiler is fixed.
+        */
+       bitmap_clear(bitmap, 0, BITS_PER_LONG);
+#if defined(__s390__) && defined(__clang__)
+       if (!const_test_bit(7, bitmap))
+#else
+       if (!test_bit(7, bitmap))
+#endif
+               bitmap_set(bitmap, 5, 2);
+
+       /* Equals to `unsigned long bitopvar = BIT(20)` */
+       __change_bit(31, &bitopvar);
+       bitmap_shift_right(&bitopvar, &bitopvar, 11, BITS_PER_LONG);
+
+       /* Equals to `unsigned long var = BIT(25)` */
+       var |= BIT(25);
+       if (var & BIT(0))
+               var ^= GENMASK(9, 6);
+
+       /* __const_hweight<32|64>(GENMASK(6, 5)) == 2 */
+       res = bitmap_weight(bitmap, 20);
+       BUILD_BUG_ON(!__builtin_constant_p(res));
+       BUILD_BUG_ON(res != 2);
+
+       /* !(BIT(31) & BIT(18)) == 1 */
+       res = !test_bit(18, &bitopvar);
+       BUILD_BUG_ON(!__builtin_constant_p(res));
+       BUILD_BUG_ON(!res);
+
+       /* BIT(2) & GENMASK(14, 8) == 0 */
+       res = initvar & GENMASK(14, 8);
+       BUILD_BUG_ON(!__builtin_constant_p(res));
+       BUILD_BUG_ON(res);
+
+       /* ~BIT(25) */
+       BUILD_BUG_ON(!__builtin_constant_p(~var));
+       BUILD_BUG_ON(~var != ~BIT(25));
+}
+
 static void __init selftest(void)
 {
        test_zero_clear();
@@ -884,6 +945,7 @@ static void __init selftest(void)
        test_for_each_set_clump8();
        test_bitmap_cut();
        test_bitmap_print_buf();
+       test_bitmap_const_eval();
 }
 
 KSTM_MODULE_LOADERS(test_bitmap);