lib/tests/printf_kunit.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-)
Old GCC can miscompile printf_kunit's errptr() test when branch
profiling is enabled. BUILD_BUG_ON(IS_ERR(PTR)) is a constant false
expression, but CONFIG_TRACE_BRANCH_PROFILING and
CONFIG_PROFILE_ALL_BRANCHES make the IS_ERR() path side-effectful.
GCC's IPA splitter can then outline the cold assert arm into
errptr.part.* and leave that clone with an unconditional
__compiletime_assert_*() call, causing a false build failure.
This started showing up after test_hashed() became a macro and moved its
local buffer into errptr(), which changed GCC's inlining and splitting
decisions enough to expose the compiler bug.
Mark errptr() noinline to keep it out of that buggy IPA path while
preserving the BUILD_BUG_ON(IS_ERR(PTR)) check and the macro-based
printf argument checking.
Fixes: 9bfa52dac27a ("printf: convert test_hashed into macro")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202604030636.NqjaJvYp-lkp@intel.com/
Signed-off-by: Tamir Duberstein <tamird@kernel.org>
---
lib/tests/printf_kunit.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/lib/tests/printf_kunit.c b/lib/tests/printf_kunit.c
index f6f21b445ece..a8087e8ac826 100644
--- a/lib/tests/printf_kunit.c
+++ b/lib/tests/printf_kunit.c
@@ -749,7 +749,23 @@ static void fourcc_pointer(struct kunit *kunittest)
fourcc_pointer_test(kunittest, try_cb, ARRAY_SIZE(try_cb), "%p4cb");
}
-static void
+/*
+ * GCC < 12.1 can miscompile this test when branch profiling is enabled.
+ *
+ * BUILD_BUG_ON(IS_ERR(PTR)) is a constant false expression, but old GCC can
+ * still trip over it after CONFIG_TRACE_BRANCH_PROFILING and
+ * CONFIG_PROFILE_ALL_BRANCHES rewrite the IS_ERR() unlikely() path into
+ * side-effectful branch counter updates. IPA splitting then outlines the cold
+ * assert arm into errptr.part.* and leaves that clone with an unconditional
+ * __compiletime_assert_*() call, so the build fails even though PTR is not an
+ * ERR_PTR.
+ *
+ * Keep this test out of that buggy IPA path so the BUILD_BUG_ON() can stay in
+ * place without open-coding IS_ERR(). This can be removed once the minimum GCC
+ * includes commit 76fe49423047 ("Fix tree-optimization/101941: IPA splitting
+ * out function with error attribute"), which first shipped in GCC 12.1.
+ */
+static noinline void
errptr(struct kunit *kunittest)
{
test("-1234", "%pe", ERR_PTR(-1234));
---
base-commit: d8a9a4b11a137909e306e50346148fc5c3b63f9d
change-id: 20260405-printf-test-old-gcc-f13fecda6524
Best regards,
--
Tamir Duberstein <tamird@kernel.org>
On Sun, 05 Apr 2026 13:31:50 -0400
Tamir Duberstein <tamird@kernel.org> wrote:
> Old GCC can miscompile printf_kunit's errptr() test when branch
> profiling is enabled. BUILD_BUG_ON(IS_ERR(PTR)) is a constant false
> expression, but CONFIG_TRACE_BRANCH_PROFILING and
> CONFIG_PROFILE_ALL_BRANCHES make the IS_ERR() path side-effectful.
> GCC's IPA splitter can then outline the cold assert arm into
> errptr.part.* and leave that clone with an unconditional
> __compiletime_assert_*() call, causing a false build failure.
>
> This started showing up after test_hashed() became a macro and moved its
> local buffer into errptr(), which changed GCC's inlining and splitting
> decisions enough to expose the compiler bug.
>
> Mark errptr() noinline to keep it out of that buggy IPA path while
> preserving the BUILD_BUG_ON(IS_ERR(PTR)) check and the macro-based
> printf argument checking.
Why not convert that check to a run-time one?
It isn't as though IS_ERR() is usually used with constants.
(There are a lot of other tests which would be better as compile-time
ones; since the run-time code just checks the compiler generated
the correct constant. So a compile failure saves you having to run
the tests; but that isn't true here.)
I'd also test -4095 and -4096...
>
> Fixes: 9bfa52dac27a ("printf: convert test_hashed into macro")
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202604030636.NqjaJvYp-lkp@intel.com/
> Signed-off-by: Tamir Duberstein <tamird@kernel.org>
> ---
> lib/tests/printf_kunit.c | 18 +++++++++++++++++-
> 1 file changed, 17 insertions(+), 1 deletion(-)
>
> diff --git a/lib/tests/printf_kunit.c b/lib/tests/printf_kunit.c
> index f6f21b445ece..a8087e8ac826 100644
> --- a/lib/tests/printf_kunit.c
> +++ b/lib/tests/printf_kunit.c
> @@ -749,7 +749,23 @@ static void fourcc_pointer(struct kunit *kunittest)
> fourcc_pointer_test(kunittest, try_cb, ARRAY_SIZE(try_cb), "%p4cb");
> }
>
> -static void
> +/*
> + * GCC < 12.1 can miscompile this test when branch profiling is enabled.
> + *
> + * BUILD_BUG_ON(IS_ERR(PTR)) is a constant false expression, but old GCC can
> + * still trip over it after CONFIG_TRACE_BRANCH_PROFILING and
> + * CONFIG_PROFILE_ALL_BRANCHES rewrite the IS_ERR() unlikely() path into
> + * side-effectful branch counter updates. IPA splitting then outlines the cold
> + * assert arm into errptr.part.* and leaves that clone with an unconditional
> + * __compiletime_assert_*() call, so the build fails even though PTR is not an
> + * ERR_PTR.
> + *
> + * Keep this test out of that buggy IPA path so the BUILD_BUG_ON() can stay in
> + * place without open-coding IS_ERR(). This can be removed once the minimum GCC
> + * includes commit 76fe49423047 ("Fix tree-optimization/101941: IPA splitting
> + * out function with error attribute"), which first shipped in GCC 12.1.
> + */
> +static noinline void
While that might make a difference, I'm not sure that it has to.
You aren't changing anything directly related to the failing expansion.
David
> errptr(struct kunit *kunittest)
> {
> test("-1234", "%pe", ERR_PTR(-1234));
>
> ---
> base-commit: d8a9a4b11a137909e306e50346148fc5c3b63f9d
> change-id: 20260405-printf-test-old-gcc-f13fecda6524
>
> Best regards,
> --
> Tamir Duberstein <tamird@kernel.org>
>
>
On Sun, Apr 5, 2026 at 1:32 PM Tamir Duberstein <tamird@kernel.org> wrote:
>
> Old GCC can miscompile printf_kunit's errptr() test when branch
> profiling is enabled. BUILD_BUG_ON(IS_ERR(PTR)) is a constant false
> expression, but CONFIG_TRACE_BRANCH_PROFILING and
> CONFIG_PROFILE_ALL_BRANCHES make the IS_ERR() path side-effectful.
> GCC's IPA splitter can then outline the cold assert arm into
> errptr.part.* and leave that clone with an unconditional
> __compiletime_assert_*() call, causing a false build failure.
>
> This started showing up after test_hashed() became a macro and moved its
> local buffer into errptr(), which changed GCC's inlining and splitting
> decisions enough to expose the compiler bug.
>
> Mark errptr() noinline to keep it out of that buggy IPA path while
> preserving the BUILD_BUG_ON(IS_ERR(PTR)) check and the macro-based
> printf argument checking.
>
> Fixes: 9bfa52dac27a ("printf: convert test_hashed into macro")
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202604030636.NqjaJvYp-lkp@intel.com/
> Signed-off-by: Tamir Duberstein <tamird@kernel.org>
Adding tag per stable instructions:
Cc: stable@vger.kernel.org
On Sun, 05 Apr 2026 13:31:50 -0400
Tamir Duberstein <tamird@kernel.org> wrote:
> Old GCC can miscompile printf_kunit's errptr() test when branch
> profiling is enabled. BUILD_BUG_ON(IS_ERR(PTR)) is a constant false
> expression, but CONFIG_TRACE_BRANCH_PROFILING and
> CONFIG_PROFILE_ALL_BRANCHES make the IS_ERR() path side-effectful.
> GCC's IPA splitter can then outline the cold assert arm into
> errptr.part.* and leave that clone with an unconditional
> __compiletime_assert_*() call, causing a false build failure.
>
> This started showing up after test_hashed() became a macro and moved its
> local buffer into errptr(), which changed GCC's inlining and splitting
> decisions enough to expose the compiler bug.
>
> Mark errptr() noinline to keep it out of that buggy IPA path while
> preserving the BUILD_BUG_ON(IS_ERR(PTR)) check and the macro-based
> printf argument checking.
>
> Fixes: 9bfa52dac27a ("printf: convert test_hashed into macro")
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202604030636.NqjaJvYp-lkp@intel.com/
> Signed-off-by: Tamir Duberstein <tamird@kernel.org>
Another solution which I would be fine with is:
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index e130da35808f..c07e8eadfdd0 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -692,6 +692,7 @@ config PROFILE_ANNOTATED_BRANCHES
config PROFILE_ALL_BRANCHES
bool "Profile all if conditionals" if !FORTIFY_SOURCE
select TRACE_BRANCH_PROFILING
+ depends on !KUNIT
help
This tracer profiles all branch conditions. Every if ()
taken in the kernel is recorded whether it hit or miss.
-- Steve
On Mon, Apr 6, 2026 at 11:14 AM Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Sun, 05 Apr 2026 13:31:50 -0400
> Tamir Duberstein <tamird@kernel.org> wrote:
>
> > Old GCC can miscompile printf_kunit's errptr() test when branch
> > profiling is enabled. BUILD_BUG_ON(IS_ERR(PTR)) is a constant false
> > expression, but CONFIG_TRACE_BRANCH_PROFILING and
> > CONFIG_PROFILE_ALL_BRANCHES make the IS_ERR() path side-effectful.
> > GCC's IPA splitter can then outline the cold assert arm into
> > errptr.part.* and leave that clone with an unconditional
> > __compiletime_assert_*() call, causing a false build failure.
> >
> > This started showing up after test_hashed() became a macro and moved its
> > local buffer into errptr(), which changed GCC's inlining and splitting
> > decisions enough to expose the compiler bug.
> >
> > Mark errptr() noinline to keep it out of that buggy IPA path while
> > preserving the BUILD_BUG_ON(IS_ERR(PTR)) check and the macro-based
> > printf argument checking.
> >
> > Fixes: 9bfa52dac27a ("printf: convert test_hashed into macro")
> > Reported-by: kernel test robot <lkp@intel.com>
> > Closes: https://lore.kernel.org/oe-kbuild-all/202604030636.NqjaJvYp-lkp@intel.com/
> > Signed-off-by: Tamir Duberstein <tamird@kernel.org>
>
> Another solution which I would be fine with is:
>
> diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
> index e130da35808f..c07e8eadfdd0 100644
> --- a/kernel/trace/Kconfig
> +++ b/kernel/trace/Kconfig
> @@ -692,6 +692,7 @@ config PROFILE_ANNOTATED_BRANCHES
> config PROFILE_ALL_BRANCHES
> bool "Profile all if conditionals" if !FORTIFY_SOURCE
> select TRACE_BRANCH_PROFILING
> + depends on !KUNIT
> help
> This tracer profiles all branch conditions. Every if ()
> taken in the kernel is recorded whether it hit or miss.
>
>
> -- Steve
Thanks Steve. IMO that is a very big hammer and not warranted in this
case. There's been talk of encouraging distros to enable CONFIG_KUNIT
by default [0], which would probably interact poorly with the change
you propose.
Link: https://lore.kernel.org/all/CABVgOS=KZrM2dWyp1HzVS0zh7vquLxmTY2T2Ti53DQADrW+sJg@mail.gmail.com/
[0]
On Mon, 6 Apr 2026 11:21:39 -0400 Tamir Duberstein <tamird@kernel.org> wrote: > Thanks Steve. IMO that is a very big hammer and not warranted in this > case. There's been talk of encouraging distros to enable CONFIG_KUNIT > by default [0], which would probably interact poorly with the change > you propose. > Branch profiling is really just a niche that is enabled specifically for seeing all branches taken in the kernel. It hooks to all "if" statements! As you can imagine, it causes a rather large overhead in performance. This option is only used by developers doing special analysis of their code (namely me ;-). The only real concern I would have is if the kunit test developers would want to use the branch profiling on their code, in which case my suggestion would prevent that. -- Steve
On Mon, 6 Apr 2026 12:32:32 -0400 Steven Rostedt <rostedt@goodmis.org> wrote: > On Mon, 6 Apr 2026 11:21:39 -0400 > Tamir Duberstein <tamird@kernel.org> wrote: > > > Thanks Steve. IMO that is a very big hammer and not warranted in this > > case. There's been talk of encouraging distros to enable CONFIG_KUNIT > > by default [0], which would probably interact poorly with the change > > you propose. > > > > Branch profiling is really just a niche that is enabled specifically for > seeing all branches taken in the kernel. It hooks to all "if" statements! > As you can imagine, it causes a rather large overhead in performance. > > This option is only used by developers doing special analysis of their code > (namely me ;-). Is there any way to stop randconfig picking up options like these? It is rather a waste of brain-cycles trying to fix them. If you want the option to test a specific bit of code it is easy to hack/disable any problematic parts. Even having the KASAN/KMSAN code compiled into allmodconfig is a PITA when you are trying to check that code compiles to something sensible. David
On Tue 2026-04-07 16:08:09, David Laight wrote: > On Mon, 6 Apr 2026 12:32:32 -0400 > Steven Rostedt <rostedt@goodmis.org> wrote: > > > On Mon, 6 Apr 2026 11:21:39 -0400 > > Tamir Duberstein <tamird@kernel.org> wrote: > > > > > Thanks Steve. IMO that is a very big hammer and not warranted in this > > > case. There's been talk of encouraging distros to enable CONFIG_KUNIT > > > by default [0], which would probably interact poorly with the change > > > you propose. > > > > > > > Branch profiling is really just a niche that is enabled specifically for > > seeing all branches taken in the kernel. It hooks to all "if" statements! > > As you can imagine, it causes a rather large overhead in performance. > > > > This option is only used by developers doing special analysis of their code > > (namely me ;-). > > Is there any way to stop randconfig picking up options like these? > It is rather a waste of brain-cycles trying to fix them. > If you want the option to test a specific bit of code it is easy to > hack/disable any problematic parts. > > Even having the KASAN/KMSAN code compiled into allmodconfig is a PITA > when you are trying to check that code compiles to something sensible. This does not look like a good idea. KASAN/KMSAN are very useful features. People will want to keep them working. Removing them from randconfig would just postpone detection of the problem. We would need to deal with it sooner or later anyway. Best Regards, Petr
On Wed, 8 Apr 2026 09:24:58 +0200 Petr Mladek <pmladek@suse.com> wrote: > On Tue 2026-04-07 16:08:09, David Laight wrote: > > On Mon, 6 Apr 2026 12:32:32 -0400 > > Steven Rostedt <rostedt@goodmis.org> wrote: > > > > > On Mon, 6 Apr 2026 11:21:39 -0400 > > > Tamir Duberstein <tamird@kernel.org> wrote: > > > > > > > Thanks Steve. IMO that is a very big hammer and not warranted in this > > > > case. There's been talk of encouraging distros to enable CONFIG_KUNIT > > > > by default [0], which would probably interact poorly with the change > > > > you propose. > > > > > > > > > > Branch profiling is really just a niche that is enabled specifically for > > > seeing all branches taken in the kernel. It hooks to all "if" statements! > > > As you can imagine, it causes a rather large overhead in performance. > > > > > > This option is only used by developers doing special analysis of their code > > > (namely me ;-). > > > > Is there any way to stop randconfig picking up options like these? > > It is rather a waste of brain-cycles trying to fix them. > > If you want the option to test a specific bit of code it is easy to > > hack/disable any problematic parts. > > > > Even having the KASAN/KMSAN code compiled into allmodconfig is a PITA > > when you are trying to check that code compiles to something sensible. > > This does not look like a good idea. KASAN/KMSAN are very useful > features. People will want to keep them working. Removing them from > randconfig would just postpone detection of the problem. We would > need to deal with it sooner or later anyway. True, but when I build an allmodconfig build to check how the asm looks I really don't want them. For the 'bot' builds you also want to know whether they are defined. Changes to how things are built rather than what is built can throw up unexpected warnings that are very hard to pin down. It is bad enough finding things that affect one obscure architecture with a specific compiler version when the compiler just makes slightly different decisions, without having unusual compilation/config options is the mix to muddy the waters further. David > > Best Regards, > Petr
On Wed, Apr 08, 2026 at 10:04:25AM +0100, David Laight wrote: > On Wed, 8 Apr 2026 09:24:58 +0200 > Petr Mladek <pmladek@suse.com> wrote: > > On Tue 2026-04-07 16:08:09, David Laight wrote: > > > On Mon, 6 Apr 2026 12:32:32 -0400 > > > Steven Rostedt <rostedt@goodmis.org> wrote: > > > > On Mon, 6 Apr 2026 11:21:39 -0400 > > > > Tamir Duberstein <tamird@kernel.org> wrote: ... > > > Even having the KASAN/KMSAN code compiled into allmodconfig is a PITA > > > when you are trying to check that code compiles to something sensible. > > > > This does not look like a good idea. KASAN/KMSAN are very useful > > features. People will want to keep them working. Removing them from > > randconfig would just postpone detection of the problem. We would > > need to deal with it sooner or later anyway. > > True, but when I build an allmodconfig build to check how the asm looks > I really don't want them. Isn't easy to disable that in the command line to `make`? > For the 'bot' builds you also want to know whether they are defined. > Changes to how things are built rather than what is built can throw > up unexpected warnings that are very hard to pin down. > > It is bad enough finding things that affect one obscure architecture > with a specific compiler version when the compiler just makes slightly > different decisions, without having unusual compilation/config options > is the mix to muddy the waters further. -- With Best Regards, Andy Shevchenko
On Wed, 8 Apr 2026 14:29:59 +0300 Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote: > On Wed, Apr 08, 2026 at 10:04:25AM +0100, David Laight wrote: > > On Wed, 8 Apr 2026 09:24:58 +0200 > > Petr Mladek <pmladek@suse.com> wrote: > > > On Tue 2026-04-07 16:08:09, David Laight wrote: > > > > On Mon, 6 Apr 2026 12:32:32 -0400 > > > > Steven Rostedt <rostedt@goodmis.org> wrote: > > > > > On Mon, 6 Apr 2026 11:21:39 -0400 > > > > > Tamir Duberstein <tamird@kernel.org> wrote: > > ... > > > > > Even having the KASAN/KMSAN code compiled into allmodconfig is a PITA > > > > when you are trying to check that code compiles to something sensible. > > > > > > This does not look like a good idea. KASAN/KMSAN are very useful > > > features. People will want to keep them working. Removing them from > > > randconfig would just postpone detection of the problem. We would > > > need to deal with it sooner or later anyway. > > > > True, but when I build an allmodconfig build to check how the asm looks > > I really don't want them. > > Isn't easy to disable that in the command line to `make`? It is a config option, and I think you need to reset it every time you rerun 'make allmodconfig' to pick up config changes. You can enable -Werror with W=e, but not disable it if you want to set W=1. I did have a patch that let you use W=1-e which is useful. David > > > For the 'bot' builds you also want to know whether they are defined. > > Changes to how things are built rather than what is built can throw > > up unexpected warnings that are very hard to pin down. > > > > It is bad enough finding things that affect one obscure architecture > > with a specific compiler version when the compiler just makes slightly > > different decisions, without having unusual compilation/config options > > is the mix to muddy the waters further. >
On Mon 2026-04-06 12:32:32, Steven Rostedt wrote: > On Mon, 6 Apr 2026 11:21:39 -0400 > Tamir Duberstein <tamird@kernel.org> wrote: > > > Thanks Steve. IMO that is a very big hammer and not warranted in this > > case. There's been talk of encouraging distros to enable CONFIG_KUNIT > > by default [0], which would probably interact poorly with the change > > you propose. > > > > Branch profiling is really just a niche that is enabled specifically for > seeing all branches taken in the kernel. It hooks to all "if" statements! > As you can imagine, it causes a rather large overhead in performance. > > This option is only used by developers doing special analysis of their code > (namely me ;-). > > The only real concern I would have is if the kunit test developers would > want to use the branch profiling on their code, in which case my suggestion > would prevent that. I wonder if it might be possible to disable the branch profiling just for the printf_kunit.c as a compromise. Would "#undef if" in printf_kunit.c help? Or I see that DISABLE_BRANCH_PROFILING is an official way to disable the feature. I wonder if the following change would solve the problem. I am sorry, I could not test it easily. diff --git a/lib/tests/Makefile b/lib/tests/Makefile index 05f74edbc62b..45d69769ccdf 100644 --- a/lib/tests/Makefile +++ b/lib/tests/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_MIN_HEAP_KUNIT_TEST) += min_heap_kunit.o CFLAGS_overflow_kunit.o = $(call cc-disable-warning, tautological-constant-out-of-range-compare) obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o obj-$(CONFIG_PRINTF_KUNIT_TEST) += printf_kunit.o +CFLAGS_printf_kunit.o += -DDISABLE_BRANCH_PROFILING obj-$(CONFIG_RANDSTRUCT_KUNIT_TEST) += randstruct_kunit.o obj-$(CONFIG_SCANF_KUNIT_TEST) += scanf_kunit.o obj-$(CONFIG_SEQ_BUF_KUNIT_TEST) += seq_buf_kunit.o Best Regards, Petr
On Tue, Apr 7, 2026 at 7:27 AM Petr Mladek <pmladek@suse.com> wrote: > > On Mon 2026-04-06 12:32:32, Steven Rostedt wrote: > > On Mon, 6 Apr 2026 11:21:39 -0400 > > Tamir Duberstein <tamird@kernel.org> wrote: > > > > > Thanks Steve. IMO that is a very big hammer and not warranted in this > > > case. There's been talk of encouraging distros to enable CONFIG_KUNIT > > > by default [0], which would probably interact poorly with the change > > > you propose. > > > > > > > Branch profiling is really just a niche that is enabled specifically for > > seeing all branches taken in the kernel. It hooks to all "if" statements! > > As you can imagine, it causes a rather large overhead in performance. > > > > This option is only used by developers doing special analysis of their code > > (namely me ;-). > > > > The only real concern I would have is if the kunit test developers would > > want to use the branch profiling on their code, in which case my suggestion > > would prevent that. > > I wonder if it might be possible to disable the branch profiling just > for the printf_kunit.c as a compromise. > > Would "#undef if" in printf_kunit.c help? > > Or I see that DISABLE_BRANCH_PROFILING is an official > way to disable the feature. > > I wonder if the following change would solve the problem. > I am sorry, I could not test it easily. Yes, we can disable it for the whole file. I decided against that because narrow workarounds are better than broad ones IMO, but it is ultimately up to your preference. FWIW I did test that this patch fixes the problem in GCC 8.5.0.
On Tue 2026-04-07 09:34:57, Tamir Duberstein wrote: > On Tue, Apr 7, 2026 at 7:27 AM Petr Mladek <pmladek@suse.com> wrote: > > > > On Mon 2026-04-06 12:32:32, Steven Rostedt wrote: > > > On Mon, 6 Apr 2026 11:21:39 -0400 > > > Tamir Duberstein <tamird@kernel.org> wrote: > > > > > > > Thanks Steve. IMO that is a very big hammer and not warranted in this > > > > case. There's been talk of encouraging distros to enable CONFIG_KUNIT > > > > by default [0], which would probably interact poorly with the change > > > > you propose. > > > > > > > > > > Branch profiling is really just a niche that is enabled specifically for > > > seeing all branches taken in the kernel. It hooks to all "if" statements! > > > As you can imagine, it causes a rather large overhead in performance. > > > > > > This option is only used by developers doing special analysis of their code > > > (namely me ;-). > > > > > > The only real concern I would have is if the kunit test developers would > > > want to use the branch profiling on their code, in which case my suggestion > > > would prevent that. > > > > I wonder if it might be possible to disable the branch profiling just > > for the printf_kunit.c as a compromise. > > > > Would "#undef if" in printf_kunit.c help? > > > > Or I see that DISABLE_BRANCH_PROFILING is an official > > way to disable the feature. > > > > I wonder if the following change would solve the problem. > > I am sorry, I could not test it easily. > > Yes, we can disable it for the whole file. I decided against that > because narrow workarounds are better than broad ones IMO, but it is > ultimately up to your preference. I might be wrong but I think that nobody would want to profile/optimize this kunit test. So, this looks like the best solution because it is straightforward. The variant adding "noinline" looks too hacky to me. > FWIW I did test that this patch fixes the problem in GCC 8.5.0. Thanks for testing. Would you like to prepare a proper patch or should I do so? Best Regards, Petr
On Wed, Apr 8, 2026 at 3:16 AM Petr Mladek <pmladek@suse.com> wrote: > > On Tue 2026-04-07 09:34:57, Tamir Duberstein wrote: > > On Tue, Apr 7, 2026 at 7:27 AM Petr Mladek <pmladek@suse.com> wrote: > > > > > > On Mon 2026-04-06 12:32:32, Steven Rostedt wrote: > > > > On Mon, 6 Apr 2026 11:21:39 -0400 > > > > Tamir Duberstein <tamird@kernel.org> wrote: > > > > > > > > > Thanks Steve. IMO that is a very big hammer and not warranted in this > > > > > case. There's been talk of encouraging distros to enable CONFIG_KUNIT > > > > > by default [0], which would probably interact poorly with the change > > > > > you propose. > > > > > > > > > > > > > Branch profiling is really just a niche that is enabled specifically for > > > > seeing all branches taken in the kernel. It hooks to all "if" statements! > > > > As you can imagine, it causes a rather large overhead in performance. > > > > > > > > This option is only used by developers doing special analysis of their code > > > > (namely me ;-). > > > > > > > > The only real concern I would have is if the kunit test developers would > > > > want to use the branch profiling on their code, in which case my suggestion > > > > would prevent that. > > > > > > I wonder if it might be possible to disable the branch profiling just > > > for the printf_kunit.c as a compromise. > > > > > > Would "#undef if" in printf_kunit.c help? > > > > > > Or I see that DISABLE_BRANCH_PROFILING is an official > > > way to disable the feature. > > > > > > I wonder if the following change would solve the problem. > > > I am sorry, I could not test it easily. > > > > Yes, we can disable it for the whole file. I decided against that > > because narrow workarounds are better than broad ones IMO, but it is > > ultimately up to your preference. > > I might be wrong but I think that nobody would want to > profile/optimize this kunit test. So, this looks like the best > solution because it is straightforward. The variant adding > "noinline" looks too hacky to me. > > > FWIW I did test that this patch fixes the problem in GCC 8.5.0. > > Thanks for testing. > > Would you like to prepare a proper patch or should I do so? Please go ahead with your preferred approach.
Old GCC can miscompile printf_kunit's errptr() test when branch
profiling is enabled. BUILD_BUG_ON(IS_ERR(PTR)) is a constant false
expression, but CONFIG_TRACE_BRANCH_PROFILING and
CONFIG_PROFILE_ALL_BRANCHES make the IS_ERR() path side-effectful.
GCC's IPA splitter can then outline the cold assert arm into
errptr.part.* and leave that clone with an unconditional
__compiletime_assert_*() call, causing a false build failure.
This started showing up after test_hashed() became a macro and moved its
local buffer into errptr(), which changed GCC's inlining and splitting
decisions enough to expose the compiler bug.
Workaround the problem by disabling the branch profiling for
printf_kunit.o. It is a straightforward and acceptable solution.
Fixes: 9bfa52dac27a ("printf: convert test_hashed into macro")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202604030636.NqjaJvYp-lkp@intel.com/
Cc: stable@vger.kernel.org
Signed-off-by: Petr Mladek <pmladek@suse.com>
---
Changes against v1:
+ Disable the branch profiling for the whole printf_kunit.o
instead of using "noinline".
lib/tests/Makefile | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/tests/Makefile b/lib/tests/Makefile
index 05f74edbc62b..fbb2aad26994 100644
--- a/lib/tests/Makefile
+++ b/lib/tests/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o
obj-$(CONFIG_MIN_HEAP_KUNIT_TEST) += min_heap_kunit.o
CFLAGS_overflow_kunit.o = $(call cc-disable-warning, tautological-constant-out-of-range-compare)
obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o
+CFLAGS_printf_kunit.o += -DDISABLE_BRANCH_PROFILING
obj-$(CONFIG_PRINTF_KUNIT_TEST) += printf_kunit.o
obj-$(CONFIG_RANDSTRUCT_KUNIT_TEST) += randstruct_kunit.o
obj-$(CONFIG_SCANF_KUNIT_TEST) += scanf_kunit.o
--
2.53.0
On Wed, Apr 8, 2026 at 8:28 AM Petr Mladek <pmladek@suse.com> wrote:
>
> Old GCC can miscompile printf_kunit's errptr() test when branch
> profiling is enabled. BUILD_BUG_ON(IS_ERR(PTR)) is a constant false
> expression, but CONFIG_TRACE_BRANCH_PROFILING and
> CONFIG_PROFILE_ALL_BRANCHES make the IS_ERR() path side-effectful.
> GCC's IPA splitter can then outline the cold assert arm into
> errptr.part.* and leave that clone with an unconditional
> __compiletime_assert_*() call, causing a false build failure.
>
> This started showing up after test_hashed() became a macro and moved its
> local buffer into errptr(), which changed GCC's inlining and splitting
> decisions enough to expose the compiler bug.
>
> Workaround the problem by disabling the branch profiling for
> printf_kunit.o. It is a straightforward and acceptable solution.
>
> Fixes: 9bfa52dac27a ("printf: convert test_hashed into macro")
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202604030636.NqjaJvYp-lkp@intel.com/
> Cc: stable@vger.kernel.org
> Signed-off-by: Petr Mladek <pmladek@suse.com>
> ---
> Changes against v1:
>
> + Disable the branch profiling for the whole printf_kunit.o
> instead of using "noinline".
>
> lib/tests/Makefile | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/lib/tests/Makefile b/lib/tests/Makefile
> index 05f74edbc62b..fbb2aad26994 100644
> --- a/lib/tests/Makefile
> +++ b/lib/tests/Makefile
> @@ -40,6 +40,7 @@ obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o
> obj-$(CONFIG_MIN_HEAP_KUNIT_TEST) += min_heap_kunit.o
> CFLAGS_overflow_kunit.o = $(call cc-disable-warning, tautological-constant-out-of-range-compare)
> obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o
> +CFLAGS_printf_kunit.o += -DDISABLE_BRANCH_PROFILING
> obj-$(CONFIG_PRINTF_KUNIT_TEST) += printf_kunit.o
> obj-$(CONFIG_RANDSTRUCT_KUNIT_TEST) += randstruct_kunit.o
> obj-$(CONFIG_SCANF_KUNIT_TEST) += scanf_kunit.o
> --
> 2.53.0
>
It would be good to add a comment explaining when this workaround can
be removed.
GCC < 12.1 can miscompile printf_kunit's errptr() test when branch
profiling is enabled. BUILD_BUG_ON(IS_ERR(PTR)) is a constant false
expression, but CONFIG_TRACE_BRANCH_PROFILING and
CONFIG_PROFILE_ALL_BRANCHES make the IS_ERR() path side-effectful.
GCC's IPA splitter can then outline the cold assert arm into
errptr.part.* and leave that clone with an unconditional
__compiletime_assert_*() call, causing a false build failure.
This started showing up after test_hashed() became a macro and moved its
local buffer into errptr(), which changed GCC's inlining and splitting
decisions enough to expose the compiler bug.
Workaround the problem by disabling the branch profiling for
printf_kunit.o. It is a straightforward and acceptable solution.
The workaround can be removed once the minimum GCC includes commit
76fe49423047 ("Fix tree-optimization/101941: IPA splitting out
function with error attribute"), which first shipped in GCC 12.1.
Fixes: 9bfa52dac27a ("printf: convert test_hashed into macro")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202604030636.NqjaJvYp-lkp@intel.com/
Cc: stable@vger.kernel.org
Signed-off-by: Petr Mladek <pmladek@suse.com>
---
Changes against v2:
+ Added info about gcc version and commit where the miscompilation
was fixed. (Tamir)
Changes against v1:
+ Disable the branch profiling for the whole printf_kunit.o
instead of using "noinline".
lib/tests/Makefile | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/tests/Makefile b/lib/tests/Makefile
index 05f74edbc62b..7e9c2fa52e35 100644
--- a/lib/tests/Makefile
+++ b/lib/tests/Makefile
@@ -40,6 +40,8 @@ obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o
obj-$(CONFIG_MIN_HEAP_KUNIT_TEST) += min_heap_kunit.o
CFLAGS_overflow_kunit.o = $(call cc-disable-warning, tautological-constant-out-of-range-compare)
obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o
+# GCC < 12.1 can miscompile errptr() test when branch profiling is enabled.
+CFLAGS_printf_kunit.o += -DDISABLE_BRANCH_PROFILING
obj-$(CONFIG_PRINTF_KUNIT_TEST) += printf_kunit.o
obj-$(CONFIG_RANDSTRUCT_KUNIT_TEST) += randstruct_kunit.o
obj-$(CONFIG_SCANF_KUNIT_TEST) += scanf_kunit.o
--
2.53.0
On Tue, Apr 14, 2026 at 11:41 AM Petr Mladek <pmladek@suse.com> wrote:
>
> GCC < 12.1 can miscompile printf_kunit's errptr() test when branch
> profiling is enabled. BUILD_BUG_ON(IS_ERR(PTR)) is a constant false
> expression, but CONFIG_TRACE_BRANCH_PROFILING and
> CONFIG_PROFILE_ALL_BRANCHES make the IS_ERR() path side-effectful.
> GCC's IPA splitter can then outline the cold assert arm into
> errptr.part.* and leave that clone with an unconditional
> __compiletime_assert_*() call, causing a false build failure.
>
> This started showing up after test_hashed() became a macro and moved its
> local buffer into errptr(), which changed GCC's inlining and splitting
> decisions enough to expose the compiler bug.
>
> Workaround the problem by disabling the branch profiling for
> printf_kunit.o. It is a straightforward and acceptable solution.
>
> The workaround can be removed once the minimum GCC includes commit
> 76fe49423047 ("Fix tree-optimization/101941: IPA splitting out
> function with error attribute"), which first shipped in GCC 12.1.
>
> Fixes: 9bfa52dac27a ("printf: convert test_hashed into macro")
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202604030636.NqjaJvYp-lkp@intel.com/
> Cc: stable@vger.kernel.org
> Signed-off-by: Petr Mladek <pmladek@suse.com>
Acked-by: Tamir Duberstein <tamird@kernel.org>
On Tue 2026-04-14 12:07:59, Tamir Duberstein wrote:
> On Tue, Apr 14, 2026 at 11:41 AM Petr Mladek <pmladek@suse.com> wrote:
> >
> > GCC < 12.1 can miscompile printf_kunit's errptr() test when branch
> > profiling is enabled. BUILD_BUG_ON(IS_ERR(PTR)) is a constant false
> > expression, but CONFIG_TRACE_BRANCH_PROFILING and
> > CONFIG_PROFILE_ALL_BRANCHES make the IS_ERR() path side-effectful.
> > GCC's IPA splitter can then outline the cold assert arm into
> > errptr.part.* and leave that clone with an unconditional
> > __compiletime_assert_*() call, causing a false build failure.
> >
> > This started showing up after test_hashed() became a macro and moved its
> > local buffer into errptr(), which changed GCC's inlining and splitting
> > decisions enough to expose the compiler bug.
> >
> > Workaround the problem by disabling the branch profiling for
> > printf_kunit.o. It is a straightforward and acceptable solution.
> >
> > The workaround can be removed once the minimum GCC includes commit
> > 76fe49423047 ("Fix tree-optimization/101941: IPA splitting out
> > function with error attribute"), which first shipped in GCC 12.1.
> >
> > Fixes: 9bfa52dac27a ("printf: convert test_hashed into macro")
> > Reported-by: kernel test robot <lkp@intel.com>
> > Closes: https://lore.kernel.org/oe-kbuild-all/202604030636.NqjaJvYp-lkp@intel.com/
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Petr Mladek <pmladek@suse.com>
>
> Acked-by: Tamir Duberstein <tamird@kernel.org>
Thanks a lot for checking.
JFYI, I have committed the patch into printk/linux.git,
branch for-7.1-printf-kunit-build.
Best Regards,
Petr
On Sun, Apr 05, 2026 at 01:31:50PM -0400, Tamir Duberstein wrote:
> Old GCC can miscompile printf_kunit's errptr() test when branch
> profiling is enabled. BUILD_BUG_ON(IS_ERR(PTR)) is a constant false
> expression, but CONFIG_TRACE_BRANCH_PROFILING and
> CONFIG_PROFILE_ALL_BRANCHES make the IS_ERR() path side-effectful.
> GCC's IPA splitter can then outline the cold assert arm into
> errptr.part.* and leave that clone with an unconditional
> __compiletime_assert_*() call, causing a false build failure.
>
> This started showing up after test_hashed() became a macro and moved its
> local buffer into errptr(), which changed GCC's inlining and splitting
> decisions enough to expose the compiler bug.
>
> Mark errptr() noinline to keep it out of that buggy IPA path while
> preserving the BUILD_BUG_ON(IS_ERR(PTR)) check and the macro-based
> printf argument checking.
>
> Fixes: 9bfa52dac27a ("printf: convert test_hashed into macro")
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202604030636.NqjaJvYp-lkp@intel.com/
> Signed-off-by: Tamir Duberstein <tamird@kernel.org>
> ---
> lib/tests/printf_kunit.c | 18 +++++++++++++++++-
> 1 file changed, 17 insertions(+), 1 deletion(-)
>
> diff --git a/lib/tests/printf_kunit.c b/lib/tests/printf_kunit.c
> index f6f21b445ece..a8087e8ac826 100644
> --- a/lib/tests/printf_kunit.c
> +++ b/lib/tests/printf_kunit.c
> @@ -749,7 +749,23 @@ static void fourcc_pointer(struct kunit *kunittest)
> fourcc_pointer_test(kunittest, try_cb, ARRAY_SIZE(try_cb), "%p4cb");
> }
>
> -static void
> +/*
> + * GCC < 12.1 can miscompile this test when branch profiling is enabled.
> + *
> + * BUILD_BUG_ON(IS_ERR(PTR)) is a constant false expression, but old GCC can
> + * still trip over it after CONFIG_TRACE_BRANCH_PROFILING and
> + * CONFIG_PROFILE_ALL_BRANCHES rewrite the IS_ERR() unlikely() path into
> + * side-effectful branch counter updates. IPA splitting then outlines the cold
> + * assert arm into errptr.part.* and leaves that clone with an unconditional
> + * __compiletime_assert_*() call, so the build fails even though PTR is not an
> + * ERR_PTR.
> + *
> + * Keep this test out of that buggy IPA path so the BUILD_BUG_ON() can stay in
> + * place without open-coding IS_ERR(). This can be removed once the minimum GCC
> + * includes commit 76fe49423047 ("Fix tree-optimization/101941: IPA splitting
> + * out function with error attribute"), which first shipped in GCC 12.1.
> + */
> +static noinline void
> errptr(struct kunit *kunittest)
> {
> test("-1234", "%pe", ERR_PTR(-1234));
>
> ---
> base-commit: d8a9a4b11a137909e306e50346148fc5c3b63f9d
> change-id: 20260405-printf-test-old-gcc-f13fecda6524
>
> Best regards,
> --
> Tamir Duberstein <tamird@kernel.org>
>
>
<formletter>
This is not the correct way to submit patches for inclusion in the
stable kernel tree. Please read:
https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html
for how to do this properly.
</formletter>
© 2016 - 2026 Red Hat, Inc.