[commit: ghc] wip/kavon-nosplit-llvm: fixed up funPrologue and doReturnTo, though the latter produces verbose LLVM right now (6aab359)
git at git.haskell.org
git at git.haskell.org
Tue Jun 27 09:15:28 UTC 2017
Repository : ssh://git@git.haskell.org/ghc
On branch : wip/kavon-nosplit-llvm
Link : http://ghc.haskell.org/trac/ghc/changeset/6aab3593333693d57ea38fe5fd58a4b7253adf67/ghc
>---------------------------------------------------------------
commit 6aab3593333693d57ea38fe5fd58a4b7253adf67
Author: Kavon Farvardin <kavon at farvard.in>
Date: Thu May 18 15:08:13 2017 +0100
fixed up funPrologue and doReturnTo, though the latter produces verbose LLVM right now
>---------------------------------------------------------------
6aab3593333693d57ea38fe5fd58a4b7253adf67
compiler/llvmGen/LlvmCodeGen/Base.hs | 17 +++++++---
compiler/llvmGen/LlvmCodeGen/CodeGen.hs | 59 ++++++++++++++++++---------------
2 files changed, 44 insertions(+), 32 deletions(-)
diff --git a/compiler/llvmGen/LlvmCodeGen/Base.hs b/compiler/llvmGen/LlvmCodeGen/Base.hs
index 7369cdb..ac49c0c 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, llvmStdConv,
strCLabel_llvm, strDisplayName_llvm, strProcedureName_llvm,
getGlobalPtr, generateExternDecls,
@@ -145,10 +145,11 @@ llvmFunSection dflags lbl
| gopt Opt_SplitSections dflags = Just (concatFS [fsLit ".text.", lbl])
| otherwise = Nothing
--- | A Function's arguments
-llvmFunArgs :: DynFlags -> LiveGlobalRegs -> [LlvmVar]
-llvmFunArgs dflags live =
- map (lmGlobalRegArg dflags) (filter isPassed (activeStgRegs platform))
+-- | The full set of Cmm registers passed to a function, in the correct order,
+-- given the live argument registers. This is used for both call and return.
+llvmStdConv :: DynFlags -> LiveGlobalRegs -> [GlobalReg]
+llvmStdConv dflags live =
+ filter isPassed (activeStgRegs platform)
where platform = targetPlatform dflags
isLive r = not (isSSE r) || r `elem` alwaysLive || r `elem` live
isPassed r = not (isSSE r) || isLive r
@@ -159,6 +160,12 @@ llvmFunArgs dflags live =
isSSE (ZmmReg _) = True
isSSE _ = False
+-- | A Function's arguments
+llvmFunArgs :: DynFlags -> LiveGlobalRegs -> [LlvmVar]
+llvmFunArgs dflags live =
+ map (lmGlobalRegArg dflags) (llvmStdConv dflags live)
+
+
-- | Llvm standard fun attributes
llvmStdFunAttrs :: [LlvmFuncAttr]
llvmStdFunAttrs = [NoUnwind]
diff --git a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
index aa0baef..13f7258 100644
--- a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
+++ b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
@@ -40,7 +40,7 @@ import qualified Data.Semigroup as Semigroup
#endif
import Data.List ( nub )
import Data.Maybe ( catMaybes )
-import Control.Monad ( foldM, filterM )
+import Control.Monad ( foldM )
type Atomic = Bool
type LlvmStatements = OrdList LlvmStatement
@@ -818,29 +818,30 @@ genNativeCall _ expr live = do
doReturnTo :: ContInfo -> LlvmVar -> LlvmM LlvmStatements
-doReturnTo (retl, _, retRegs) llRetV = do
- -- find the struct fields corresponding to each live register
- -- according to the return convention.
- platform <- getDynFlag targetPlatform
- let regOrder = activeStgRegs platform
- needsUpdate r = do
- hasAlloca <- checkStackReg r
- return (hasAlloca && (r `elem` alwaysLive || r `elem` retRegs))
-
- -- liveRegs is ordered by the return convention.
- liveRegs <- filterM needsUpdate regOrder
-
- -- for each reg, we will add to the stms an extract
- -- from llRetV, followed by a store to the alloca backing the reg
- let extract (i, stms) reg = do
- regAlloca <- getCmmReg $ CmmGlobal reg
- let (LMPointer ty) = getVarType regAlloca
- (newVal, s1) <- doExpr ty $ ExtractV llRetV i
- let s2 = Store newVal regAlloca
- return (i+1, stms `snocOL` s1 `snocOL` s2)
-
- -- update the allocas that correspond to the regs
- (_, updateStms) <- foldM extract (0, nilOL) liveRegs
+doReturnTo (retl, _, retArgs) llRetV = do
+ dflags <- getDynFlags
+ let
+ -- TODO(kavon): seems retRegs includes all of the Rx registers
+ -- even if they are not live. LLVM will clean that up but it'd be nice if
+ -- we could avoid emitting those extracts by slimming down the retRegs list.
+
+ -- retRegs is a subset of allRegs, with the _same relative ordering_
+ retRegs = llvmStdConv dflags retArgs
+ allRegs = activeStgRegs $ targetPlatform dflags
+
+ extract (z@(_, [], _)) _ = return z -- no more slots needed
+ extract (i, x:xs, stms) reg
+ | x /= reg = -- skip if x doesn't go in this slot
+ return (i+1, x:xs, stms)
+ | otherwise = do
+ regAlloca <- getCmmReg $ CmmGlobal reg
+ let (LMPointer ty) = getVarType regAlloca
+ (newVal, s1) <- doExpr ty $ ExtractV llRetV i
+ let s2 = Store newVal regAlloca
+ return (i+1, xs, stms `snocOL` s1 `snocOL` s2)
+
+ -- update the allocas that correspond to the retRegs
+ (_, [], updateStms) <- foldM extract (0, retRegs, nilOL) allRegs
let br = Branch $ blockIdToLlvm retl
return (updateStms `snocOL` br)
@@ -1753,7 +1754,7 @@ genLit _ CmmHighStackMark
-- once we're done.
funPrologue :: LiveGlobalRegs -> [CmmBlock] -> LlvmM StmtData
funPrologue live cmmBlocks = do
-
+ dflags <- getDynFlags
trash <- getTrashRegs
let getAssignedRegs :: CmmNode O O -> [CmmReg]
getAssignedRegs (CmmAssign reg _) = [reg]
@@ -1762,10 +1763,14 @@ funPrologue live cmmBlocks = do
getAssignedRegs (CmmUnsafeForeignCall _ rs _) = map CmmGlobal trash ++ map CmmLocal rs
getAssignedRegs _ = []
getRegsBlock (_, body, _) = concatMap getAssignedRegs $ blockToList body
- assignedRegs = nub $ concatMap (getRegsBlock . blockSplit) cmmBlocks
+
+ -- because we emit non-tail calls, the pinned registers such as the BasePtr is
+ -- returned and we need to use an alloca for it. -kavon
+ conventionRegs = map CmmGlobal $ llvmStdConv dflags live
+
+ assignedRegs = nub $ concatMap (getRegsBlock . blockSplit) cmmBlocks ++ conventionRegs
isLive r = r `elem` alwaysLive || r `elem` live
- dflags <- getDynFlags
stmtss <- flip mapM assignedRegs $ \reg ->
case reg of
CmmLocal (LocalReg un _) -> do
More information about the ghc-commits
mailing list