funEpilogue :: LiveGlobalRegs -> LlvmM ([LlvmVar], LlvmStatements)
funEpilogue live = do

    -- Have information and liveness optimisation is enabled?
    let liveRegs = alwaysLive ++ live
        isSSE (FloatReg _)  = True
        isSSE (DoubleReg _) = True
        isSSE (XmmReg _)    = True
        isSSE (YmmReg _)    = True
        isSSE (ZmmReg _)    = True
        isSSE _             = False

    -- Set to value or "undef" depending on whether the register is
    -- actually live
    dflags <- getDynFlags
    let loadExpr r = do
          (v, _, s) <- getCmmRegVal (CmmGlobal r)
          return (Just $ v, s)
        loadUndef r = do
          let ty = (pLower . getVarType $ lmGlobalRegVar dflags r)
          return (Just $ LMLitVar $ LMUndefLit ty, nilOL)
    platform <- getDynFlag targetPlatform
    loads <- flip mapM (activeStgRegs platform) $ \r -> case () of
      _ | r `elem` liveRegs  -> loadExpr r
        | not (isSSE r)      -> loadUndef r
        | otherwise          -> return (Nothing, nilOL)

    let (vars, stmts) = unzip loads
    return (catMaybes vars, concatOL stmts)


-- | A series of statements to trash all the STG registers.
--
-- In LLVM we pass the STG registers around everywhere in function calls.
-- So this means LLVM considers them live across the entire function, when
-- in reality they usually aren't. For Caller save registers across C calls
-- the saving and restoring of them is done by the Cmm code generator,
-- using Cmm local vars. So to stop LLVM saving them as well (and saving
-- all of them since it thinks they're always live, we trash them just
-- before the call by assigning the 'undef' value to them. The ones we
-- need are restored from the Cmm local var and the ones we don't need
-- are fine to be trashed.
funEpilogue :: LiveGlobalRegs -> LlvmM ([LlvmVar], LlvmStatements)
funEpilogue live = do

    -- Have information and liveness optimisation is enabled?
    let liveRegs = alwaysLive ++ live
        isSSE (FloatReg _)  = True
        isSSE (DoubleReg _) = True
        isSSE (XmmReg _)    = True
        isSSE (YmmReg _)    = True
        isSSE (ZmmReg _)    = True
        isSSE _             = False

    -- Set to value or "undef" depending on whether the register is
    -- actually live
    dflags <- getDynFlags
    let loadExpr r = do
          (v, _, s) <- getCmmRegVal (CmmGlobal r)
          return (Just $ v, s)
        loadUndef r = do
          let ty = (pLower . getVarType $ lmGlobalRegVar dflags r)
          return (Just $ LMLitVar $ LMUndefLit ty, nilOL)
    platform <- getDynFlag targetPlatform
    loads <- flip mapM (activeStgRegs platform) $ \r -> case () of
      _ | r `elem` liveRegs  -> loadExpr r
        | not (isSSE r)      -> loadUndef r
        | otherwise          -> return (Nothing, nilOL)

    let (vars, stmts) = unzip loads
    return (catMaybes vars, concatOL stmts)


-- | A series of statements to trash all the STG registers.
--
-- In LLVM we pass the STG registers around everywhere in function calls.
-- So this means LLVM considers them live across the entire function, when
-- in reality they usually aren't. For Caller save registers across C calls
-- the saving and restoring of them is done by the Cmm code generator,
-- using Cmm local vars. So to stop LLVM saving them as well (and saving
-- all of them since it thinks they're always live, we trash them just
-- before the call by assigning the 'undef' value to them. The ones we
-- need are restored from the Cmm local var and the ones we don't need
-- are fine to be trashed.
funEpilogue live = do

    -- Have information and liveness optimisation is enabled?
    let liveRegs = alwaysLive ++ live
        isSSE (FloatReg _)  = True
        isSSE (DoubleReg _) = True
        isSSE (XmmReg _)    = True
        isSSE (YmmReg _)    = True
        isSSE (ZmmReg _)    = True
        isSSE _             = False

    -- Set to value or "undef" depending on whether the register is
    -- actually live
    dflags <- getDynFlags
    let loadExpr r = do
          (v, _, s) <- getCmmRegVal (CmmGlobal r)
          return (Just $ v, s)
        loadUndef r = do
          let ty = (pLower . getVarType $ lmGlobalRegVar dflags r)
          return (Just $ LMLitVar $ LMUndefLit ty, nilOL)
    platform <- getDynFlag targetPlatform
    loads <- flip mapM (activeStgRegs platform) $ \r -> case () of
      _ | r `elem` liveRegs  -> loadExpr r
        | not (isSSE r)      -> loadUndef r
        | otherwise          -> return (Nothing, nilOL)

    let (vars, stmts) = unzip loads
    return (catMaybes vars, concatOL stmts)


-- | A series of statements to trash all the STG registers.
--
-- In LLVM we pass the STG registers around everywhere in function calls.
-- So this means LLVM considers them live across the entire function, when
-- in reality they usually aren't. For Caller save registers across C calls
-- the saving and restoring of them is done by the Cmm code generator,
-- using Cmm local vars. So to stop LLVM saving them as well (and saving
-- all of them since it thinks they're always live, we trash them just
-- before the call by assigning the 'undef' value to them. The ones we
-- need are restored from the Cmm local var and the ones we don't need
-- are fine to be trashed.