summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Tibell <johan.tibell@gmail.com>2012-11-29 00:06:19 -0800
committerJohan Tibell <johan.tibell@gmail.com>2012-12-06 21:23:07 -0800
commit566920c77bce252d807e9a7cc3da862e5817d340 (patch)
treedff9b617664a4879fe759db3e46567887e8c4039
parent9b2882c13705689e9ef7cd2e1dd4f1ec3647d7d2 (diff)
downloadhaskell-566920c77bce252d807e9a7cc3da862e5817d340.tar.gz
Add -funbox-strict-primitive-fields
When enabled, this flag causes all strict fields which representation is smaller or equal to the size of a pointer to be unboxed.
-rw-r--r--compiler/basicTypes/DataCon.lhs-boot2
-rw-r--r--compiler/main/DynFlags.hs2
-rw-r--r--compiler/typecheck/TcTyClsDecls.lhs47
-rw-r--r--compiler/types/TyCon.lhs37
4 files changed, 87 insertions, 1 deletions
diff --git a/compiler/basicTypes/DataCon.lhs-boot b/compiler/basicTypes/DataCon.lhs-boot
index 94bf889325..716dc7e547 100644
--- a/compiler/basicTypes/DataCon.lhs-boot
+++ b/compiler/basicTypes/DataCon.lhs-boot
@@ -2,9 +2,11 @@
module DataCon where
import Name( Name )
import {-# SOURCE #-} TyCon( TyCon )
+import {-# SOURCE #-} TypeRep (Type)
data DataCon
dataConName :: DataCon -> Name
+dataConRepArgTys :: DataCon -> [Type]
dataConTyCon :: DataCon -> TyCon
isVanillaDataCon :: DataCon -> Bool
instance Eq DataCon
diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs
index 8686e553d0..1c47d6dfad 100644
--- a/compiler/main/DynFlags.hs
+++ b/compiler/main/DynFlags.hs
@@ -269,6 +269,7 @@ data GeneralFlag
| Opt_DoEtaReduction
| Opt_CaseMerge
| Opt_UnboxStrictFields
+ | Opt_UnboxStrictPrimitiveFields
| Opt_DictsCheap
| Opt_EnableRewriteRules -- Apply rewrite rules during simplification
| Opt_Vectorise
@@ -2359,6 +2360,7 @@ fFlags = [
( "do-eta-reduction", Opt_DoEtaReduction, nop ),
( "case-merge", Opt_CaseMerge, nop ),
( "unbox-strict-fields", Opt_UnboxStrictFields, nop ),
+ ( "unbox-strict-primitive-fields", Opt_UnboxStrictPrimitiveFields, nop ),
( "dicts-cheap", Opt_DictsCheap, nop ),
( "excess-precision", Opt_ExcessPrecision, nop ),
( "eager-blackholing", Opt_EagerBlackHoling, nop ),
diff --git a/compiler/typecheck/TcTyClsDecls.lhs b/compiler/typecheck/TcTyClsDecls.lhs
index ffcf5c2991..a7606012ba 100644
--- a/compiler/typecheck/TcTyClsDecls.lhs
+++ b/compiler/typecheck/TcTyClsDecls.lhs
@@ -37,6 +37,7 @@ import TcClassDcl
import TcHsType
import TcMType
import TcType
+import qualified TysPrim
import TysWiredIn( unitTy )
import Type
import Kind
@@ -1208,6 +1209,9 @@ chooseBoxingStrategy dflags arg_ty bang
HsNoBang -> HsNoBang
HsStrict | gopt Opt_UnboxStrictFields dflags
-> can_unbox HsStrict arg_ty
+ | gopt Opt_UnboxStrictPrimitiveFields dflags &&
+ can_unbox_prim arg_ty
+ -> HsUnpack
| otherwise -> HsStrict
HsNoUnpack -> HsStrict
HsUnpack -> can_unbox HsUnpackFailed arg_ty
@@ -1234,6 +1238,49 @@ chooseBoxingStrategy dflags arg_ty bang
else HsUnpack
| otherwise -> fail_bang
+
+ -- TODO: Deal with type synonyms?
+
+ can_unbox_prim :: TcType -> Bool
+ -- We unpack any field which final unpacked size would be smaller
+ -- or equal to the size of a pointer.
+ can_unbox_prim arg_ty
+ = case splitTyConApp_maybe arg_ty of
+ Nothing -> False
+
+ Just (arg_tycon, _)
+ | isAbstractTyCon arg_tycon -> False
+ -- See Note [Don't complain about UNPACK on abstract TyCons]
+ | isPrimTyCon arg_tycon &&
+ arg_tycon `elem` ptrSizedPrimTyCons -> True
+ -- TODO: Check that the PrimTyCon corresponds to a type
+ -- with pointer-sized representation.
+ | isEmptyDataTyCon arg_tycon -> True
+ | not (isRecursiveTyCon arg_tycon) -- Note [Recusive unboxing]
+ , Just ty <- tyConSingleFieldDataCon_maybe arg_tycon
+ -> can_unbox_prim ty
+ | otherwise -> False
+
+ptrSizedPrimTyCons :: [TyCon]
+ptrSizedPrimTyCons =
+ [ TysPrim.addrPrimTyCon
+ , TysPrim.arrayPrimTyCon
+ , TysPrim.byteArrayPrimTyCon
+ , TysPrim.arrayArrayPrimTyCon
+ , TysPrim.charPrimTyCon
+ , TysPrim.doublePrimTyCon
+ , TysPrim.floatPrimTyCon
+ , TysPrim.intPrimTyCon
+ , TysPrim.int32PrimTyCon
+ , TysPrim.int64PrimTyCon
+ , TysPrim.mutableArrayPrimTyCon
+ , TysPrim.mutableByteArrayPrimTyCon
+ , TysPrim.mutableArrayArrayPrimTyCon
+ , TysPrim.wordPrimTyCon
+ , TysPrim.word32PrimTyCon
+ , TysPrim.word64PrimTyCon
+ ]
+
\end{code}
Note [Don't complain about UNPACK on abstract TyCons]
diff --git a/compiler/types/TyCon.lhs b/compiler/types/TyCon.lhs
index 458f5c6e20..36c52a4ab8 100644
--- a/compiler/types/TyCon.lhs
+++ b/compiler/types/TyCon.lhs
@@ -53,6 +53,7 @@ module TyCon(
isTyConAssoc, tyConAssoc_maybe,
isRecursiveTyCon,
isImplicitTyCon,
+ isEmptyDataTyCon,
-- ** Extracting information out of TyCons
tyConName,
@@ -72,6 +73,7 @@ module TyCon(
algTyConRhs,
newTyConRhs, newTyConEtadRhs, unwrapNewTyCon_maybe,
tupleTyConBoxity, tupleTyConSort, tupleTyConArity,
+ tyConSingleFieldDataCon_maybe,
-- ** Manipulating TyCons
tcExpandTyCon_maybe, coreExpandTyCon_maybe,
@@ -88,7 +90,7 @@ module TyCon(
#include "HsVersions.h"
import {-# SOURCE #-} TypeRep ( Kind, Type, PredType )
-import {-# SOURCE #-} DataCon ( DataCon, isVanillaDataCon )
+import {-# SOURCE #-} DataCon ( DataCon, dataConRepArgTys, isVanillaDataCon )
import Var
import Class
@@ -1074,6 +1076,18 @@ isDataTyCon (AlgTyCon {algTcRhs = rhs})
isDataTyCon (TupleTyCon {tyConTupleSort = sort}) = isBoxed (tupleSortBoxity sort)
isDataTyCon _ = False
+isEmptyDataTyCon :: TyCon -> Bool
+isEmptyDataTyCon (AlgTyCon {algTcRhs = DataTyCon { data_cons = [data_con] } })
+ = isEmptyDataCon data_con
+isEmptyDataTyCon (TupleTyCon {dataCon = data_con })
+ = isEmptyDataCon data_con
+isEmptyDataTyCon _ = False
+
+isEmptyDataCon :: DataCon -> Bool
+isEmptyDataCon data_con = case dataConRepArgTys data_con of
+ [] -> True
+ _ -> False
+
-- | 'isDistinctTyCon' is true of 'TyCon's that are equal only to
-- themselves, even via coercions (except for unsafeCoerce).
-- This excludes newtypes, type functions, type synonyms.
@@ -1128,6 +1142,27 @@ isProductTyCon tc@(AlgTyCon {}) = case algTcRhs tc of
isProductTyCon (TupleTyCon {}) = True
isProductTyCon _ = False
+-- | If the given 'TyCon' has a /single/ data constructor with a /single/ field,
+-- i.e. it is a @data@ type with one alternative and one field, or a @newtype@
+-- then the type of that field is returned. If the 'TyCon' has a single
+-- constructor with more than one field, more than one constructor, or
+-- represents a primitive or function type constructor then @Nothing@ is
+-- returned. In any other case, the function panics
+tyConSingleFieldDataCon_maybe :: TyCon -> Maybe Type
+tyConSingleFieldDataCon_maybe tc@(AlgTyCon {}) = case algTcRhs tc of
+ DataTyCon{ data_cons = [data_con] }
+ | isVanillaDataCon data_con -> case dataConRepArgTys data_con of
+ [ty] -> Just ty
+ _ -> Nothing
+ | otherwise -> Nothing
+ NewTyCon { data_con = data_con }
+ -> case dataConRepArgTys data_con of
+ [ty] -> Just ty
+ _ -> pprPanic "tyConSingleFieldDataCon_maybe"
+ (ppr $ dataConRepArgTys data_con)
+ _ -> Nothing
+tyConSingleFieldDataCon_maybe _ = Nothing
+
-- | Is this a 'TyCon' representing a type synonym (@type@)?
isSynTyCon :: TyCon -> Bool
isSynTyCon (SynTyCon {}) = True