[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 5 commits: base: specify tie-breaking behavior of min, max, and related list/Foldable functions
Marge Bot (@marge-bot)
gitlab at gitlab.haskell.org
Fri May 24 02:29:01 UTC 2024
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
a3e0b68b by Ryan Hendrickson at 2024-05-23T15:52:03-04:00
base: specify tie-breaking behavior of min, max, and related list/Foldable functions
- - - - -
4f28fc33 by doyougnu at 2024-05-23T22:28:33-04:00
cmm: add word <-> double/float bitcast
- closes: #25331
This is the last step in the project plan described in #25331. This
commit:
- adds bitcast operands for x86_64, LLVM, aarch64
- For PPC and i386 we resort to using the cmm implementations
- renames conversion MachOps from Conv to Round|Truncate
- - - - -
b826064a by Cheng Shao at 2024-05-23T22:28:36-04:00
hadrian: build cbits with -ffunction-sections -fdata-sections when split sections is enabled
-------------------------
Metric Decrease:
size_hello_artifact
size_hello_unicode
-------------------------
- - - - -
5d6653b3 by Cheng Shao at 2024-05-23T22:28:36-04:00
driver: build .hc with -ffunction-sections -fdata-sections when split sections is enabled
- - - - -
dcd64e4c by crumbtoo at 2024-05-23T22:28:39-04:00
user_guide: Fix typo in MultiWayIf chapter
Close #24829
- - - - -
27 changed files:
- compiler/GHC/Cmm/MachOp.hs
- compiler/GHC/Cmm/Opt.hs
- compiler/GHC/Cmm/Parser.y
- compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
- compiler/GHC/CmmToAsm/AArch64/Instr.hs
- compiler/GHC/CmmToAsm/AArch64/Ppr.hs
- compiler/GHC/CmmToAsm/PPC/CodeGen.hs
- compiler/GHC/CmmToAsm/Wasm/FromCmm.hs
- compiler/GHC/CmmToAsm/X86/CodeGen.hs
- compiler/GHC/CmmToAsm/X86/Instr.hs
- compiler/GHC/CmmToAsm/X86/Ppr.hs
- compiler/GHC/CmmToC.hs
- compiler/GHC/CmmToLlvm/CodeGen.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Platform.hs
- compiler/GHC/StgToCmm/Prim.hs
- docs/users_guide/exts/multiway_if.rst
- hadrian/src/Settings/Builders/SplitSections.hs
- libraries/base/src/Data/Bifoldable.hs
- libraries/base/src/Data/Foldable1.hs
- libraries/base/src/Data/Semigroup.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Foldable.hs
- libraries/ghc-internal/src/GHC/Internal/Data/OldList.hs
- libraries/ghc-internal/src/GHC/Internal/List.hs
- libraries/ghc-platform/src/GHC/Platform/ArchOS.hs
- libraries/ghc-prim/GHC/Classes.hs
- rts/include/stg/Prim.h
Changes:
=====================================
compiler/GHC/Cmm/MachOp.hs
=====================================
@@ -140,8 +140,8 @@ data MachOp
-- Conversions. Some of these will be NOPs.
-- Floating-point conversions use the signed variant.
- | MO_SF_Conv Width Width -- Signed int -> Float
- | MO_FS_Conv Width Width -- Float -> Signed int
+ | MO_SF_Round Width Width -- Signed int -> Float
+ | MO_FS_Truncate Width Width -- Float -> Signed int
| MO_SS_Conv Width Width -- Signed int -> Signed int
| MO_UU_Conv Width Width -- unsigned int -> unsigned int
| MO_XX_Conv Width Width -- int -> int; puts no requirements on the
@@ -152,7 +152,10 @@ data MachOp
-- MO_XX_Conv, e.g.,
-- MO_XX_CONV W64 W8 (MO_XX_CONV W8 W64 x)
-- is equivalent to just x.
- | MO_FF_Conv Width Width -- Float -> Float
+ | MO_FF_Conv Width Width -- Float -> Float
+
+ | MO_WF_Bitcast Width -- Word32/Word64 -> Float/Double
+ | MO_FW_Bitcast Width -- Float/Double -> Word32/Word64
-- Vector element insertion and extraction operations
| MO_V_Insert Length Width -- Insert scalar into vector
@@ -476,9 +479,11 @@ machOpResultType platform mop tys =
MO_SS_Conv _ to -> cmmBits to
MO_UU_Conv _ to -> cmmBits to
MO_XX_Conv _ to -> cmmBits to
- MO_FS_Conv _ to -> cmmBits to
- MO_SF_Conv _ to -> cmmFloat to
+ MO_FS_Truncate _ to -> cmmBits to
+ MO_SF_Round _ to -> cmmFloat to
MO_FF_Conv _ to -> cmmFloat to
+ MO_WF_Bitcast w -> cmmFloat w
+ MO_FW_Bitcast w -> cmmBits w
MO_V_Insert l w -> cmmVec l (cmmBits w)
MO_V_Extract _ w -> cmmBits w
@@ -568,12 +573,14 @@ machOpArgReps platform op =
MO_U_Shr r -> [r, wordWidth platform]
MO_S_Shr r -> [r, wordWidth platform]
- 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_SS_Conv from _ -> [from]
+ MO_UU_Conv from _ -> [from]
+ MO_XX_Conv from _ -> [from]
+ MO_SF_Round from _ -> [from]
+ MO_FS_Truncate from _ -> [from]
+ MO_FF_Conv from _ -> [from]
+ MO_WF_Bitcast w -> [w]
+ MO_FW_Bitcast w -> [w]
MO_V_Insert l r -> [typeWidth (vec l (cmmBits r)),r, W32]
MO_V_Extract l r -> [typeWidth (vec l (cmmBits r)), W32]
=====================================
compiler/GHC/Cmm/Opt.hs
=====================================
@@ -89,7 +89,7 @@ cmmMachOpFoldM _ op [CmmLit (CmmInt x rep)]
-- "from" type, in order to truncate to the correct size.
-- The final narrow/widen to the destination type
-- is implicit in the CmmLit.
- MO_SF_Conv _from to -> CmmLit (CmmFloat (fromInteger x) to)
+ MO_SF_Round _frm to -> CmmLit (CmmFloat (fromInteger x) to)
MO_SS_Conv from to -> CmmLit (CmmInt (narrowS from x) to)
MO_UU_Conv from to -> CmmLit (CmmInt (narrowU from x) to)
MO_XX_Conv from to -> CmmLit (CmmInt (narrowS from x) to)
=====================================
compiler/GHC/Cmm/Parser.y
=====================================
@@ -1078,12 +1078,12 @@ machOps = listToUFM $
( "f2f32", flip MO_FF_Conv W32 ), -- TODO; rounding mode
( "f2f64", flip MO_FF_Conv W64 ), -- TODO; rounding mode
- ( "f2i8", flip MO_FS_Conv W8 ),
- ( "f2i16", flip MO_FS_Conv W16 ),
- ( "f2i32", flip MO_FS_Conv W32 ),
- ( "f2i64", flip MO_FS_Conv W64 ),
- ( "i2f32", flip MO_SF_Conv W32 ),
- ( "i2f64", flip MO_SF_Conv W64 )
+ ( "f2i8", flip MO_FS_Truncate W8 ),
+ ( "f2i16", flip MO_FS_Truncate W16 ),
+ ( "f2i32", flip MO_FS_Truncate W32 ),
+ ( "f2i64", flip MO_FS_Truncate W64 ),
+ ( "i2f32", flip MO_SF_Round W32 ),
+ ( "i2f64", flip MO_SF_Round W64 )
]
callishMachOps :: Platform -> UniqFM FastString ([CmmExpr] -> (CallishMachOp, [CmmExpr]))
=====================================
compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
=====================================
@@ -755,8 +755,8 @@ getRegister' config plat expr
MO_S_Neg w -> negate code w reg
MO_F_Neg w -> return $ Any (floatFormat w) (\dst -> code `snocOL` NEG (OpReg w dst) (OpReg w reg))
- MO_SF_Conv from to -> return $ Any (floatFormat to) (\dst -> code `snocOL` SCVTF (OpReg to dst) (OpReg from reg)) -- (Signed ConVerT Float)
- MO_FS_Conv from to -> return $ Any (intFormat to) (\dst -> code `snocOL` FCVTZS (OpReg to dst) (OpReg from reg)) -- (float convert (-> zero) signed)
+ MO_SF_Round from to -> return $ Any (floatFormat to) (\dst -> code `snocOL` SCVTF (OpReg to dst) (OpReg from reg)) -- (Signed ConVerT Float)
+ MO_FS_Truncate from to -> return $ Any (intFormat to) (\dst -> code `snocOL` FCVTZS (OpReg to dst) (OpReg from reg)) -- (float convert (-> zero) signed)
-- TODO this is very hacky
-- Note, UBFM and SBFM expect source and target register to be of the same size, so we'll use @max from to@
@@ -764,6 +764,8 @@ getRegister' config plat expr
MO_UU_Conv from to -> return $ Any (intFormat to) (\dst -> code `snocOL` UBFM (OpReg (max from to) dst) (OpReg (max from to) reg) (OpImm (ImmInt 0)) (toImm (min from to)))
MO_SS_Conv from to -> ss_conv from to reg code
MO_FF_Conv from to -> return $ Any (floatFormat to) (\dst -> code `snocOL` FCVT (OpReg to dst) (OpReg from reg))
+ MO_WF_Bitcast w -> return $ Any (floatFormat w) (\dst -> code `snocOL` FMOV (OpReg w dst) (OpReg w reg))
+ MO_FW_Bitcast w -> return $ Any (intFormat w) (\dst -> code `snocOL` FMOV (OpReg w dst) (OpReg w reg))
-- Conversions
MO_XX_Conv _from to -> swizzleRegisterRep (intFormat to) <$> getRegister e
=====================================
compiler/GHC/CmmToAsm/AArch64/Instr.hs
=====================================
@@ -132,6 +132,7 @@ regUsageOfInstr platform instr = case instr of
DMBISH -> usage ([], [])
-- 9. Floating Point Instructions --------------------------------------------
+ FMOV dst src -> usage (regOp src, regOp dst)
FCVT dst src -> usage (regOp src, regOp dst)
SCVTF dst src -> usage (regOp src, regOp dst)
FCVTZS dst src -> usage (regOp src, regOp dst)
@@ -267,6 +268,7 @@ patchRegsOfInstr instr env = case instr of
DMBISH -> DMBISH
-- 9. Floating Point Instructions ------------------------------------------
+ FMOV o1 o2 -> FMOV (patchOp o1) (patchOp o2)
FCVT o1 o2 -> FCVT (patchOp o1) (patchOp o2)
SCVTF o1 o2 -> SCVTF (patchOp o1) (patchOp o2)
FCVTZS o1 o2 -> FCVTZS (patchOp o1) (patchOp o2)
@@ -623,6 +625,8 @@ data Instr
-- 8. Synchronization Instructions -----------------------------------------
| DMBISH
-- 9. Floating Point Instructions
+ -- move to/from general purpose <-> floating, or floating to floating
+ | FMOV Operand Operand
-- Float ConVerT
| FCVT Operand Operand
-- Signed ConVerT Float
@@ -694,6 +698,7 @@ instrCon i =
BL{} -> "BL"
BCOND{} -> "BCOND"
DMBISH{} -> "DMBISH"
+ FMOV{} -> "FMOV"
FCVT{} -> "FCVT"
SCVTF{} -> "SCVTF"
FCVTZS{} -> "FCVTZS"
=====================================
compiler/GHC/CmmToAsm/AArch64/Ppr.hs
=====================================
@@ -524,6 +524,7 @@ pprInstr platform instr = case instr of
DMBISH -> line $ text "\tdmb ish"
-- 9. Floating Point Instructions --------------------------------------------
+ FMOV o1 o2 -> op2 (text "\tfmov") o1 o2
FCVT o1 o2 -> op2 (text "\tfcvt") o1 o2
SCVTF o1 o2 -> op2 (text "\tscvtf") o1 o2
FCVTZS o1 o2 -> op2 (text "\tfcvtzs") o1 o2
=====================================
compiler/GHC/CmmToAsm/PPC/CodeGen.hs
=====================================
@@ -516,8 +516,8 @@ getRegister' config platform (CmmMachOp mop [x]) -- unary MachOps
MO_FF_Conv W64 W32 -> trivialUCode FF32 FRSP x
MO_FF_Conv W32 W64 -> conversionNop FF64 x
- MO_FS_Conv from to -> coerceFP2Int from to x
- MO_SF_Conv from to -> coerceInt2FP from to x
+ MO_FS_Truncate from to -> coerceFP2Int from to x
+ MO_SF_Round from to -> coerceInt2FP from to x
MO_SS_Conv from to
| from >= to -> conversionNop (intFormat to) x
=====================================
compiler/GHC/CmmToAsm/Wasm/FromCmm.hs
=====================================
@@ -620,6 +620,49 @@ lower_MO_FF_Conv lbl W64 W32 [x] = do
x_instr `WasmConcat` WasmF32DemoteF64
lower_MO_FF_Conv _ _ _ _ = panic "lower_MO_FF_Conv: unreachable"
+
+-- | Lower a 'MO_WF_Bitcast' operation. Note that this is not a conversion,
+-- rather it reinterprets the data.
+lower_MO_WF_Bitcast ::
+ CLabel ->
+ Width ->
+ [CmmActual] ->
+ WasmCodeGenM w (SomeWasmExpr w)
+lower_MO_WF_Bitcast lbl W32 [x] = do
+ WasmExpr x_instr <- lower_CmmExpr_Typed lbl TagI32 x
+ pure $
+ SomeWasmExpr TagF32 $
+ WasmExpr $
+ x_instr `WasmConcat` WasmReinterpret TagI32 TagF32
+lower_MO_WF_Bitcast lbl W64 [x] = do
+ WasmExpr x_instr <- lower_CmmExpr_Typed lbl TagI64 x
+ pure $
+ SomeWasmExpr TagF64 $
+ WasmExpr $
+ x_instr `WasmConcat` WasmReinterpret TagI64 TagF64
+lower_MO_WF_Bitcast _ _ _ = panic "lower_MO_WF_Bitcast: unreachable"
+
+-- | Lower a 'MO_FW_Bitcast' operation. Note that this is not a conversion,
+-- rather it reinterprets the data.
+lower_MO_FW_Bitcast ::
+ CLabel ->
+ Width ->
+ [CmmActual] ->
+ WasmCodeGenM w (SomeWasmExpr w)
+lower_MO_FW_Bitcast lbl W32 [x] = do
+ WasmExpr x_instr <- lower_CmmExpr_Typed lbl TagF32 x
+ pure $
+ SomeWasmExpr TagI32 $
+ WasmExpr $
+ x_instr `WasmConcat` WasmReinterpret TagF32 TagI32
+lower_MO_FW_Bitcast lbl W64 [x] = do
+ WasmExpr x_instr <- lower_CmmExpr_Typed lbl TagF64 x
+ pure $
+ SomeWasmExpr TagI64 $
+ WasmExpr $
+ x_instr `WasmConcat` WasmReinterpret TagF64 TagI64
+lower_MO_FW_Bitcast _ _ _ = panic "lower_MO_FW_Bitcast: unreachable"
+
-- | Lower a 'CmmMachOp'.
lower_CmmMachOp ::
CLabel ->
@@ -799,14 +842,14 @@ lower_CmmMachOp lbl (MO_Not w0) [x] =
lower_CmmMachOp lbl (MO_Shl w0) xs = lower_MO_Shl lbl w0 xs
lower_CmmMachOp lbl (MO_U_Shr w0) xs = lower_MO_U_Shr lbl w0 xs
lower_CmmMachOp lbl (MO_S_Shr w0) xs = lower_MO_S_Shr lbl w0 xs
-lower_CmmMachOp lbl (MO_SF_Conv w0 w1) xs =
+lower_CmmMachOp lbl (MO_SF_Round w0 w1) xs =
lower_MO_Un_Conv
(WasmConvert Signed)
lbl
(cmmBits w0)
(cmmFloat w1)
xs
-lower_CmmMachOp lbl (MO_FS_Conv w0 w1) xs =
+lower_CmmMachOp lbl (MO_FS_Truncate w0 w1) xs =
lower_MO_Un_Conv
(WasmTruncSat Signed)
lbl
@@ -817,6 +860,8 @@ lower_CmmMachOp lbl (MO_SS_Conv w0 w1) xs = lower_MO_SS_Conv lbl w0 w1 xs
lower_CmmMachOp lbl (MO_UU_Conv w0 w1) xs = lower_MO_UU_Conv lbl w0 w1 xs
lower_CmmMachOp lbl (MO_XX_Conv w0 w1) xs = lower_MO_UU_Conv lbl w0 w1 xs
lower_CmmMachOp lbl (MO_FF_Conv w0 w1) xs = lower_MO_FF_Conv lbl w0 w1 xs
+lower_CmmMachOp lbl (MO_FW_Bitcast w) xs = lower_MO_FW_Bitcast lbl w xs
+lower_CmmMachOp lbl (MO_WF_Bitcast w) xs = lower_MO_WF_Bitcast lbl w xs
lower_CmmMachOp _ mop _ =
pprPanic "lower_CmmMachOp: unreachable" $
vcat [ text "offending MachOp:" <+> pprMachOp mop ]
=====================================
compiler/GHC/CmmToAsm/X86/CodeGen.hs
=====================================
@@ -848,10 +848,8 @@ getRegister' _ is32Bit (CmmReg reg)
do
let
fmt = cmmTypeFormat (cmmRegType reg)
- format = fmt
- --
platform <- ncgPlatform <$> getConfig
- return (Fixed format
+ return (Fixed fmt
(getRegisterReg platform reg)
nilOL)
@@ -1004,6 +1002,11 @@ getRegister' platform is32Bit (CmmMachOp mop [x]) = -- unary MachOps
MO_SS_Conv rep1 rep2 | rep1 == rep2 -> conversionNop (intFormat rep1) x
MO_XX_Conv rep1 rep2 | rep1 == rep2 -> conversionNop (intFormat rep1) x
+ MO_FW_Bitcast W32 -> bitcast FF32 II32 x
+ MO_WF_Bitcast W32 -> bitcast II32 FF32 x
+ MO_FW_Bitcast W64 -> bitcast FF64 II64 x
+ MO_WF_Bitcast W64 -> bitcast II64 FF64 x
+
-- widenings
MO_UU_Conv W8 W32 -> integerExtend W8 W32 MOVZxL x
MO_UU_Conv W16 W32 -> integerExtend W16 W32 MOVZxL x
@@ -1045,8 +1048,8 @@ getRegister' platform is32Bit (CmmMachOp mop [x]) = -- unary MachOps
MO_FF_Conv W64 W32 -> coerceFP2FP W32 x
- MO_FS_Conv from to -> coerceFP2Int from to x
- MO_SF_Conv from to -> coerceInt2FP from to x
+ MO_FS_Truncate from to -> coerceFP2Int from to x
+ MO_SF_Round from to -> coerceInt2FP from to x
MO_V_Insert {} -> needLlvm
MO_V_Extract {} -> needLlvm
@@ -1084,6 +1087,12 @@ getRegister' platform is32Bit (CmmMachOp mop [x]) = -- unary MachOps
instr (intFormat from) (OpReg reg) (OpReg dst)
return (Any (intFormat to) code)
+ bitcast :: Format -> Format -> CmmExpr -> NatM Register
+ bitcast fmt rfmt expr =
+ do (src, e_code) <- getSomeReg expr
+ let code = \dst -> e_code `snocOL` (MOVD fmt (OpReg src) (OpReg dst))
+ return (Any rfmt code)
+
toI8Reg :: Width -> CmmExpr -> NatM Register
toI8Reg new_rep expr
= do codefn <- getAnyReg expr
=====================================
compiler/GHC/CmmToAsm/X86/Instr.hs
=====================================
@@ -202,6 +202,11 @@ data Instr
-- operand is interpreted to be a 32-bit sign-extended value.
-- True 64-bit operands need to be moved with @MOVABS@, which we
-- currently don't use.
+ | MOVD Format Operand Operand -- ^ MOVD/MOVQ SSE2 instructions
+ -- (bitcast between a general purpose
+ -- register and a float register).
+ -- Format is input format, output format is
+ -- calculated in Ppr.hs
| CMOV Cond Format Operand Reg
| MOVZxL Format Operand Operand
-- ^ The format argument is the size of operand 1 (the number of bits we keep)
@@ -368,6 +373,7 @@ regUsageOfInstr :: Platform -> Instr -> RegUsage
regUsageOfInstr platform instr
= case instr of
MOV _ src dst -> usageRW src dst
+ MOVD _ src dst -> usageRW src dst
CMOV _ _ src dst -> mkRU (use_R src [dst]) [dst]
MOVZxL _ src dst -> usageRW src dst
MOVSxL _ src dst -> usageRW src dst
@@ -549,6 +555,7 @@ patchRegsOfInstr :: Instr -> (Reg -> Reg) -> Instr
patchRegsOfInstr instr env
= case instr of
MOV fmt src dst -> patch2 (MOV fmt) src dst
+ MOVD fmt src dst -> patch2 (MOVD fmt) src dst
CMOV cc fmt src dst -> CMOV cc fmt (patchOp src) (env dst)
MOVZxL fmt src dst -> patch2 (MOVZxL fmt) src dst
MOVSxL fmt src dst -> patch2 (MOVSxL fmt) src dst
=====================================
compiler/GHC/CmmToAsm/X86/Ppr.hs
=====================================
@@ -591,6 +591,9 @@ pprInstr platform i = case i of
CMOV cc format src dst
-> pprCondOpReg (text "cmov") format cc src dst
+ MOVD format src dst
+ -> pprMovdOpOp (text "mov") format src dst
+
MOVZxL II32 src dst
-> pprFormatOpOp (text "mov") II32 src dst
-- 32-to-64 bit zero extension on x86_64 is accomplished by a simple
@@ -980,6 +983,29 @@ pprInstr platform i = case i of
pprOperand platform format op2
]
+ pprMovdOpOp :: Line doc -> Format -> Operand -> Operand -> doc
+ pprMovdOpOp name format op1 op2
+ = let instr = case format of
+ -- bitcasts to/from a general purpose register to a floating point
+ -- register require II32 or II64.
+ II32 -> text "d"
+ II64 -> text "q"
+ FF32 -> text "d"
+ FF64 -> text "q"
+ _ -> panic "X86.Ppr.pprMovdOpOp: improper format for movd/movq."
+ out_fmt = case format of
+ II32 -> FF32
+ II64 -> FF64
+ FF32 -> II32
+ FF64 -> II64
+ _ -> panic "X86.Ppr.pprMovdOpOp: improper format for movd/movq."
+ in line $ hcat [
+ char '\t' <> name <> instr <> space,
+ pprOperand platform format op1,
+ comma,
+ pprOperand platform out_fmt op2
+ ]
+
pprFormatOpRegReg :: Line doc -> Format -> Operand -> Reg -> Reg -> doc
pprFormatOpRegReg name format op1 op2 op3
= line $ hcat [
=====================================
compiler/GHC/CmmToC.hs
=====================================
@@ -784,6 +784,28 @@ pprMachOp_for_C platform mop = case mop of
-- We won't know to generate (void*) casts here, but maybe from
-- context elsewhere
+-- bitcasts, in the C backend these are performed with __builtin_memcpy.
+-- See rts/include/stg/Prim.h
+
+ MO_FW_Bitcast W32 -> text "hs_bitcastfloat2word"
+ MO_FW_Bitcast W64 -> text "hs_bitcastdouble2word64"
+
+ MO_WF_Bitcast W32 -> text "hs_bitcastword2float"
+ MO_WF_Bitcast W64 -> text "hs_bitcastword642double"
+
+ MO_FW_Bitcast w -> pprTrace "offending mop:"
+ (text "MO_FW_Bitcast")
+ (panic $ "PprC.pprMachOp_for_C: MO_FW_Bitcast"
+ ++ " called with improper width!"
+ ++ show w)
+
+ MO_WF_Bitcast w -> pprTrace "offending mop:"
+ (text "MO_WF_Bitcast")
+ (panic $ "PprC.pprMachOp_for_C: MO_WF_Bitcast"
+ ++ " called with improper width!"
+ ++ show w)
+
+
-- noop casts
MO_UU_Conv from to | from == to -> empty
MO_UU_Conv _from to -> parens (machRep_U_CType platform to)
@@ -797,8 +819,8 @@ pprMachOp_for_C platform mop = case mop of
MO_FF_Conv from to | from == to -> empty
MO_FF_Conv _from to -> parens (machRep_F_CType to)
- MO_SF_Conv _from to -> parens (machRep_F_CType to)
- MO_FS_Conv _from to -> parens (machRep_S_CType platform to)
+ MO_SF_Round _from to -> parens (machRep_F_CType to)
+ MO_FS_Truncate _from to -> parens (machRep_S_CType platform to)
MO_RelaxedRead _ -> pprTrace "offending mop:"
(text "MO_RelaxedRead")
@@ -896,7 +918,7 @@ signedOp (MO_S_Gt _) = True
signedOp (MO_S_Lt _) = True
signedOp (MO_S_Shr _) = True
signedOp (MO_SS_Conv _ _) = True
-signedOp (MO_SF_Conv _ _) = True
+signedOp (MO_SF_Round _ _) = True
signedOp _ = False
shiftOp :: MachOp -> Maybe Width
@@ -1447,7 +1469,6 @@ floatToWord32 r = CmmInt (toInteger (castFloatToWord32 (fromRational r))) W32
doubleToWord64 :: Rational -> CmmLit
doubleToWord64 r = CmmInt (toInteger (castDoubleToWord64 (fromRational r))) W64
-
-- ---------------------------------------------------------------------------
-- Utils
=====================================
compiler/GHC/CmmToLlvm/CodeGen.hs
=====================================
@@ -1431,8 +1431,8 @@ genMachOp _ op [x] = case op of
let all0 = LMLitVar $ LMFloatLit (-0) (widthToLlvmFloat w)
in negate (widthToLlvmFloat w) all0 LM_MO_FSub
- MO_SF_Conv _ w -> fiConv (widthToLlvmFloat w) LM_Sitofp
- MO_FS_Conv _ w -> fiConv (widthToLlvmInt w) LM_Fptosi
+ MO_SF_Round _ w -> fiConv (widthToLlvmFloat w) LM_Sitofp
+ MO_FS_Truncate _ w -> fiConv (widthToLlvmInt w) LM_Fptosi
MO_SS_Conv from to
-> sameConv from (widthToLlvmInt to) LM_Trunc LM_Sext
@@ -1446,6 +1446,9 @@ genMachOp _ op [x] = case op of
MO_FF_Conv from to
-> sameConv from (widthToLlvmFloat to) LM_Fptrunc LM_Fpext
+ MO_WF_Bitcast w -> fiConv (widthToLlvmFloat w) LM_Bitcast
+ MO_FW_Bitcast w -> fiConv (widthToLlvmInt w) LM_Bitcast
+
MO_VS_Neg len w ->
let ty = widthToLlvmInt w
vecty = LMVector len ty
@@ -1704,13 +1707,16 @@ genMachOp_slow opt op [x, y] = case op of
MO_S_Neg _ -> panicOp
MO_F_Neg _ -> panicOp
- MO_SF_Conv _ _ -> panicOp
- MO_FS_Conv _ _ -> panicOp
+ MO_SF_Round _ _ -> panicOp
+ MO_FS_Truncate _ _ -> panicOp
MO_SS_Conv _ _ -> panicOp
MO_UU_Conv _ _ -> panicOp
MO_XX_Conv _ _ -> panicOp
MO_FF_Conv _ _ -> panicOp
+ MO_WF_Bitcast _to -> panicOp
+ MO_FW_Bitcast _to -> panicOp
+
MO_V_Insert {} -> panicOp
MO_VS_Neg {} -> panicOp
=====================================
compiler/GHC/Driver/Pipeline/Execute.hs
=====================================
@@ -463,6 +463,13 @@ runCcPhase cc_phase pipe_env hsc_env location input_fn = do
then [ "-ffloat-store" ]
else []) ++
+ -- if -fsplit-sections is enabled, we should also build .hc
+ -- files with these flags.
+ (if gopt Opt_SplitSections dflags &&
+ platformOS (targetPlatform dflags) /= OSDarwin
+ then ["-ffunction-sections", "-fdata-sections"]
+ else []) ++
+
-- gcc's -fstrict-aliasing allows two accesses to memory
-- to be considered non-aliasing if they have different types.
-- This interacts badly with the C code we generate, which is
=====================================
compiler/GHC/Platform.hs
=====================================
@@ -17,6 +17,7 @@ module GHC.Platform
, ByteOrder(..)
, target32Bit
, isARM
+ , isPPC
, osElfTarget
, osMachOTarget
, osSubsectionsViaSymbols
=====================================
compiler/GHC/StgToCmm/Prim.hs
=====================================
@@ -1543,15 +1543,24 @@ emitPrimOp cfg primop =
-- Conversions
- IntToDoubleOp -> \args -> opTranslate args (MO_SF_Conv (wordWidth platform) W64)
- DoubleToIntOp -> \args -> opTranslate args (MO_FS_Conv W64 (wordWidth platform))
+ IntToDoubleOp -> \args -> opTranslate args (MO_SF_Round (wordWidth platform) W64)
+ DoubleToIntOp -> \args -> opTranslate args (MO_FS_Truncate W64 (wordWidth platform))
- IntToFloatOp -> \args -> opTranslate args (MO_SF_Conv (wordWidth platform) W32)
- FloatToIntOp -> \args -> opTranslate args (MO_FS_Conv W32 (wordWidth platform))
+ IntToFloatOp -> \args -> opTranslate args (MO_SF_Round (wordWidth platform) W32)
+ FloatToIntOp -> \args -> opTranslate args (MO_FS_Truncate W32 (wordWidth platform))
FloatToDoubleOp -> \args -> opTranslate args (MO_FF_Conv W32 W64)
DoubleToFloatOp -> \args -> opTranslate args (MO_FF_Conv W64 W32)
+ CastFloatToWord32Op ->
+ \args -> translateBitcasts (MO_FW_Bitcast W32) args
+ CastWord32ToFloatOp ->
+ \args -> translateBitcasts (MO_WF_Bitcast W32) args
+ CastDoubleToWord64Op ->
+ \args -> translateBitcasts (MO_FW_Bitcast W64) args
+ CastWord64ToDoubleOp ->
+ \args -> translateBitcasts (MO_WF_Bitcast W64) args
+
IntQuotRemOp -> \args -> opCallishHandledLater args $
if allowQuotRem
then Left (MO_S_QuotRem (wordWidth platform))
@@ -1746,10 +1755,6 @@ emitPrimOp cfg primop =
TraceMarkerOp -> alwaysExternal
SetThreadAllocationCounter -> alwaysExternal
KeepAliveOp -> alwaysExternal
- CastWord32ToFloatOp -> alwaysExternal
- CastWord64ToDoubleOp -> alwaysExternal
- CastDoubleToWord64Op -> alwaysExternal
- CastFloatToWord32Op -> alwaysExternal
where
profile = stgToCmmProfile cfg
@@ -1834,6 +1839,14 @@ emitPrimOp cfg primop =
allowInt2Mul = stgToCmmAllowIntMul2Instr cfg
allowWord2Mul = stgToCmmAllowWordMul2Instr cfg
+ -- a bit of a hack, for certain code generaters, e.g. PPC, and i386 we
+ -- continue to use the cmm versions of these functions instead of inline
+ -- assembly. Tracked in #24841.
+ ppc = isPPC $ platformArch platform
+ i386 = target32Bit platform
+ translateBitcasts mop args | ppc || i386 = alwaysExternal args
+ | otherwise = opTranslate args mop
+
allowFMA = stgToCmmAllowFMAInstr cfg
fmaOp :: FMASign -> Width -> [CmmActual] -> PrimopCmmEmit
=====================================
docs/users_guide/exts/multiway_if.rst
=====================================
@@ -57,5 +57,5 @@ Note that multi-way if supports guards other than boolean conditions: ::
if | parseNumbers settings
, Just (exponent, mantissa) <- decomposeNumber str
, let (integralPart, fractionPart) = parse mantissa
- , integralPart >= 0 = ...
- | otherwise = ...
+ , integralPart >= 0 -> ...
+ | otherwise -> ...
=====================================
hadrian/src/Settings/Builders/SplitSections.hs
=====================================
@@ -32,5 +32,12 @@ splitSectionsArgs = do
, builder MergeObjects ? ifM (expr isWinTarget)
(pure ["-T", "driver/utils/merge_sections_pe.ld"])
(pure ["-T", "driver/utils/merge_sections.ld"])
+ , builder (Cc CompileC) ? arg "-ffunction-sections" <> arg "-fdata-sections"
+ , builder (Ghc CompileCWithGhc) ? arg "-optc-ffunction-sections"
+ <> arg
+ "-optc-fdata-sections"
+ , builder (Ghc CompileCppWithGhc) ? arg "-optcxx-ffunction-sections"
+ <> arg
+ "-optcxx-fdata-sections"
]
) else mempty
=====================================
libraries/base/src/Data/Bifoldable.hs
=====================================
@@ -640,7 +640,13 @@ bielem x = biany (== x) (== x)
biconcat :: Bifoldable t => t [a] [a] -> [a]
biconcat = bifold
--- | The largest element of a non-empty structure.
+-- | The largest element of a non-empty structure. This function is equivalent
+-- to @'bifoldr1' 'max'@, and its behavior on structures with multiple largest
+-- elements depends on the relevant implementation of 'max'. For the default
+-- implementation of 'max' (@max x y = if x <= y then y else x@), structure
+-- order is used as a tie-breaker: if there are multiple largest elements, the
+-- rightmost of them is chosen (this is equivalent to @'bimaximumBy'
+-- 'compare'@).
--
-- ==== __Examples__
--
@@ -670,7 +676,13 @@ bimaximum = fromMaybe (error "bimaximum: empty structure") .
getMax . bifoldMap mj mj
where mj = Max #. (Just :: a -> Maybe a)
--- | The least element of a non-empty structure.
+-- | The least element of a non-empty structure. This function is equivalent to
+-- @'bifoldr1' 'min'@, and its behavior on structures with multiple least
+-- elements depends on the relevant implementation of 'min'. For the default
+-- implementation of 'min' (@min x y = if x <= y then x else y@), structure
+-- order is used as a tie-breaker: if there are multiple least elements, the
+-- leftmost of them is chosen (this is equivalent to @'biminimumBy'
+-- 'compare'@).
--
-- ==== __Examples__
--
@@ -927,7 +939,8 @@ biall :: Bifoldable t => (a -> Bool) -> (b -> Bool) -> t a b -> Bool
biall p q = getAll #. bifoldMap (All . p) (All . q)
-- | The largest element of a non-empty structure with respect to the
--- given comparison function.
+-- given comparison function. Structure order is used as a tie-breaker: if
+-- there are multiple largest elements, the rightmost of them is chosen.
--
-- ==== __Examples__
--
@@ -956,7 +969,8 @@ bimaximumBy cmp = bifoldr1 max'
_ -> y
-- | The least element of a non-empty structure with respect to the
--- given comparison function.
+-- given comparison function. Structure order is used as a tie-breaker: if
+-- there are multiple least elements, the leftmost of them is chosen.
--
-- ==== __Examples__
--
=====================================
libraries/base/src/Data/Foldable1.hs
=====================================
@@ -130,7 +130,13 @@ class Foldable t => Foldable1 t where
toNonEmpty :: t a -> NonEmpty a
toNonEmpty = runNonEmptyDList . foldMap1 singleton
- -- | The largest element of a non-empty structure.
+ -- | The largest element of a non-empty structure. This function is
+ -- equivalent to @'foldr1' 'Data.Ord.max'@, and its behavior on structures
+ -- with multiple largest elements depends on the relevant implementation of
+ -- 'Data.Ord.max'. For the default implementation of 'Data.Ord.max' (@max x
+ -- y = if x <= y then y else x@), structure order is used as a tie-breaker:
+ -- if there are multiple largest elements, the rightmost of them is chosen
+ -- (this is equivalent to @'maximumBy' 'Data.Ord.compare'@).
--
-- >>> maximum (32 :| [64, 8, 128, 16])
-- 128
@@ -139,7 +145,13 @@ class Foldable t => Foldable1 t where
maximum :: Ord a => t a -> a
maximum = getMax #. foldMap1' Max
- -- | The least element of a non-empty structure.
+ -- | The least element of a non-empty structure. This function is
+ -- equivalent to @'foldr1' 'Data.Ord.min'@, and its behavior on structures
+ -- with multiple largest elements depends on the relevant implementation of
+ -- 'Data.Ord.min'. For the default implementation of 'Data.Ord.min' (@min x
+ -- y = if x <= y then x else y@), structure order is used as a tie-breaker:
+ -- if there are multiple least elements, the leftmost of them is chosen
+ -- (this is equivalent to @'minimumBy' 'Data.Ord.compare'@).
--
-- >>> minimum (32 :| [64, 8, 128, 16])
-- 8
@@ -362,7 +374,8 @@ foldlMapM1 g f t = g x >>= \y -> foldlM f y xs
where x:|xs = toNonEmpty t
-- | The largest element of a non-empty structure with respect to the
--- given comparison function.
+-- given comparison function. Structure order is used as a tie-breaker: if
+-- there are multiple largest elements, the rightmost of them is chosen.
--
-- @since 4.18.0.0
maximumBy :: Foldable1 t => (a -> a -> Ordering) -> t a -> a
@@ -372,7 +385,8 @@ maximumBy cmp = foldl1' max'
_ -> y
-- | The least element of a non-empty structure with respect to the
--- given comparison function.
+-- given comparison function. Structure order is used as a tie-breaker: if
+-- there are multiple least elements, the leftmost of them is chosen.
--
-- @since 4.18.0.0
minimumBy :: Foldable1 t => (a -> a -> Ordering) -> t a -> a
=====================================
libraries/base/src/Data/Semigroup.hs
=====================================
@@ -340,7 +340,11 @@ instance Num a => Num (Max a) where
fromInteger = Max . fromInteger
-- | 'Arg' isn't itself a 'Semigroup' in its own right, but it can be
--- placed inside 'Min' and 'Max' to compute an arg min or arg max.
+-- placed inside 'Min' and 'Max' to compute an arg min or arg max. In
+-- the event of ties, the leftmost qualifying 'Arg' is chosen; contrast
+-- with the behavior of 'minimum' and 'maximum' for many other types,
+-- where ties are broken by considering elements to the left in the
+-- structure to be less than elements to the right.
--
-- ==== __Examples__
--
@@ -397,11 +401,25 @@ instance Foldable (Arg a) where
instance Traversable (Arg a) where
traverse f (Arg x a) = Arg x `fmap` f a
--- | @since 4.9.0.0
+-- |
+-- Note that `Arg`'s 'Eq' instance does not satisfy extensionality:
+--
+-- >>> Arg 0 0 == Arg 0 1
+-- True
+-- >>> let f (Arg _ x) = x in f (Arg 0 0) == f (Arg 0 1)
+-- False
+--
+-- @since 4.9.0.0
instance Eq a => Eq (Arg a b) where
Arg a _ == Arg b _ = a == b
--- | @since 4.9.0.0
+-- |
+-- Note that `Arg`'s 'Ord' instance has 'min' and 'max' implementations that
+-- differ from the tie-breaking conventions of the default implementation of
+-- 'min' and 'max' in class 'Ord'; 'Arg' breaks ties by favoring the first
+-- argument in both functions.
+--
+-- @since 4.9.0.0
instance Ord a => Ord (Arg a b) where
Arg a _ `compare` Arg b _ = compare a b
min x@(Arg a _) y@(Arg b _)
=====================================
libraries/ghc-internal/src/GHC/Internal/Data/Foldable.hs
=====================================
@@ -555,7 +555,13 @@ class Foldable t where
elem :: Eq a => a -> t a -> Bool
elem = any . (==)
- -- | The largest element of a non-empty structure.
+ -- | The largest element of a non-empty structure. This function is
+ -- equivalent to @'foldr1' 'max'@, and its behavior on structures with
+ -- multiple largest elements depends on the relevant implementation of
+ -- 'max'. For the default implementation of 'max' (@max x y = if x <= y
+ -- then y else x@), structure order is used as a tie-breaker: if there are
+ -- multiple largest elements, the rightmost of them is chosen (this is
+ -- equivalent to @'maximumBy' 'compare'@).
--
-- This function is non-total and will raise a runtime exception if the
-- structure happens to be empty. A structure that supports random access
@@ -583,7 +589,13 @@ class Foldable t where
getMax . foldMap' (Max #. (Just :: a -> Maybe a))
{-# INLINEABLE maximum #-}
- -- | The least element of a non-empty structure.
+ -- | The least element of a non-empty structure. This function is
+ -- equivalent to @'foldr1' 'min'@, and its behavior on structures with
+ -- multiple largest elements depends on the relevant implementation of
+ -- 'min'. For the default implementation of 'min' (@min x y = if x <= y
+ -- then x else y@), structure order is used as a tie-breaker: if there are
+ -- multiple least elements, the leftmost of them is chosen (this is
+ -- equivalent to @'minimumBy' 'compare'@).
--
-- This function is non-total and will raise a runtime exception if the
-- structure happens to be empty. A structure that supports random access
@@ -1288,7 +1300,8 @@ all :: Foldable t => (a -> Bool) -> t a -> Bool
all p = getAll #. foldMap (All #. p)
-- | The largest element of a non-empty structure with respect to the
--- given comparison function.
+-- given comparison function. Structure order is used as a tie-breaker: if
+-- there are multiple largest elements, the rightmost of them is chosen.
--
-- ==== __Examples__
--
@@ -1314,7 +1327,8 @@ maximumBy cmp = fromMaybe (errorWithoutStackTrace "maximumBy: empty structure")
{-# INLINE[2] maximumBy #-}
-- | The least element of a non-empty structure with respect to the
--- given comparison function.
+-- given comparison function. Structure order is used as a tie-breaker: if
+-- there are multiple least elements, the leftmost of them is chosen.
--
-- ==== __Examples__
--
=====================================
libraries/ghc-internal/src/GHC/Internal/Data/OldList.hs
=====================================
@@ -958,10 +958,11 @@ insertBy cmp x ys@(y:ys')
GT -> y : insertBy cmp x ys'
_ -> x : ys
--- | The 'maximumBy' function is the non-overloaded version of 'maximum',
--- which takes a comparison function and a list
+-- | The 'maximumBy' function takes a comparison function and a list
-- and returns the greatest element of the list by the comparison function.
-- The list must be finite and non-empty.
+-- List order is used as a tie-breaker: if there are multiple greatest
+-- elements, the last of them is chosen.
--
-- ==== __Examples__
--
@@ -980,10 +981,11 @@ maximumBy cmp xs = foldl1 maxBy xs
GT -> x
_ -> y
--- | The 'minimumBy' function is the non-overloaded version of 'minimum',
--- which takes a comparison function and a list
+-- | The 'minimumBy' function takes a comparison function and a list
-- and returns the least element of the list by the comparison function.
-- The list must be finite and non-empty.
+-- List order is used as a tie-breaker: if there are multiple least
+-- elements, the first of them is chosen.
--
-- ==== __Examples__
--
=====================================
libraries/ghc-internal/src/GHC/Internal/List.hs
=====================================
@@ -808,8 +808,11 @@ scanr1 f (x:xs) = f x q : qs
-- | 'maximum' returns the maximum value from a list,
-- which must be non-empty, finite, and of an ordered type.
--- It is a special case of 'GHC.Internal.Data.List.maximumBy', which allows the
--- programmer to supply their own comparison function.
+-- This function is equivalent to @'foldr1' 'max'@, and its behavior on lists
+-- with multiple maxima depends on the relevant implementation of 'max'. For
+-- the default implementation of 'max', list order is used as a tie-breaker: if
+-- there are multiple maxima, the rightmost of them is chosen (this is
+-- equivalent to @'GHC.Internal.Data.List.maximumBy' 'compare'@).
--
-- >>> maximum []
-- *** Exception: Prelude.maximum: empty list
@@ -832,8 +835,11 @@ maximum xs = foldl1' max xs
-- | 'minimum' returns the minimum value from a list,
-- which must be non-empty, finite, and of an ordered type.
--- It is a special case of 'GHC.Internal.Data.List.minimumBy', which allows the
--- programmer to supply their own comparison function.
+-- This function is equivalent to @'foldr1' 'min'@, and its behavior on lists
+-- with multiple minima depends on the relevant implementation of 'min'. For
+-- the default implementation of 'min', list order is used as a tie-breaker: if
+-- there are multiple minima, the leftmost of them is chosen (this is
+-- equivalent to @'GHC.Internal.Data.List.minimumBy' 'compare'@).
--
-- >>> minimum []
-- *** Exception: Prelude.minimum: empty list
=====================================
libraries/ghc-platform/src/GHC/Platform/ArchOS.hs
=====================================
@@ -10,7 +10,7 @@ module GHC.Platform.ArchOS
, ArmISAExt(..)
, ArmABI(..)
, PPC_64ABI(..)
- , isARM
+ , isARM, isPPC
, stringEncodeArch
-- * Operating systems
@@ -188,6 +188,11 @@ isARM (ArchARM {}) = True
isARM ArchAArch64 = True
isARM _ = False
+isPPC :: Arch -> Bool
+isPPC (ArchPPC_64 _) = True
+isPPC ArchPPC = True
+isPPC _ = False
+
-- | This predicate tells us whether the OS support Mach-O shared libraries.
osMachOTarget :: OS -> Bool
osMachOTarget OSDarwin = True
=====================================
libraries/ghc-prim/GHC/Classes.hs
=====================================
@@ -393,7 +393,29 @@ instance Ord TyCon where
--
-- Note that (7.) and (8.) do /not/ require 'min' and 'max' to return either of
-- their arguments. The result is merely required to /equal/ one of the
--- arguments in terms of '(==)'.
+-- arguments in terms of '(==)'. Users who expect a stronger guarantee are advised
+-- to write their own min and/or max functions.
+--
+-- The nuance of the above distinction is not always fully internalized by
+-- developers, and in the past (tracing back to the Haskell 1.4 Report) the
+-- specification for 'Ord' asserted the stronger property that @(min x y, max x
+-- y) = (x, y)@ or @(y, x)@, or in other words, that 'min' and 'max' /will/
+-- return one of their arguments, using argument order as the tie-breaker if
+-- the arguments are equal by comparison. A few list and
+-- 'Data.Foldable.Foldable' functions have behavior that is best understood
+-- with this assumption in mind: all variations of @minimumBy@ and @maximumBy@
+-- (which can't use 'min' and 'max' in their implementations) are written such
+-- that @minimumBy 'compare'@ and @maximumBy 'compare'@ are respectively
+-- equivalent to @minimum@ and @maximum@ (which do use 'min' and 'max') only if
+-- 'min' and 'max' adhere to this tie-breaking convention. Otherwise, if there
+-- are multiple least or largest elements in a container, @minimum@ and
+-- @maximum@ may not return the /same/ one that @minimumBy 'compare'@ and
+-- @maximumBy 'compare'@ do (though they should return something that is
+-- /equal/). (This is relevant for types with non-extensional equality, like
+-- 'Data.Semigroup.Arg', but also in cases where the precise reference held
+-- matters for memory-management reasons.) Unless there is a reason to deviate,
+-- it is less confusing for implementors of 'Ord' to respect this same
+-- convention (as the default definitions of 'min' and 'max' do).
--
-- Minimal complete definition: either 'compare' or '<='.
-- Using 'compare' can be more efficient for complex types.
=====================================
rts/include/stg/Prim.h
=====================================
@@ -135,3 +135,30 @@ StgWord hs_ctz8(StgWord x);
StgWord hs_ctz16(StgWord x);
StgWord hs_ctz32(StgWord x);
StgWord hs_ctz64(StgWord64 x);
+
+/* bitcasts, instead of creating a new C file we static inline these here. We
+ * use __builtin_memcpy instead of memcpy from string.h to avoid function
+ * prototype conflicts that occur in the C backend with the inclusion of
+ * string.h*/
+static inline StgFloat hs_bitcastword2float(StgWord32 x) {
+ StgFloat dest;
+ __builtin_memcpy(&dest, &x, sizeof(StgFloat));
+ return dest;
+}
+
+static inline StgDouble hs_bitcastword642double(StgWord64 x) {
+ StgDouble dest;
+ __builtin_memcpy(&dest, &x, sizeof(StgDouble));
+ return dest;
+}
+
+static inline StgWord32 hs_bitcastfloat2word(StgFloat x) {
+ StgWord32 dest;
+ __builtin_memcpy(&dest, &x, sizeof(StgWord32));
+ return dest;
+}
+static inline StgWord64 hs_bitcastdouble2word64(StgDouble x) {
+ StgWord64 dest;
+ __builtin_memcpy(&dest, &x, sizeof(StgWord64));
+ return dest;
+}
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/a69500e850145378ff777c40a7c6eeb862ccef5a...dcd64e4c86a8eda724aed2a3b036d9e53e4c7797
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/a69500e850145378ff777c40a7c6eeb862ccef5a...dcd64e4c86a8eda724aed2a3b036d9e53e4c7797
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20240523/97862fa4/attachment-0001.html>
More information about the ghc-commits
mailing list