Simon Jakobi pushed to branch wip/sjakobi/T27437 at Glasgow Haskell Compiler / GHC

Commits:

2 changed files:

Changes:

  • compiler/GHC/Cmm/Dataflow/Label.hs
    ... ... @@ -35,6 +35,7 @@ module GHC.Cmm.Dataflow.Label
    35 35
         , mapEmpty
    
    36 36
         , mapSingleton
    
    37 37
         , mapInsert
    
    38
    +    , mapInsertLookup
    
    38 39
         , mapInsertWith
    
    39 40
         , mapDelete
    
    40 41
         , mapAlter
    
    ... ... @@ -199,6 +200,13 @@ mapSingleton (Label k) v = LM (M.singleton k v)
    199 200
     mapInsert :: Label -> v -> LabelMap v -> LabelMap v
    
    200 201
     mapInsert (Label k) v (LM m) = LM (M.insert k v m)
    
    201 202
     
    
    203
    +-- | Insert a value, also returning the value previously bound to the key (if
    
    204
    +-- any). Fuses the insert and lookup into a single traversal of the map.
    
    205
    +mapInsertLookup :: Label -> v -> LabelMap v -> (Maybe v, LabelMap v)
    
    206
    +mapInsertLookup (Label k) v (LM m) =
    
    207
    +  case M.insertLookupWithKey (\_ new _ -> new) k v m of
    
    208
    +    (old, m') -> (old, LM m')
    
    209
    +
    
    202 210
     mapInsertWith :: (v -> v -> v) -> Label -> v -> LabelMap v -> LabelMap v
    
    203 211
     mapInsertWith f (Label k) v (LM m) = LM (M.insertWith f k v m)
    
    204 212
     
    

  • compiler/GHC/CmmToAsm/Reg/Liveness.hs
    ... ... @@ -879,7 +879,7 @@ computeLiveness platform sccs
    879 879
                                             , ppr sccs'])
    
    880 880
     
    
    881 881
     livenessSCCs
    
    882
    -       :: Instruction instr
    
    882
    +       :: forall instr. Instruction instr
    
    883 883
            => Platform
    
    884 884
            -> BlockMap Regs
    
    885 885
            -> [SCC (LiveBasicBlock instr)]          -- accum
    
    ... ... @@ -891,23 +891,27 @@ livenessSCCs _ blockmap done []
    891 891
             = (done, blockmap)
    
    892 892
     
    
    893 893
     livenessSCCs platform blockmap done (AcyclicSCC block : sccs)
    
    894
    - = let  (blockmap', block')     = livenessBlock platform blockmap block
    
    894
    + = let  (_, blockmap', block')  = livenessBlock platform blockmap block
    
    895 895
        in   livenessSCCs platform blockmap' (AcyclicSCC block' : done) sccs
    
    896 896
     
    
    897 897
     livenessSCCs platform blockmap done
    
    898 898
             (CyclicSCC blocks : sccs) =
    
    899 899
             livenessSCCs platform blockmap' (CyclicSCC blocks':done) sccs
    
    900
    - where      (blockmap', blocks') = fixpoint blockmap
    
    900
    + where      (blockmap', blocks') = iterateUntilUnchanged blockmap
    
    901 901
     
    
    902 902
                 -- Iterate the liveness pass over the SCC until the block map reaches
    
    903 903
                 -- a fixed point. Only the SCC's own blocks can change between
    
    904 904
                 -- iterations (livenessBlock only inserts the block it processes, and
    
    905 905
                 -- earlier SCCs are already finalised).
    
    906
    -            fixpoint bm
    
    907
    -              | changed   = fixpoint bm'
    
    906
    +            iterateUntilUnchanged :: BlockMap Regs -> (BlockMap Regs, [LiveBasicBlock instr])
    
    907
    +            iterateUntilUnchanged bm
    
    908
    +              | changed   = iterateUntilUnchanged bm'
    
    908 909
                   | otherwise = (bm', blocks'')
    
    909 910
                   where (changed, bm', blocks'') = linearLiveness bm blocks
    
    910 911
     
    
    912
    +            -- Like @mapAccumL (livenessBlock platform)@, but also OR's together
    
    913
    +            -- the per-block changed flags reported by livenessBlock, so the
    
    914
    +            -- caller can detect the fixed point without comparing block maps.
    
    911 915
                 linearLiveness
    
    912 916
                     :: Instruction instr
    
    913 917
                     => BlockMap Regs -> [LiveBasicBlock instr]
    
    ... ... @@ -917,16 +921,13 @@ livenessSCCs platform blockmap done
    917 921
                     go !changed bm [] = (changed, bm, [])
    
    918 922
                     go !changed bm (block : blks') =
    
    919 923
                       case livenessBlock platform bm block of
    
    920
    -                    (bm', block') ->
    
    921
    -                      let bid       = blockId block
    
    922
    -                          !changed' = changed
    
    923
    -                                   || mapLookup bid bm /= mapLookup bid bm'
    
    924
    +                    (blockChanged, bm', block') ->
    
    925
    +                      let !changed' = changed || blockChanged
    
    924 926
                           in case go changed' bm' blks' of
    
    925 927
                                (changed'', bm'', blks'') ->
    
    926 928
                                  (changed'', bm'', block' : blks'')
    
    927 929
     
    
    928 930
     
    
    929
    -
    
    930 931
     -- | Annotate a basic block with register liveness information.
    
    931 932
     --
    
    932 933
     livenessBlock
    
    ... ... @@ -934,19 +935,23 @@ livenessBlock
    934 935
             => Platform
    
    935 936
             -> BlockMap Regs
    
    936 937
             -> LiveBasicBlock instr
    
    937
    -        -> (BlockMap Regs, LiveBasicBlock instr)
    
    938
    +        -> (Bool, BlockMap Regs, LiveBasicBlock instr)
    
    938 939
     
    
    939 940
     livenessBlock platform blockmap (BasicBlock block_id instrs)
    
    940 941
      = let
    
    941 942
             (regsLiveOnEntry, instrs1)
    
    942 943
                 = livenessBack platform noRegs blockmap [] (reverse instrs)
    
    943
    -        blockmap'       = mapInsert block_id regsLiveOnEntry blockmap
    
    944
    +        -- Fuse the insert with the lookup of the old entry, so the fixpoint
    
    945
    +        -- loop in livenessSCCs can tell whether this block changed for free,
    
    946
    +        -- without a separate map traversal.
    
    947
    +        (oldEntry, blockmap') = mapInsertLookup block_id regsLiveOnEntry blockmap
    
    948
    +        changed         = oldEntry /= Just regsLiveOnEntry
    
    944 949
     
    
    945 950
             instrs2         = livenessForward platform regsLiveOnEntry instrs1
    
    946 951
     
    
    947 952
             output          = BasicBlock block_id instrs2
    
    948 953
     
    
    949
    -   in   ( blockmap', output)
    
    954
    +   in   (changed, blockmap', output)
    
    950 955
     
    
    951 956
     -- | Calculate liveness going forwards,
    
    952 957
     --   filling in when regs are born