Worker/wrapper split keeps absent unlifted newtype arguments
Exactly what it says on the tin. Workers generated for functions that have unused unlifted arguments keep the arguments if they are wrapped in a newtype. This program reproduces the issue:
{-# LANGUAGE MagicHash, UnliftedNewtypes #-}
module Ww where
import GHC.Exts (Int#)
newtype T = T Int#
f :: T -> Int# -> T -> T
f a _ _ = a
{-# NOINLINE f #-} -- to force worker/wrappering
-- RHS size: {terms: 11, types: 6, coercions: 0, joins: 0/4}
$wf_swK
= \ w_swH [Dmd=<S,1*U>] w_swJ [Dmd=<L,A>] ->
let { w_swI = 0# } in
let { a_aip = w_swH } in
let { ds_dww = w_swI } in let { ds_dwx = w_swJ } in a_aip
-- RHS size: {terms: 6, types: 3, coercions: 0, joins: 0/0}
f = \ w_swH [Dmd=<S,1*U>] w_swI [Dmd=<L,A>] w_swJ [Dmd=<L,A>] ->
$wf_swK w_swH w_swJ
The source of the bug appears to be Literal.absentLiteralOf
, which looks up a literal to use as a dummy RHS for an unlifted binding. The problem is that it just looks up a value by type, not representation:
absentLiteralOf :: TyCon -> Maybe Literal
-- Return a literal of the appropriate primitive
-- TyCon, to use as a placeholder when it doesn't matter
-- Rubbish literals are handled in WwLib, because
-- 1. Looking at the TyCon is not enough, we need the actual type
-- 2. This would need to return a type application to a literal
absentLiteralOf tc = lookupUFM absent_lits (tyConName tc)
absent_lits :: UniqFM Literal
absent_lits = listToUFM [ (addrPrimTyConKey, LitNullAddr)
, (charPrimTyConKey, LitChar 'x')
, (intPrimTyConKey, mkLitIntUnchecked 0)
, (int64PrimTyConKey, mkLitInt64Unchecked 0)
, (wordPrimTyConKey, mkLitWordUnchecked 0)
, (word64PrimTyConKey, mkLitWord64Unchecked 0)
, (floatPrimTyConKey, LitFloat 0)
, (doublePrimTyConKey, LitDouble 0)
]
I imagine the right there to do here is to look up the representation, instead, and to add a coercion as appropriate. If someone can tell me the right way to insert the coercion, I think I can figure out the rest and open a MR.