[Git][ghc/ghc][master] Don't re-use stack slots for growing registers
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC Commits: 023c301c by sheaf at 2026-01-13T04:57:30-05:00 Don't re-use stack slots for growing registers This commit avoids re-using a stack slot for a register that has grown but already had a stack slot. For example, suppose we have stack slot assigments %v1 :: FF64 |-> StackSlot 0 %v2 :: FF64 |-> StackSlot 1 Later, we start using %v1 at a larger format (e.g. F64x2) and we need to spill it again. Then we **must not** use StackSlot 0, as a spill at format F64x2 would clobber the data in StackSlot 1. This can cause some fragmentation of the `StackMap`, but that's probably OK. Fixes #26668 - - - - - 2 changed files: - compiler/GHC/CmmToAsm/Reg/Linear.hs - compiler/GHC/CmmToAsm/Reg/Linear/StackMap.hs Changes: ===================================== compiler/GHC/CmmToAsm/Reg/Linear.hs ===================================== @@ -406,7 +406,7 @@ linearRA block_live block_id = go [] [] -- | Do allocation for a single instruction. raInsn :: OutputableRegConstraint freeRegs instr - => BlockMap Regs -- ^ map of what vregs are love on entry to each block. + => BlockMap Regs -- ^ map of what vregs are live on entry to each block. -> [instr] -- ^ accumulator for instructions already processed. -> BlockId -- ^ the id of the current block, for debugging -> LiveInstr instr -- ^ the instr to have its regs allocated, with liveness info. ===================================== compiler/GHC/CmmToAsm/Reg/Linear/StackMap.hs ===================================== @@ -37,7 +37,11 @@ data StackMap -- See Note [UniqFM and the register allocator] -- | Assignment of vregs to stack slots. - , stackMapAssignment :: UniqFM Unique StackSlot } + -- + -- We record not just the slot, but also how many stack slots the vreg + -- takes up, in order to avoid re-using a stack slot for a register + -- that has grown but already had a stack slot (#26668). + , stackMapAssignment :: UniqFM Unique (StackSlot, Int) } -- | An empty stack map, with all slots available. @@ -50,14 +54,19 @@ emptyStackMap = StackMap 0 emptyUFM -- getStackSlotFor :: StackMap -> Format -> Unique -> (StackMap, Int) -getStackSlotFor fs@(StackMap _ reserved) _fmt regUnique - | Just slot <- lookupUFM reserved regUnique = (fs, slot) - -getStackSlotFor (StackMap freeSlot reserved) fmt regUnique = - let - nbSlots = (formatInBytes fmt + 7) `div` 8 - in - (StackMap (freeSlot+nbSlots) (addToUFM reserved regUnique freeSlot), freeSlot) +getStackSlotFor fs@(StackMap freeSlot reserved) fmt regUnique + -- The register already has a stack slot; try to re-use it. + | Just (slot, nbSlots) <- lookupUFM reserved regUnique + -- Make sure the slot is big enough for this format, in case the register + -- has grown (#26668). + , nbNeededSlots <= nbSlots + = (fs, slot) + | otherwise + = (StackMap (freeSlot+nbNeededSlots) (addToUFM reserved regUnique (freeSlot, nbNeededSlots)), freeSlot) + -- NB: this can create fragmentation if a register keeps growing. + -- That's probably OK, as this is only happens very rarely. + where + !nbNeededSlots = (formatInBytes fmt + 7) `div` 8 -- | Return the number of stack slots that were allocated getStackUse :: StackMap -> Int View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/023c301c51e7346af3d4d773c448277a... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/023c301c51e7346af3d4d773c448277a... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Marge Bot (@marge-bot)