Ticket #5208: 0002-Unroll-memcpy-in-the-X86-backend.patch

File 0002-Unroll-memcpy-in-the-X86-backend.patch, 5.6 KB (added by tibbe, 2 years ago)
  • compiler/nativeGen/Size.hs

    From 7aa142ad48c9b0b3ab2ff2074b899b4ad0b9f3c8 Mon Sep 17 00:00:00 2001
    From: Johan Tibell <johan.tibell@gmail.com>
    Date: Thu, 26 May 2011 22:42:04 +0200
    Subject: [PATCH 2/2] Unroll memcpy in the X86 backend
    
    ---
     compiler/nativeGen/Size.hs        |   16 ++++---
     compiler/nativeGen/X86/CodeGen.hs |   89 ++++++++++++++++++++++++++++++++++++-
     2 files changed, 97 insertions(+), 8 deletions(-)
    
    diff --git a/compiler/nativeGen/Size.hs b/compiler/nativeGen/Size.hs
    index 6b5b1af..5d939d7 100644
    a b  
    1212--              properly. eg SPARC doesn't care about FF80. 
    1313-- 
    1414module Size ( 
    15         Size(..), 
    16         intSize, 
    17         floatSize, 
    18         isFloatSize, 
    19         cmmTypeSize, 
    20         sizeToWidth 
     15    Size(..), 
     16    intSize, 
     17    floatSize, 
     18    isFloatSize, 
     19    cmmTypeSize, 
     20    sizeToWidth, 
     21    sizeInBytes 
    2122) 
    2223 
    2324where 
     
    99100        FF32            -> W32 
    100101        FF64            -> W64 
    101102        FF80            -> W80 
    102          
    103103 
     104sizeInBytes :: Size -> Int 
     105sizeInBytes = widthInBytes . sizeToWidth 
  • compiler/nativeGen/X86/CodeGen.hs

    diff --git a/compiler/nativeGen/X86/CodeGen.hs b/compiler/nativeGen/X86/CodeGen.hs
    index 0901360..fcefbd8 100644
    a b  
    5555import DynFlags 
    5656 
    5757import Control.Monad    ( mapAndUnzipM ) 
     58import Data.Bits 
    5859import Data.Maybe       ( catMaybes ) 
    5960import Data.Int 
    6061 
    6162#if WORD_SIZE_IN_BITS==32 
    6263import Data.Maybe       ( fromJust ) 
    6364import Data.Word 
    64 import Data.Bits 
    6565#endif 
    6666 
    6767sse2Enabled :: NatM Bool 
     
    15041504 
    15051505-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    15061506 
     1507-- Unroll memcpy calls if the source and destination pointers are at 
     1508-- least DWORD aligned and the number of bytes to copy isn't too 
     1509-- large.  Otherwise, call C's memcpy. 
     1510genCCall (CmmPrim MO_Memcpy) _ args@[CmmHinted dst _, CmmHinted src _, 
     1511                                     CmmHinted (CmmLit (CmmInt n _)) _, 
     1512                                     CmmHinted (CmmLit (CmmInt align _)) _] 
     1513    | n <= maxInlineSizeThreshold && align .&. 3 == 0 = do 
     1514        code_dst <- getAnyReg dst 
     1515        dst_r <- getNewRegNat size 
     1516        code_src <- getAnyReg src 
     1517        src_r <- getNewRegNat size 
     1518        tmp_r <- getNewRegNat size 
     1519        return $ code_dst dst_r `appOL` code_src src_r `appOL` 
     1520            go dst_r src_r tmp_r n 
     1521  where 
     1522    size = if align .&. 4 /= 0 then II32 else archWordSize 
     1523 
     1524    sizeBytes = fromIntegral (sizeInBytes size) 
     1525 
     1526    go :: Reg -> Reg -> Reg -> Integer -> OrdList Instr 
     1527    go dst src tmp i 
     1528        | i >= sizeBytes = 
     1529            unitOL (MOV size (OpAddr src_addr) (OpReg tmp)) `appOL` 
     1530            unitOL (MOV size (OpReg tmp) (OpAddr dst_addr)) `appOL` 
     1531            go dst src tmp (i - sizeBytes) 
     1532        -- Deal with remaining bytes. 
     1533        | i >= 4 =  -- Will never happen on 32-bit 
     1534            unitOL (MOV II32 (OpAddr src_addr) (OpReg tmp)) `appOL` 
     1535            unitOL (MOV II32 (OpReg tmp) (OpAddr dst_addr)) `appOL` 
     1536            go dst src tmp (i - 4) 
     1537        | i >= 2 = 
     1538            unitOL (MOVZxL II16 (OpAddr src_addr) (OpReg tmp)) `appOL` 
     1539            unitOL (MOV II16 (OpReg tmp) (OpAddr dst_addr)) `appOL` 
     1540            go dst src tmp (i - 2) 
     1541        | i >= 1 = 
     1542            unitOL (MOVZxL II8 (OpAddr src_addr) (OpReg tmp)) `appOL` 
     1543            unitOL (MOV II8 (OpReg tmp) (OpAddr dst_addr)) `appOL` 
     1544            go dst src tmp (i - 1) 
     1545        | otherwise = nilOL 
     1546      where 
     1547        src_addr = AddrBaseIndex (EABaseReg src) EAIndexNone 
     1548                   (ImmInteger (n - i)) 
     1549        dst_addr = AddrBaseIndex (EABaseReg dst) EAIndexNone 
     1550                   (ImmInteger (n - i)) 
     1551 
     1552genCCall (CmmPrim MO_Memset) _ args@[CmmHinted dst _, 
     1553                                     CmmHinted (CmmLit (CmmInt c _)) _, 
     1554                                     CmmHinted (CmmLit (CmmInt n _)) _, 
     1555                                     CmmHinted (CmmLit (CmmInt align _)) _] 
     1556    | n <= maxInlineSizeThreshold && align .&. 3 == 0 = do 
     1557        code_dst <- getAnyReg dst 
     1558        dst_r <- getNewRegNat size 
     1559        return $ code_dst dst_r `appOL` go dst_r n 
     1560  where 
     1561    (size, val) = case align .&. 3 of 
     1562        2 -> (II16, c2) 
     1563        0 -> (II32, c4) 
     1564        _ -> (II8, c) 
     1565    c2 = c `shiftL` 8 .|. c 
     1566    c4 = c2 `shiftL` 16 .|. c2 
     1567 
     1568    sizeBytes = fromIntegral (sizeInBytes size) 
     1569 
     1570    go :: Reg -> Integer -> OrdList Instr 
     1571    go dst i 
     1572        -- TODO: Add movabs instruction and support 64-bit sets. 
     1573        | i >= sizeBytes =  -- This might be smaller than the below sizes 
     1574            unitOL (MOV size (OpImm (ImmInteger val)) (OpAddr dst_addr)) `appOL` 
     1575            go dst (i - sizeBytes) 
     1576        | i >= 4 =  -- Will never happen on 32-bit 
     1577            unitOL (MOV II32 (OpImm (ImmInteger c4)) (OpAddr dst_addr)) `appOL` 
     1578            go dst (i - 4) 
     1579        | i >= 2 = 
     1580            unitOL (MOV II16 (OpImm (ImmInteger c2)) (OpAddr dst_addr)) `appOL` 
     1581            go dst (i - 2) 
     1582        | i >= 1 = 
     1583            unitOL (MOV II8 (OpImm (ImmInteger c)) (OpAddr dst_addr)) `appOL` 
     1584            go dst (i - 1) 
     1585        | otherwise = nilOL 
     1586      where 
     1587        dst_addr = AddrBaseIndex (EABaseReg dst) EAIndexNone 
     1588                   (ImmInteger (n - i)) 
     1589 
    15071590#if i386_TARGET_ARCH 
    15081591 
    15091592genCCall (CmmPrim MO_WriteBarrier) _ _ = return nilOL 
     
    18741957 
    18751958#endif /* x86_64_TARGET_ARCH */ 
    18761959 
     1960-- | We're willing to inline and unroll memcpy/memset calls that touch 
     1961-- at most these many bytes.  This threshold is the same as the one 
     1962-- used by GCC and LLVM. 
     1963maxInlineSizeThreshold = 128 
    18771964 
    18781965outOfLineCmmOp :: CallishMachOp -> Maybe HintedCmmFormal -> [HintedCmmActual] -> NatM InstrBlock 
    18791966outOfLineCmmOp mop res args