Skip to content

Instantly share code, notes, and snippets.

@kavon
Created September 22, 2017 23:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kavon/566fc6c21ff51803538884b79dc1d841 to your computer and use it in GitHub Desktop.
Save kavon/566fc6c21ff51803538884b79dc1d841 to your computer and use it in GitHub Desktop.
working on T14251 so that we add padding during LLVM codegen
diff --git a/compiler/llvmGen/LlvmCodeGen/Base.hs b/compiler/llvmGen/LlvmCodeGen/Base.hs
index 6e20da4..e1b7e76 100644
--- a/compiler/llvmGen/LlvmCodeGen/Base.hs
+++ b/compiler/llvmGen/LlvmCodeGen/Base.hs
@@ -26,7 +26,7 @@ module LlvmCodeGen.Base (
cmmToLlvmType, widthToLlvmFloat, widthToLlvmInt, llvmFunTy,
llvmFunSig, llvmFunArgs, llvmStdFunAttrs, llvmFunAlign, llvmInfAlign,
- llvmPtrBits, tysToParams, llvmFunSection,
+ llvmPtrBits, tysToParams, llvmFunSection, padLiveArgs, sortSSERegs,
strCLabel_llvm, strDisplayName_llvm, strProcedureName_llvm,
getGlobalPtr, generateExternDecls,
@@ -58,6 +58,7 @@ import ErrUtils
import qualified Stream
import Control.Monad (ap)
+import Data.List (sortBy)
-- ----------------------------------------------------------------------------
-- * Some Data Types
@@ -147,16 +148,59 @@ llvmFunSection dflags lbl
-- | A Function's arguments
llvmFunArgs :: DynFlags -> LiveGlobalRegs -> [LlvmVar]
llvmFunArgs dflags live =
- map (lmGlobalRegArg dflags) (filter isPassed (activeStgRegs platform))
+ map (lmGlobalRegArg dflags) (filter isPassed allRegs)
where platform = targetPlatform dflags
- isLive r = not (isSSE r) || r `elem` alwaysLive || r `elem` live
+ allRegs = sortSSERegs $ activeStgRegs platform
+ paddedLive = map (\(_,r) -> r) $ padLiveArgs live
+ isLive r = not (isSSE r) || r `elem` alwaysLive || r `elem` paddedLive
isPassed r = not (isSSE r) || isLive r
- isSSE (FloatReg _) = True
- isSSE (DoubleReg _) = True
- isSSE (XmmReg _) = True
- isSSE (YmmReg _) = True
- isSSE (ZmmReg _) = True
- isSSE _ = False
+ isSSE r
+ | Just _ <- sseRegNum r = True
+ | otherwise = False
+
+
+sseRegNum :: GlobalReg -> Maybe Int
+sseRegNum (FloatReg i) = Just i
+sseRegNum (DoubleReg i) = Just i
+sseRegNum (XmmReg i) = Just i
+sseRegNum (YmmReg i) = Just i
+sseRegNum (ZmmReg i) = Just i
+sseRegNum _ = Nothing
+
+-- Only sorts regs that will end up in SSE registers
+-- such that the ones which are assigned to the same
+-- register will be adjacent in the list. Other elements
+-- are not reordered.
+sortSSERegs :: [GlobalReg] -> [GlobalReg]
+sortSSERegs regs = sortBy sseOrd regs
+ where
+ sseOrd a b = case (sseRegNum a, sseRegNum b) of
+ (Just x, Just y) -> compare x y
+ _ -> EQ
+
+-- assumes that the live list is sorted by Ord GlobalReg's compare function.
+-- the bool indicates whether the global reg was added as padding.
+padLiveArgs :: LiveGlobalRegs -> [(Bool, GlobalReg)]
+padLiveArgs live = reverse padded
+ where
+ (_, padded) = foldl assignSlots (1, []) $ sortSSERegs live
+
+ assignSlots (i, acc) r
+ | Just k <- sseRegNum r
+ , i < k
+ = let -- add k-i slots of padding
+ diff = k-i
+ acc' = genPad i diff ++ (False, r) : acc
+ i' = i + diff
+ in
+ (i', acc')
+
+ | otherwise = (i, (False, r):acc)
+
+ genPad start n =
+ take n $ flip map (iterate (+1) start) (\i ->
+ (True, FloatReg i))
+
-- | Llvm standard fun attributes
llvmStdFunAttrs :: [LlvmFuncAttr]
diff --git a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
index 584d90c..6dd1fc3 100644
--- a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
+++ b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
@@ -1732,8 +1732,10 @@ funPrologue live cmmBlocks = do
funEpilogue :: LiveGlobalRegs -> LlvmM ([LlvmVar], LlvmStatements)
funEpilogue live = do
- -- Have information and liveness optimisation is enabled?
- let liveRegs = alwaysLive ++ live
+ -- the bool indicates whether the register is padding.
+ let alwaysNeeded = map (\r -> (False, r)) alwaysLive
+ livePadded = alwaysNeeded ++ padLiveArgs live
+
isSSE (FloatReg _) = True
isSSE (DoubleReg _) = True
isSSE (XmmReg _) = True
@@ -1751,9 +1753,12 @@ funEpilogue live = 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
+ let allRegs = sortSSERegs $ activeStgRegs platform
+ loads <- flip mapM allRegs $ \r -> case () of
+ _ | (False, r) `elem` livePadded
+ -> loadExpr r -- if r is not padding, load it
+ | not (isSSE r) || (True, r) `elem` livePadded
+ -> loadUndef r
| otherwise -> return (Nothing, nilOL)
let (vars, stmts) = unzip loads
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment