linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
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) \

  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