Split Reg into vreg/hreg and add register pairs
[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 Cmm
76 import CmmOpt           ( cmmMiniInline, cmmMachOpFold )
77 import PprCmm
78 import CLabel
79 import State
80
81 import UniqFM
82 import Unique           ( Unique, getUnique )
83 import UniqSupply
84 import List             ( groupBy, sortBy )
85 import DynFlags
86 #if powerpc_TARGET_ARCH
87 import StaticFlags      ( opt_Static, opt_PIC )
88 #endif
89 import Util
90 import Config           ( cProjectVersion )
91 import Module
92
93 import Digraph
94 import qualified Pretty
95 import BufWrite
96 import Outputable
97 import FastString
98 import UniqSet
99 import ErrUtils
100
101 -- DEBUGGING ONLY
102 --import OrdList
103
104 import Data.List
105 import Data.Int
106 import Data.Word
107 import Data.Bits
108 import Data.Maybe
109 import GHC.Exts
110 import Control.Monad
111 import System.IO
112
113 {-
114 The native-code generator has machine-independent and
115 machine-dependent modules.
116
117 This module ("AsmCodeGen") is the top-level machine-independent
118 module.  Before entering machine-dependent land, we do some
119 machine-independent optimisations (defined below) on the
120 'CmmStmts's.
121
122 We convert to the machine-specific 'Instr' datatype with
123 'cmmCodeGen', assuming an infinite supply of registers.  We then use
124 a machine-independent register allocator ('regAlloc') to rejoin
125 reality.  Obviously, 'regAlloc' has machine-specific helper
126 functions (see about "RegAllocInfo" below).
127
128 Finally, we order the basic blocks of the function so as to minimise
129 the number of jumps between blocks, by utilising fallthrough wherever
130 possible.
131
132 The machine-dependent bits break down as follows:
133
134   * ["MachRegs"]  Everything about the target platform's machine
135     registers (and immediate operands, and addresses, which tend to
136     intermingle/interact with registers).
137
138   * ["MachInstrs"]  Includes the 'Instr' datatype (possibly should
139     have a module of its own), plus a miscellany of other things
140     (e.g., 'targetDoubleSize', 'smStablePtrTable', ...)
141
142   * ["MachCodeGen"]  is where 'Cmm' stuff turns into
143     machine instructions.
144
145   * ["PprMach"] 'pprInstr' turns an 'Instr' into text (well, really
146     a 'Doc').
147
148   * ["RegAllocInfo"] In the register allocator, we manipulate
149     'MRegsState's, which are 'BitSet's, one bit per machine register.
150     When we want to say something about a specific machine register
151     (e.g., ``it gets clobbered by this instruction''), we set/unset
152     its bit.  Obviously, we do this 'BitSet' thing for efficiency
153     reasons.
154
155     The 'RegAllocInfo' module collects together the machine-specific
156     info needed to do register allocation.
157
158    * ["RegisterAlloc"] The (machine-independent) register allocator.
159 -}
160
161 -- -----------------------------------------------------------------------------
162 -- Top-level of the native codegen
163
164 --------------------
165 nativeCodeGen :: DynFlags -> Handle -> UniqSupply -> [RawCmm] -> IO ()
166 nativeCodeGen dflags h us cmms
167  = do
168         let split_cmms  = concat $ map add_split cmms
169
170         -- BufHandle is a performance hack.  We could hide it inside
171         -- Pretty if it weren't for the fact that we do lots of little
172         -- printDocs here (in order to do codegen in constant space).
173         bufh <- newBufHandle h
174         (imports, prof) <- cmmNativeGens dflags bufh us split_cmms [] [] 0
175         bFlush bufh
176
177         let (native, colorStats, linearStats)
178                 = unzip3 prof
179
180         -- dump native code
181         dumpIfSet_dyn dflags
182                 Opt_D_dump_asm "Asm code"
183                 (vcat $ map (docToSDoc . pprNatCmmTop) $ concat native)
184
185         -- dump global NCG stats for graph coloring allocator
186         (case concat $ catMaybes colorStats of
187           []    -> return ()
188           stats -> do   
189                 -- build the global register conflict graph
190                 let graphGlobal 
191                         = foldl Color.union Color.initGraph
192                         $ [ Color.raGraph stat
193                                 | stat@Color.RegAllocStatsStart{} <- stats]
194            
195                 dumpSDoc dflags Opt_D_dump_asm_stats "NCG stats"
196                         $ Color.pprStats stats graphGlobal
197
198                 dumpIfSet_dyn dflags
199                         Opt_D_dump_asm_conflicts "Register conflict graph"
200                         $ Color.dotGraph 
201                                 targetRegDotColor 
202                                 (Color.trivColorable 
203                                         targetVirtualRegSqueeze 
204                                         targetRealRegSqueeze)
205                         $ graphGlobal)
206
207
208         -- dump global NCG stats for linear allocator
209         (case concat $ catMaybes linearStats of
210                 []      -> return ()
211                 stats   -> dumpSDoc dflags Opt_D_dump_asm_stats "NCG stats"
212                                 $ Linear.pprStats (concat native) stats)
213
214         -- write out the imports
215         Pretty.printDoc Pretty.LeftMode h
216                 $ makeImportsDoc dflags (concat imports)
217
218         return  ()
219
220  where  add_split (Cmm tops)
221                 | dopt Opt_SplitObjs dflags = split_marker : tops
222                 | otherwise                 = tops
223
224         split_marker = CmmProc [] mkSplitMarkerLabel [] (ListGraph [])
225
226
227 -- | Do native code generation on all these cmms.
228 --
229 cmmNativeGens dflags h us [] impAcc profAcc count
230         = return (reverse impAcc, reverse profAcc)
231
232 cmmNativeGens dflags h us (cmm : cmms) impAcc profAcc count
233  = do
234         (us', native, imports, colorStats, linearStats)
235                 <- cmmNativeGen dflags us cmm count
236
237         Pretty.bufLeftRender h
238                 $ {-# SCC "pprNativeCode" #-} Pretty.vcat $ map pprNatCmmTop native
239
240         let lsPprNative =
241                 if  dopt Opt_D_dump_asm       dflags
242                  || dopt Opt_D_dump_asm_stats dflags
243                         then native
244                         else []
245
246         let count'      = count + 1;
247
248
249         -- force evaulation all this stuff to avoid space leaks
250         seqString (showSDoc $ vcat $ map ppr imports) `seq` return ()
251         lsPprNative     `seq` return ()
252         count'          `seq` return ()
253
254         cmmNativeGens dflags h us' cmms
255                         (imports : impAcc)
256                         ((lsPprNative, colorStats, linearStats) : profAcc)
257                         count'
258
259  where  seqString []            = ()
260         seqString (x:xs)        = x `seq` seqString xs `seq` ()
261
262
263 -- | Complete native code generation phase for a single top-level chunk of Cmm.
264 --      Dumping the output of each stage along the way.
265 --      Global conflict graph and NGC stats
266 cmmNativeGen 
267         :: DynFlags
268         -> UniqSupply
269         -> RawCmmTop                                    -- ^ the cmm to generate code for
270         -> Int                                          -- ^ sequence number of this top thing
271         -> IO   ( UniqSupply
272                 , [NatCmmTop Instr]                     -- native code
273                 , [CLabel]                              -- things imported by this cmm
274                 , Maybe [Color.RegAllocStats Instr]     -- stats for the coloring register allocator
275                 , Maybe [Linear.RegAllocStats])         -- stats for the linear register allocators
276
277 cmmNativeGen dflags us cmm count
278  = do
279
280         -- rewrite assignments to global regs
281         let (fixed_cmm, usFix)  =
282                 {-# SCC "fixAssignsTop" #-}
283                 initUs us $ fixAssignsTop cmm
284
285         -- cmm to cmm optimisations
286         let (opt_cmm, imports) =
287                 {-# SCC "cmmToCmm" #-}
288                 cmmToCmm dflags fixed_cmm
289
290         dumpIfSet_dyn dflags
291                 Opt_D_dump_opt_cmm "Optimised Cmm"
292                 (pprCmm $ Cmm [opt_cmm])
293
294         -- generate native code from cmm
295         let ((native, lastMinuteImports), usGen) =
296                 {-# SCC "genMachCode" #-}
297                 initUs usFix $ genMachCode dflags opt_cmm
298
299         dumpIfSet_dyn dflags
300                 Opt_D_dump_asm_native "Native code"
301                 (vcat $ map (docToSDoc . pprNatCmmTop) native)
302
303
304         -- tag instructions with register liveness information
305         let (withLiveness, usLive) =
306                 {-# SCC "regLiveness" #-}
307                 initUs usGen $ mapUs regLiveness native
308
309         dumpIfSet_dyn dflags
310                 Opt_D_dump_asm_liveness "Liveness annotations added"
311                 (vcat $ map ppr withLiveness)
312
313                 
314         -- allocate registers
315         (alloced, usAlloc, ppr_raStatsColor, ppr_raStatsLinear) <-
316          if ( dopt Opt_RegsGraph dflags
317            || dopt Opt_RegsIterative dflags)
318           then do
319                 -- the regs usable for allocation
320                 let (alloc_regs :: UniqFM (UniqSet RealReg))
321                         = foldr (\r -> plusUFM_C unionUniqSets
322                                         $ unitUFM (targetClassOfRealReg r) (unitUniqSet r))
323                                 emptyUFM
324                         $ allocatableRegs
325
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     (shortcut_blocks, others) = partitionWith split blocks
635     split (BasicBlock id [insn]) | Just dest <- canShortcut insn 
636                                  = Left (id,dest)
637     split other = Right other
638
639     -- build a mapping from BlockId to JumpDest for shorting branches
640     mapping = foldl add emptyUFM shortcut_blocks
641     add ufm (id,dest) = addToUFM ufm id dest
642     
643 apply_mapping ufm (CmmData sec statics) 
644   = CmmData sec (map (shortcutStatic (lookupUFM ufm)) statics)
645   -- we need to get the jump tables, so apply the mapping to the entries
646   -- of a CmmData too.
647 apply_mapping ufm (CmmProc info lbl params (ListGraph blocks))
648   = CmmProc info lbl params (ListGraph $ map short_bb blocks)
649   where
650     short_bb (BasicBlock id insns) = BasicBlock id $! map short_insn insns
651     short_insn i = shortcutJump (lookupUFM ufm) i
652                  -- shortcutJump should apply the mapping repeatedly,
653                  -- just in case we can short multiple branches.
654
655 -- -----------------------------------------------------------------------------
656 -- Instruction selection
657
658 -- Native code instruction selection for a chunk of stix code.  For
659 -- this part of the computation, we switch from the UniqSM monad to
660 -- the NatM monad.  The latter carries not only a Unique, but also an
661 -- Int denoting the current C stack pointer offset in the generated
662 -- code; this is needed for creating correct spill offsets on
663 -- architectures which don't offer, or for which it would be
664 -- prohibitively expensive to employ, a frame pointer register.  Viz,
665 -- x86.
666
667 -- The offset is measured in bytes, and indicates the difference
668 -- between the current (simulated) C stack-ptr and the value it was at
669 -- the beginning of the block.  For stacks which grow down, this value
670 -- should be either zero or negative.
671
672 -- Switching between the two monads whilst carrying along the same
673 -- Unique supply breaks abstraction.  Is that bad?
674
675 genMachCode 
676         :: DynFlags 
677         -> RawCmmTop 
678         -> UniqSM 
679                 ( [NatCmmTop Instr]
680                 , [CLabel])
681
682 genMachCode dflags cmm_top
683   = do  { initial_us <- getUs
684         ; let initial_st           = mkNatM_State initial_us 0 dflags
685               (new_tops, final_st) = initNat initial_st (cmmTopCodeGen dflags cmm_top)
686               final_delta          = natm_delta final_st
687               final_imports        = natm_imports final_st
688         ; if   final_delta == 0
689           then return (new_tops, final_imports)
690           else pprPanic "genMachCode: nonzero final delta" (int final_delta)
691     }
692
693 -- -----------------------------------------------------------------------------
694 -- Fixup assignments to global registers so that they assign to 
695 -- locations within the RegTable, if appropriate.
696
697 -- Note that we currently don't fixup reads here: they're done by
698 -- the generic optimiser below, to avoid having two separate passes
699 -- over the Cmm.
700
701 fixAssignsTop :: RawCmmTop -> UniqSM RawCmmTop
702 fixAssignsTop top@(CmmData _ _) = returnUs top
703 fixAssignsTop (CmmProc info lbl params (ListGraph blocks)) =
704   mapUs fixAssignsBlock blocks `thenUs` \ blocks' ->
705   returnUs (CmmProc info lbl params (ListGraph blocks'))
706
707 fixAssignsBlock :: CmmBasicBlock -> UniqSM CmmBasicBlock
708 fixAssignsBlock (BasicBlock id stmts) =
709   fixAssigns stmts `thenUs` \ stmts' ->
710   returnUs (BasicBlock id stmts')
711
712 fixAssigns :: [CmmStmt] -> UniqSM [CmmStmt]
713 fixAssigns stmts =
714   mapUs fixAssign stmts `thenUs` \ stmtss ->
715   returnUs (concat stmtss)
716
717 fixAssign :: CmmStmt -> UniqSM [CmmStmt]
718 fixAssign (CmmAssign (CmmGlobal reg) src)
719   | Left  realreg <- reg_or_addr
720   = returnUs [CmmAssign (CmmGlobal reg) src]
721   | Right baseRegAddr <- reg_or_addr
722   = returnUs [CmmStore baseRegAddr src]
723            -- Replace register leaves with appropriate StixTrees for
724            -- the given target. GlobalRegs which map to a reg on this
725            -- arch are left unchanged.  Assigning to BaseReg is always
726            -- illegal, so we check for that.
727   where
728         reg_or_addr = get_GlobalReg_reg_or_addr reg
729
730 fixAssign other_stmt = returnUs [other_stmt]
731
732 -- -----------------------------------------------------------------------------
733 -- Generic Cmm optimiser
734
735 {-
736 Here we do:
737
738   (a) Constant folding
739   (b) Simple inlining: a temporary which is assigned to and then
740       used, once, can be shorted.
741   (c) Replacement of references to GlobalRegs which do not have
742       machine registers by the appropriate memory load (eg.
743       Hp ==>  *(BaseReg + 34) ).
744   (d) Position independent code and dynamic linking
745         (i)  introduce the appropriate indirections
746              and position independent refs
747         (ii) compile a list of imported symbols
748
749 Ideas for other things we could do (ToDo):
750
751   - shortcut jumps-to-jumps
752   - eliminate dead code blocks
753   - simple CSE: if an expr is assigned to a temp, then replace later occs of
754     that expr with the temp, until the expr is no longer valid (can push through
755     temp assignments, and certain assigns to mem...)
756 -}
757
758 cmmToCmm :: DynFlags -> RawCmmTop -> (RawCmmTop, [CLabel])
759 cmmToCmm _ top@(CmmData _ _) = (top, [])
760 cmmToCmm dflags (CmmProc info lbl params (ListGraph blocks)) = runCmmOpt dflags $ do
761   blocks' <- mapM cmmBlockConFold (cmmMiniInline blocks)
762   return $ CmmProc info lbl params (ListGraph blocks')
763
764 newtype CmmOptM a = CmmOptM (([CLabel], DynFlags) -> (# a, [CLabel] #))
765
766 instance Monad CmmOptM where
767   return x = CmmOptM $ \(imports, _) -> (# x,imports #)
768   (CmmOptM f) >>= g =
769     CmmOptM $ \(imports, dflags) ->
770                 case f (imports, dflags) of
771                   (# x, imports' #) ->
772                     case g x of
773                       CmmOptM g' -> g' (imports', dflags)
774
775 addImportCmmOpt :: CLabel -> CmmOptM ()
776 addImportCmmOpt lbl = CmmOptM $ \(imports, dflags) -> (# (), lbl:imports #)
777
778 getDynFlagsCmmOpt :: CmmOptM DynFlags
779 getDynFlagsCmmOpt = CmmOptM $ \(imports, dflags) -> (# dflags, imports #)
780
781 runCmmOpt :: DynFlags -> CmmOptM a -> (a, [CLabel])
782 runCmmOpt dflags (CmmOptM f) = case f ([], dflags) of
783                         (# result, imports #) -> (result, imports)
784
785 cmmBlockConFold :: CmmBasicBlock -> CmmOptM CmmBasicBlock
786 cmmBlockConFold (BasicBlock id stmts) = do
787   stmts' <- mapM cmmStmtConFold stmts
788   return $ BasicBlock id stmts'
789
790 cmmStmtConFold stmt
791    = case stmt of
792         CmmAssign reg src
793            -> do src' <- cmmExprConFold DataReference src
794                  return $ case src' of
795                    CmmReg reg' | reg == reg' -> CmmNop
796                    new_src -> CmmAssign reg new_src
797
798         CmmStore addr src
799            -> do addr' <- cmmExprConFold DataReference addr
800                  src'  <- cmmExprConFold DataReference src
801                  return $ CmmStore addr' src'
802
803         CmmJump addr regs
804            -> do addr' <- cmmExprConFold JumpReference addr
805                  return $ CmmJump addr' regs
806
807         CmmCall target regs args srt returns
808            -> do target' <- case target of
809                               CmmCallee e conv -> do
810                                 e' <- cmmExprConFold CallReference e
811                                 return $ CmmCallee e' conv
812                               other -> return other
813                  args' <- mapM (\(CmmHinted arg hint) -> do
814                                   arg' <- cmmExprConFold DataReference arg
815                                   return (CmmHinted arg' hint)) args
816                  return $ CmmCall target' regs args' srt returns
817
818         CmmCondBranch test dest
819            -> do test' <- cmmExprConFold DataReference test
820                  return $ case test' of
821                    CmmLit (CmmInt 0 _) -> 
822                      CmmComment (mkFastString ("deleted: " ++ 
823                                         showSDoc (pprStmt stmt)))
824
825                    CmmLit (CmmInt n _) -> CmmBranch dest
826                    other -> CmmCondBranch test' dest
827
828         CmmSwitch expr ids
829            -> do expr' <- cmmExprConFold DataReference expr
830                  return $ CmmSwitch expr' ids
831
832         other
833            -> return other
834
835
836 cmmExprConFold referenceKind expr
837    = case expr of
838         CmmLoad addr rep
839            -> do addr' <- cmmExprConFold DataReference addr
840                  return $ CmmLoad addr' rep
841
842         CmmMachOp mop args
843            -- For MachOps, we first optimize the children, and then we try 
844            -- our hand at some constant-folding.
845            -> do args' <- mapM (cmmExprConFold DataReference) args
846                  return $ cmmMachOpFold mop args'
847
848         CmmLit (CmmLabel lbl)
849            -> do
850                 dflags <- getDynFlagsCmmOpt
851                 cmmMakeDynamicReference dflags addImportCmmOpt referenceKind lbl
852         CmmLit (CmmLabelOff lbl off)
853            -> do
854                  dflags <- getDynFlagsCmmOpt
855                  dynRef <- cmmMakeDynamicReference dflags addImportCmmOpt referenceKind lbl
856                  return $ cmmMachOpFold (MO_Add wordWidth) [
857                      dynRef,
858                      (CmmLit $ CmmInt (fromIntegral off) wordWidth)
859                    ]
860
861 #if powerpc_TARGET_ARCH
862            -- On powerpc (non-PIC), it's easier to jump directly to a label than
863            -- to use the register table, so we replace these registers
864            -- with the corresponding labels:
865         CmmReg (CmmGlobal EagerBlackholeInfo)
866           | not opt_PIC
867           -> cmmExprConFold referenceKind $
868              CmmLit (CmmLabel (mkRtsCodeLabel (sLit "__stg_EAGER_BLACKHOLE_INFO"))) 
869         CmmReg (CmmGlobal GCEnter1)
870           | not opt_PIC
871           -> cmmExprConFold referenceKind $
872              CmmLit (CmmLabel (mkRtsCodeLabel (sLit "__stg_gc_enter_1"))) 
873         CmmReg (CmmGlobal GCFun)
874           | not opt_PIC
875           -> cmmExprConFold referenceKind $
876              CmmLit (CmmLabel (mkRtsCodeLabel (sLit "__stg_gc_fun")))
877 #endif
878
879         CmmReg (CmmGlobal mid)
880            -- Replace register leaves with appropriate StixTrees for
881            -- the given target.  MagicIds which map to a reg on this
882            -- arch are left unchanged.  For the rest, BaseReg is taken
883            -- to mean the address of the reg table in MainCapability,
884            -- and for all others we generate an indirection to its
885            -- location in the register table.
886            -> case get_GlobalReg_reg_or_addr mid of
887                  Left  realreg -> return expr
888                  Right baseRegAddr 
889                     -> case mid of 
890                           BaseReg -> cmmExprConFold DataReference baseRegAddr
891                           other   -> cmmExprConFold DataReference
892                                         (CmmLoad baseRegAddr (globalRegType mid))
893            -- eliminate zero offsets
894         CmmRegOff reg 0
895            -> cmmExprConFold referenceKind (CmmReg reg)
896
897         CmmRegOff (CmmGlobal mid) offset
898            -- RegOf leaves are just a shorthand form. If the reg maps
899            -- to a real reg, we keep the shorthand, otherwise, we just
900            -- expand it and defer to the above code. 
901            -> case get_GlobalReg_reg_or_addr mid of
902                 Left  realreg -> return expr
903                 Right baseRegAddr
904                    -> cmmExprConFold DataReference (CmmMachOp (MO_Add wordWidth) [
905                                         CmmReg (CmmGlobal mid),
906                                         CmmLit (CmmInt (fromIntegral offset)
907                                                        wordWidth)])
908         other
909            -> return other
910
911 -- -----------------------------------------------------------------------------
912 -- Utils
913
914 bind f x = x $! f
915
916 \end{code}
917