From 6e9501c0e3c3bb807981c0378c969d0667a7ce0b Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Tue, 16 Feb 2010 15:05:06 +0000 Subject: [PATCH] Beef up cmmMiniInline a tiny bit Allow a temporary assignment to be pushed past an assignment to a global if the global is not mentioned in the rhs of the assignment we are inlining. This fixes up some bad code. We should make sure we're doing something equivalent in the new backend in due course. --- compiler/cmm/CmmExpr.hs | 11 +++++++++++ compiler/cmm/CmmOpt.hs | 41 ++++++++++++++++++++------------------- compiler/codeGen/CgUtils.hs | 7 ------- compiler/codeGen/StgCmmUtils.hs | 3 +-- 4 files changed, 33 insertions(+), 29 deletions(-) diff --git a/compiler/cmm/CmmExpr.hs b/compiler/cmm/CmmExpr.hs index a4d07c2..39099f1 100644 --- a/compiler/cmm/CmmExpr.hs +++ b/compiler/cmm/CmmExpr.hs @@ -22,6 +22,7 @@ module CmmExpr , DefinerOfSlots, UserOfSlots, foldSlotsDefd, foldSlotsUsed , RegSet, emptyRegSet, elemRegSet, extendRegSet, deleteFromRegSet, mkRegSet , plusRegSet, minusRegSet, timesRegSet + , regUsedIn , Area(..), AreaId(..), SubArea, SubAreaSet, AreaMap, isStackSlotOf -- MachOp @@ -274,6 +275,16 @@ instance DefinerOfLocalRegs a => DefinerOfLocalRegs (Maybe a) where foldRegsDefd _ set Nothing = set foldRegsDefd f set (Just x) = foldRegsDefd f set x +----------------------------------------------------------------------------- +-- Another reg utility + +regUsedIn :: CmmReg -> CmmExpr -> Bool +_ `regUsedIn` CmmLit _ = False +reg `regUsedIn` CmmLoad e _ = reg `regUsedIn` e +reg `regUsedIn` CmmReg reg' = reg == reg' +reg `regUsedIn` CmmRegOff reg' _ = reg == reg' +reg `regUsedIn` CmmMachOp _ es = any (reg `regUsedIn`) es +_ `regUsedIn` CmmStackSlot _ _ = False ----------------------------------------------------------------------------- -- Stack slots diff --git a/compiler/cmm/CmmOpt.hs b/compiler/cmm/CmmOpt.hs index 8326a48..8163073 100644 --- a/compiler/cmm/CmmOpt.hs +++ b/compiler/cmm/CmmOpt.hs @@ -116,27 +116,18 @@ cmmMiniInlineStmts uses (stmt@(CmmAssign (CmmLocal (LocalReg u _)) expr) : stmts cmmMiniInlineStmts uses (stmt:stmts) = stmt : cmmMiniInlineStmts uses stmts +lookForInline u expr (stmt : rest) + | Just 1 <- lookupUFM (countUses stmt) u, ok_to_inline + = Just (inlineStmt u expr stmt : rest) + + | ok_to_skip + = case lookForInline u expr rest of + Nothing -> Nothing + Just stmts -> Just (stmt:stmts) + + | otherwise + = Nothing --- Try to inline a temporary assignment. We can skip over assignments to --- other tempoararies, because we know that expressions aren't side-effecting --- and temporaries are single-assignment. -lookForInline u expr (stmt@(CmmAssign (CmmLocal (LocalReg u' _)) rhs) : rest) - | u /= u' - = case lookupUFM (countUses rhs) u of - Just 1 -> Just (inlineStmt u expr stmt : rest) - _other -> case lookForInline u expr rest of - Nothing -> Nothing - Just stmts -> Just (stmt:stmts) - -lookForInline u expr (CmmNop : rest) - = lookForInline u expr rest - -lookForInline _ _ [] = Nothing - -lookForInline u expr (stmt:stmts) - = case lookupUFM (countUses stmt) u of - Just 1 | ok_to_inline -> Just (inlineStmt u expr stmt : stmts) - _other -> Nothing where -- we don't inline into CmmCall if the expression refers to global -- registers. This is a HACK to avoid global registers clashing with @@ -147,6 +138,16 @@ lookForInline u expr (stmt:stmts) CmmCall{} -> hasNoGlobalRegs expr _ -> True + -- We can skip over assignments to other tempoararies, because we + -- know that expressions aren't side-effecting and temporaries are + -- single-assignment. + ok_to_skip = case stmt of + CmmNop -> True + CmmAssign (CmmLocal (LocalReg u' _)) rhs | u' /= u -> True + CmmAssign g@(CmmGlobal _) rhs -> not (g `regUsedIn` expr) + _other -> False + + inlineStmt :: Unique -> CmmExpr -> CmmStmt -> CmmStmt inlineStmt u a (CmmAssign r e) = CmmAssign r (inlineExpr u a e) inlineStmt u a (CmmStore e1 e2) = CmmStore (inlineExpr u a e1) (inlineExpr u a e2) diff --git a/compiler/codeGen/CgUtils.hs b/compiler/codeGen/CgUtils.hs index 8ce1ffc..f8b41a0 100644 --- a/compiler/codeGen/CgUtils.hs +++ b/compiler/codeGen/CgUtils.hs @@ -945,13 +945,6 @@ anySrc p (CmmComment _) = False anySrc p CmmNop = False anySrc p other = True -- Conservative -regUsedIn :: CmmReg -> CmmExpr -> Bool -reg `regUsedIn` CmmLit _ = False -reg `regUsedIn` CmmLoad e _ = reg `regUsedIn` e -reg `regUsedIn` CmmReg reg' = reg == reg' -reg `regUsedIn` CmmRegOff reg' _ = reg == reg' -reg `regUsedIn` CmmMachOp _ es = any (reg `regUsedIn`) es - locUsedIn :: CmmExpr -> CmmType -> CmmExpr -> Bool -- (locUsedIn a r e) checks whether writing to r[a] could affect the value of -- 'e'. Returns True if it's not sure. diff --git a/compiler/codeGen/StgCmmUtils.hs b/compiler/codeGen/StgCmmUtils.hs index 9cfb241..4b1446a 100644 --- a/compiler/codeGen/StgCmmUtils.hs +++ b/compiler/codeGen/StgCmmUtils.hs @@ -49,7 +49,7 @@ module StgCmmUtils ( import StgCmmMonad import StgCmmClosure import BlockId -import Cmm +import Cmm hiding (regUsedIn) import MkZipCfgCmm import CLabel import CmmUtils @@ -596,7 +596,6 @@ reg `regUsedIn` CmmRegOff (CmmLocal reg') _ = reg == reg' reg `regUsedIn` CmmMachOp _ es = any (reg `regUsedIn`) es _reg `regUsedIn` _other = False -- The CmmGlobal cases - ------------------------------------------------------------------------- -- mkSwitch ------------------------------------------------------------------------- -- 1.7.10.4