Skip to content

Useless code for some empty cases

Summary

GHC should force known-void values first.

Steps to reproduce

import Data.Void

data Wat = Wat !Void !Int

hello :: Void -> Int -> Wat
hello v i = Wat v $ product [1..i]

This produces Core

hello :: Void -> Int -> Wat
[GblId,
 Arity=2,
 Caf=NoCafRefs,
 Str=<B,1*U><B,1*H>b,
 Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True,
         WorkFree=True, Expandable=True,
         Guidance=ALWAYS_IF(arity=2,unsat_ok=True,boring_ok=True)
         Tmpl= \ (v_a19r [Occ=Once] :: Void) (i_a19s [Occ=Once!] :: Int) ->
                 case i_a19s of { I# _ [Occ=Dead] -> case v_a19r of { } }}]
hello
  = \ (v_a19r :: Void) (i_a19s :: Int) ->
      case i_a19s of { I# y_a2k3 -> case v_a19r of { } }

This is a bit strange! We produce code to match on the Int even though we know we will fail on the inner case. This feature seems (to my uneducated eye) to persist into assembly. This bloats the binary.

Expected behavior

I'd expect the compiled code to look like

hello
  = \ (v_a19r :: Void) (i_a19s :: Int) ->
      case i_a19r of { }

I don't know whether it would be helpful or harmful to change the unfolding similarly.

Environment

  • GHC version used: 8.10.1

Optional:

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