Skip to content

How to prevent this optimization?

Here is a simplified snippet:

{-# LANGUAGE UnboxedTuples, MagicHash #-}

module Lib where

import Data.Array.Byte
import GHC.Exts
import GHC.ST

newInherit :: ByteArray -> Int -> ByteArray
newInherit (ByteArray dst#) (I# len#) = runST $ ST $ \s ->
  let (# s', newM #) = (case isByteArrayPinned# dst# of
        0# -> newByteArray# len# s
        _  -> newPinnedByteArray# len# s) in
    let (# s'', new #) = unsafeFreezeByteArray# newM s' in
      (# s'', ByteArray new #)

I'm very keen to preserve this code structure as is: namely, do not propagate unsafeFreezeByteArray# into branches of isByteArrayPinned#. The reason is that in the actual program (https://github.com/Bodigrim/linear-builder/issues/4#issuecomment-1465331108) there is more action other than just freezing, which gets unnecessary duplicated.

However, GHC is very stubborn to emit this:

(\ (s1_aBL :: State# s_aCj) ->
  case isByteArrayPinned# dst#_aBJ of ds2_dDh { __DEFAULT ->
  case ds2_dDh of {
    __DEFAULT ->
      case newPinnedByteArray# @s_aCj len#_aBK s1_aBL of
      { (# ipv_sDs, ipv1_sDt #) ->
      case unsafeFreezeByteArray# @s_aCj ipv1_sDt ipv_sDs of
      { (# ipv2_sDo, ipv3_sDp #) ->
      (# ipv2_sDo, Data.Array.Byte.ByteArray ipv3_sDp #)
      }
      };
    0# ->
      case newByteArray# @s_aCj len#_aBK s1_aBL of
      { (# ipv_sDv, ipv1_sDw #) ->
      case unsafeFreezeByteArray# @s_aCj ipv1_sDw ipv_sDv of
      { (# ipv2_sDo, ipv3_sDp #) ->
      (# ipv2_sDo, Data.Array.Byte.ByteArray ipv3_sDp #)
      }
      }
  }
  })

The only way to avoid it seems to pass -fmax-simplifier-iterations=0 obtaining

(\ (s1_aBL :: State# s_aCj) ->
  case case isByteArrayPinned# dst#_aBJ of ds2_dDh { __DEFAULT ->
       case ds2_dDh of {
         __DEFAULT -> newPinnedByteArray# @s_aCj len#_aBK s1_aBL;
         0# -> newByteArray# @s_aCj len#_aBK s1_aBL
       }
       }
  of ds2_dDn
  { __DEFAULT ->
  case ds2_dDn of { (# s'_aCy, newM_aCz #) ->
  case unsafeFreezeByteArray# @s_aCj newM_aCz s'_aCy of ds3_dDg
  { __DEFAULT ->
  case ds3_dDg of { (# s''_aCH, new_aCI #) ->
  (# s''_aCH, Data.Array.Byte.ByteArray new_aCI #)
  }
  }
  }
  })

But in not-so-toy example -fmax-simplifier-iterations=0 is not an option.

Is there anything else I can do? Any trick to explain to GHC what I want?

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