moduleCmmMachOp(MachOp (..),pprMachOp ,isCommutableMachOp ,isAssociativeMachOp ,isComparisonMachOp ,maybeIntComparison ,machOpResultType ,machOpArgReps ,maybeInvertComparison ,isFloatComparison -- MachOp builders,mo_wordAdd ,mo_wordSub ,mo_wordEq ,mo_wordNe ,mo_wordMul ,mo_wordSQuot ,mo_wordSRem ,mo_wordSNeg ,mo_wordUQuot ,mo_wordURem ,mo_wordSGe ,mo_wordSLe ,mo_wordSGt ,mo_wordSLt ,mo_wordUGe ,mo_wordULe ,mo_wordUGt ,mo_wordULt ,mo_wordAnd ,mo_wordOr ,mo_wordXor ,mo_wordNot ,mo_wordShl ,mo_wordSShr ,mo_wordUShr ,mo_u_8To32 ,mo_s_8To32 ,mo_u_16To32 ,mo_s_16To32 ,mo_u_8ToWord ,mo_s_8ToWord ,mo_u_16ToWord ,mo_s_16ToWord ,mo_u_32ToWord ,mo_s_32ToWord ,mo_32To8 ,mo_32To16 ,mo_WordTo8 ,mo_WordTo16 ,mo_WordTo32 ,mo_WordTo64 -- CallishMachOp,CallishMachOp (..),callishMachOpHints ,pprCallishMachOp ,machOpMemcpyishAlign -- Atomic read-modify-write,AtomicMachOp (..))whereimportGhcPreludeimportCmmTypeimportOutputableimportDynFlags------------------------------------------------------------------------------- MachOp-----------------------------------------------------------------------------{- |
Machine-level primops; ones which we can reasonably delegate to the
native code generators to handle.
Most operations are parameterised by the 'Width' that they operate on.
Some operations have separate signed and unsigned versions, and float
and integer versions.
-}dataMachOp -- Integer operations (insensitive to signed/unsigned)=MO_Add Width|MO_Sub Width|MO_Eq Width|MO_Ne Width|MO_Mul Width-- low word of multiply-- Signed multiply/divide|MO_S_MulMayOflo Width-- nonzero if signed multiply overflows|MO_S_Quot Width-- signed / (same semantics as IntQuotOp)|MO_S_Rem Width-- signed % (same semantics as IntRemOp)|MO_S_Neg Width-- unary --- Unsigned multiply/divide|MO_U_MulMayOflo Width-- nonzero if unsigned multiply overflows|MO_U_Quot Width-- unsigned / (same semantics as WordQuotOp)|MO_U_Rem Width-- unsigned % (same semantics as WordRemOp)-- Signed comparisons|MO_S_Ge Width|MO_S_Le Width|MO_S_Gt Width|MO_S_Lt Width-- Unsigned comparisons|MO_U_Ge Width|MO_U_Le Width|MO_U_Gt Width|MO_U_Lt Width-- Floating point arithmetic|MO_F_Add Width|MO_F_Sub Width|MO_F_Neg Width-- unary -|MO_F_Mul Width|MO_F_Quot Width-- Floating point comparison|MO_F_Eq Width|MO_F_Ne Width|MO_F_Ge Width|MO_F_Le Width|MO_F_Gt Width|MO_F_Lt Width-- Bitwise operations. Not all of these may be supported-- at all sizes, and only integral Widths are valid.|MO_And Width|MO_Or Width|MO_Xor Width|MO_Not Width|MO_Shl Width|MO_U_Shr Width-- unsigned shift right|MO_S_Shr Width-- signed shift right-- Conversions. Some of these will be NOPs.-- Floating-point conversions use the signed variant.|MO_SF_Conv WidthWidth-- Signed int -> Float|MO_FS_Conv WidthWidth-- Float -> Signed int|MO_SS_Conv WidthWidth-- Signed int -> Signed int|MO_UU_Conv WidthWidth-- unsigned int -> unsigned int|MO_XX_Conv WidthWidth-- int -> int; puts no requirements on the-- contents of upper bits when extending;-- narrowing is simply truncation; the only-- expectation is that we can recover the-- original value by applying the opposite-- MO_XX_Conv, e.g.,-- MO_XX_CONV W64 W8 (MO_XX_CONV W8 W64 x)-- is equivalent to just x.|MO_FF_Conv WidthWidth-- Float -> Float-- Vector element insertion and extraction operations|MO_V_Insert LengthWidth-- Insert scalar into vector|MO_V_Extract LengthWidth-- Extract scalar from vector-- Integer vector operations|MO_V_Add LengthWidth|MO_V_Sub LengthWidth|MO_V_Mul LengthWidth-- Signed vector multiply/divide|MO_VS_Quot LengthWidth|MO_VS_Rem LengthWidth|MO_VS_Neg LengthWidth-- Unsigned vector multiply/divide|MO_VU_Quot LengthWidth|MO_VU_Rem LengthWidth-- Floting point vector element insertion and extraction operations|MO_VF_Insert LengthWidth-- Insert scalar into vector|MO_VF_Extract LengthWidth-- Extract scalar from vector-- Floating point vector operations|MO_VF_Add LengthWidth|MO_VF_Sub LengthWidth|MO_VF_Neg LengthWidth-- unary negation|MO_VF_Mul LengthWidth|MO_VF_Quot LengthWidth-- Alignment check (for -falignment-sanitisation)|MO_AlignmentCheck IntWidthderiving(Eq,Show)pprMachOp::MachOp ->SDocpprMachOp mo =text(showmo )-- ------------------------------------------------------------------------------- Some common MachReps-- A 'wordRep' is a machine word on the target architecture-- Specifically, it is the size of an Int#, Word#, Addr#-- and the unit of allocation on the stack and the heap-- Any pointer is also guaranteed to be a wordRep.mo_wordAdd,mo_wordSub,mo_wordEq,mo_wordNe,mo_wordMul,mo_wordSQuot,mo_wordSRem,mo_wordSNeg,mo_wordUQuot,mo_wordURem,mo_wordSGe,mo_wordSLe,mo_wordSGt,mo_wordSLt,mo_wordUGe,mo_wordULe,mo_wordUGt,mo_wordULt,mo_wordAnd,mo_wordOr,mo_wordXor,mo_wordNot,mo_wordShl,mo_wordSShr,mo_wordUShr,mo_u_8ToWord,mo_s_8ToWord,mo_u_16ToWord,mo_s_16ToWord,mo_u_32ToWord,mo_s_32ToWord,mo_WordTo8,mo_WordTo16,mo_WordTo32,mo_WordTo64::DynFlags->MachOp mo_u_8To32,mo_s_8To32,mo_u_16To32,mo_s_16To32,mo_32To8,mo_32To16::MachOp mo_wordAdd dflags =MO_Add (wordWidthdflags )mo_wordSub dflags =MO_Sub (wordWidthdflags )mo_wordEq dflags =MO_Eq (wordWidthdflags )mo_wordNe dflags =MO_Ne (wordWidthdflags )mo_wordMul dflags =MO_Mul (wordWidthdflags )mo_wordSQuot dflags =MO_S_Quot (wordWidthdflags )mo_wordSRem dflags =MO_S_Rem (wordWidthdflags )mo_wordSNeg dflags =MO_S_Neg (wordWidthdflags )mo_wordUQuot dflags =MO_U_Quot (wordWidthdflags )mo_wordURem dflags =MO_U_Rem (wordWidthdflags )mo_wordSGe dflags =MO_S_Ge (wordWidthdflags )mo_wordSLe dflags =MO_S_Le (wordWidthdflags )mo_wordSGt dflags =MO_S_Gt (wordWidthdflags )mo_wordSLt dflags =MO_S_Lt (wordWidthdflags )mo_wordUGe dflags =MO_U_Ge (wordWidthdflags )mo_wordULe dflags =MO_U_Le (wordWidthdflags )mo_wordUGt dflags =MO_U_Gt (wordWidthdflags )mo_wordULt dflags =MO_U_Lt (wordWidthdflags )mo_wordAnd dflags =MO_And (wordWidthdflags )mo_wordOr dflags =MO_Or (wordWidthdflags )mo_wordXor dflags =MO_Xor (wordWidthdflags )mo_wordNot dflags =MO_Not (wordWidthdflags )mo_wordShl dflags =MO_Shl (wordWidthdflags )mo_wordSShr dflags =MO_S_Shr (wordWidthdflags )mo_wordUShr dflags =MO_U_Shr (wordWidthdflags )mo_u_8To32 =MO_UU_Conv W8W32mo_s_8To32 =MO_SS_Conv W8W32mo_u_16To32 =MO_UU_Conv W16W32mo_s_16To32 =MO_SS_Conv W16W32mo_u_8ToWord dflags =MO_UU_Conv W8(wordWidthdflags )mo_s_8ToWord dflags =MO_SS_Conv W8(wordWidthdflags )mo_u_16ToWord dflags =MO_UU_Conv W16(wordWidthdflags )mo_s_16ToWord dflags =MO_SS_Conv W16(wordWidthdflags )mo_s_32ToWord dflags =MO_SS_Conv W32(wordWidthdflags )mo_u_32ToWord dflags =MO_UU_Conv W32(wordWidthdflags )mo_WordTo8 dflags =MO_UU_Conv (wordWidthdflags )W8mo_WordTo16 dflags =MO_UU_Conv (wordWidthdflags )W16mo_WordTo32 dflags =MO_UU_Conv (wordWidthdflags )W32mo_WordTo64 dflags =MO_UU_Conv (wordWidthdflags )W64mo_32To8 =MO_UU_Conv W32W8mo_32To16 =MO_UU_Conv W32W16-- ------------------------------------------------------------------------------ isCommutableMachOp{- |
Returns 'True' if the MachOp has commutable arguments. This is used
in the platform-independent Cmm optimisations.
If in doubt, return 'False'. This generates worse code on the
native routes, but is otherwise harmless.
-}isCommutableMachOp::MachOp ->BoolisCommutableMachOp mop =casemop ofMO_Add _->TrueMO_Eq _->TrueMO_Ne _->TrueMO_Mul _->TrueMO_S_MulMayOflo _->TrueMO_U_MulMayOflo _->TrueMO_And _->TrueMO_Or _->TrueMO_Xor _->TrueMO_F_Add _->TrueMO_F_Mul _->True_other ->False-- ------------------------------------------------------------------------------ isAssociativeMachOp{- |
Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
This is used in the platform-independent Cmm optimisations.
If in doubt, return 'False'. This generates worse code on the
native routes, but is otherwise harmless.
-}isAssociativeMachOp::MachOp ->BoolisAssociativeMachOp mop =casemop ofMO_Add {}->True-- NB: does not includeMO_Mul {}->True-- floatint point!MO_And {}->TrueMO_Or {}->TrueMO_Xor {}->True_other ->False-- ------------------------------------------------------------------------------ isComparisonMachOp{- |
Returns 'True' if the MachOp is a comparison.
If in doubt, return False. This generates worse code on the
native routes, but is otherwise harmless.
-}isComparisonMachOp::MachOp ->BoolisComparisonMachOp mop =casemop ofMO_Eq _->TrueMO_Ne _->TrueMO_S_Ge _->TrueMO_S_Le _->TrueMO_S_Gt _->TrueMO_S_Lt _->TrueMO_U_Ge _->TrueMO_U_Le _->TrueMO_U_Gt _->TrueMO_U_Lt _->TrueMO_F_Eq {}->TrueMO_F_Ne {}->TrueMO_F_Ge {}->TrueMO_F_Le {}->TrueMO_F_Gt {}->TrueMO_F_Lt {}->True_other ->False{- |
Returns @Just w@ if the operation is an integer comparison with width
@w@, or @Nothing@ otherwise.
-}maybeIntComparison::MachOp ->MaybeWidthmaybeIntComparison mop =casemop ofMO_Eq w ->Justw MO_Ne w ->Justw MO_S_Ge w ->Justw MO_S_Le w ->Justw MO_S_Gt w ->Justw MO_S_Lt w ->Justw MO_U_Ge w ->Justw MO_U_Le w ->Justw MO_U_Gt w ->Justw MO_U_Lt w ->Justw _->NothingisFloatComparison::MachOp ->BoolisFloatComparison mop =casemop ofMO_F_Eq {}->TrueMO_F_Ne {}->TrueMO_F_Ge {}->TrueMO_F_Le {}->TrueMO_F_Gt {}->TrueMO_F_Lt {}->True_other ->False-- ------------------------------------------------------------------------------- Inverting conditions-- Sometimes it's useful to be able to invert the sense of a-- condition. Not all conditional tests are invertible: in-- particular, floating point conditionals cannot be inverted, because-- there exist floating-point values which return False for both senses-- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).maybeInvertComparison::MachOp ->MaybeMachOp maybeInvertComparison op =caseop of-- None of these Just cases include floating pointMO_Eq r ->Just(MO_Ne r )MO_Ne r ->Just(MO_Eq r )MO_U_Lt r ->Just(MO_U_Ge r )MO_U_Gt r ->Just(MO_U_Le r )MO_U_Le r ->Just(MO_U_Gt r )MO_U_Ge r ->Just(MO_U_Lt r )MO_S_Lt r ->Just(MO_S_Ge r )MO_S_Gt r ->Just(MO_S_Le r )MO_S_Le r ->Just(MO_S_Gt r )MO_S_Ge r ->Just(MO_S_Lt r )_other ->Nothing-- ------------------------------------------------------------------------------ machOpResultType{- |
Returns the MachRep of the result of a MachOp.
-}machOpResultType::DynFlags->MachOp ->[CmmType]->CmmTypemachOpResultType dflags mop tys =casemop ofMO_Add {}->ty1 -- Preserve GC-ptr-hoodMO_Sub {}->ty1 -- of first argMO_Mul r ->cmmBitsr MO_S_MulMayOflo r ->cmmBitsr MO_S_Quot r ->cmmBitsr MO_S_Rem r ->cmmBitsr MO_S_Neg r ->cmmBitsr MO_U_MulMayOflo r ->cmmBitsr MO_U_Quot r ->cmmBitsr MO_U_Rem r ->cmmBitsr MO_Eq {}->comparisonResultRep dflags MO_Ne {}->comparisonResultRep dflags MO_S_Ge {}->comparisonResultRep dflags MO_S_Le {}->comparisonResultRep dflags MO_S_Gt {}->comparisonResultRep dflags MO_S_Lt {}->comparisonResultRep dflags MO_U_Ge {}->comparisonResultRep dflags MO_U_Le {}->comparisonResultRep dflags MO_U_Gt {}->comparisonResultRep dflags MO_U_Lt {}->comparisonResultRep dflags MO_F_Add r ->cmmFloatr MO_F_Sub r ->cmmFloatr MO_F_Mul r ->cmmFloatr MO_F_Quot r ->cmmFloatr MO_F_Neg r ->cmmFloatr MO_F_Eq {}->comparisonResultRep dflags MO_F_Ne {}->comparisonResultRep dflags MO_F_Ge {}->comparisonResultRep dflags MO_F_Le {}->comparisonResultRep dflags MO_F_Gt {}->comparisonResultRep dflags MO_F_Lt {}->comparisonResultRep dflags MO_And {}->ty1 -- Used for pointer maskingMO_Or {}->ty1 MO_Xor {}->ty1 MO_Not r ->cmmBitsr MO_Shl r ->cmmBitsr MO_U_Shr r ->cmmBitsr MO_S_Shr r ->cmmBitsr MO_SS_Conv _to ->cmmBitsto MO_UU_Conv _to ->cmmBitsto MO_XX_Conv _to ->cmmBitsto MO_FS_Conv _to ->cmmBitsto MO_SF_Conv _to ->cmmFloatto MO_FF_Conv _to ->cmmFloatto MO_V_Insert l w ->cmmVecl (cmmBitsw )MO_V_Extract _w ->cmmBitsw MO_V_Add l w ->cmmVecl (cmmBitsw )MO_V_Sub l w ->cmmVecl (cmmBitsw )MO_V_Mul l w ->cmmVecl (cmmBitsw )MO_VS_Quot l w ->cmmVecl (cmmBitsw )MO_VS_Rem l w ->cmmVecl (cmmBitsw )MO_VS_Neg l w ->cmmVecl (cmmBitsw )MO_VU_Quot l w ->cmmVecl (cmmBitsw )MO_VU_Rem l w ->cmmVecl (cmmBitsw )MO_VF_Insert l w ->cmmVecl (cmmFloatw )MO_VF_Extract _w ->cmmFloatw MO_VF_Add l w ->cmmVecl (cmmFloatw )MO_VF_Sub l w ->cmmVecl (cmmFloatw )MO_VF_Mul l w ->cmmVecl (cmmFloatw )MO_VF_Quot l w ->cmmVecl (cmmFloatw )MO_VF_Neg l w ->cmmVecl (cmmFloatw )MO_AlignmentCheck __->ty1 where(ty1 :_)=tys comparisonResultRep::DynFlags->CmmTypecomparisonResultRep =bWord-- is it?-- ------------------------------------------------------------------------------- machOpArgReps-- | This function is used for debugging only: we can check whether an-- application of a MachOp is "type-correct" by checking that the MachReps of-- its arguments are the same as the MachOp expects. This is used when-- linting a CmmExpr.machOpArgReps::DynFlags->MachOp ->[Width]machOpArgReps dflags op =caseop ofMO_Add r ->[r ,r ]MO_Sub r ->[r ,r ]MO_Eq r ->[r ,r ]MO_Ne r ->[r ,r ]MO_Mul r ->[r ,r ]MO_S_MulMayOflo r ->[r ,r ]MO_S_Quot r ->[r ,r ]MO_S_Rem r ->[r ,r ]MO_S_Neg r ->[r ]MO_U_MulMayOflo r ->[r ,r ]MO_U_Quot r ->[r ,r ]MO_U_Rem r ->[r ,r ]MO_S_Ge r ->[r ,r ]MO_S_Le r ->[r ,r ]MO_S_Gt r ->[r ,r ]MO_S_Lt r ->[r ,r ]MO_U_Ge r ->[r ,r ]MO_U_Le r ->[r ,r ]MO_U_Gt r ->[r ,r ]MO_U_Lt r ->[r ,r ]MO_F_Add r ->[r ,r ]MO_F_Sub r ->[r ,r ]MO_F_Mul r ->[r ,r ]MO_F_Quot r ->[r ,r ]MO_F_Neg r ->[r ]MO_F_Eq r ->[r ,r ]MO_F_Ne r ->[r ,r ]MO_F_Ge r ->[r ,r ]MO_F_Le r ->[r ,r ]MO_F_Gt r ->[r ,r ]MO_F_Lt r ->[r ,r ]MO_And r ->[r ,r ]MO_Or r ->[r ,r ]MO_Xor r ->[r ,r ]MO_Not r ->[r ]MO_Shl r ->[r ,wordWidthdflags ]MO_U_Shr r ->[r ,wordWidthdflags ]MO_S_Shr r ->[r ,wordWidthdflags ]MO_SS_Conv from _->[from ]MO_UU_Conv from _->[from ]MO_XX_Conv from _->[from ]MO_SF_Conv from _->[from ]MO_FS_Conv from _->[from ]MO_FF_Conv from _->[from ]MO_V_Insert l r ->[typeWidth(vecl (cmmBitsr )),r ,wordWidthdflags ]MO_V_Extract l r ->[typeWidth(vecl (cmmBitsr )),wordWidthdflags ]MO_V_Add _r ->[r ,r ]MO_V_Sub _r ->[r ,r ]MO_V_Mul _r ->[r ,r ]MO_VS_Quot _r ->[r ,r ]MO_VS_Rem _r ->[r ,r ]MO_VS_Neg _r ->[r ]MO_VU_Quot _r ->[r ,r ]MO_VU_Rem _r ->[r ,r ]MO_VF_Insert l r ->[typeWidth(vecl (cmmFloatr )),r ,wordWidthdflags ]MO_VF_Extract l r ->[typeWidth(vecl (cmmFloatr )),wordWidthdflags ]MO_VF_Add _r ->[r ,r ]MO_VF_Sub _r ->[r ,r ]MO_VF_Mul _r ->[r ,r ]MO_VF_Quot _r ->[r ,r ]MO_VF_Neg _r ->[r ]MO_AlignmentCheck _r ->[r ]------------------------------------------------------------------------------- CallishMachOp------------------------------------------------------------------------------- CallishMachOps tend to be implemented by foreign calls in some backends,-- so we separate them out. In Cmm, these can only occur in a-- statement position, in contrast to an ordinary MachOp which can occur-- anywhere in an expression.dataCallishMachOp =MO_F64_Pwr |MO_F64_Sin |MO_F64_Cos |MO_F64_Tan |MO_F64_Sinh |MO_F64_Cosh |MO_F64_Tanh |MO_F64_Asin |MO_F64_Acos |MO_F64_Atan |MO_F64_Asinh |MO_F64_Acosh |MO_F64_Atanh |MO_F64_Log |MO_F64_Exp |MO_F64_Fabs |MO_F64_Sqrt |MO_F32_Pwr |MO_F32_Sin |MO_F32_Cos |MO_F32_Tan |MO_F32_Sinh |MO_F32_Cosh |MO_F32_Tanh |MO_F32_Asin |MO_F32_Acos |MO_F32_Atan |MO_F32_Asinh |MO_F32_Acosh |MO_F32_Atanh |MO_F32_Log |MO_F32_Exp |MO_F32_Fabs |MO_F32_Sqrt |MO_UF_Conv Width|MO_S_QuotRem Width|MO_U_QuotRem Width|MO_U_QuotRem2 Width|MO_Add2 Width|MO_AddWordC Width|MO_SubWordC Width|MO_AddIntC Width|MO_SubIntC Width|MO_U_Mul2 Width|MO_WriteBarrier |MO_Touch -- Keep variables live (when using interior pointers)-- Prefetch|MO_Prefetch_Data Int-- Prefetch hint. May change program performance but not-- program behavior.-- the Int can be 0-3. Needs to be known at compile time-- to interact with code generation correctly.-- TODO: add support for prefetch WRITES,-- currently only exposes prefetch reads, which-- would the majority of use cases in ghc anyways-- These three MachOps are parameterised by the known alignment-- of the destination and source (for memcpy/memmove) pointers.-- This information may be used for optimisation in backends.|MO_Memcpy Int|MO_Memset Int|MO_Memmove Int|MO_Memcmp Int|MO_PopCnt Width|MO_Pdep Width|MO_Pext Width|MO_Clz Width|MO_Ctz Width|MO_BSwap Width|MO_BRev Width-- Atomic read-modify-write.|MO_AtomicRMW WidthAtomicMachOp |MO_AtomicRead Width|MO_AtomicWrite Width|MO_Cmpxchg Widthderiving(Eq,Show)-- | The operation to perform atomically.dataAtomicMachOp =AMO_Add |AMO_Sub |AMO_And |AMO_Nand |AMO_Or |AMO_Xor deriving(Eq,Show)pprCallishMachOp::CallishMachOp ->SDocpprCallishMachOp mo =text(showmo )callishMachOpHints::CallishMachOp ->([ForeignHint],[ForeignHint])callishMachOpHints op =caseop ofMO_Memcpy _->([],[AddrHint,AddrHint,NoHint])MO_Memset _->([],[AddrHint,NoHint,NoHint])MO_Memmove _->([],[AddrHint,AddrHint,NoHint])MO_Memcmp _->([],[AddrHint,AddrHint,NoHint])_->([],[])-- empty lists indicate NoHint-- | The alignment of a 'memcpy'-ish operation.machOpMemcpyishAlign::CallishMachOp ->MaybeIntmachOpMemcpyishAlign op =caseop ofMO_Memcpy align ->Justalign MO_Memset align ->Justalign MO_Memmove align ->Justalign MO_Memcmp align ->Justalign _->Nothing

AltStyle によって変換されたページ (->オリジナル) /