From: David Laight <david.laight.linux@gmail.com>
To: Oleg Nesterov <oleg@redhat.com>
Cc: Ingo Molnar <mingo@redhat.com>,
Peter Zijlstra <peterz@infradead.org>,
Thomas Gleixner <tglx@linutronix.de>,
Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
"H. Peter Anvin" <hpa@zytor.com>,
"Li,Rongqing" <lirongqing@baidu.com>,
Steven Rostedt <rostedt@goodmis.org>,
linux-kernel@vger.kernel.org, x86@kernel.org
Subject: Re: [PATCH] x86/math64: handle #DE in mul_u64_u64_div_u64()
Date: Wed, 23 Jul 2025 22:48:30 +0100 [thread overview]
Message-ID: <20250723224831.4492ec75@pumpkin> (raw)
In-Reply-To: <20250723093825.GA12884@redhat.com>
On Wed, 23 Jul 2025 11:38:25 +0200
Oleg Nesterov <oleg@redhat.com> wrote:
> On 07/22, David Laight wrote:
> >
> > On Tue, 22 Jul 2025 15:21:48 +0200
> > Oleg Nesterov <oleg@redhat.com> wrote:
> >
> > > static inline u64 mul_u64_u64_div_u64(u64 a, u64 mul, u64 div)
> > > {
> > > char ok = 0;
> > > u64 q;
> > >
> > > asm ("mulq %3; 1: divq %4; movb $1,%1; 2:\n"
> > > _ASM_EXTABLE(1b, 2b)
> > > : "=a" (q), "+q" (ok)
> > > : "a" (a), "rm" (mul), "rm" (div)
> > > : "rdx");
> > >
> > > if (ok)
> > > return q;
> > > BUG_ON(!div);
> > > WARN_ONCE(1, "muldiv overflow.\n");
> >
> > I wonder what WARN_ON_ONCE("muldiv overflow") outputs?
>
> Well, it outputs "muldiv overflow." ;) So I am not sure it is better
> than just WARN_ON_ONCE(1).
>
> > Actually, without the BUG or WARN you want:
> > u64 fail = ~(u64)0;
> > then
> > incq $1 ... "+r" (fail)
> > and finally
> > return q | fail;
> > to remove the conditional branches from the normal path
> > (apart from one the caller might do)
>
> I was thinking about
>
> static inline u64 mul_u64_u64_div_u64(u64 a, u64 mul, u64 div)
> {
> u64 q;
>
> asm ("mulq %2; 1: divq %3; jmp 3f; 2: movq $-1,%0; 3:\n"
> _ASM_EXTABLE(1b, 2b)
> : "=a" (q)
> : "a" (a), "rm" (mul), "rm" (div)
> : "rdx");
>
> return q;
> }
>
> to remove the conditional branch and additional variable. Your version
> is probably beterr... But this is without WARN/BUG.
I wish there was a way of doing a WARN_ONCE from asm with a single instruction.
Then you could put one after your 2:
Otherwise is it a conditional and a load of inlined code.
> So, which version do you prefer?
I wish I knew :-)
Yours is a few bytes shorter, uses one less register, but has that unconditional jmp.
I suspect we don't worry about the cpu not predicting a jump - especially with
the divq.
It's not as though some real-time code relies on this code being as fast
as absolutely possible.
Not using a register is probably the main win.
So maybe I lose (this time).
Further work could add an 'int *' parameter that is set non-zero (from %rax)
if the divide traps; optimised out if NULL.
The easy way is two copies of the asm statement.
But I've already got two copies in the version that does (a * b + c)/d
and four copies is getting silly.
Actually this seems ok - at least as a real function:
u64 mul_u64_add_u64_div_u64(u64 a, u64 b, u64 c, u64 div)
{
unsigned __int128 v = (__int128)a * b + c;
asm ("1: divq %1; jmp 3f; 2: movq $-1,%%rax; 3:\n"
_ASM_EXTABLE(1b, 2b)
: "+A" (v)
: "r" (div));
return v;
}
But (as I found with 32bit) gcc can decide to do a 128x128 multiply.
It does do a full 128bit add - with an extra register for the zero.
Not that you should never pass "rm" to clang, needs to be "r".
There is a #define for it.
David
>
> Oleg.
>
next prev parent reply other threads:[~2025-07-23 21:48 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-21 13:04 [PATCH] x86/math64: handle #DE in mul_u64_u64_div_u64() Oleg Nesterov
2025-07-21 18:20 ` David Laight
2025-07-22 10:50 ` Oleg Nesterov
2025-07-22 12:09 ` David Laight
2025-07-22 13:21 ` Oleg Nesterov
2025-07-22 22:03 ` David Laight
2025-07-23 9:38 ` Oleg Nesterov
2025-07-23 21:48 ` David Laight [this message]
2025-07-24 8:11 ` Oleg Nesterov
2025-07-24 8:25 ` Oleg Nesterov
2025-07-24 11:14 ` Oleg Nesterov
2025-07-25 1:00 ` H. Peter Anvin
2025-07-25 10:12 ` Oleg Nesterov
2025-07-25 21:46 ` David Laight
2025-07-26 9:55 ` Oleg Nesterov
2025-07-24 12:00 ` David Laight
2025-07-24 13:58 ` Oleg Nesterov
2025-07-22 16:53 ` H. Peter Anvin
2025-07-22 21:53 ` David Laight
2025-07-22 16:50 ` H. Peter Anvin
2025-07-22 17:58 ` Oleg Nesterov
2025-07-22 18:12 ` H. Peter Anvin
2025-07-22 18:38 ` Oleg Nesterov
2025-07-22 19:26 ` H. Peter Anvin
2025-07-22 21:56 ` David Laight
2025-07-27 12:34 ` [PATCH v2] " Oleg Nesterov
2025-07-28 18:53 ` David Laight
2025-07-30 2:30 ` [????] " Li,Rongqing
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=20250723224831.4492ec75@pumpkin \
--to=david.laight.linux@gmail.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lirongqing@baidu.com \
--cc=mingo@redhat.com \
--cc=oleg@redhat.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=tglx@linutronix.de \
--cc=x86@kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.