[Git][ghc/ghc][wip/romes/det-llvm] determinism: Deterministic MonadGetUnique LlvmM

Rodrigo Mesquita (@alt-romes) gitlab at gitlab.haskell.org
Wed Sep 25 15:19:11 UTC 2024



Rodrigo Mesquita pushed to branch wip/romes/det-llvm at Glasgow Haskell Compiler / GHC


Commits:
165f0b4b by Rodrigo Mesquita at 2024-09-25T16:18:08+01:00
determinism: Deterministic MonadGetUnique LlvmM

Update LlvmM to thread a unique deterministic supply (using UniqDSMT),
and use it in the MonadGetUnique instance.

This makes uniques sampled from LlvmM deterministic, which guarantees
object determinism with -fllvm.

Fixes #25274

- - - - -


2 changed files:

- compiler/GHC/CmmToLlvm.hs
- compiler/GHC/CmmToLlvm/Base.hs


Changes:

=====================================
compiler/GHC/CmmToLlvm.hs
=====================================
@@ -85,25 +85,23 @@ llvmCodeGen logger cfg h dus cmm_stream
            llvm_ver = fromMaybe supportedLlvmVersionLowerBound mb_ver
 
        -- run code generation
-       a <- runLlvm logger cfg llvm_ver bufh $
-         llvmCodeGen' cfg dus cmm_stream
+       (a, _) <- runLlvm logger cfg llvm_ver bufh dus $
+         llvmCodeGen' cfg cmm_stream
 
        bFlush bufh
 
        return a
 
 llvmCodeGen' :: LlvmCgConfig
-             -> DUniqSupply -- ^ The deterministic uniq supply to run the CgStream.
-                            -- See Note [Deterministic Uniques in the CG]
              -> CgStream RawCmmGroup a -> LlvmM a
-llvmCodeGen' cfg dus cmm_stream
+llvmCodeGen' cfg cmm_stream
   = do  -- Preamble
         renderLlvm (llvmHeader cfg) (llvmHeader cfg)
         ghcInternalFunctions
         cmmMetaLlvmPrelude
 
         -- Procedures
-        (a, _) <- runUDSMT dus $ Stream.consume cmm_stream (hoistUDSMT liftIO) (liftUDSMT . llvmGroupLlvmGens)
+        a <- Stream.consume cmm_stream (GHC.CmmToLlvm.Base.liftUDSMT) (llvmGroupLlvmGens)
 
         -- Declare aliases for forward references
         decls <- generateExternDecls


=====================================
compiler/GHC/CmmToLlvm/Base.hs
=====================================
@@ -23,7 +23,7 @@ module GHC.CmmToLlvm.Base (
         ghcInternalFunctions, getPlatform, getConfig,
 
         getMetaUniqueId,
-        setUniqMeta, getUniqMeta, liftIO,
+        setUniqMeta, getUniqMeta, liftIO, liftUDSMT,
 
         cmmToLlvmType, widthToLlvmFloat, widthToLlvmInt, llvmFunTy,
         llvmFunSig, llvmFunArgs, llvmStdFunAttrs, llvmFunAlign, llvmInfAlign,
@@ -55,7 +55,6 @@ import GHC.Types.Unique.FM
 import GHC.Types.Unique
 import GHC.Utils.BufHandle   ( BufHandle )
 import GHC.Types.Unique.Set
-import GHC.Types.Unique.Supply
 import qualified GHC.Types.Unique.DSM as DSM
 import GHC.Utils.Logger
 
@@ -64,6 +63,7 @@ import Control.Monad.Trans.State (StateT (..))
 import Data.List (isPrefixOf)
 import qualified Data.List.NonEmpty as NE
 import Data.Ord (comparing)
+import qualified Control.Monad.IO.Class as IO
 
 -- ----------------------------------------------------------------------------
 -- * Some Data Types
@@ -277,14 +277,13 @@ data LlvmEnv = LlvmEnv
 type LlvmEnvMap = UniqFM Unique LlvmType
 
 -- | The Llvm monad. Wraps @LlvmEnv@ state as well as the @IO@ monad
-newtype LlvmM a = LlvmM { runLlvmM :: LlvmEnv -> IO (a, LlvmEnv) }
+newtype LlvmM a = LlvmM { runLlvmM :: LlvmEnv -> DSM.UniqDSMT IO (a, LlvmEnv) }
     deriving stock (Functor)
-    deriving (Applicative, Monad) via StateT LlvmEnv IO
+    deriving (Applicative, Monad) via StateT LlvmEnv (DSM.UniqDSMT IO)
 
 instance HasLogger LlvmM where
     getLogger = LlvmM $ \env -> return (envLogger env, env)
 
-
 -- | Get target platform
 getPlatform :: LlvmM Platform
 getPlatform = llvmCgPlatform <$> getConfig
@@ -293,23 +292,30 @@ getConfig :: LlvmM LlvmCgConfig
 getConfig = LlvmM $ \env -> return (envConfig env, env)
 
 
--- TODO(#25274): If you want Llvm code to be deterministic, this instance should use a
--- deterministic unique supply to produce uniques, rather than using 'uniqFromTag'.
+-- This instance uses a deterministic unique supply from UniqDSMT, so new
+-- uniques within LlvmM will be sampled deterministically.
 instance DSM.MonadGetUnique LlvmM where
   getUniqueM = do
     tag <- getEnv envTag
-    liftIO $! uniqFromTag tag
+    liftUDSMT $! do
+      uq <- DSM.getUniqueM
+      return (newTagUnique uq tag)
 
 -- | Lifting of IO actions. Not exported, as we want to encapsulate IO.
 liftIO :: IO a -> LlvmM a
-liftIO m = LlvmM $ \env -> do x <- m
+liftIO m = LlvmM $ \env -> do x <- IO.liftIO m
                               return (x, env)
 
+-- | Lifting of UniqDSMT actions. Gives access to the deterministic unique supply being threaded through by LlvmM.
+liftUDSMT :: DSM.UniqDSMT IO a -> LlvmM a
+liftUDSMT m = LlvmM $ \env -> do x <- m
+                                 return (x, env)
+
 -- | Get initial Llvm environment.
-runLlvm :: Logger -> LlvmCgConfig -> LlvmVersion -> BufHandle -> LlvmM a -> IO a
-runLlvm logger cfg ver out m = do
-    (a, _) <- runLlvmM m env
-    return a
+runLlvm :: Logger -> LlvmCgConfig -> LlvmVersion -> BufHandle -> DSM.DUniqSupply -> LlvmM a -> IO (a, DSM.DUniqSupply)
+runLlvm logger cfg ver out us m = do
+    ((a, _), us') <- DSM.runUDSMT us $ runLlvmM m env
+    return (a, us')
   where env = LlvmEnv { envFunMap    = emptyUFM
                       , envVarMap    = emptyUFM
                       , envStackRegs = []



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/165f0b4b9f8548d9cba99a8c8fd4bd70a36f178c

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/165f0b4b9f8548d9cba99a8c8fd4bd70a36f178c
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20240925/2f3fb7de/attachment-0001.html>


More information about the ghc-commits mailing list