From: Linus Torvalds <torvalds@linuxfoundation.org>
To: Arnd Bergmann <arnd@kernel.org>
Cc: David Laight <David.Laight@aculab.com>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
Jens Axboe <axboe@kernel.dk>,
Matthew Wilcox <willy@infradead.org>,
Christoph Hellwig <hch@infradead.org>,
Andrew Morton <akpm@linux-foundation.org>,
Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
Dan Carpenter <dan.carpenter@linaro.org>,
"Jason A . Donenfeld" <Jason@zx2c4.com>,
"pedro.falcato@gmail.com" <pedro.falcato@gmail.com>,
Mateusz Guzik <mjguzik@gmail.com>,
"linux-mm@kvack.org" <linux-mm@kvack.org>,
Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Subject: Re: [PATCH v2 1/8] minmax: Put all the clamp() definitions together
Date: Mon, 29 Jul 2024 20:59:47 -0700 [thread overview]
Message-ID: <CAHk-=wgRDupSBzUX_N_Qo_eaYyDfOH=VTihhikN36cGxCc+jvg@mail.gmail.com> (raw)
In-Reply-To: <CAHk-=whCvSUpbOawsbj4A6EUT7jO8562FG+vqiLQvW0CBBZZzA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 693 bytes --]
On Mon, 29 Jul 2024 at 16:21, Linus Torvalds
<torvalds@linuxfoundation.org> wrote:
>
> Attached is the patch I have in my tree right now - it complains about
> a 'bcachefs' comparison between an 'u16' and a 's64', because I also
> removed the 'implicit integer promotion is ok' logic, because I think
> it's wrong.
>
> I don't think a min(u16,s64) is a valid minimum, for exactly the same
> reason a min(u32,s64) is not valid.
Oh, and I noticed that it screws up the 32-bit case, and that does
need a workaround for that.
So here's a better version. The patch contains one possible fix to
bcachefs for the type confusion there, but I'll wait for Kent to
respond on that.
Linus
[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 5120 bytes --]
fs/bcachefs/alloc_background.h | 2 +-
include/linux/compiler.h | 9 ++++++
include/linux/minmax.h | 66 +++++++++++++++++++++++++++++++-----------
3 files changed, 59 insertions(+), 18 deletions(-)
diff --git a/fs/bcachefs/alloc_background.h b/fs/bcachefs/alloc_background.h
index 8d2b62c9588e..b61b92bf7ba9 100644
--- a/fs/bcachefs/alloc_background.h
+++ b/fs/bcachefs/alloc_background.h
@@ -87,7 +87,7 @@ static inline s64 bch2_bucket_sectors_total(struct bch_alloc_v4 a)
return a.stripe_sectors + a.dirty_sectors + a.cached_sectors;
}
-static inline s64 bch2_bucket_sectors_dirty(struct bch_alloc_v4 a)
+static inline u64 bch2_bucket_sectors_dirty(struct bch_alloc_v4 a)
{
return a.stripe_sectors + a.dirty_sectors;
}
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 2594553bb30b..2df665fa2964 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -296,6 +296,15 @@ static inline void *offset_to_ptr(const int *off)
#define is_signed_type(type) (((type)(-1)) < (__force type)1)
#define is_unsigned_type(type) (!is_signed_type(type))
+/*
+ * Useful shorthand for "is this condition known at compile-time?"
+ *
+ * Note that the condition may involve non-constant values,
+ * but the compiler may know enough about the details of the
+ * values to determine that the condition is statically true.
+ */
+#define statically_true(x) (__builtin_constant_p(x) && (x))
+
/*
* This is needed in functions which generate the stack canary, see
* arch/x86/kernel/smpboot.c::start_secondary() for an example.
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index e3e4353df983..af53ebe3d2b8 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -26,19 +26,52 @@
#define __typecheck(x, y) \
(!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
-/* is_signed_type() isn't a constexpr for pointer types */
-#define __is_signed(x) \
- __builtin_choose_expr(__is_constexpr(is_signed_type(typeof(x))), \
- is_signed_type(typeof(x)), 0)
+/*
+ * __sign_use for integer expressions:
+ * bit #0 set if ok for unsigned comparisons
+ * bit #1 set if ok for signed comparisons
+ *
+ * In particular, non-negative integer expressions
+ * are ok for both.
+ *
+ * Note that 'x' is the original expression, and 'ux'
+ * is the unique variable that contains the value.
+ *
+ * We use 'ux' for pure type checking, and 'x' for
+ * when we need to look at the value (but without
+ * evaluating it for side effects! Careful to only
+ * evaluate it with __builtin_constant_p() etc)
+ */
+#define __sign_use(x,ux) \
+ (is_signed_type(typeof(ux))?2+__is_nonneg(x,ux):1)
-/* True for a non-negative signed int constant */
-#define __is_noneg_int(x) \
- (__builtin_choose_expr(__is_constexpr(x) && __is_signed(x), x, -1) >= 0)
+/*
+ * To avoid warnings about casting pointers to integers
+ * of different sizes, we need that special sign type.
+ *
+ * On 64-bit we can just always use 'long', since any
+ * integer or pointer type can just be cast to that.
+ *
+ * This does not work for 128-bit signed integers since
+ * the cast would truncate them, but we do not use s128
+ * types in the kernel (we do use 'u128', but they will
+ * be handled by the !is_signed_type() case).
+ *
+ * NOTE! The cast is there only to avoid any warnings
+ * from when values that aren't signed integer types.
+ */
+#ifdef CONFIG_64BIT
+ #define __signed_type(ux) long
+#else
+ #define __signed_type(ux) typeof(__builtin_choose_expr(sizeof(ux)>32,1LL,1L))
+#endif
+#define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0)
-#define __types_ok(x, y, ux, uy) \
- (__is_signed(ux) == __is_signed(uy) || \
- __is_signed((ux) + 0) == __is_signed((uy) + 0) || \
- __is_noneg_int(x) || __is_noneg_int(y))
+#define __types_ok(x,y,ux,uy) \
+ (__sign_use(x,ux) & __sign_use(y,uy))
+
+#define __types_ok3(x,y,z,ux,uy,uz) \
+ (__sign_use(x,ux) & __sign_use(y,uy) & __sign_use(z,uz))
#define __cmp_op_min <
#define __cmp_op_max >
@@ -53,8 +86,8 @@
#define __careful_cmp_once(op, x, y, ux, uy) ({ \
__auto_type ux = (x); __auto_type uy = (y); \
- static_assert(__types_ok(x, y, ux, uy), \
- #op "(" #x ", " #y ") signedness error, fix types or consider u" #op "() before " #op "_t()"); \
+ BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \
+ #op"("#x", "#y") signedness error"); \
__cmp(op, ux, uy); })
#define __careful_cmp(op, x, y) \
@@ -67,11 +100,10 @@
__auto_type uval = (val); \
__auto_type ulo = (lo); \
__auto_type uhi = (hi); \
- static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \
- (lo) <= (hi), true), \
+ BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \
"clamp() low limit " #lo " greater than high limit " #hi); \
- static_assert(__types_ok(uval, lo, uval, ulo), "clamp() 'lo' signedness error"); \
- static_assert(__types_ok(uval, hi, uval, uhi), "clamp() 'hi' signedness error"); \
+ BUILD_BUG_ON_MSG(!__types_ok3(val,lo,hi,uval,ulo,uhi), \
+ "clamp("#val", "#lo", "#hi") signedness error"); \
__clamp(uval, ulo, uhi); })
#define __careful_clamp(val, lo, hi) \
next prev parent reply other threads:[~2024-07-30 4:00 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-28 14:15 [PATCH v2 0/8] minmax: reduce compilation time David Laight
2024-07-28 14:17 ` [PATCH v2 1/8] minmax: Put all the clamp() definitions together David Laight
2024-07-28 17:24 ` Linus Torvalds
2024-07-28 18:11 ` David Laight
2024-07-28 19:55 ` Linus Torvalds
2024-07-28 20:09 ` David Laight
2024-07-28 20:13 ` Linus Torvalds
2024-07-28 20:22 ` David Laight
2024-07-28 20:31 ` Linus Torvalds
2024-07-28 22:13 ` David Laight
2024-07-28 22:22 ` Linus Torvalds
2024-07-29 8:01 ` David Laight
2024-07-28 21:01 ` Linus Torvalds
2024-07-28 21:53 ` David Laight
2024-07-29 4:15 ` Linus Torvalds
2024-07-29 22:25 ` Arnd Bergmann
2024-07-29 23:21 ` Linus Torvalds
2024-07-30 1:52 ` Linus Torvalds
2024-07-30 3:59 ` Linus Torvalds [this message]
2024-07-30 10:10 ` Arnd Bergmann
2024-07-30 14:14 ` Arnd Bergmann
2024-07-30 18:02 ` Linus Torvalds
2024-07-30 19:52 ` Linus Torvalds
2024-07-30 21:47 ` David Laight
2024-07-30 22:44 ` Linus Torvalds
2024-07-30 23:03 ` Linus Torvalds
2024-07-31 8:09 ` David Laight
2024-07-31 10:50 ` Arnd Bergmann
2024-07-31 15:38 ` Linus Torvalds
2024-07-31 15:56 ` David Laight
2024-07-31 16:04 ` Linus Torvalds
2024-12-04 13:15 ` Geert Uytterhoeven
2024-12-04 17:16 ` David Laight
2024-07-30 16:35 ` Linus Torvalds
2024-07-30 16:46 ` Linus Torvalds
2024-07-30 12:03 ` David Laight
2024-07-28 18:23 ` David Laight
2024-07-28 14:18 ` [PATCH v2 2/8] minmax: Use _Static_assert() instead of static_assert() David Laight
2024-07-28 17:51 ` Christophe JAILLET
2024-07-28 18:12 ` David Laight
2024-07-28 14:19 ` [PATCH v2 3/8] compiler.h: Add __if_constexpr(expr, if_const, if_not_const) David Laight
2024-07-28 14:20 ` [PATCH v2 4/8] minmax: Simplify signedness check David Laight
2024-07-28 16:57 ` Linus Torvalds
2024-07-28 18:14 ` David Laight
2024-07-28 20:13 ` David Laight
2024-07-28 14:21 ` [PATCH v2 5/8] minmax: Factor out the zero-extension logic from umin/umax David Laight
2024-07-28 14:22 ` [PATCH v2 6/8] minmax: Optimise _Static_assert() check in clamp() David Laight
2024-07-28 14:23 ` [PATCH v2 7/8] minmax: Use __auto_type David Laight
2024-07-28 16:59 ` Linus Torvalds
2024-07-28 14:24 ` [PATCH v2 8/8] minmax: minmax: Add __types_ok3() and optimise defines with 3 arguments David Laight
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAHk-=wgRDupSBzUX_N_Qo_eaYyDfOH=VTihhikN36cGxCc+jvg@mail.gmail.com' \
--to=torvalds@linuxfoundation.org \
--cc=David.Laight@aculab.com \
--cc=Jason@zx2c4.com \
--cc=akpm@linux-foundation.org \
--cc=andriy.shevchenko@linux.intel.com \
--cc=arnd@kernel.org \
--cc=axboe@kernel.dk \
--cc=dan.carpenter@linaro.org \
--cc=hch@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lorenzo.stoakes@oracle.com \
--cc=mjguzik@gmail.com \
--cc=pedro.falcato@gmail.com \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox