[llvm] [X86] Lower vector unsigned integer division through f64 division (PR #205263)
Adam Scott via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 30 02:16:00 PDT 2026
as4230 wrote:
> For u8/u16, it should be vdivps rather than vdivpd?
> https://llvm.org/docs/LangRef.html#i-sdiv
>
> > The value produced is the signed integer quotient of the two operands rounded towards zero.
> > Note that signed integer division and unsigned integer division are distinct operations; for unsigned integer division, use ‘udiv’.
> > Division by zero is undefined behavior. For vectors, if any element of the divisor is zero, the operation has undefined >behavior. Overflow also leads to undefined behavior; this is a rare case, but can occur, for example, by doing a 32-bit >division of -2147483648 by -1.
> > If the exact keyword is present, the result value of the sdiv is a [poison value](https://llvm.org/docs/LangRef.html#poisonvalues) if the result would be rounded.
>
> Sounds like unnecessary to limit this to unsigned?
Yes and yes. I think this covers the same cases as magic multiply, just for variable divisors instead of constants, so I threw in urem and srem too.
I ran a sort of grid search over cases like this:
```
define <16 x i8> @ud8(<16 x i8> %a, <16 x i8> %b) {
%r = udiv <16 x i8> %a, %b
ret <16 x i8> %r
}
```
and counted instructions before and after the fold (sd = signed divide, ur = unsigned remainder, and so on, and a * means the fold came out worse):
```
case SSE2 s->f AVX1 s->f AVX2 s->f AVX512 s->f
ud8 96->39 108->33 108->21 108->9
ur8 82->50 97->41 97->27 97->13
sd8 96->40 108->33 108->21 108->9
sr8 82->49 97->41 97->28 97->13
ud16 48->21 42->15 42->10 42->9
ur16 48->25 42->17 42->12 42->11
sd16 48->18 42->16 42->10 42->9
sr16 48->20 42->18 42->12 42->11
ud32 31->35 * 22->21 22->17 22->6
ur32 31->45 * 22->23 * 22->19 22->8
sd32 31->12 22->6 22->6 22->6
sr32 31->20 22->8 22->8 22->8
```
The only cases that lose are unsigned i32 on SSE2 and AVX1, where the f64 to u32 conversion has no real instruction and gets emulated. So I lowered the guard down to SSE2 and just bail unsigned i32 below AVX2. The i64 path handles signed and rem now too.
https://github.com/llvm/llvm-project/pull/205263
More information about the llvm-commits
mailing list