Skip to content

Unroll cloneSmallArray when possible

Motivation

Currently, cloneSmallArray# never unrolls the memcpy:

{-# language MagicHash #-}
module CloneFive
  ( cloneFive
  ) where
import GHC.Exts
cloneFive :: SmallArray# a -> SmallArray# a
cloneFive x = cloneSmallArray# x 42# 5#

With -O2, we get this cmm:

     {offset
       cCr: // global
           Hp = Hp + 56;
           if (Hp > HpLim) (likely: False) goto cCv; else goto cCu;
       cCv: // global
           HpAlloc = 56;
           R2 = R2;
           R1 = CloneFive.cloneFive_closure;
           call (stg_gc_fun)(R2, R1) args: 8, res: 0, upd: 8;
       cCu: // global
           I64[Hp - 48] = stg_SMALL_MUT_ARR_PTRS_FROZEN_CLEAN_info;
           I64[Hp - 40] = 5;
           _cCl::I64 = Hp - 48;
           call MO_Memcpy 8(_cCl::I64 + 16, R2 + 352, 40);
           R1 = _cCl::I64;
           call (P64[Sp])(R1) args: 8, res: 0, upd: 8;
     }

Proposal

Unroll the memcpy when the length is statically known. This is already done for memset in several places.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information