[commit: ghc] master: Mimic OldCmm basic block ordering in the LLVM backend. (b39e4de)
Geoffrey Mainland
gmainlan at microsoft.com
Fri Feb 1 23:02:15 CET 2013
Repository : ssh://darcs.haskell.org//srv/darcs/ghc
On branch : master
http://hackage.haskell.org/trac/ghc/changeset/b39e4de19a0aa3cbc42d72a02f83cec77f48f3a0
>---------------------------------------------------------------
commit b39e4de19a0aa3cbc42d72a02f83cec77f48f3a0
Author: Geoffrey Mainland <gmainlan at microsoft.com>
Date: Wed Jan 16 16:06:48 2013 +0000
Mimic OldCmm basic block ordering in the LLVM backend.
In OldCmm, the false case of a conditional was a fallthrough. In Cmm,
conditionals have both true and false successors. When we convert Cmm to LLVM,
we now first re-order Cmm blocks so that the false successor of a conditional
occurs next in the list of basic blocks, i.e., it is a fallthrough, just like it
(necessarily) did in OldCmm. Surprisingly, this can make a big performance
difference.
>---------------------------------------------------------------
compiler/cmm/CmmUtils.hs | 31 ++++++++++++++++++++++++++++++-
compiler/llvmGen/LlvmCodeGen/CodeGen.hs | 2 +-
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/compiler/cmm/CmmUtils.hs b/compiler/cmm/CmmUtils.hs
index 435df58..5530b77 100644
--- a/compiler/cmm/CmmUtils.hs
+++ b/compiler/cmm/CmmUtils.hs
@@ -52,7 +52,8 @@ module CmmUtils(
modifyGraph,
ofBlockMap, toBlockMap, insertBlock,
- ofBlockList, toBlockList, bodyToBlockList, toBlockListEntryFirst,
+ ofBlockList, toBlockList, bodyToBlockList,
+ toBlockListEntryFirst, toBlockListEntryFirstFalseFallthrough,
foldGraphBlocks, mapGraphNodes, postorderDfs, mapGraphNodes1,
analFwd, analBwd, analRewFwd, analRewBwd,
@@ -448,6 +449,34 @@ toBlockListEntryFirst g
Just entry_block = mapLookup entry_id m
others = filter ((/= entry_id) . entryLabel) (mapElems m)
+-- | Like 'toBlockListEntryFirst', but we strive to ensure that we order blocks
+-- so that the false case of a conditional jumps to the next block in the output
+-- list of blocks. This matches the way OldCmm blocks were output since in
+-- OldCmm the false case was a fallthrough, whereas in Cmm conditional branches
+-- have both true and false successors. Block ordering can make a big difference
+-- in performance in the LLVM backend. Note that we rely crucially on the order
+-- of successors returned for CmmCondBranch by the NonLocal instance for CmmNode
+-- defind in cmm/CmmNode.hs. -GBM
+toBlockListEntryFirstFalseFallthrough :: CmmGraph -> [CmmBlock]
+toBlockListEntryFirstFalseFallthrough g
+ | mapNull m = []
+ | otherwise = dfs setEmpty [entry_block]
+ where
+ m = toBlockMap g
+ entry_id = g_entry g
+ Just entry_block = mapLookup entry_id m
+
+ dfs :: LabelSet -> [CmmBlock] -> [CmmBlock]
+ dfs _ [] = []
+ dfs visited (block:bs)
+ | id `setMember` visited = dfs visited bs
+ | otherwise = block : dfs (setInsert id visited) bs'
+ where id = entryLabel block
+ bs' = foldr add_id bs (successors block)
+ add_id id bs = case mapLookup id m of
+ Just b -> b : bs
+ Nothing -> bs
+
ofBlockList :: BlockId -> [CmmBlock] -> CmmGraph
ofBlockList entry blocks = CmmGraph { g_entry = entry
, g_graph = GMany NothingO body NothingO }
diff --git a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
index 609be3d..9159817 100644
--- a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
+++ b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
@@ -40,7 +40,7 @@ type LlvmStatements = OrdList LlvmStatement
--
genLlvmProc :: LlvmEnv -> RawCmmDecl -> UniqSM (LlvmEnv, [LlvmCmmDecl])
genLlvmProc env (CmmProc infos lbl live graph) = do
- let blocks = toBlockListEntryFirst graph
+ let blocks = toBlockListEntryFirstFalseFallthrough graph
(env', lmblocks, lmdata) <- basicBlocksCodeGen env live blocks ([], [])
let info = mapLookup (g_entry graph) infos
proc = CmmProc info lbl live (ListGraph lmblocks)
More information about the ghc-commits
mailing list