[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