3

I'm currently playing around a bit with the possibility of removing a level of indirection from all lifted but newtype-like types (single constructor with a single argument) in Haste; for instance, Int would get a plain number as its runtime representation (i.e. 42), rather than an array containing a constructor tag and a number as is currently done (i.e. [0,42]).

However, GHC seems to be optimizing conversions between types that have an identical runtime representation, which breaks this scheme. Consider the following:

data Integer = Small Int# | Big ExternalGMPStuff
data Int = I# Int#

convert :: Int -> Integer
convert (I# i) = Small i

This is how the Integer and Int types are defined with GHC. Now, Small and I# will end up having the same constructor tag, which means that for small values, Integer and Int will have the same runtime representation. The convert function may thus reasonably be optimized away and indeed it seems like GHC is doing just that, in some cases.

When the runtime representation of Int changes to be the same as that of Int#, this optimization is obviously not valid anymore. Since being able to remove a level of indirection from all types that do not need it would be a rather big win, I would very much like to know:

a) In what circumstances does GHC perform this kind of optimization (triggering this is not very straightforward, and I can't find any rewrite rules in base or integer-gmp that explicitly do this); and b) is there any way to make it stop without having to disable optimizations altogether?

valderman
  • 8,365
  • 4
  • 22
  • 29
  • Does it really do that? I would suspect it's other optimization that make it appear it does. – augustss Feb 16 '14 at 15:14
  • I am not quite sure if it actually does; I have a vague recollection of seeing something to that effect (a comment, a rewrite rule, something else; maybe Integer-specific) somewhere in `base`, but triggering this behavior is trickier than it should be if this is what actually happens. The answer might well be "under no circumstances, ever". – valderman Feb 16 '14 at 16:33
  • "When the runtime representation of Int changes to be the same as that of Int#" but this changes the semantics of a program. `Int` is boxed but `Int#` is unboxed. Am I missing something? If you don't want the indirection provided by `data Int = I# Int#`, then why not use `Int#`? In many programs the indirection is desirable. – user2407038 Feb 17 '14 at 09:58
  • In "normal" Haskell, this is indeed the case, yes. However, when compiling to Javascript (which is what Haste does), we may be able to get all the semantics of the indirection with less of the overhead by doing something slightly clever. – valderman Feb 17 '14 at 17:47
  • I would be surprised if GHC does this currently, but maybe it should! – Reid Barton Sep 24 '14 at 19:55

0 Answers0