Simon Jakobi pushed to branch wip/sjakobi/cmmsink-touch at Glasgow Haskell Compiler / GHC

Commits:

6 changed files:

Changes:

  • compiler/GHC/Cmm/MachOp.hs
    ... ... @@ -18,6 +18,7 @@ module GHC.Cmm.MachOp
    18 18
     
    
    19 19
         -- CallishMachOp
    
    20 20
         , CallishMachOp(..), callishMachOpHints
    
    21
    +    , callishMachOpClobbersMemory
    
    21 22
         , pprCallishMachOp
    
    22 23
         , machOpMemcpyishAlign
    
    23 24
         , callishMachOpArgTys
    
    ... ... @@ -876,6 +877,18 @@ callishMachOpHints op = case op of
    876 877
       _                -> ([],[])
    
    877 878
       -- empty lists indicate NoHint
    
    878 879
     
    
    880
    +-- | May this operation write to memory, or otherwise act as a memory
    
    881
    +-- barrier?  When in doubt, answer 'True'.
    
    882
    +--
    
    883
    +-- Used by the sinking pass to decide whether a memory read may be moved
    
    884
    +-- past a call of this operation; see Note [Foreign calls clobber heap]
    
    885
    +-- in GHC.Cmm.Sink.
    
    886
    +callishMachOpClobbersMemory :: CallishMachOp -> Bool
    
    887
    +callishMachOpClobbersMemory op = case op of
    
    888
    +  MO_Touch           -> False  -- pure liveness marker, no instructions
    
    889
    +  MO_Prefetch_Data _ -> False  -- reads memory, writes nothing
    
    890
    +  _                  -> True
    
    891
    +
    
    879 892
     -- | The alignment of a 'memcpy'-ish operation.
    
    880 893
     machOpMemcpyishAlign :: CallishMachOp -> Maybe Int
    
    881 894
     machOpMemcpyishAlign op = case op of
    

  • compiler/GHC/Cmm/Parser.y
    ... ... @@ -1203,6 +1203,8 @@ callishMachOps platform = listToUFM $
    1203 1203
             ( "prefetch2", (MO_Prefetch_Data 2,)),
    
    1204 1204
             ( "prefetch3", (MO_Prefetch_Data 3,)),
    
    1205 1205
     
    
    1206
    +        ( "touch", (MO_Touch,) ),
    
    1207
    +
    
    1206 1208
             ( "bswap16", (MO_BSwap W16,) ),
    
    1207 1209
             ( "bswap32", (MO_BSwap W32,) ),
    
    1208 1210
             ( "bswap64", (MO_BSwap W64,) )
    

  • compiler/GHC/Cmm/Sink.hs
    ... ... @@ -719,7 +719,10 @@ conflicts platform assig@(r, rhs, addr) node
    719 719
       = True
    
    720 720
     
    
    721 721
       -- (c) foreign calls clobber heap: see Note [Foreign calls clobber heap]
    
    722
    -  | CmmUnsafeForeignCall{} <- node, memConflicts addr AnyMem      = True
    
    722
    +  | CmmUnsafeForeignCall target _ _ <- node
    
    723
    +  , foreignTargetClobbersMemory target
    
    724
    +  , memConflicts addr AnyMem
    
    725
    +  = True
    
    723 726
     
    
    724 727
       -- (d) native calls clobber any memory
    
    725 728
       | CmmCall{} <- node, memConflicts addr AnyMem                   = True
    
    ... ... @@ -732,6 +735,12 @@ conflicts platform assig@(r, rhs, addr) node
    732 735
     
    
    733 736
       | otherwise = False
    
    734 737
     
    
    738
    +-- | May this foreign-call target write to memory, or otherwise act as a
    
    739
    +-- memory barrier?  See Note [Foreign calls clobber heap].
    
    740
    +foreignTargetClobbersMemory :: ForeignTarget -> Bool
    
    741
    +foreignTargetClobbersMemory (PrimTarget op)    = callishMachOpClobbersMemory op
    
    742
    +foreignTargetClobbersMemory (ForeignTarget {}) = True
    
    743
    +
    
    735 744
     {- Note [Inlining foldRegsDefd]
    
    736 745
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    737 746
     foldRegsDefd is, after optimization, *not* a small function so
    
    ... ... @@ -874,6 +883,16 @@ data AbsMem
    874 883
     -- `suspendThread` releases the capability used by the thread, hence we mustn't
    
    875 884
     -- float accesses to heap, stack or virtual global registers stored in the
    
    876 885
     -- capability (e.g. with unregisterised build, see #19237).
    
    886
    +--
    
    887
    +-- Conversely, a few CallishMachOps neither write memory nor imply a
    
    888
    +-- barrier, and needn't block sinking ('callishMachOpClobbersMemory' in
    
    889
    +-- GHC.Cmm.MachOp classifies them):
    
    890
    +--
    
    891
    +--  * MO_Touch is a pure liveness marker: no backend emits any code for it.
    
    892
    +--    Sinking is intra-block, so the Core-level touch# reordering hazard
    
    893
    +--    of #18040 does not arise.
    
    894
    +--
    
    895
    +--  * MO_Prefetch_Data reads memory but writes nothing.
    
    877 896
     
    
    878 897
     
    
    879 898
     bothMems :: AbsMem -> AbsMem -> AbsMem
    

  • testsuite/tests/codeGen/should_gen_asm/T27782.asm
    1
    +loadTouch:
    
    2
    +        movzbl
    
    3
    +        jmp
    
    4
    +loadPrefetch:
    
    5
    +        prefetchnta
    
    6
    +        movzbl
    
    7
    +        jmp

  • testsuite/tests/codeGen/should_gen_asm/T27782.cmm
    1
    +#include "Cmm.h"
    
    2
    +
    
    3
    +// A load must sink past touch# and prefetch, which don't clobber memory,
    
    4
    +// so that it can be folded into the instruction that uses it.
    
    5
    +
    
    6
    +loadTouch (W_ p, P_ o) {
    
    7
    +    bits8 b;
    
    8
    +    b = bits8[p];
    
    9
    +    prim %touch(o);
    
    10
    +    return (%zx64(b));
    
    11
    +}
    
    12
    +
    
    13
    +loadPrefetch (W_ p, W_ q) {
    
    14
    +    bits8 b;
    
    15
    +    b = bits8[p];
    
    16
    +    prim %prefetch0(q);
    
    17
    +    return (%zx64(b));
    
    18
    +}

  • testsuite/tests/codeGen/should_gen_asm/all.T
    ... ... @@ -27,6 +27,7 @@ test('T25233', [unless(arch('x86_64'), skip),
    27 27
                     when(unregisterised(), skip)], compile_grep_asm, ['hs', True, '-O'])
    
    28 28
     test('T25233b', [unless(arch('x86_64'), skip),
    
    29 29
                      when(unregisterised(), skip)], compile_grep_asm, ['cmm', True, ''])
    
    30
    +test('T27782', is_amd64_codegen, compile_cmp_asm, ['cmm', ''])
    
    30 31
     is_aarch64_codegen = [
    
    31 32
         unless(arch('aarch64'), skip),
    
    32 33
         when(unregisterised(), skip),