Skip to content

ppc64le: Add POWER8 VSX backend (little- and big-endian)#1258

Open
Scottcjn wants to merge 1 commit into
pq-code-package:mainfrom
Scottcjn:ppc64le-backend
Open

ppc64le: Add POWER8 VSX backend (little- and big-endian)#1258
Scottcjn wants to merge 1 commit into
pq-code-package:mainfrom
Scottcjn:ppc64le-backend

Conversation

@Scottcjn

@Scottcjn Scottcjn commented Jul 2, 2026

Copy link
Copy Markdown

This adds a POWER8 (ppc64) VSX backend to mldsa-native, working on both little- and big-endian POWER. The repository previously had aarch64 and x86_64 native backends; this is the first ppc64 one. It is selected automatically via MLD_SYS_PPC64LE / MLD_SYS_PPC64BE and replaces:

primitive approach
poly_caddq element-wise conditional +q (vcmpgtsw / vadduwm / xxsel)
poly_pointwise_montgomery word-domain Montgomery multiply
polyvecl_pointwise_acc_montgomery_l{4,5,7} accumulate 64-bit products, single reduction
ntt Cooley-Tukey forward NTT
intt Gentleman-Sande inverse NTT + Montgomery scaling

Montgomery reduction

int32 reduction in the word domain: even/odd 32x32->64 products via vmulesw/vmulosw, m = low32(prod * QINV) via vmuluwm, then (prod - m*q) >> 32 taken as the high words. Low words are recombined with vmrgow and high words with vmrgew, the same even/odd convention on both ends, a closed permutation back to input coefficient order. Because this relies only on the architectural (endian-invariant) VSX element numbering and never on where a load physically places coefficients, the kernels are bit-exact on both endians with no code differences.

NTT / inverse NTT

Natural coefficient order, matching the C reference exactly. The outer six layers (len >= 4) are vectorized four coefficients at a time with a per-block broadcast twiddle; the inner two layers (len = 2, 1) have within-vector partners and run scalar. Twiddles stream from a natural-order table (one per block, k ascending for the forward transform, descending + negated for the inverse), so twiddle addressing is a single moving pointer.

VSX requirement and fallback

The kernels require POWER8 VSX. The meta.h wrappers guard each call on __POWER8_VECTOR__ and return MLD_NATIVE_FUNC_FALLBACK otherwise, so a toolchain targeting an older CPU (in particular big-endian defaults) builds and runs correctly through the C reference, matching how the mlkem-native ppc64le backend handles this. The big-endian test lane passes -mcpu=power8 explicitly so the backend is actually exercised there.

Notes

  • The backend files are hand-maintained: scripts/cfify does not yet emit CFI for ppc64 and the autogen has no ppc64 simpasm job, so dev/ and mldsa/src/native/ppc64le/ are kept in sync directly. Happy to wire up autogen support as a follow-up.
  • Inner NTT layers use a scalar fallback for now; vectorizing them is a natural follow-up optimization.

Testing

  • Little-endian on an IBM POWER8 S824 (-mcpu=power8, OPT=1): run_func, run_kat, and run_unit pass for ML-DSA-44/65/87 with the native backend active (verified via the ppc64le symbols in the test binaries).
  • No-VSX fallback on the same machine (CC='gcc -mno-vsx', OPT=1): builds, links, and the same suites pass through the C reference, with no ppc64le assembly symbols in the binaries.
  • Big-endian under qemu-ppc64 (powerpc64-linux-gnu, -mcpu=power8): the same unit, func, and KAT suites pass with the native backend active.

Resubmission of #1191 (closed under the contributor policy before we had been in touch), rebased onto current main and extended with the VSX fallback guards and the big-endian test lane flag.

@Scottcjn Scottcjn requested a review from a team as a code owner July 2, 2026 00:30
@mkannwischer

Copy link
Copy Markdown
Contributor

Thanks @Scottcjn.
It is unlikely that any of the maintainers has the capacity to review a large backend addition like this PR any time soon as we need to get the v1.0.0 release out first.

It's my understanding that a colleague of @bhess also has a ppc backend for mldsa-native which will likely be upstreamed shortly. Preference will likely be given to that backend.

Until then I'm happy to keep this PR open.

@Scottcjn

Scottcjn commented Jul 2, 2026

Copy link
Copy Markdown
Author

Standing by.

First ppc64 native backend for mldsa-native, alongside the existing
aarch64 and x86_64 backends. Selected automatically via MLD_SYS_PPC64LE
/ MLD_SYS_PPC64BE. Replaces poly_caddq, poly_pointwise_montgomery,
polyvecl_pointwise_acc_montgomery (L in {4,5,7}), ntt and intt.

The int32 Montgomery reduction works in the word domain: even/odd
32x32->64 products via vmulesw/vmulosw, m = low32(prod * QINV) via
vmuluwm, then (prod - m*q) >> 32 taken as the high words, recombined
with vmrgow/vmrgew. It relies only on architectural (endian-invariant)
VSX element numbering, so the kernels are bit-exact on both endians with
no code differences.

NTT and inverse NTT use natural coefficient order matching the C
reference. The outer six layers (len >= 4) are vectorized four
coefficients at a time with a per-block broadcast twiddle; the inner two
layers (len = 1, 2) run scalar.

The kernels require POWER8 VSX. On toolchains targeting an older CPU
the meta.h wrappers return MLD_NATIVE_FUNC_FALLBACK so the C reference
is used instead, matching the mlkem-native ppc64le backend. The
big-endian test lane passes -mcpu=power8 explicitly since big-endian
toolchains default to a pre-POWER8 CPU.

dev/ and mldsa/src/native/ppc64le/ are kept in sync by hand: scripts/cfify
does not yet emit CFI for ppc64 and the autogen has no ppc64 simpasm job.
Inner NTT layers use a scalar fallback for now.

Validated on an IBM POWER8 S824 (-mcpu=power8): tests unit matches the C
reference for poly_ntt / poly_invntt_tomont; tests func and tests kat pass
for ML-DSA-44/65/87. Big-endian validated under qemu-ppc64
(powerpc64-linux-gnu, -mcpu=power8): the same unit, func and kat suites
pass with the native backend active.

Signed-off-by: Scott Boudreaux <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants