
#6135: Unboxed Booleans -------------------------------+-------------------------------------------- Reporter: benl | Owner: jstolarek Type: feature request | Status: patch Priority: normal | Milestone: 7.8.1 Component: Compiler | Version: 7.4.1 Resolution: | Keywords: Os: Unknown/Multiple | Architecture: Unknown/Multiple Failure: None/Unknown | Difficulty: Unknown Testcase: | Blockedby: Blocking: | Related: #605 -------------------------------+-------------------------------------------- Comment(by jstolarek): I spent some time on figuring out why my patch works. Here's what I come up with (hopefully I got things right). Previously the !PrimOps of type `Compare` used to return `Bool` (`prelude/PrimOp.lhs`): {{{ getPrimOpResultInfo :: PrimOp -> PrimOpResultInfo getPrimOpResultInfo op = case (primOpInfo op) of Compare _ _ -> ReturnsAlg boolTyCon }}} I changed them to return `Int#`: {{{ getPrimOpResultInfo :: PrimOp -> PrimOpResultInfo getPrimOpResultInfo op = case (primOpInfo op) of Compare _ _ -> ReturnsPrim (tyConPrimRep intPrimTyCon) }}} This is how primops are converted from Core to STG (`CoreToStg.lhs`, `coreToStgApp` function): {{{ res_ty = exprType (mkApps (Var f) args) app = case idDetails f of -- Some primitive operator that might be implemented as a library call. PrimOpId op -> ASSERT( saturated ) StgOpApp (StgPrimOp op) args' res_ty }}} Previously `res_ty` was set to `Bool`, now it is `Int#`. STG representation of a primop is converted to Cmm (`StgCmmExpr.hs`) by `cgExpr` function: {{{ cgExpr (StgOpApp op args ty) = cgOpApp op args ty }}} So previously `cgOpApp` function matched this guard: {{{ | ReturnsAlg tycon <- result_info , isEnumerationTyCon tycon -- c.f. cgExpr (...TagToEnumOp...) = do dflags <- getDynFlags tag_reg <- newTemp (bWord dflags) cgPrimOp [tag_reg] primop args emitReturn [tagToClosure dflags tycon (CmmReg (CmmLocal tag_reg))] }}} and now it matches this one: {{{ | ReturnsPrim rep <- result_info = do dflags <- getDynFlags res <- newTemp (primRepCmmType dflags rep) cgPrimOp [res] primop args emitReturn [CmmReg (CmmLocal res)] }}} The main difference being that there is no call to `tagToClosure`, which was the goal of this ticket - to return an unboxed unlifted value instead of a closure that needs to be entered or have its tag examined. This leads me to a conclusion: since `tagToClosure` is an implementation of `tagToEnum#` primop, there should be no performance difference between the previous version of code, where call to `tagToEnum#` was generated implicitly by the code generator, and the new primop wrappers, which make the call to `tagToEnum#` explicit. In theory at least, because kahan for some reason is slower. I'm investigating this but so far I found nothing that would be obvious. And I'm also working on identifying code that is no longer necessary. One thing that keeps me puzzled is that there are still primops that return `Bool`, e.g. {{{ primop SameMutVarOp "sameMutVar#" GenPrimOp MutVar# s a -> MutVar# s a -> Bool }}} I'm not sure if this allows me to remove special case that Simon M. mentioned. -- Ticket URL: http://hackage.haskell.org/trac/ghc/ticket/6135#comment:68 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler