mldsa-0.1.1.0: src/Barrier.hs
-- |
-- Module : Barrier
-- License : BSD-3-Clause
-- Copyright : (c) 2026 Olivier Chéron
--
-- Utilities to block LLVM optimizations that are unwanted. Currently this
-- targets the X86 CMOV conversion pass, to make sure constant-time masking
-- operations are preserved and not transformed into branches.
--
{-# LANGUAGE CPP #-}
#if (defined(i386_HOST_ARCH) || defined(x86_64_HOST_ARCH)) \
&& defined(__GLASGOW_HASKELL_LLVM__)
#define MLDSA_USE_VALUE_BARRIER 1
#endif
#ifdef MLDSA_USE_VALUE_BARRIER
{-# LANGUAGE MagicHash #-}
#endif
module Barrier
( barrier32
) where
import Data.Word
#ifdef MLDSA_USE_VALUE_BARRIER
#if MIN_VERSION_base(4,16,0)
import GHC.Exts (Word32#)
#else
import GHC.Exts (Word#)
#endif
import GHC.Word (Word32(W32#))
-- Implements a value barrier: at call site the content of the function is
-- opaque to the optimizer, thus the call prevents optimizations that need
-- knowledge of the value.
--
-- We want to avoid memory allocations and use CPU registers so the mechanism
-- relies on unlifted values in and out.
barrier32 :: Word32 -> Word32
barrier32 (W32# x#) = W32# (barrier32# x#)
{-# INLINE barrier32 #-}
#if MIN_VERSION_base(4,16,0)
barrier32# :: Word32# -> Word32#
#else
barrier32# :: Word# -> Word#
#endif
barrier32# x# = x#
{-# NOINLINE barrier32# #-}
#else
-- When using the NCG, or not on X86, the call can be completely eliminated.
barrier32 :: Word32 -> Word32
barrier32 = id
{-# INLINE barrier32 #-}
#endif