NCG: Refactor representation of code with liveness info
[ghc-hetmet.git] / compiler / nativeGen / AsmCodeGen.lhs
1 -- -----------------------------------------------------------------------------
2 --
3 -- (c) The University of Glasgow 1993-2004
4 -- 
5 -- This is the top-level module in the native code generator.
6 --
7 -- -----------------------------------------------------------------------------
8
9 \begin{code}
10 {-# OPTIONS -w #-}
11 -- The above warning supression flag is a temporary kludge.
12 -- While working on this module you are encouraged to remove it and fix
13 -- any warnings in the module. See
14 --     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
15 -- for details
16
17 module AsmCodeGen ( nativeCodeGen ) where
18
19 #include "HsVersions.h"
20 #include "nativeGen/NCG.h"
21
22
23 #if   alpha_TARGET_ARCH
24 import Alpha.CodeGen
25 import Alpha.Regs
26 import Alpha.RegInfo
27 import Alpha.Instr
28
29 #elif i386_TARGET_ARCH || x86_64_TARGET_ARCH
30 import X86.CodeGen
31 import X86.Regs
32 import X86.RegInfo
33 import X86.Instr
34 import X86.Ppr
35
36 #elif sparc_TARGET_ARCH
37 import SPARC.CodeGen
38 import SPARC.Regs
39 import SPARC.Instr
40 import SPARC.Ppr
41 import SPARC.ShortcutJump
42
43 #elif powerpc_TARGET_ARCH
44 import PPC.CodeGen
45 import PPC.Cond
46 import PPC.Regs
47 import PPC.RegInfo
48 import PPC.Instr
49 import PPC.Ppr
50
51 #else
52 #error "AsmCodeGen: unknown architecture"
53
54 #endif
55
56 import RegAlloc.Liveness
57 import qualified RegAlloc.Linear.Main           as Linear
58
59 import qualified GraphColor                     as Color
60 import qualified RegAlloc.Graph.Main            as Color
61 import qualified RegAlloc.Graph.Stats           as Color
62 import qualified RegAlloc.Graph.Coalesce        as Color
63 import qualified RegAlloc.Graph.TrivColorable   as Color
64
65 import qualified SPARC.CodeGen.Expand           as SPARC
66
67 import TargetReg
68 import Platform
69 import Instruction
70 import PIC
71 import Reg
72 import RegClass
73 import NCGMonad
74
75 import BlockId
76 import CgUtils          ( fixStgRegisters )
77 import Cmm
78 import CmmOpt           ( cmmMiniInline, cmmMachOpFold )
79 import PprCmm
80 import CLabel
81 import State
82
83 import UniqFM
84 import Unique           ( Unique, getUnique )
85 import UniqSupply
86 import DynFlags
87 #if powerpc_TARGET_ARCH
88 import StaticFlags      ( opt_Static, opt_PIC )
89 #endif
90 import Util
91 import Config           ( cProjectVersion )
92 import Module
93
94 import Digraph
95 import qualified Pretty
96 import BufWrite
97 import Outputable
98 import FastString
99 import UniqSet
100 import ErrUtils
101
102 -- DEBUGGING ONLY
103 --import OrdList
104
105 import Data.List
106 import Data.Int
107 import Data.Word
108 import Data.Bits
109 import Data.Maybe
110 import GHC.Exts
111 import Control.Monad
112 import System.IO
113
114 {-
115 The native-code generator has machine-independent and
116 machine-dependent modules.
117
118 This module ("AsmCodeGen") is the top-level machine-independent
119 module.  Before entering machine-dependent land, we do some
120 machine-independent optimisations (defined below) on the
121 'CmmStmts's.
122
123 We convert to the machine-specific 'Instr' datatype with
124 'cmmCodeGen', assuming an infinite supply of registers.  We then use
125 a machine-independent register allocator ('regAlloc') to rejoin
126 reality.  Obviously, 'regAlloc' has machine-specific helper
127 functions (see about "RegAllocInfo" below).
128
129 Finally, we order the basic blocks of the function so as to minimise
130 the number of jumps between blocks, by utilising fallthrough wherever
131 possible.
132
133 The machine-dependent bits break down as follows:
134
135   * ["MachRegs"]  Everything about the target platform's machine
136     registers (and immediate operands, and addresses, which tend to
137     intermingle/interact with registers).
138
139   * ["MachInstrs"]  Includes the 'Instr' datatype (possibly should
140     have a module of its own), plus a miscellany of other things
141     (e.g., 'targetDoubleSize', 'smStablePtrTable', ...)
142
143   * ["MachCodeGen"]  is where 'Cmm' stuff turns into
144     machine instructions.
145
146   * ["PprMach"] 'pprInstr' turns an 'Instr' into text (well, really
147     a 'Doc').
148
149   * ["RegAllocInfo"] In the register allocator, we manipulate
150     'MRegsState's, which are 'BitSet's, one bit per machine register.
151     When we want to say something about a specific machine register
152     (e.g., ``it gets clobbered by this instruction''), we set/unset
153     its bit.  Obviously, we do this 'BitSet' thing for efficiency
154     reasons.
155
156     The 'RegAllocInfo' module collects together the machine-specific
157     info needed to do register allocation.
158
159    * ["RegisterAlloc"] The (machine-independent) register allocator.
160 -}
161
162 -- -----------------------------------------------------------------------------
163 -- Top-level of the native codegen
164
165 --------------------
166 nativeCodeGen :: DynFlags -> Handle -> UniqSupply -> [RawCmm] -> IO ()
167 nativeCodeGen dflags h us cmms
168  = do
169         let split_cmms  = concat $ map add_split cmms
170
171         -- BufHandle is a performance hack.  We could hide it inside
172         -- Pretty if it weren't for the fact that we do lots of little
173         -- printDocs here (in order to do codegen in constant space).
174         bufh <- newBufHandle h
175         (imports, prof) <- cmmNativeGens dflags bufh us split_cmms [] [] 0
176         bFlush bufh
177
178         let (native, colorStats, linearStats)
179                 = unzip3 prof
180
181         -- dump native code
182         dumpIfSet_dyn dflags
183                 Opt_D_dump_asm "Asm code"
184                 (vcat $ map (docToSDoc . pprNatCmmTop) $ concat native)
185
186         -- dump global NCG stats for graph coloring allocator
187         (case concat $ catMaybes colorStats of
188           []    -> return ()
189           stats -> do   
190                 -- build the global register conflict graph
191                 let graphGlobal 
192                         = foldl Color.union Color.initGraph
193                         $ [ Color.raGraph stat
194                                 | stat@Color.RegAllocStatsStart{} <- stats]
195            
196                 dumpSDoc dflags Opt_D_dump_asm_stats "NCG stats"
197                         $ Color.pprStats stats graphGlobal
198
199                 dumpIfSet_dyn dflags
200                         Opt_D_dump_asm_conflicts "Register conflict graph"
201                         $ Color.dotGraph 
202                                 targetRegDotColor 
203                                 (Color.trivColorable 
204                                         targetVirtualRegSqueeze 
205                                         targetRealRegSqueeze)
206                         $ graphGlobal)
207
208
209         -- dump global NCG stats for linear allocator
210         (case concat $ catMaybes linearStats of
211                 []      -> return ()
212                 stats   -> dumpSDoc dflags Opt_D_dump_asm_stats "NCG stats"
213                                 $ Linear.pprStats (concat native) stats)
214
215         -- write out the imports
216         Pretty.printDoc Pretty.LeftMode h
217                 $ makeImportsDoc dflags (concat imports)
218
219         return  ()
220
221  where  add_split (Cmm tops)
222                 | dopt Opt_SplitObjs dflags = split_marker : tops
223                 | otherwise                 = tops
224
225         split_marker = CmmProc [] mkSplitMarkerLabel [] (ListGraph [])
226
227
228 -- | Do native code generation on all these cmms.
229 --
230 cmmNativeGens dflags h us [] impAcc profAcc count
231         = return (reverse impAcc, reverse profAcc)
232
233 cmmNativeGens dflags h us (cmm : cmms) impAcc profAcc count
234  = do
235         (us', native, imports, colorStats, linearStats)
236                 <- cmmNativeGen dflags us cmm count
237
238         Pretty.bufLeftRender h
239                 $ {-# SCC "pprNativeCode" #-} Pretty.vcat $ map pprNatCmmTop native
240
241            -- carefully evaluate this strictly.  Binding it with 'let'
242            -- and then using 'seq' doesn't work, because the let
243            -- apparently gets inlined first.
244         lsPprNative <- return $!
245                 if  dopt Opt_D_dump_asm       dflags
246                  || dopt Opt_D_dump_asm_stats dflags
247                         then native
248                         else []
249
250         count' <- return $! count + 1;
251
252         -- force evaulation all this stuff to avoid space leaks
253         seqString (showSDoc $ vcat $ map ppr imports) `seq` return ()
254
255         cmmNativeGens dflags h us' cmms
256                         (imports : impAcc)
257                         ((lsPprNative, colorStats, linearStats) : profAcc)
258                         count'
259
260  where  seqString []            = ()
261         seqString (x:xs)        = x `seq` seqString xs `seq` ()
262
263
264 -- | Complete native code generation phase for a single top-level chunk of Cmm.
265 --      Dumping the output of each stage along the way.
266 --      Global conflict graph and NGC stats
267 cmmNativeGen 
268         :: DynFlags
269         -> UniqSupply
270         -> RawCmmTop                                    -- ^ the cmm to generate code for
271         -> Int                                          -- ^ sequence number of this top thing
272         -> IO   ( UniqSupply
273                 , [NatCmmTop Instr]                     -- native code
274                 , [CLabel]                              -- things imported by this cmm
275                 , Maybe [Color.RegAllocStats Instr]     -- stats for the coloring register allocator
276                 , Maybe [Linear.RegAllocStats])         -- stats for the linear register allocators
277
278 cmmNativeGen dflags us cmm count
279  = do
280
281         -- rewrite assignments to global regs
282         let fixed_cmm =
283                 {-# SCC "fixStgRegisters" #-}
284                 fixStgRegisters cmm
285
286         -- cmm to cmm optimisations
287         let (opt_cmm, imports) =
288                 {-# SCC "cmmToCmm" #-}
289                 cmmToCmm dflags fixed_cmm
290
291         dumpIfSet_dyn dflags
292                 Opt_D_dump_opt_cmm "Optimised Cmm"
293                 (pprCmm $ Cmm [opt_cmm])
294
295         -- generate native code from cmm
296         let ((native, lastMinuteImports), usGen) =
297                 {-# SCC "genMachCode" #-}
298                 initUs us $ genMachCode dflags opt_cmm
299
300         dumpIfSet_dyn dflags
301                 Opt_D_dump_asm_native "Native code"
302                 (vcat $ map (docToSDoc . pprNatCmmTop) native)
303
304         -- tag instructions with register liveness information
305         let (withLiveness, usLive) =
306                 {-# SCC "regLiveness" #-}
307                 initUs usGen 
308                         $ mapUs regLiveness 
309                         $ map natCmmTopToLive native
310
311         dumpIfSet_dyn dflags
312                 Opt_D_dump_asm_liveness "Liveness annotations added"
313                 (vcat $ map ppr withLiveness)
314                 
315         -- allocate registers
316         (alloced, usAlloc, ppr_raStatsColor, ppr_raStatsLinear) <-
317          if ( dopt Opt_RegsGraph dflags
318            || dopt Opt_RegsIterative dflags)
319           then do
320                 -- the regs usable for allocation
321                 let (alloc_regs :: UniqFM (UniqSet RealReg))
322                         = foldr (\r -> plusUFM_C unionUniqSets
323                                         $ unitUFM (targetClassOfRealReg r) (unitUniqSet r))
324                                 emptyUFM
325                         $ allocatableRegs
326
327                 -- do the graph coloring register allocation
328                 let ((alloced, regAllocStats), usAlloc)
329                         = {-# SCC "RegAlloc" #-}
330                           initUs usLive
331                           $ Color.regAlloc
332                                 dflags
333                                 alloc_regs
334                                 (mkUniqSet [0..maxSpillSlots])
335                                 withLiveness
336
337                 -- dump out what happened during register allocation
338                 dumpIfSet_dyn dflags
339                         Opt_D_dump_asm_regalloc "Registers allocated"
340                         (vcat $ map (docToSDoc . pprNatCmmTop) alloced)
341
342                 dumpIfSet_dyn dflags
343                         Opt_D_dump_asm_regalloc_stages "Build/spill stages"
344                         (vcat   $ map (\(stage, stats)
345                                         -> text "# --------------------------"
346                                         $$ text "#  cmm " <> int count <> text " Stage " <> int stage
347                                         $$ ppr stats)
348                                 $ zip [0..] regAllocStats)
349
350                 let mPprStats =
351                         if dopt Opt_D_dump_asm_stats dflags
352                          then Just regAllocStats else Nothing
353
354                 -- force evaluation of the Maybe to avoid space leak
355                 mPprStats `seq` return ()
356
357                 return  ( alloced, usAlloc
358                         , mPprStats
359                         , Nothing)
360
361           else do
362                 -- do linear register allocation
363                 let ((alloced, regAllocStats), usAlloc) 
364                         = {-# SCC "RegAlloc" #-}
365                           initUs usLive
366                           $ liftM unzip
367                           $ mapUs Linear.regAlloc withLiveness
368
369                 dumpIfSet_dyn dflags
370                         Opt_D_dump_asm_regalloc "Registers allocated"
371                         (vcat $ map (docToSDoc . pprNatCmmTop) alloced)
372
373                 let mPprStats =
374                         if dopt Opt_D_dump_asm_stats dflags
375                          then Just (catMaybes regAllocStats) else Nothing
376
377                 -- force evaluation of the Maybe to avoid space leak
378                 mPprStats `seq` return ()
379
380                 return  ( alloced, usAlloc
381                         , Nothing
382                         , mPprStats)
383
384         ---- shortcut branches
385         let shorted     =
386                 {-# SCC "shortcutBranches" #-}
387                 shortcutBranches dflags alloced
388
389         ---- sequence blocks
390         let sequenced   =
391                 {-# SCC "sequenceBlocks" #-}
392                 map sequenceTop shorted
393
394         ---- x86fp_kludge
395         let kludged =
396 #if i386_TARGET_ARCH
397                 {-# SCC "x86fp_kludge" #-}
398                 map x86fp_kludge sequenced
399 #else
400                 sequenced
401 #endif
402
403         ---- expansion of SPARC synthetic instrs
404 #if sparc_TARGET_ARCH
405         let expanded = 
406                 {-# SCC "sparc_expand" #-}
407                 map SPARC.expandTop kludged
408
409         dumpIfSet_dyn dflags
410                 Opt_D_dump_asm_expanded "Synthetic instructions expanded"
411                 (vcat $ map (docToSDoc . pprNatCmmTop) expanded)
412 #else
413         let expanded = 
414                 kludged
415 #endif
416
417         return  ( usAlloc
418                 , expanded
419                 , lastMinuteImports ++ imports
420                 , ppr_raStatsColor
421                 , ppr_raStatsLinear)
422
423
424 #if i386_TARGET_ARCH
425 x86fp_kludge :: NatCmmTop Instr -> NatCmmTop Instr
426 x86fp_kludge top@(CmmData _ _) = top
427 x86fp_kludge top@(CmmProc info lbl params (ListGraph code)) = 
428         CmmProc info lbl params (ListGraph $ i386_insert_ffrees code)
429 #endif
430
431
432 -- | Build a doc for all the imports.
433 --
434 makeImportsDoc :: DynFlags -> [CLabel] -> Pretty.Doc
435 makeImportsDoc dflags imports
436  = dyld_stubs imports
437
438 #if HAVE_SUBSECTIONS_VIA_SYMBOLS
439                 -- On recent versions of Darwin, the linker supports
440                 -- dead-stripping of code and data on a per-symbol basis.
441                 -- There's a hack to make this work in PprMach.pprNatCmmTop.
442             Pretty.$$ Pretty.text ".subsections_via_symbols"
443 #endif
444 #if HAVE_GNU_NONEXEC_STACK
445                 -- On recent GNU ELF systems one can mark an object file
446                 -- as not requiring an executable stack. If all objects
447                 -- linked into a program have this note then the program
448                 -- will not use an executable stack, which is good for
449                 -- security. GHC generated code does not need an executable
450                 -- stack so add the note in:
451             Pretty.$$ Pretty.text ".section .note.GNU-stack,\"\",@progbits"
452 #endif
453 #if !defined(darwin_TARGET_OS)
454                 -- And just because every other compiler does, lets stick in
455                 -- an identifier directive: .ident "GHC x.y.z"
456             Pretty.$$ let compilerIdent = Pretty.text "GHC" Pretty.<+>
457                                           Pretty.text cProjectVersion
458                        in Pretty.text ".ident" Pretty.<+>
459                           Pretty.doubleQuotes compilerIdent
460 #endif
461
462  where
463         -- Generate "symbol stubs" for all external symbols that might
464         -- come from a dynamic library.
465         dyld_stubs :: [CLabel] -> Pretty.Doc
466 {-      dyld_stubs imps = Pretty.vcat $ map pprDyldSymbolStub $
467                                     map head $ group $ sort imps-}
468
469         arch    = platformArch  $ targetPlatform dflags
470         os      = platformOS    $ targetPlatform dflags
471         
472         -- (Hack) sometimes two Labels pretty-print the same, but have
473         -- different uniques; so we compare their text versions...
474         dyld_stubs imps
475                 | needImportedSymbols arch os
476                 = Pretty.vcat $
477                         (pprGotDeclaration arch os :) $
478                         map ( pprImportedSymbol arch os . fst . head) $
479                         groupBy (\(_,a) (_,b) -> a == b) $
480                         sortBy (\(_,a) (_,b) -> compare a b) $
481                         map doPpr $
482                         imps
483                 | otherwise
484                 = Pretty.empty
485
486         doPpr lbl = (lbl, Pretty.render $ pprCLabel lbl astyle)
487         astyle = mkCodeStyle AsmStyle
488
489
490 -- -----------------------------------------------------------------------------
491 -- Sequencing the basic blocks
492
493 -- Cmm BasicBlocks are self-contained entities: they always end in a
494 -- jump, either non-local or to another basic block in the same proc.
495 -- In this phase, we attempt to place the basic blocks in a sequence
496 -- such that as many of the local jumps as possible turn into
497 -- fallthroughs.
498
499 sequenceTop 
500         :: NatCmmTop Instr
501         -> NatCmmTop Instr
502
503 sequenceTop top@(CmmData _ _) = top
504 sequenceTop (CmmProc info lbl params (ListGraph blocks)) = 
505   CmmProc info lbl params (ListGraph $ makeFarBranches $ sequenceBlocks blocks)
506
507 -- The algorithm is very simple (and stupid): we make a graph out of
508 -- the blocks where there is an edge from one block to another iff the
509 -- first block ends by jumping to the second.  Then we topologically
510 -- sort this graph.  Then traverse the list: for each block, we first
511 -- output the block, then if it has an out edge, we move the
512 -- destination of the out edge to the front of the list, and continue.
513
514 -- FYI, the classic layout for basic blocks uses postorder DFS; this
515 -- algorithm is implemented in cmm/ZipCfg.hs (NR 6 Sep 2007).
516
517 sequenceBlocks 
518         :: Instruction instr
519         => [NatBasicBlock instr] 
520         -> [NatBasicBlock instr]
521
522 sequenceBlocks [] = []
523 sequenceBlocks (entry:blocks) = 
524   seqBlocks (mkNode entry : reverse (flattenSCCs (sccBlocks blocks)))
525   -- the first block is the entry point ==> it must remain at the start.
526
527
528 sccBlocks 
529         :: Instruction instr
530         => [NatBasicBlock instr] 
531         -> [SCC ( NatBasicBlock instr
532                 , Unique
533                 , [Unique])]
534
535 sccBlocks blocks = stronglyConnCompFromEdgedVerticesR (map mkNode blocks)
536
537 -- we're only interested in the last instruction of
538 -- the block, and only if it has a single destination.
539 getOutEdges 
540         :: Instruction instr
541         => [instr] -> [Unique]
542
543 getOutEdges instrs 
544         = case jumpDestsOfInstr (last instrs) of
545                 [one] -> [getUnique one]
546                 _many -> []
547
548 mkNode block@(BasicBlock id instrs) = (block, getUnique id, getOutEdges instrs)
549
550 seqBlocks [] = []
551 seqBlocks ((block,_,[]) : rest)
552   = block : seqBlocks rest
553 seqBlocks ((block@(BasicBlock id instrs),_,[next]) : rest)
554   | can_fallthrough = BasicBlock id (init instrs) : seqBlocks rest'
555   | otherwise       = block : seqBlocks rest'
556   where
557         (can_fallthrough, rest') = reorder next [] rest
558           -- TODO: we should do a better job for cycles; try to maximise the
559           -- fallthroughs within a loop.
560 seqBlocks _ = panic "AsmCodegen:seqBlocks"
561
562 reorder id accum [] = (False, reverse accum)
563 reorder id accum (b@(block,id',out) : rest)
564   | id == id'  = (True, (block,id,out) : reverse accum ++ rest)
565   | otherwise  = reorder id (b:accum) rest
566
567
568 -- -----------------------------------------------------------------------------
569 -- Making far branches
570
571 -- Conditional branches on PowerPC are limited to +-32KB; if our Procs get too
572 -- big, we have to work around this limitation.
573
574 makeFarBranches 
575         :: [NatBasicBlock Instr] 
576         -> [NatBasicBlock Instr]
577
578 #if powerpc_TARGET_ARCH
579 makeFarBranches blocks
580     | last blockAddresses < nearLimit = blocks
581     | otherwise = zipWith handleBlock blockAddresses blocks
582     where
583         blockAddresses = scanl (+) 0 $ map blockLen blocks
584         blockLen (BasicBlock _ instrs) = length instrs
585         
586         handleBlock addr (BasicBlock id instrs)
587                 = BasicBlock id (zipWith makeFar [addr..] instrs)
588         
589         makeFar addr (BCC ALWAYS tgt) = BCC ALWAYS tgt
590         makeFar addr (BCC cond tgt)
591             | abs (addr - targetAddr) >= nearLimit
592             = BCCFAR cond tgt
593             | otherwise
594             = BCC cond tgt
595             where Just targetAddr = lookupUFM blockAddressMap tgt
596         makeFar addr other            = other
597         
598         nearLimit = 7000 -- 8192 instructions are allowed; let's keep some
599                          -- distance, as we have a few pseudo-insns that are
600                          -- pretty-printed as multiple instructions,
601                          -- and it's just not worth the effort to calculate
602                          -- things exactly
603         
604         blockAddressMap = listToUFM $ zip (map blockId blocks) blockAddresses
605 #else
606 makeFarBranches = id
607 #endif
608
609 -- -----------------------------------------------------------------------------
610 -- Shortcut branches
611
612 shortcutBranches 
613         :: DynFlags 
614         -> [NatCmmTop Instr] 
615         -> [NatCmmTop Instr]
616
617 shortcutBranches dflags tops
618   | optLevel dflags < 1 = tops    -- only with -O or higher
619   | otherwise           = map (apply_mapping mapping) tops'
620   where
621     (tops', mappings) = mapAndUnzip build_mapping tops
622     mapping = foldr plusUFM emptyUFM mappings
623
624 build_mapping top@(CmmData _ _) = (top, emptyUFM)
625 build_mapping (CmmProc info lbl params (ListGraph []))
626   = (CmmProc info lbl params (ListGraph []), emptyUFM)
627 build_mapping (CmmProc info lbl params (ListGraph (head:blocks)))
628   = (CmmProc info lbl params (ListGraph (head:others)), mapping)
629         -- drop the shorted blocks, but don't ever drop the first one,
630         -- because it is pointed to by a global label.
631   where
632     -- find all the blocks that just consist of a jump that can be
633     -- shorted.
634     -- Don't completely eliminate loops here -- that can leave a dangling jump!
635     (_, shortcut_blocks, others) = foldl split (emptyBlockSet, [], []) blocks
636     split (s, shortcut_blocks, others) b@(BasicBlock id [insn])
637         | Just (DestBlockId dest) <- canShortcut insn,
638           (elemBlockSet dest s) || dest == id -- loop checks
639         = (s, shortcut_blocks, b : others)
640     split (s, shortcut_blocks, others) (BasicBlock id [insn])
641         | Just dest <- canShortcut insn
642         = (extendBlockSet s id, (id,dest) : shortcut_blocks, others)
643     split (s, shortcut_blocks, others) other = (s, shortcut_blocks, other : others)
644
645
646     -- build a mapping from BlockId to JumpDest for shorting branches
647     mapping = foldl add emptyUFM shortcut_blocks
648     add ufm (id,dest) = addToUFM ufm id dest
649     
650 apply_mapping ufm (CmmData sec statics) 
651   = CmmData sec (map (shortcutStatic (lookupUFM ufm)) statics)
652   -- we need to get the jump tables, so apply the mapping to the entries
653   -- of a CmmData too.
654 apply_mapping ufm (CmmProc info lbl params (ListGraph blocks))
655   = CmmProc info lbl params (ListGraph $ map short_bb blocks)
656   where
657     short_bb (BasicBlock id insns) = BasicBlock id $! map short_insn insns
658     short_insn i = shortcutJump (lookupUFM ufm) i
659                  -- shortcutJump should apply the mapping repeatedly,
660                  -- just in case we can short multiple branches.
661
662 -- -----------------------------------------------------------------------------
663 -- Instruction selection
664
665 -- Native code instruction selection for a chunk of stix code.  For
666 -- this part of the computation, we switch from the UniqSM monad to
667 -- the NatM monad.  The latter carries not only a Unique, but also an
668 -- Int denoting the current C stack pointer offset in the generated
669 -- code; this is needed for creating correct spill offsets on
670 -- architectures which don't offer, or for which it would be
671 -- prohibitively expensive to employ, a frame pointer register.  Viz,
672 -- x86.
673
674 -- The offset is measured in bytes, and indicates the difference
675 -- between the current (simulated) C stack-ptr and the value it was at
676 -- the beginning of the block.  For stacks which grow down, this value
677 -- should be either zero or negative.
678
679 -- Switching between the two monads whilst carrying along the same
680 -- Unique supply breaks abstraction.  Is that bad?
681
682 genMachCode 
683         :: DynFlags 
684         -> RawCmmTop 
685         -> UniqSM 
686                 ( [NatCmmTop Instr]
687                 , [CLabel])
688
689 genMachCode dflags cmm_top
690   = do  { initial_us <- getUs
691         ; let initial_st           = mkNatM_State initial_us 0 dflags
692               (new_tops, final_st) = initNat initial_st (cmmTopCodeGen dflags cmm_top)
693               final_delta          = natm_delta final_st
694               final_imports        = natm_imports final_st
695         ; if   final_delta == 0
696           then return (new_tops, final_imports)
697           else pprPanic "genMachCode: nonzero final delta" (int final_delta)
698     }
699
700
701 -- -----------------------------------------------------------------------------
702 -- Generic Cmm optimiser
703
704 {-
705 Here we do:
706
707   (a) Constant folding
708   (b) Simple inlining: a temporary which is assigned to and then
709       used, once, can be shorted.
710   (c) Position independent code and dynamic linking
711         (i)  introduce the appropriate indirections
712              and position independent refs
713         (ii) compile a list of imported symbols
714
715 Ideas for other things we could do (ToDo):
716
717   - shortcut jumps-to-jumps
718   - eliminate dead code blocks
719   - simple CSE: if an expr is assigned to a temp, then replace later occs of
720     that expr with the temp, until the expr is no longer valid (can push through
721     temp assignments, and certain assigns to mem...)
722 -}
723
724 cmmToCmm :: DynFlags -> RawCmmTop -> (RawCmmTop, [CLabel])
725 cmmToCmm _ top@(CmmData _ _) = (top, [])
726 cmmToCmm dflags (CmmProc info lbl params (ListGraph blocks)) = runCmmOpt dflags $ do
727   blocks' <- mapM cmmBlockConFold (cmmMiniInline blocks)
728   return $ CmmProc info lbl params (ListGraph blocks')
729
730 newtype CmmOptM a = CmmOptM (([CLabel], DynFlags) -> (# a, [CLabel] #))
731
732 instance Monad CmmOptM where
733   return x = CmmOptM $ \(imports, _) -> (# x,imports #)
734   (CmmOptM f) >>= g =
735     CmmOptM $ \(imports, dflags) ->
736                 case f (imports, dflags) of
737                   (# x, imports' #) ->
738                     case g x of
739                       CmmOptM g' -> g' (imports', dflags)
740
741 addImportCmmOpt :: CLabel -> CmmOptM ()
742 addImportCmmOpt lbl = CmmOptM $ \(imports, dflags) -> (# (), lbl:imports #)
743
744 getDynFlagsCmmOpt :: CmmOptM DynFlags
745 getDynFlagsCmmOpt = CmmOptM $ \(imports, dflags) -> (# dflags, imports #)
746
747 runCmmOpt :: DynFlags -> CmmOptM a -> (a, [CLabel])
748 runCmmOpt dflags (CmmOptM f) = case f ([], dflags) of
749                         (# result, imports #) -> (result, imports)
750
751 cmmBlockConFold :: CmmBasicBlock -> CmmOptM CmmBasicBlock
752 cmmBlockConFold (BasicBlock id stmts) = do
753   stmts' <- mapM cmmStmtConFold stmts
754   return $ BasicBlock id stmts'
755
756 cmmStmtConFold stmt
757    = case stmt of
758         CmmAssign reg src
759            -> do src' <- cmmExprConFold DataReference src
760                  return $ case src' of
761                    CmmReg reg' | reg == reg' -> CmmNop
762                    new_src -> CmmAssign reg new_src
763
764         CmmStore addr src
765            -> do addr' <- cmmExprConFold DataReference addr
766                  src'  <- cmmExprConFold DataReference src
767                  return $ CmmStore addr' src'
768
769         CmmJump addr regs
770            -> do addr' <- cmmExprConFold JumpReference addr
771                  return $ CmmJump addr' regs
772
773         CmmCall target regs args srt returns
774            -> do target' <- case target of
775                               CmmCallee e conv -> do
776                                 e' <- cmmExprConFold CallReference e
777                                 return $ CmmCallee e' conv
778                               other -> return other
779                  args' <- mapM (\(CmmHinted arg hint) -> do
780                                   arg' <- cmmExprConFold DataReference arg
781                                   return (CmmHinted arg' hint)) args
782                  return $ CmmCall target' regs args' srt returns
783
784         CmmCondBranch test dest
785            -> do test' <- cmmExprConFold DataReference test
786                  return $ case test' of
787                    CmmLit (CmmInt 0 _) -> 
788                      CmmComment (mkFastString ("deleted: " ++ 
789                                         showSDoc (pprStmt stmt)))
790
791                    CmmLit (CmmInt n _) -> CmmBranch dest
792                    other -> CmmCondBranch test' dest
793
794         CmmSwitch expr ids
795            -> do expr' <- cmmExprConFold DataReference expr
796                  return $ CmmSwitch expr' ids
797
798         other
799            -> return other
800
801
802 cmmExprConFold referenceKind expr
803    = case expr of
804         CmmLoad addr rep
805            -> do addr' <- cmmExprConFold DataReference addr
806                  return $ CmmLoad addr' rep
807
808         CmmMachOp mop args
809            -- For MachOps, we first optimize the children, and then we try 
810            -- our hand at some constant-folding.
811            -> do args' <- mapM (cmmExprConFold DataReference) args
812                  return $ cmmMachOpFold mop args'
813
814         CmmLit (CmmLabel lbl)
815            -> do
816                 dflags <- getDynFlagsCmmOpt
817                 cmmMakeDynamicReference dflags addImportCmmOpt referenceKind lbl
818         CmmLit (CmmLabelOff lbl off)
819            -> do
820                  dflags <- getDynFlagsCmmOpt
821                  dynRef <- cmmMakeDynamicReference dflags addImportCmmOpt referenceKind lbl
822                  return $ cmmMachOpFold (MO_Add wordWidth) [
823                      dynRef,
824                      (CmmLit $ CmmInt (fromIntegral off) wordWidth)
825                    ]
826
827 #if powerpc_TARGET_ARCH
828            -- On powerpc (non-PIC), it's easier to jump directly to a label than
829            -- to use the register table, so we replace these registers
830            -- with the corresponding labels:
831         CmmReg (CmmGlobal EagerBlackholeInfo)
832           | not opt_PIC
833           -> cmmExprConFold referenceKind $
834              CmmLit (CmmLabel (mkCmmCodeLabel rtsPackageId (fsLit "__stg_EAGER_BLACKHOLE_info")))
835         CmmReg (CmmGlobal GCEnter1)
836           | not opt_PIC
837           -> cmmExprConFold referenceKind $
838              CmmLit (CmmLabel (mkCmmCodeLabel rtsPackageId (fsLit "__stg_gc_enter_1"))) 
839         CmmReg (CmmGlobal GCFun)
840           | not opt_PIC
841           -> cmmExprConFold referenceKind $
842              CmmLit (CmmLabel (mkCmmCodeLabel rtsPackageId (fsLit "__stg_gc_fun")))
843 #endif
844
845         other
846            -> return other
847
848 \end{code}
849