Commit 8a0ab97b authored by Edward Z. Yang's avatar Edward Z. Yang
Browse files

Unsafe foreign calls (fat machine instructions) do not kill all registers.



The new code generator was doing some interesting spilling across
unsafe foreign calls:

     _c1ao::I32 = Hp - 4;
     I32[Sp - 20] = _c1ao::I32;
     foreign "ccall"
       newCAF((BaseReg, PtrHint), (R1, PtrHint))[_unsafe_call_];
     _c1ao::I32 = I32[Sp - 20];

This is fairly unnecessary, and resulted from over-conservative
liveness analysis from CmmLive.  We can see that the old code
generator only saved volatile registers across unsafe foreign calls:
spilling variables was done by saveVolatileVarsAndRegs, which was
only performed for ordinary calls.

This commit removes the excess kill from the liveness analysis, as well
as the *redundant* excess kill from spilling-and-reloading, and adds a
note to CmmNode to this effect.  The only registers we need to kill
are the ones that the foreign call assigns to, just like any other
machine instruction.
Signed-off-by: Edward Z. Yang's avatarEdward Z. Yang <ezyang@mit.edu>
parent 1fb38442
...@@ -63,12 +63,12 @@ gen a live = foldRegsUsed extendRegSet live a ...@@ -63,12 +63,12 @@ gen a live = foldRegsUsed extendRegSet live a
kill :: DefinerOfLocalRegs a => a -> RegSet -> RegSet kill :: DefinerOfLocalRegs a => a -> RegSet -> RegSet
kill a live = foldRegsDefd delOneFromUniqSet live a kill a live = foldRegsDefd delOneFromUniqSet live a
-- Testing!
xferLive :: BwdTransfer CmmNode CmmLive xferLive :: BwdTransfer CmmNode CmmLive
xferLive = mkBTransfer3 fst mid lst xferLive = mkBTransfer3 fst mid lst
where fst _ f = f where fst _ f = f
mid :: CmmNode O O -> CmmLive -> CmmLive mid :: CmmNode O O -> CmmLive -> CmmLive
mid n f = gen_kill n $ case n of CmmUnsafeForeignCall {} -> emptyRegSet mid n f = gen_kill n f
_ -> f
lst :: CmmNode O C -> FactBase CmmLive -> CmmLive lst :: CmmNode O C -> FactBase CmmLive -> CmmLive
lst n f = gen_kill n $ case n of CmmCall {} -> emptyRegSet lst n f = gen_kill n $ case n of CmmCall {} -> emptyRegSet
CmmForeignCall {} -> emptyRegSet CmmForeignCall {} -> emptyRegSet
......
...@@ -92,6 +92,8 @@ data CmmNode e x where ...@@ -92,6 +92,8 @@ data CmmNode e x where
A MidForeign call is used for *unsafe* foreign calls; A MidForeign call is used for *unsafe* foreign calls;
a LastForeign call is used for *safe* foreign calls. a LastForeign call is used for *safe* foreign calls.
Unsafe ones are easy: think of them as a "fat machine instruction". Unsafe ones are easy: think of them as a "fat machine instruction".
In particular, they do *not* kill all live registers (there was a bit
of code in GHC that conservatively assumed otherwise.)
Safe ones are trickier. A safe foreign call Safe ones are trickier. A safe foreign call
r = f(x) r = f(x)
......
...@@ -100,11 +100,11 @@ dualLiveTransfers entry procPoints = mkBTransfer3 first middle last ...@@ -100,11 +100,11 @@ dualLiveTransfers entry procPoints = mkBTransfer3 first middle last
where check live id x = if id == entry then noLiveOnEntry id (in_regs live) x else x where check live id x = if id == entry then noLiveOnEntry id (in_regs live) x else x
middle :: CmmNode O O -> DualLive -> DualLive middle :: CmmNode O O -> DualLive -> DualLive
middle m live = changeStack updSlots $ changeRegs (xferLiveMiddle m) (changeRegs regs_in live) middle m = changeStack updSlots
where xferLiveMiddle = case getBTransfer3 xferLive of (_, middle, _) -> middle . changeRegs updRegs
regs_in :: RegSet -> RegSet where -- Reuse middle of liveness analysis from CmmLive
regs_in live = case m of CmmUnsafeForeignCall {} -> emptyRegSet updRegs = case getBTransfer3 xferLive of (_, middle, _) -> middle m
_ -> live
updSlots live = foldSlotsUsed reload (foldSlotsDefd spill live m) m updSlots live = foldSlotsUsed reload (foldSlotsDefd spill live m) m
spill live s@(RegSlot r, _, _) = check s $ deleteFromRegSet live r spill live s@(RegSlot r, _, _) = check s $ deleteFromRegSet live r
spill live _ = live spill live _ = live
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment