diff options
-rw-r--r-- | compiler/llvmGen/LlvmCodeGen/Base.hs | 123 | ||||
-rw-r--r-- | compiler/llvmGen/LlvmCodeGen/CodeGen.hs | 6 |
2 files changed, 39 insertions, 90 deletions
diff --git a/compiler/llvmGen/LlvmCodeGen/Base.hs b/compiler/llvmGen/LlvmCodeGen/Base.hs index 0a40b73766..ec91bacc4c 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, padLiveArgs, isFPR, + llvmPtrBits, tysToParams, llvmFunSection, padLiveArgs, isSSE, strCLabel_llvm, strDisplayName_llvm, strProcedureName_llvm, getGlobalPtr, generateExternDecls, @@ -47,7 +47,6 @@ import CodeGen.Platform ( activeStgRegs ) import DynFlags import FastString import Cmm hiding ( succ ) -import CmmUtils ( regsOverlap ) import Outputable as Outp import Platform import UniqFM @@ -59,7 +58,8 @@ import ErrUtils import qualified Stream import Control.Monad (ap) -import Data.List (sort, groupBy, head) +import Data.List (sort) +import Data.Maybe (mapMaybe) -- ---------------------------------------------------------------------------- -- * Some Data Types @@ -152,91 +152,36 @@ llvmFunArgs dflags live = map (lmGlobalRegArg dflags) (filter isPassed allRegs) where platform = targetPlatform dflags allRegs = activeStgRegs platform - paddedLive = map (\(_,r) -> r) $ padLiveArgs dflags live + paddedLive = map (\(_,r) -> r) $ padLiveArgs live isLive r = r `elem` alwaysLive || r `elem` paddedLive - isPassed r = not (isFPR r) || isLive r - - -isFPR :: GlobalReg -> Bool -isFPR (FloatReg _) = True -isFPR (DoubleReg _) = True -isFPR (XmmReg _) = True -isFPR (YmmReg _) = True -isFPR (ZmmReg _) = True -isFPR _ = False - -sameFPRClass :: GlobalReg -> GlobalReg -> Bool -sameFPRClass (FloatReg _) (FloatReg _) = True -sameFPRClass (DoubleReg _) (DoubleReg _) = True -sameFPRClass (XmmReg _) (XmmReg _) = True -sameFPRClass (YmmReg _) (YmmReg _) = True -sameFPRClass (ZmmReg _) (ZmmReg _) = True -sameFPRClass _ _ = False - -normalizeFPRNum :: GlobalReg -> GlobalReg -normalizeFPRNum (FloatReg _) = FloatReg 1 -normalizeFPRNum (DoubleReg _) = DoubleReg 1 -normalizeFPRNum (XmmReg _) = XmmReg 1 -normalizeFPRNum (YmmReg _) = YmmReg 1 -normalizeFPRNum (ZmmReg _) = ZmmReg 1 -normalizeFPRNum _ = error "normalizeFPRNum expected only FPR regs" - -getFPRCtor :: GlobalReg -> Int -> GlobalReg -getFPRCtor (FloatReg _) = FloatReg -getFPRCtor (DoubleReg _) = DoubleReg -getFPRCtor (XmmReg _) = XmmReg -getFPRCtor (YmmReg _) = YmmReg -getFPRCtor (ZmmReg _) = ZmmReg -getFPRCtor _ = error "getFPRCtor expected only FPR regs" - -fprRegNum :: GlobalReg -> Int -fprRegNum (FloatReg i) = i -fprRegNum (DoubleReg i) = i -fprRegNum (XmmReg i) = i -fprRegNum (YmmReg i) = i -fprRegNum (ZmmReg i) = i -fprRegNum _ = error "fprRegNum expected only FPR regs" - --- | Input: dynflags, and the list of live registers --- --- Output: An augmented list of live registers, where padding was --- added to the list of registers to ensure the calling convention is --- correctly used by LLVM. --- --- Each global reg in the returned list is tagged with a bool, which --- indicates whether the global reg was added as padding, or was an original --- live register. --- --- That is, True => padding, False => a real, live global register. --- --- Also, the returned list is not sorted in any particular order. --- -padLiveArgs :: DynFlags -> LiveGlobalRegs -> [(Bool, GlobalReg)] -padLiveArgs dflags live = - if platformUnregisterised plat - then taggedLive -- not using GHC's register convention for platform. - else padding ++ taggedLive - where - taggedLive = map (\x -> (False, x)) live - plat = targetPlatform dflags - - fprLive = filter isFPR live - padding = concatMap calcPad $ groupBy sharesClass fprLive - - sharesClass :: GlobalReg -> GlobalReg -> Bool - sharesClass a b = sameFPRClass a b || overlappingClass - where - overlappingClass = regsOverlap dflags (norm a) (norm b) - norm = CmmGlobal . normalizeFPRNum - - calcPad :: [GlobalReg] -> [(Bool, GlobalReg)] - calcPad rs = getFPRPadding (getFPRCtor $ head rs) rs - -getFPRPadding :: (Int -> GlobalReg) -> LiveGlobalRegs -> [(Bool, GlobalReg)] -getFPRPadding paddingCtor live = padding + isPassed r = not (isSSE r) || isLive r + + +isSSE :: GlobalReg -> Bool +isSSE (FloatReg _) = True +isSSE (DoubleReg _) = True +isSSE (XmmReg _) = True +isSSE (YmmReg _) = True +isSSE (ZmmReg _) = True +isSSE _ = 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 + +-- the bool indicates whether the global reg was added as padding. +-- the returned list is not sorted in any particular order, +-- but does indicate the set of live registers needed, with SSE padding. +padLiveArgs :: LiveGlobalRegs -> [(Bool, GlobalReg)] +padLiveArgs live = allRegs where - fprRegNums = sort $ map fprRegNum live - (_, padding) = foldl assignSlots (1, []) $ fprRegNums + sseRegNums = sort $ mapMaybe sseRegNum live + (_, padding) = foldl assignSlots (1, []) $ sseRegNums + allRegs = padding ++ map (\r -> (False, r)) live assignSlots (i, acc) regNum | i == regNum = -- don't need padding here @@ -250,7 +195,11 @@ getFPRPadding paddingCtor live = padding genPad start n = take n $ flip map (iterate (+1) start) (\i -> - (True, paddingCtor i)) + (True, FloatReg i)) + -- NOTE: Picking float should be fine for the following reasons: + -- (1) Float aliases with all the other SSE register types on + -- the given platform. + -- (2) The argument is not live anyways. -- | Llvm standard fun attributes diff --git a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs index d24075ec7c..de839fbdeb 100644 --- a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs +++ b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs @@ -1818,14 +1818,14 @@ funPrologue live cmmBlocks = do -- STG Liveness optimisation done here. funEpilogue :: LiveGlobalRegs -> LlvmM ([LlvmVar], LlvmStatements) funEpilogue live = do - dflags <- getDynFlags -- the bool indicates whether the register is padding. let alwaysNeeded = map (\r -> (False, r)) alwaysLive - livePadded = alwaysNeeded ++ padLiveArgs dflags live + livePadded = alwaysNeeded ++ padLiveArgs live -- 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) @@ -1837,7 +1837,7 @@ funEpilogue live = do loads <- flip mapM allRegs $ \r -> case () of _ | (False, r) `elem` livePadded -> loadExpr r -- if r is not padding, load it - | not (isFPR r) || (True, r) `elem` livePadded + | not (isSSE r) || (True, r) `elem` livePadded -> loadUndef r | otherwise -> return (Nothing, nilOL) |