commit 533281ee35a0ab32fdd3d2cb0a2b058ec3b0e6f2
parent e303bda7578385f488c2f23baa2e1a6a2b0b2aaf
Author: Jared Tobin <jared@jtobin.io>
Date: Tue, 27 Oct 2026 17:34:29 +0400
merge impl/cmov-converter: LLVM's x86 cmov converter off under the llvm flag
On x86_64, LLVM compiled the borrow-masked correction of sub_mod,
sub_mod#, and sub_mod_c# as a branch on the borrow: InstCombine forms
a select from the mask, the x86 backend a cmov, and its cmov
converter rewrites a cmov whose operand is a load (the modulus, read
from the boxed Wider or the stack) as a branch. A differential trace
of sub_mod showed the branch splitting sixteen secrets eight and
eight.
The library's llvm flag now passes -optlc=-x86-cmov-converter=false
on x86_64, which keeps the four cmovs (on Intel's DOIT list). No
other module's code changes; NCG builds and aarch64 were unaffected.
The tests pass under the flag on x86_64, and the same trace shows no
origin.
Diffstat:
2 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
@@ -1,5 +1,13 @@
# Changelog
+- unreleased
+ * Under the llvm flag on x86_64, the library is compiled with LLVM's
+ x86 cmov converter off (-optlc=-x86-cmov-converter=false). The
+ converter rewrites a conditional move whose operand is a load as a
+ branch, and so made the borrow-masked correction of sub_mod,
+ sub_mod#, and sub_mod_c# a branch on the borrow, which depends on
+ the operands. NCG builds, and aarch64, were unaffected.
+
- 0.2.0 (2026-08-01)
* Addresses a couple of minor issues detected by an LLM scan:
diff --git a/ppad-fixed.cabal b/ppad-fixed.cabal
@@ -31,6 +31,11 @@ library
-Wall
if flag(llvm)
ghc-options: -fllvm -O2
+ -- LLVM's x86 backend rewrites a cmov whose operand is a load as a
+ -- branch (its cmov converter), which makes sub_mod#'s borrow-masked
+ -- correction a branch on the borrow; keep the cmov.
+ if flag(llvm) && arch(x86_64)
+ ghc-options: -optlc=-x86-cmov-converter=false
exposed-modules:
Data.Choice
, Data.Word.Limb