PrimOp.hs 26 KB
 Austin Seipp committed Dec 03, 2014 1 2 3 {- (c) The GRASP/AQUA Project, Glasgow University, 1992-1998  simonpj committed Jun 08, 1999 4 \section[PrimOp]{Primitive operations (machine-level)}  Austin Seipp committed Dec 03, 2014 5 -}  simonpj committed Jun 08, 1999 6   Herbert Valerio Riedel committed May 15, 2014 7 8 {-# LANGUAGE CPP #-}  Herbert Valerio Riedel committed Apr 10, 2016 9 10 11 -- The default is a bit too low for the quite large primOpInfo definition {-# OPTIONS_GHC -fmax-pmcheck-iterations=10000000 #-}  simonpj committed Jun 08, 1999 12 module PrimOp (  gmainlan@microsoft.com committed Sep 22, 2013 13  PrimOp(..), PrimOpVecCat(..), allThePrimOps,  Ian Lynagh committed Sep 30, 2011 14 15  primOpType, primOpSig, primOpTag, maxPrimOpTag, primOpOcc,  Ben Gamari committed Jun 23, 2019 16  primOpWrapperId,  simonpj committed Jun 08, 1999 17   Ian Lynagh committed Sep 30, 2011 18  tagToEnumKey,  simonpj@microsoft.com committed Aug 16, 2006 19   Simon Marlow committed May 24, 2011 20  primOpOutOfLine, primOpCodeSize,  Simon Peyton Jones committed Jan 12, 2012 21  primOpOkForSpeculation, primOpOkForSideEffects,  Michal Terepeta committed Nov 23, 2012 22  primOpIsCheap, primOpFixity,  simonpj committed Jun 08, 1999 23   Simon Peyton Jones committed Apr 28, 2017 24  getPrimOpResultInfo, isComparisonPrimOp, PrimOpResultInfo(..),  Duncan Coutts committed Jun 09, 2009 25 26  PrimCall(..)  simonpj committed Jun 08, 1999 27 28 29 30  ) where #include "HsVersions.h"  Herbert Valerio Riedel committed Sep 19, 2017 31 32 import GhcPrelude  simonpj committed Jun 08, 1999 33 34 35 import TysPrim import TysWiredIn  gmainlan@microsoft.com committed Sep 22, 2013 36 import CmmType  simonpj@microsoft.com committed Nov 19, 2009 37 import Demand  Ben Gamari committed Jun 23, 2019 38 39 40 41 import Id ( Id, mkVanillaGlobalWithInfo ) import IdInfo ( vanillaIdInfo, setCafInfo, CafInfo(NoCafRefs) ) import Name import PrelNames ( gHC_PRIMOPWRAPPERS )  eir@cis.upenn.edu committed Feb 24, 2016 42 import TyCon ( TyCon, isPrimTyCon, PrimRep(..) )  eir@cis.upenn.edu committed Dec 11, 2015 43 import Type  Richard Eisenberg committed Jan 19, 2017 44 import RepType ( typePrimRep1, tyConPrimRep1 )  Alan Zimmerman committed Dec 07, 2016 45 46 import BasicTypes ( Arity, Fixity(..), FixityDirection(..), Boxity(..), SourceText(..) )  Ben Gamari committed Jun 23, 2019 47 import SrcLoc ( wiredInSrcSpan )  Ian Lynagh committed Sep 30, 2011 48 import ForeignCall ( CLabelString )  Ben Gamari committed Jun 23, 2019 49 import Unique ( Unique, mkPrimOpIdUnique, mkPrimOpWrapperUnique )  simonpj committed Jun 08, 1999 50 import Outputable  Ian Lynagh committed Mar 29, 2008 51 import FastString  Edward Z. Yang committed Oct 14, 2015 52 import Module ( UnitId )  simonpj committed Jun 08, 1999 53   Austin Seipp committed Dec 03, 2014 54 55 56 {- ************************************************************************ * *  simonpj committed Jun 08, 1999 57 \subsection[PrimOp-datatype]{Datatype for @PrimOp@ (an enumeration)}  Austin Seipp committed Dec 03, 2014 58 59 * * ************************************************************************  simonpj committed Jun 08, 1999 60 61  These are in \tr{state-interface.verb} order.  Austin Seipp committed Dec 03, 2014 62 -}  sewardj committed Aug 07, 2000 63   Ian Lynagh committed Sep 30, 2011 64 -- supplies:  sewardj committed Aug 07, 2000 65 -- data PrimOp = ...  sewardj committed Aug 08, 2000 66 #include "primop-data-decl.hs-incl"  simonpj committed Jun 08, 1999 67   Ian Lynagh committed Sep 30, 2011 68 -- supplies  thomie committed Aug 21, 2015 69 -- primOpTag :: PrimOp -> Int  sewardj committed Aug 08, 2000 70 #include "primop-tag.hs-incl"  thomie committed Aug 21, 2015 71 primOpTag _ = error "primOpTag: unknown primop"  simonpj committed Jun 08, 1999 72   sewardj committed Aug 07, 2000 73   simonpj committed Jun 08, 1999 74 instance Eq PrimOp where  thomie committed Aug 21, 2015 75  op1 == op2 = primOpTag op1 == primOpTag op2  simonpj committed Jun 08, 1999 76 77  instance Ord PrimOp where  thomie committed Aug 21, 2015 78 79 80 81  op1 < op2 = primOpTag op1 < primOpTag op2 op1 <= op2 = primOpTag op1 <= primOpTag op2 op1 >= op2 = primOpTag op1 >= primOpTag op2 op1 > op2 = primOpTag op1 > primOpTag op2  simonpj committed Jun 08, 1999 82  op1 compare op2 | op1 < op2 = LT  Ian Lynagh committed Sep 30, 2011 83 84  | op1 == op2 = EQ | otherwise = GT  simonpj committed Jun 08, 1999 85 86 87 88  instance Outputable PrimOp where ppr op = pprPrimOp op  gmainlan@microsoft.com committed Sep 22, 2013 89 90 91 92 data PrimOpVecCat = IntVec | WordVec | FloatVec  Austin Seipp committed Dec 03, 2014 93 -- An @Enum@-derived list would be better; meanwhile... (ToDo)  simonpj committed Oct 09, 2003 94   sewardj committed Aug 07, 2000 95 96 allThePrimOps :: [PrimOp] allThePrimOps =  sewardj committed Aug 08, 2000 97 #include "primop-list.hs-incl"  simonpj committed Jun 08, 1999 98   simonpj@microsoft.com committed Aug 16, 2006 99 100 101 tagToEnumKey :: Unique tagToEnumKey = mkPrimOpIdUnique (primOpTag TagToEnumOp)  Austin Seipp committed Dec 03, 2014 102 103 104 {- ************************************************************************ * *  simonpj committed Jun 08, 1999 105 \subsection[PrimOp-info]{The essential info about each @PrimOp@}  Austin Seipp committed Dec 03, 2014 106 107 * * ************************************************************************  simonpj committed Jun 08, 1999 108 109 110 111 112 113 114 115 116 117  The @String@ in the @PrimOpInfos@ is the base name'' by which the user may refer to the primitive operation. The conventional \tr{#}-for- unboxed ops is added on later. The reason for the funny characters in the names is so we do not interfere with the programmer's Haskell name spaces. We use @PrimKinds@ for the type'' information, because they're (slightly) more convenient to use than @TyCons@.  Austin Seipp committed Dec 03, 2014 118 119 -}  simonpj committed Jun 08, 1999 120 data PrimOpInfo  Ian Lynagh committed Sep 30, 2011 121 122 123 124  = Dyadic OccName -- string :: T -> T -> T Type | Monadic OccName -- string :: T -> T Type  Jan Stolarek committed Aug 14, 2013 125  | Compare OccName -- string :: T -> T -> Int#  Ian Lynagh committed Sep 30, 2011 126 127 128 129 130  Type | GenPrimOp OccName -- string :: \/a1..an . T1 -> .. -> Tk -> T [TyVar] [Type] Type  simonpj committed Jun 08, 1999 131   Ian Lynagh committed Mar 29, 2008 132 mkDyadic, mkMonadic, mkCompare :: FastString -> Type -> PrimOpInfo  simonmar committed Jan 06, 2006 133 134 135 mkDyadic str ty = Dyadic (mkVarOccFS str) ty mkMonadic str ty = Monadic (mkVarOccFS str) ty mkCompare str ty = Compare (mkVarOccFS str) ty  Ian Lynagh committed Mar 29, 2008 136 137  mkGenPrimOp :: FastString -> [TyVar] -> [Type] -> Type -> PrimOpInfo  simonmar committed Jan 06, 2006 138 mkGenPrimOp str tvs tys ty = GenPrimOp (mkVarOccFS str) tvs tys ty  simonpj committed Jun 08, 1999 139   Austin Seipp committed Dec 03, 2014 140 141 142 {- ************************************************************************ * *  simonpj committed Jun 08, 1999 143 \subsubsection{Strictness}  Austin Seipp committed Dec 03, 2014 144 145 * * ************************************************************************  simonpj committed Jun 08, 1999 146 147  Not all primops are strict!  Austin Seipp committed Dec 03, 2014 148 -}  simonpj committed Jun 08, 1999 149   simonmar committed Dec 10, 2001 150 primOpStrictness :: PrimOp -> Arity -> StrictSig  Ian Lynagh committed Sep 30, 2011 151 152 153  -- See Demand.StrictnessInfo for discussion of what the results -- The arity should be the arity of the primop; that's why -- this function isn't exported.  sewardj committed Aug 08, 2000 154 #include "primop-strictness.hs-incl"  simonpj committed Jun 08, 1999 155   Austin Seipp committed Dec 03, 2014 156 157 158 {- ************************************************************************ * *  Michal Terepeta committed Nov 23, 2012 159 \subsubsection{Fixity}  Austin Seipp committed Dec 03, 2014 160 161 162 * * ************************************************************************ -}  Michal Terepeta committed Nov 23, 2012 163 164 165 166  primOpFixity :: PrimOp -> Maybe Fixity #include "primop-fixity.hs-incl"  Austin Seipp committed Dec 03, 2014 167 168 169 {- ************************************************************************ * *  simonpj committed Jun 08, 1999 170 \subsubsection[PrimOp-comparison]{PrimOpInfo basic comparison ops}  Austin Seipp committed Dec 03, 2014 171 172 * * ************************************************************************  simonpj committed Jun 08, 1999 173 174 175  @primOpInfo@ gives all essential information (from which everything else, notably a type, can be constructed) for each @PrimOp@.  Austin Seipp committed Dec 03, 2014 176 -}  simonpj committed Jun 08, 1999 177 178  primOpInfo :: PrimOp -> PrimOpInfo  sewardj committed Aug 08, 2000 179 #include "primop-primop-info.hs-incl"  gmainlan@microsoft.com committed Sep 22, 2013 180 primOpInfo _ = error "primOpInfo: unknown primop"  simonpj committed Jun 08, 1999 181   Austin Seipp committed Dec 03, 2014 182 {-  sewardj committed Aug 07, 2000 183 Here are a load of comments from the old primOp info:  simonpj committed Jun 08, 1999 184 185 186 187 188 189 190 191  A @Word#@ is an unsigned @Int#@. @decodeFloat#@ is given w/ Integer-stuff (it's similar). @decodeDouble#@ is given w/ Integer-stuff (it's similar). Decoding of floating-point numbers is sorta Integer-related. Encoding  rodlogic committed Feb 09, 2015 192 is done with plain ccalls now (see PrelNumExtra.hs).  simonpj committed Jun 08, 1999 193 194 195  A @Weak@ Pointer is created by the @mkWeak#@ primitive:  Ian Lynagh committed Sep 30, 2011 196 197  mkWeak# :: k -> v -> f -> State# RealWorld -> (# State# RealWorld, Weak# v #)  simonpj committed Jun 08, 1999 198 199 200  In practice, you'll use the higher-level  Ian Lynagh committed Sep 30, 2011 201 202  data Weak v = Weak# v mkWeak :: k -> v -> IO () -> IO (Weak v)  simonpj committed Jun 08, 1999 203 204 205 206 207  The following operation dereferences a weak pointer. The weak pointer may have been finalized, so the operation returns a result code which must be inspected before looking at the dereferenced value.  Ian Lynagh committed Sep 30, 2011 208 209  deRefWeak# :: Weak# v -> State# RealWorld -> (# State# RealWorld, v, Int# #)  simonpj committed Jun 08, 1999 210 211 212 213 214  Only look at v if the Int# returned is /= 0 !! The higher-level op is  Ian Lynagh committed Sep 30, 2011 215  deRefWeak :: Weak v -> IO (Maybe v)  simonpj committed Jun 08, 1999 216 217  Weak pointers can be finalized early by using the finalize# operation:  Ian Lynagh committed Sep 30, 2011 218 219 220  finalizeWeak# :: Weak# v -> State# RealWorld -> (# State# RealWorld, Int#, IO () #)  simonpj committed Jun 08, 1999 221 222 223  The Int# returned is either  Ian Lynagh committed Sep 30, 2011 224 225  0 if the weak pointer has already been finalized, or it has no finalizer (the third component is then invalid).  simonpj committed Jun 08, 1999 226   Ian Lynagh committed Sep 30, 2011 227 228  1 if the weak pointer is still alive, with the finalizer returned as the third component.  simonpj committed Jun 08, 1999 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265  A {\em stable name/pointer} is an index into a table of stable name entries. Since the garbage collector is told about stable pointers, it is safe to pass a stable pointer to external systems such as C routines. \begin{verbatim} makeStablePtr# :: a -> State# RealWorld -> (# State# RealWorld, StablePtr# a #) freeStablePtr :: StablePtr# a -> State# RealWorld -> State# RealWorld deRefStablePtr# :: StablePtr# a -> State# RealWorld -> (# State# RealWorld, a #) eqStablePtr# :: StablePtr# a -> StablePtr# a -> Int# \end{verbatim} It may seem a bit surprising that @makeStablePtr#@ is a @IO@ operation since it doesn't (directly) involve IO operations. The reason is that if some optimisation pass decided to duplicate calls to @makeStablePtr#@ and we only pass one of the stable pointers over, a massive space leak can result. Putting it into the IO monad prevents this. (Another reason for putting them in a monad is to ensure correct sequencing wrt the side-effecting @freeStablePtr@ operation.) An important property of stable pointers is that if you call makeStablePtr# twice on the same object you get the same stable pointer back. Note that we can implement @freeStablePtr#@ using @_ccall_@ (and, besides, it's not likely to be used from Haskell) so it's not a primop. Question: Why @RealWorld@ - won't any instance of @_ST@ do the job? [ADR] Stable Names ~~~~~~~~~~~~ A stable name is like a stable pointer, but with three important differences:  Ian Lynagh committed Sep 30, 2011 266 267 268  (a) You can't deRef one to get back to the original object. (b) You can convert one to an Int. (c) You don't need to 'freeStableName'  simonpj committed Jun 08, 1999 269 270 271 272 273 274  The existence of a stable name doesn't guarantee to keep the object it points to alive (unlike a stable pointer), hence (a). Invariants:  Ian Lynagh committed Sep 30, 2011 275 276 277 278 279  (a) makeStableName always returns the same value for a given object (same as stable pointers). (b) if two stable names are equal, it implies that the objects from which they were created were the same.  simonpj committed Jun 08, 1999 280   Ian Lynagh committed Sep 30, 2011 281 282  (c) stableNameToInt always returns the same Int for a given stable name.  simonpj committed Jun 08, 1999 283 284   Krzysztof Gogolewski committed Oct 12, 2013 285 These primops are pretty weird.  simonpj committed Jun 08, 1999 286   Ian Lynagh committed Sep 30, 2011 287  tagToEnum# :: Int -> a (result type must be an enumerated type)  simonpj committed Jun 08, 1999 288 289 290 291  The constraints aren't currently checked by the front end, but the code generator will fall over if they aren't satisfied.  Austin Seipp committed Dec 03, 2014 292 293 ************************************************************************ * *  Simon Peyton Jones committed Dec 12, 2011 294  Which PrimOps are out-of-line  Austin Seipp committed Dec 03, 2014 295 296 * * ************************************************************************  simonpj committed Jun 08, 1999 297 298 299  Some PrimOps need to be called out-of-line because they either need to perform a heap check or they block.  Austin Seipp committed Dec 03, 2014 300 -}  simonpj committed Jun 08, 1999 301   apt committed Aug 17, 2001 302 primOpOutOfLine :: PrimOp -> Bool  sewardj committed Aug 08, 2000 303 #include "primop-out-of-line.hs-incl"  simonpj committed Aug 24, 1999 304   Austin Seipp committed Dec 03, 2014 305 306 307 {- ************************************************************************ * *  Simon Peyton Jones committed Dec 12, 2011 308  Failure and side effects  Austin Seipp committed Dec 03, 2014 309 310 * * ************************************************************************  Simon Peyton Jones committed Dec 12, 2011 311   Ben Gamari committed Jun 14, 2019 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 Note [Checking versus non-checking primops] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In GHC primops break down into two classes: a. Checking primops behave, for instance, like division. In this case the primop may throw an exception (e.g. division-by-zero) and is consequently is marked with the can_fail flag described below. The ability to fail comes at the expense of precluding some optimizations. b. Non-checking primops behavior, for instance, like addition. While addition can overflow it does not produce an exception. So can_fail is set to False, and we get more optimisation opportunities. But we must never throw an exception, so we cannot rewrite to a call to error. It is important that a non-checking primop never be transformed in a way that would cause it to bottom. Doing so would violate Core's let/app invariant (see Note [CoreSyn let/app invariant] in CoreSyn) which is critical to the simplifier's ability to float without fear of changing program meaning.  Simon Peyton Jones committed Dec 12, 2011 333 334 Note [PrimOp can_fail and has_side_effects] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  Simon Peyton Jones committed Jan 12, 2012 335 336 337 Both can_fail and has_side_effects mean that the primop has some effect that is not captured entirely by its result value.  Simon Peyton Jones committed Aug 07, 2014 338 339 340 341 342 343 344 345 346 347 348 349 350 351 ---------- has_side_effects --------------------- A primop "has_side_effects" if it has some *write* effect, visible elsewhere - writing to the world (I/O) - writing to a mutable data structure (writeIORef) - throwing a synchronous Haskell exception Often such primops have a type like State -> input -> (State, output) so the state token guarantees ordering. In general we rely *only* on data dependencies of the state token to enforce write-effect ordering * NB1: if you inline unsafePerformIO, you may end up with side-effecting ops whose 'state' output is discarded.  Ryan Scott committed Mar 15, 2019 352  And programmers may do that by hand; see #9390.  Simon Peyton Jones committed Aug 07, 2014 353 354 355 356 357 358 359 360 361 362  That is why we (conservatively) do not discard write-effecting primops even if both their state and result is discarded. * NB2: We consider primops, such as raiseIO#, that can raise a (Haskell) synchronous exception to "have_side_effects" but not "can_fail". We must be careful about not discarding such things; see the paper "A semantics for imprecise exceptions". * NB3: *Read* effects (like reading an IORef) don't count here, because it doesn't matter if we don't do them, or do them more than  Gabor Greif committed Aug 07, 2014 363  once. *Sequencing* is maintained by the data dependency of the state  Simon Peyton Jones committed Aug 07, 2014 364 365 366  token. ---------- can_fail ----------------------------  Gabor Greif committed Aug 07, 2014 367 A primop "can_fail" if it can fail with an *unchecked* exception on  Simon Peyton Jones committed Aug 07, 2014 368 some elements of its input domain. Main examples:  Gabor Greif committed Aug 07, 2014 369  division (fails on zero demoninator)  Simon Peyton Jones committed Aug 07, 2014 370 371  array indexing (fails if the index is out of bounds)  Gabor Greif committed Aug 07, 2014 372 373 An "unchecked exception" is one that is an outright error, (not turned into a Haskell exception,) such as seg-fault or  Simon Peyton Jones committed Aug 07, 2014 374 375 divide-by-zero error. Such can_fail primops are ALWAYS surrounded with a test that checks for the bad cases, but we need to be  Gabor Greif committed Aug 07, 2014 376 very careful about code motion that might move it out of  Simon Peyton Jones committed Aug 07, 2014 377 378 379 380 381 382 383 384 the scope of the test. Note [Transformations affected by can_fail and has_side_effects] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The can_fail and has_side_effects properties have the following effect on program transformations. Summary table is followed by details. can_fail has_side_effects  Vladislav Zavialov committed Feb 01, 2017 385 Discard YES NO  Simon Peyton Jones committed Aug 07, 2014 386 387 388 389 390 391 392 393 394 395 Float in YES YES Float out NO NO Duplicate YES NO * Discarding. case (a op b) of _ -> rhs ===> rhs You should not discard a has_side_effects primop; e.g. case (writeIntArray# a i v s of (# _, _ #) -> True Arguably you should be able to discard this, since the returned stat token is not used, but that relies on NEVER inlining unsafePerformIO, and programmers sometimes write  Ryan Scott committed Mar 15, 2019 396  this kind of stuff by hand (#9390). So we (conservatively)  Simon Peyton Jones committed Aug 07, 2014 397 398 399 400 401  never discard a has_side_effects primop. However, it's fine to discard a can_fail primop. For example case (indexIntArray# a i) of _ -> True We can discard indexIntArray#; it has can_fail, but not  Ryan Scott committed Mar 15, 2019 402  has_side_effects; see #5658 which was all about this.  Simon Peyton Jones committed Aug 07, 2014 403 404 405 406 407 408 409 410 411 412  Notice that indexIntArray# is (in a more general handling of effects) read effect, but we don't care about that here, and treat read effects as *not* has_side_effects. Similarly (a /# b) can be discarded. It can seg-fault or cause a hardware exception, but not a synchronous Haskell exception.  Gabor Greif committed Aug 07, 2014 413  Synchronous Haskell exceptions, e.g. from raiseIO#, are treated  Simon Peyton Jones committed Aug 07, 2014 414 415 416 417 418 419 420  as has_side_effects and hence are not discarded. * Float in. You can float a can_fail or has_side_effects primop *inwards*, but not inside a lambda (see Duplication below). * Float out. You must not float a can_fail primop *outwards* lest you escape the dynamic scope of the test. Example:  Simon Peyton Jones committed Jan 12, 2012 421 422 423 424 425 426 427 428 429  case d ># 0# of True -> case x /# d of r -> r +# 1 False -> 0 Here we must not float the case outwards to give case x/# d of r -> case d ># 0# of True -> r +# 1 False -> 0  Simon Peyton Jones committed Aug 07, 2014 430 431  Nor can you float out a has_side_effects primop. For example: if blah then case writeMutVar# v True s0 of (# s1 #) -> s1  Simon Peyton Jones committed Jan 12, 2012 432  else s0  Simon Peyton Jones committed Aug 07, 2014 433  Notice that s0 is mentioned in both branches of the 'if', but  Simon Peyton Jones committed Jan 12, 2012 434 435  only one of these two will actually be consumed. But if we float out to  Simon Peyton Jones committed Aug 07, 2014 436 437  case writeMutVar# v True s0 of (# s1 #) -> if blah then s1 else s0  Simon Peyton Jones committed Jan 12, 2012 438 439 440  the writeMutVar will be performed in both branches, which is utterly wrong.  Simon Peyton Jones committed Aug 07, 2014 441 442 443 444 * Duplication. You cannot duplicate a has_side_effect primop. You might wonder how this can occur given the state token threading, but just look at Control.Monad.ST.Lazy.Imp.strictToLazy! We get something like this  Simon Peyton Jones committed Jan 12, 2012 445 446 447 448 449 450 451  p = case readMutVar# s v of (# s', r #) -> (S# s', r) s' = case p of (s', r) -> s' r = case p of (s', r) -> r (All these bindings are boxed.) If we inline p at its two call sites, we get a catastrophe: because the read is performed once when  Simon Peyton Jones committed Aug 07, 2014 452  s' is demanded, and once when 'r' is demanded, which may be much  Ryan Scott committed Mar 15, 2019 453  later. Utterly wrong. #3207 is real example of this happening.  Simon Peyton Jones committed Jan 12, 2012 454   Simon Peyton Jones committed Aug 07, 2014 455 456  However, it's fine to duplicate a can_fail primop. That is really the only difference between can_fail and has_side_effects.  Simon Peyton Jones committed Jan 12, 2012 457   Gabor Greif committed Aug 07, 2014 458 Note [Implementation: how can_fail/has_side_effects affect transformations]  Simon Peyton Jones committed Aug 07, 2014 459 460 461 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ How do we ensure that that floating/duplication/discarding are done right in the simplifier?  Simon Peyton Jones committed Jan 12, 2012 462   Simon Peyton Jones committed Aug 07, 2014 463 464 465 Two main predicates on primpops test these flags: primOpOkForSideEffects <=> not has_side_effects primOpOkForSpeculation <=> not (has_side_effects || can_fail)  Simon Peyton Jones committed Dec 12, 2011 466   Simon Peyton Jones committed Jan 12, 2012 467 468 469  * The "no-float-out" thing is achieved by ensuring that we never let-bind a can_fail or has_side_effects primop. The RHS of a let-binding (which can float in and out freely) satisfies  Simon Peyton Jones committed Aug 07, 2014 470 471  exprOkForSpeculation; this is the let/app invariant. And exprOkForSpeculation is false of can_fail and has_side_effects.  Simon Peyton Jones committed Dec 12, 2011 472   Simon Peyton Jones committed Aug 07, 2014 473  * So can_fail and has_side_effects primops will appear only as the  Simon Peyton Jones committed Jan 12, 2012 474 475  scrutinees of cases, and that's why the FloatIn pass is capable of floating case bindings inwards.  Simon Peyton Jones committed Dec 12, 2011 476   Simon Peyton Jones committed Jan 12, 2012 477 478  * The no-duplicate thing is done via primOpIsCheap, by making has_side_effects things (very very very) not-cheap!  Austin Seipp committed Dec 03, 2014 479 -}  Simon Peyton Jones committed Dec 12, 2011 480 481 482 483 484 485 486  primOpHasSideEffects :: PrimOp -> Bool #include "primop-has-side-effects.hs-incl" primOpCanFail :: PrimOp -> Bool #include "primop-can-fail.hs-incl"  simonpj committed Jun 08, 1999 487 primOpOkForSpeculation :: PrimOp -> Bool  Simon Peyton Jones committed Aug 07, 2014 488  -- See Note [PrimOp can_fail and has_side_effects]  Simon Peyton Jones committed Dec 12, 2011 489  -- See comments with CoreUtils.exprOkForSpeculation  Simon Peyton Jones committed Aug 07, 2014 490  -- primOpOkForSpeculation => primOpOkForSideEffects  Ian Lynagh committed Sep 30, 2011 491 primOpOkForSpeculation op  Simon Peyton Jones committed Aug 07, 2014 492 493 494  = primOpOkForSideEffects op && not (primOpOutOfLine op || primOpCanFail op) -- I think the "out of line" test is because out of line things can  Gabor Greif committed Aug 07, 2014 495  -- be expensive (eg sine, cosine), and so we may not want to speculate them  Simon Peyton Jones committed Jan 12, 2012 496 497 498 499  primOpOkForSideEffects :: PrimOp -> Bool primOpOkForSideEffects op = not (primOpHasSideEffects op)  Simon Peyton Jones committed Jan 13, 2012 500   Austin Seipp committed Dec 03, 2014 501 {-  Simon Marlow committed Jan 16, 2012 502 503 Note [primOpIsCheap] ~~~~~~~~~~~~~~~~~~~~  rodlogic committed Feb 09, 2015 504 @primOpIsCheap@, as used in \tr{SimplUtils.hs}. For now (HACK  Simon Marlow committed Jan 16, 2012 505 506 507 508 WARNING), we just borrow some other predicates for a what-should-be-good-enough test. "Cheap" means willing to call it more than once, and/or push it inside a lambda. The latter could change the behaviour of 'seq' for primops that can fail, so we don't treat them as cheap.  Austin Seipp committed Dec 03, 2014 509 -}  Simon Marlow committed Jan 16, 2012 510 511  primOpIsCheap :: PrimOp -> Bool  Simon Peyton Jones committed Aug 07, 2014 512 -- See Note [PrimOp can_fail and has_side_effects]  Simon Marlow committed Jan 16, 2012 513 primOpIsCheap op = primOpOkForSpeculation op  Ian Lynagh committed Sep 30, 2011 514 515 -- In March 2001, we changed this to -- primOpIsCheap op = False  simonpj committed Apr 27, 2004 516 -- thereby making *no* primops seem cheap. But this killed eta  Ian Lynagh committed Sep 30, 2011 517 -- expansion on case (x ==# y) of True -> \s -> ...  simonpj committed Apr 27, 2004 518 -- which is bad. In particular a loop like  Ian Lynagh committed Sep 30, 2011 519 -- doLoop n = loop 0  simonpj committed Apr 27, 2004 520 521 522 523 -- where -- loop i | i == n = return () -- | otherwise = bar i >> loop (i+1) -- allocated a closure every time round because it doesn't eta expand.  Ian Lynagh committed Sep 30, 2011 524 --  simonpj committed Apr 27, 2004 525 -- The problem that originally gave rise to the change was  Ian Lynagh committed Sep 30, 2011 526 -- let x = a +# b *# c in x +# x  simonpj committed Apr 27, 2004 527 528 529 -- were we don't want to inline x. But primopIsCheap doesn't control -- that (it's exprIsDupable that does) so the problem doesn't occur -- even if primOpIsCheap sometimes says 'True'.  Simon Peyton Jones committed Dec 12, 2011 530   Austin Seipp committed Dec 03, 2014 531 532 533 {- ************************************************************************ * *  Simon Peyton Jones committed Dec 12, 2011 534  PrimOp code size  Austin Seipp committed Dec 03, 2014 535 536 * * ************************************************************************  Simon Peyton Jones committed Dec 12, 2011 537   Simon Marlow committed May 24, 2011 538 539 540 541 primOpCodeSize ~~~~~~~~~~~~~~ Gives an indication of the code size of a primop, for the purposes of calculating unfolding sizes; see CoreUnfold.sizeExpr.  Austin Seipp committed Dec 03, 2014 542 -}  simonpj committed Jun 08, 1999 543   Simon Marlow committed May 24, 2011 544 545 546 547 548 549 550 primOpCodeSize :: PrimOp -> Int #include "primop-code-size.hs-incl" primOpCodeSizeDefault :: Int primOpCodeSizeDefault = 1 -- CoreUnfold.primOpSize already takes into account primOpOutOfLine -- and adds some further costs for the args in that case.  simonpj committed Jun 08, 1999 551   Simon Marlow committed May 24, 2011 552 553 primOpCodeSizeForeignCall :: Int primOpCodeSizeForeignCall = 4  Simon Marlow committed May 15, 2009 554   Austin Seipp committed Dec 03, 2014 555 556 557 {- ************************************************************************ * *  Simon Peyton Jones committed Dec 12, 2011 558  PrimOp types  Austin Seipp committed Dec 03, 2014 559 560 561 * * ************************************************************************ -}  simonpj committed Jun 08, 1999 562 563 564  primOpType :: PrimOp -> Type -- you may want to use primOpSig instead primOpType op  Ian Lynagh committed Mar 29, 2008 565 566 567 568  = case primOpInfo op of Dyadic _occ ty -> dyadic_fun_ty ty Monadic _occ ty -> monadic_fun_ty ty Compare _occ ty -> compare_fun_ty ty  simonpj committed Jun 08, 1999 569   Ian Lynagh committed Sep 30, 2011 570  GenPrimOp _occ tyvars arg_tys res_ty ->  Simon Peyton Jones committed Feb 23, 2019 571  mkSpecForAllTys tyvars (mkVisFunTys arg_tys res_ty)  simonpj committed Jun 08, 1999 572 573  primOpOcc :: PrimOp -> OccName  Ian Lynagh committed Mar 29, 2008 574 575 576 577 578 primOpOcc op = case primOpInfo op of Dyadic occ _ -> occ Monadic occ _ -> occ Compare occ _ -> occ GenPrimOp occ _ _ _ -> occ  simonpj committed Jun 08, 1999 579   Ben Gamari committed Jun 23, 2019 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 {- Note [Primop wrappers] ~~~~~~~~~~~~~~~~~~~~~~~~~ Previously hasNoBinding would claim that PrimOpIds didn't have a curried function definition. This caused quite some trouble as we would be forced to eta expand unsaturated primop applications very late in the Core pipeline. Not only would this produce unnecessary thunks, but it would also result in nasty inconsistencies in CAFfy-ness determinations (see #16846 and Note [CAFfyness inconsistencies due to late eta expansion] in TidyPgm). However, it was quite unnecessary for hasNoBinding to claim this; primops in fact *do* have curried definitions which are found in GHC.PrimopWrappers, which is auto-generated by utils/genprimops from prelude/primops.txt.pp. These wrappers are standard Haskell functions mirroring the types of the primops they wrap. For instance, in the case of plusInt# we would have: module GHC.PrimopWrappers where import GHC.Prim as P plusInt# a b = P.plusInt# a b We now take advantage of these curried definitions by letting hasNoBinding claim that PrimOpIds have a curried definition and then rewrite any unsaturated PrimOpId applications that we find during CoreToStg as applications of the associated wrapper (e.g. GHC.Prim.plusInt# 3# will get rewritten to GHC.PrimopWrappers.plusInt# 3#). The Id of the wrapper for a primop can be found using 'PrimOp.primOpWrapperId'. Nota Bene: GHC.PrimopWrappers is needed *regardless*, because it's used by GHCi, which does not implement primops direct at all. -} -- | Returns the 'Id' of the wrapper associated with the given 'PrimOp'. -- See Note [Primop wrappers]. primOpWrapperId :: PrimOp -> Id primOpWrapperId op = mkVanillaGlobalWithInfo name ty info where info = setCafInfo vanillaIdInfo NoCafRefs name = mkExternalName uniq gHC_PRIMOPWRAPPERS (primOpOcc op) wiredInSrcSpan uniq = mkPrimOpWrapperUnique (primOpTag op) ty = primOpType op  Simon Peyton Jones committed Apr 28, 2017 621 622 623 624 625 isComparisonPrimOp :: PrimOp -> Bool isComparisonPrimOp op = case primOpInfo op of Compare {} -> True _ -> False  simonpj committed Jun 08, 1999 626 627 -- primOpSig is like primOpType but gives the result split apart: -- (type variables, argument types, result type)  simonpj committed Mar 23, 2000 628 -- It also gives arity, strictness info  simonpj committed Jun 08, 1999 629   simonmar committed Dec 10, 2001 630 primOpSig :: PrimOp -> ([TyVar], [Type], Type, Arity, StrictSig)  simonpj committed Jun 08, 1999 631 primOpSig op  sewardj committed Aug 07, 2000 632  = (tyvars, arg_tys, res_ty, arity, primOpStrictness op arity)  simonpj committed Mar 23, 2000 633 634 635 636  where arity = length arg_tys (tyvars, arg_tys, res_ty) = case (primOpInfo op) of  Jan Stolarek committed Aug 14, 2013 637 638 639 640  Monadic _occ ty -> ([], [ty], ty ) Dyadic _occ ty -> ([], [ty,ty], ty ) Compare _occ ty -> ([], [ty,ty], intPrimTy) GenPrimOp _occ tyvars arg_tys res_ty -> (tyvars, arg_tys, res_ty )  simonpj committed Jun 08, 1999 641 642  data PrimOpResultInfo  Ian Lynagh committed Sep 30, 2011 643 644  = ReturnsPrim PrimRep | ReturnsAlg TyCon  simonpj committed Jun 08, 1999 645 646 647 648 649 650 651 652  -- Some PrimOps need not return a manifest primitive or algebraic value -- (i.e. they might return a polymorphic value). These PrimOps *must* -- be out of line, or the code generator won't work. getPrimOpResultInfo :: PrimOp -> PrimOpResultInfo getPrimOpResultInfo op = case (primOpInfo op) of  Richard Eisenberg committed Jan 19, 2017 653 654 655 656  Dyadic _ ty -> ReturnsPrim (typePrimRep1 ty) Monadic _ ty -> ReturnsPrim (typePrimRep1 ty) Compare _ _ -> ReturnsPrim (tyConPrimRep1 intPrimTyCon) GenPrimOp _ _ _ ty | isPrimTyCon tc -> ReturnsPrim (tyConPrimRep1 tc)  Ian Lynagh committed Sep 30, 2011 657 658 659 660  | otherwise -> ReturnsAlg tc where tc = tyConAppTyCon ty -- All primops return a tycon-app result  Ömer Sinan Ağacan committed Jul 21, 2016 661 662  -- The tycon can be an unboxed tuple or sum, though, -- which gives rise to a ReturnAlg  simonpj committed Jun 08, 1999 663   Austin Seipp committed Dec 03, 2014 664 {-  Ian Lynagh committed Oct 03, 2011 665 666 667 668 We do not currently make use of whether primops are commutable. We used to try to move constants to the right hand side for strength reduction.  Austin Seipp committed Dec 03, 2014 669 -}  simonpj committed Jun 08, 1999 670   Ian Lynagh committed Oct 03, 2011 671 {-  simonpj committed Jun 08, 1999 672 commutableOp :: PrimOp -> Bool  sewardj committed Aug 08, 2000 673 #include "primop-commutable.hs-incl"  Ian Lynagh committed Oct 03, 2011 674 -}  simonpj committed Jun 08, 1999 675   Austin Seipp committed Dec 03, 2014 676 677 -- Utils:  Ian Lynagh committed Mar 29, 2008 678 dyadic_fun_ty, monadic_fun_ty, compare_fun_ty :: Type -> Type  Simon Peyton Jones committed Feb 23, 2019 679 680 681 dyadic_fun_ty ty = mkVisFunTys [ty, ty] ty monadic_fun_ty ty = mkVisFunTy ty ty compare_fun_ty ty = mkVisFunTys [ty, ty] intPrimTy  simonpj committed Jun 08, 1999 682   Austin Seipp committed Dec 03, 2014 683 684 -- Output stuff:  simonpj committed Jun 08, 1999 685 pprPrimOp :: PrimOp -> SDoc  simonmar committed Mar 05, 2002 686 pprPrimOp other_op = pprOccName (primOpOcc other_op)  Duncan Coutts committed Jun 09, 2009 687   Austin Seipp committed Dec 03, 2014 688 689 690 {- ************************************************************************ * *  Duncan Coutts committed Jun 09, 2009 691 \subsubsection[PrimCall]{User-imported primitive calls}  Austin Seipp committed Dec 03, 2014 692 693 694 * * ************************************************************************ -}  Duncan Coutts committed Jun 09, 2009 695   Edward Z. Yang committed Oct 14, 2015 696 data PrimCall = PrimCall CLabelString UnitId  Duncan Coutts committed Jun 09, 2009 697 698  instance Outputable PrimCall where  Ian Lynagh committed Sep 30, 2011 699 700  ppr (PrimCall lbl pkgId) = text "__primcall" <+> ppr pkgId <+> ppr lbl`