add -fsimpleopt-before-flatten
[ghc-hetmet.git] / compiler / cmm / CmmOpt.hs
1 {-# OPTIONS -w #-}
2 -- The above warning supression flag is a temporary kludge.
3 -- While working on this module you are encouraged to remove it and fix
4 -- any warnings in the module. See
5 --     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
6 -- for details
7
8 -----------------------------------------------------------------------------
9 --
10 -- Cmm optimisation
11 --
12 -- (c) The University of Glasgow 2006
13 --
14 -----------------------------------------------------------------------------
15
16 module CmmOpt (
17         cmmMiniInline,
18         cmmMachOpFold,
19         cmmLoopifyForC,
20  ) where
21
22 #include "HsVersions.h"
23
24 import OldCmm
25 import CmmUtils
26 import CLabel
27 import StaticFlags
28
29 import UniqFM
30 import Unique
31 import FastTypes
32 import Outputable
33
34 import Data.Bits
35 import Data.Word
36 import Data.Int
37
38 -- -----------------------------------------------------------------------------
39 -- The mini-inliner
40
41 {-
42 This pass inlines assignments to temporaries that are used just
43 once.  It works as follows:
44
45   - count uses of each temporary
46   - for each temporary that occurs just once:
47         - attempt to push it forward to the statement that uses it
48         - only push forward past assignments to other temporaries
49           (assumes that temporaries are single-assignment)
50         - if we reach the statement that uses it, inline the rhs
51           and delete the original assignment.
52
53 [N.B. In the Quick C-- compiler, this optimization is achieved by a
54  combination of two dataflow passes: forward substitution (peephole
55  optimization) and dead-assignment elimination.  ---NR]
56
57 Possible generalisations: here is an example from factorial
58
59 Fac_zdwfac_entry:
60     cmG:
61         _smi = R2;
62         if (_smi != 0) goto cmK;
63         R1 = R3;
64         jump I64[Sp];
65     cmK:
66         _smn = _smi * R3;
67         R2 = _smi + (-1);
68         R3 = _smn;
69         jump Fac_zdwfac_info;
70
71 We want to inline _smi and _smn.  To inline _smn:
72
73    - we must be able to push forward past assignments to global regs.
74      We can do this if the rhs of the assignment we are pushing
75      forward doesn't refer to the global reg being assigned to; easy
76      to test.
77
78 To inline _smi:
79
80    - It is a trivial replacement, reg for reg, but it occurs more than
81      once.
82    - We can inline trivial assignments even if the temporary occurs
83      more than once, as long as we don't eliminate the original assignment
84      (this doesn't help much on its own).
85    - We need to be able to propagate the assignment forward through jumps;
86      if we did this, we would find that it can be inlined safely in all
87      its occurrences.
88 -}
89
90 countUses :: UserOfLocalRegs a => a -> UniqFM Int
91 countUses a = foldRegsUsed (\m r -> addToUFM m r (count m r + 1)) emptyUFM a
92   where count m r = lookupWithDefaultUFM m (0::Int) r
93
94 cmmMiniInline :: [CmmBasicBlock] -> [CmmBasicBlock]
95 cmmMiniInline blocks = map do_inline blocks 
96   where do_inline (BasicBlock id stmts)
97           = BasicBlock id (cmmMiniInlineStmts (countUses blocks) stmts)
98
99 cmmMiniInlineStmts :: UniqFM Int -> [CmmStmt] -> [CmmStmt]
100 cmmMiniInlineStmts uses [] = []
101 cmmMiniInlineStmts uses (stmt@(CmmAssign (CmmLocal (LocalReg u _)) expr) : stmts)
102         -- not used at all: just discard this assignment
103   | Nothing <- lookupUFM uses u
104   = cmmMiniInlineStmts uses stmts
105
106         -- used once: try to inline at the use site
107   | Just 1 <- lookupUFM uses u,
108     Just stmts' <- lookForInline u expr stmts
109   = 
110 #ifdef NCG_DEBUG
111      trace ("nativeGen: inlining " ++ showSDoc (pprStmt stmt)) $
112 #endif
113      cmmMiniInlineStmts uses stmts'
114
115 cmmMiniInlineStmts uses (stmt:stmts)
116   = stmt : cmmMiniInlineStmts uses stmts
117
118 lookForInline u expr stmts = lookForInline' u expr regset stmts
119     where regset = foldRegsUsed extendRegSet emptyRegSet expr
120
121 lookForInline' u expr regset (stmt : rest)
122   | Just 1 <- lookupUFM (countUses stmt) u, ok_to_inline
123   = Just (inlineStmt u expr stmt : rest)
124
125   | ok_to_skip
126   = case lookForInline' u expr regset rest of
127            Nothing    -> Nothing
128            Just stmts -> Just (stmt:stmts)
129
130   | otherwise 
131   = Nothing
132
133   where
134         -- we don't inline into CmmCall if the expression refers to global
135         -- registers.  This is a HACK to avoid global registers clashing with
136         -- C argument-passing registers, really the back-end ought to be able
137         -- to handle it properly, but currently neither PprC nor the NCG can
138         -- do it.  See also CgForeignCall:load_args_into_temps.
139     ok_to_inline = case stmt of
140                      CmmCall{} -> hasNoGlobalRegs expr
141                      _ -> True
142
143    -- Expressions aren't side-effecting.  Temporaries may or may not
144    -- be single-assignment depending on the source (the old code
145    -- generator creates single-assignment code, but hand-written Cmm
146    -- and Cmm from the new code generator is not single-assignment.)
147    -- So we do an extra check to make sure that the register being
148    -- changed is not one we were relying on.  I don't know how much of a
149    -- performance hit this is (we have to create a regset for every
150    -- instruction.) -- EZY
151     ok_to_skip = case stmt of
152                  CmmNop -> True
153                  CmmComment{} -> True
154                  CmmAssign (CmmLocal r@(LocalReg u' _)) rhs | u' /= u && not (r `elemRegSet` regset) -> True
155                  CmmAssign g@(CmmGlobal _) rhs -> not (g `regUsedIn` expr)
156                  _other -> False
157
158
159 inlineStmt :: Unique -> CmmExpr -> CmmStmt -> CmmStmt
160 inlineStmt u a (CmmAssign r e) = CmmAssign r (inlineExpr u a e)
161 inlineStmt u a (CmmStore e1 e2) = CmmStore (inlineExpr u a e1) (inlineExpr u a e2)
162 inlineStmt u a (CmmCall target regs es srt ret)
163    = CmmCall (infn target) regs es' srt ret
164    where infn (CmmCallee fn cconv) = CmmCallee (inlineExpr u a fn) cconv
165          infn (CmmPrim p) = CmmPrim p
166          es' = [ (CmmHinted (inlineExpr u a e) hint) | (CmmHinted e hint) <- es ]
167 inlineStmt u a (CmmCondBranch e d) = CmmCondBranch (inlineExpr u a e) d
168 inlineStmt u a (CmmSwitch e d) = CmmSwitch (inlineExpr u a e) d
169 inlineStmt u a (CmmJump e d) = CmmJump (inlineExpr u a e) d
170 inlineStmt u a other_stmt = other_stmt
171
172 inlineExpr :: Unique -> CmmExpr -> CmmExpr -> CmmExpr
173 inlineExpr u a e@(CmmReg (CmmLocal (LocalReg u' _)))
174   | u == u' = a
175   | otherwise = e
176 inlineExpr u a e@(CmmRegOff (CmmLocal (LocalReg u' rep)) off)
177   | u == u' = CmmMachOp (MO_Add width) [a, CmmLit (CmmInt (fromIntegral off) width)]
178   | otherwise = e
179   where
180     width = typeWidth rep
181 inlineExpr u a (CmmLoad e rep) = CmmLoad (inlineExpr u a e) rep
182 inlineExpr u a (CmmMachOp op es) = CmmMachOp op (map (inlineExpr u a) es)
183 inlineExpr u a other_expr = other_expr
184
185 -- -----------------------------------------------------------------------------
186 -- MachOp constant folder
187
188 -- Now, try to constant-fold the MachOps.  The arguments have already
189 -- been optimized and folded.
190
191 cmmMachOpFold
192     :: MachOp           -- The operation from an CmmMachOp
193     -> [CmmExpr]        -- The optimized arguments
194     -> CmmExpr
195
196 cmmMachOpFold op arg@[CmmLit (CmmInt x rep)]
197   = case op of
198       MO_S_Neg r -> CmmLit (CmmInt (-x) rep)
199       MO_Not r   -> CmmLit (CmmInt (complement x) rep)
200
201         -- these are interesting: we must first narrow to the 
202         -- "from" type, in order to truncate to the correct size.
203         -- The final narrow/widen to the destination type
204         -- is implicit in the CmmLit.
205       MO_SF_Conv from to -> CmmLit (CmmFloat (fromInteger x) to)
206       MO_SS_Conv from to -> CmmLit (CmmInt (narrowS from x) to)
207       MO_UU_Conv from to -> CmmLit (CmmInt (narrowU from x) to)
208
209       _ -> panic "cmmMachOpFold: unknown unary op"
210
211
212 -- Eliminate conversion NOPs
213 cmmMachOpFold (MO_SS_Conv rep1 rep2) [x] | rep1 == rep2 = x
214 cmmMachOpFold (MO_UU_Conv rep1 rep2) [x] | rep1 == rep2 = x
215
216 -- Eliminate nested conversions where possible
217 cmmMachOpFold conv_outer args@[CmmMachOp conv_inner [x]]
218   | Just (rep1,rep2,signed1) <- isIntConversion conv_inner,
219     Just (_,   rep3,signed2) <- isIntConversion conv_outer
220   = case () of
221         -- widen then narrow to the same size is a nop
222       _ | rep1 < rep2 && rep1 == rep3 -> x
223         -- Widen then narrow to different size: collapse to single conversion
224         -- but remember to use the signedness from the widening, just in case
225         -- the final conversion is a widen.
226         | rep1 < rep2 && rep2 > rep3 ->
227             cmmMachOpFold (intconv signed1 rep1 rep3) [x]
228         -- Nested widenings: collapse if the signedness is the same
229         | rep1 < rep2 && rep2 < rep3 && signed1 == signed2 ->
230             cmmMachOpFold (intconv signed1 rep1 rep3) [x]
231         -- Nested narrowings: collapse
232         | rep1 > rep2 && rep2 > rep3 ->
233             cmmMachOpFold (MO_UU_Conv rep1 rep3) [x]
234         | otherwise ->
235             CmmMachOp conv_outer args
236   where
237         isIntConversion (MO_UU_Conv rep1 rep2) 
238           = Just (rep1,rep2,False)
239         isIntConversion (MO_SS_Conv rep1 rep2)
240           = Just (rep1,rep2,True)
241         isIntConversion _ = Nothing
242
243         intconv True  = MO_SS_Conv
244         intconv False = MO_UU_Conv
245
246 -- ToDo: a narrow of a load can be collapsed into a narrow load, right?
247 -- but what if the architecture only supports word-sized loads, should
248 -- we do the transformation anyway?
249
250 cmmMachOpFold mop args@[CmmLit (CmmInt x xrep), CmmLit (CmmInt y _)]
251   = case mop of
252         -- for comparisons: don't forget to narrow the arguments before
253         -- comparing, since they might be out of range.
254         MO_Eq r   -> CmmLit (CmmInt (if x_u == y_u then 1 else 0) wordWidth)
255         MO_Ne r   -> CmmLit (CmmInt (if x_u /= y_u then 1 else 0) wordWidth)
256
257         MO_U_Gt r -> CmmLit (CmmInt (if x_u >  y_u then 1 else 0) wordWidth)
258         MO_U_Ge r -> CmmLit (CmmInt (if x_u >= y_u then 1 else 0) wordWidth)
259         MO_U_Lt r -> CmmLit (CmmInt (if x_u <  y_u then 1 else 0) wordWidth)
260         MO_U_Le r -> CmmLit (CmmInt (if x_u <= y_u then 1 else 0) wordWidth)
261
262         MO_S_Gt r -> CmmLit (CmmInt (if x_s >  y_s then 1 else 0) wordWidth) 
263         MO_S_Ge r -> CmmLit (CmmInt (if x_s >= y_s then 1 else 0) wordWidth)
264         MO_S_Lt r -> CmmLit (CmmInt (if x_s <  y_s then 1 else 0) wordWidth)
265         MO_S_Le r -> CmmLit (CmmInt (if x_s <= y_s then 1 else 0) wordWidth)
266
267         MO_Add r -> CmmLit (CmmInt (x + y) r)
268         MO_Sub r -> CmmLit (CmmInt (x - y) r)
269         MO_Mul r -> CmmLit (CmmInt (x * y) r)
270         MO_U_Quot r | y /= 0 -> CmmLit (CmmInt (x_u `quot` y_u) r)
271         MO_U_Rem  r | y /= 0 -> CmmLit (CmmInt (x_u `rem`  y_u) r)
272         MO_S_Quot r | y /= 0 -> CmmLit (CmmInt (x `quot` y) r)
273         MO_S_Rem  r | y /= 0 -> CmmLit (CmmInt (x `rem` y) r)
274
275         MO_And   r -> CmmLit (CmmInt (x .&. y) r)
276         MO_Or    r -> CmmLit (CmmInt (x .|. y) r)
277         MO_Xor   r -> CmmLit (CmmInt (x `xor` y) r)
278
279         MO_Shl   r -> CmmLit (CmmInt (x `shiftL` fromIntegral y) r)
280         MO_U_Shr r -> CmmLit (CmmInt (x_u `shiftR` fromIntegral y) r)
281         MO_S_Shr r -> CmmLit (CmmInt (x `shiftR` fromIntegral y) r)
282
283         other      -> CmmMachOp mop args
284
285    where
286         x_u = narrowU xrep x
287         y_u = narrowU xrep y
288         x_s = narrowS xrep x
289         y_s = narrowS xrep y
290         
291
292 -- When possible, shift the constants to the right-hand side, so that we
293 -- can match for strength reductions.  Note that the code generator will
294 -- also assume that constants have been shifted to the right when
295 -- possible.
296
297 cmmMachOpFold op [x@(CmmLit _), y]
298    | not (isLit y) && isCommutableMachOp op 
299    = cmmMachOpFold op [y, x]
300
301 -- Turn (a+b)+c into a+(b+c) where possible.  Because literals are
302 -- moved to the right, it is more likely that we will find
303 -- opportunities for constant folding when the expression is
304 -- right-associated.
305 --
306 -- ToDo: this appears to introduce a quadratic behaviour due to the
307 -- nested cmmMachOpFold.  Can we fix this?
308 --
309 -- Why do we check isLit arg1?  If arg1 is a lit, it means that arg2
310 -- is also a lit (otherwise arg1 would be on the right).  If we
311 -- put arg1 on the left of the rearranged expression, we'll get into a
312 -- loop:  (x1+x2)+x3 => x1+(x2+x3)  => (x2+x3)+x1 => x2+(x3+x1) ...
313 --
314 -- Also don't do it if arg1 is PicBaseReg, so that we don't separate the
315 -- PicBaseReg from the corresponding label (or label difference).
316 --
317 cmmMachOpFold mop1 [CmmMachOp mop2 [arg1,arg2], arg3]
318    | mop2 `associates_with` mop1
319      && not (isLit arg1) && not (isPicReg arg1)
320    = cmmMachOpFold mop2 [arg1, cmmMachOpFold mop1 [arg2,arg3]]
321    where
322      MO_Add{} `associates_with` MO_Sub{} = True
323      mop1 `associates_with` mop2 =
324         mop1 == mop2 && isAssociativeMachOp mop1
325
326 -- special case: (a - b) + c  ==>  a + (c - b)
327 cmmMachOpFold mop1@(MO_Add{}) [CmmMachOp mop2@(MO_Sub{}) [arg1,arg2], arg3]
328    | not (isLit arg1) && not (isPicReg arg1)
329    = cmmMachOpFold mop1 [arg1, cmmMachOpFold mop2 [arg3,arg2]]
330
331 -- Make a RegOff if we can
332 cmmMachOpFold (MO_Add _) [CmmReg reg, CmmLit (CmmInt n rep)]
333   = CmmRegOff reg (fromIntegral (narrowS rep n))
334 cmmMachOpFold (MO_Add _) [CmmRegOff reg off, CmmLit (CmmInt n rep)]
335   = CmmRegOff reg (off + fromIntegral (narrowS rep n))
336 cmmMachOpFold (MO_Sub _) [CmmReg reg, CmmLit (CmmInt n rep)]
337   = CmmRegOff reg (- fromIntegral (narrowS rep n))
338 cmmMachOpFold (MO_Sub _) [CmmRegOff reg off, CmmLit (CmmInt n rep)]
339   = CmmRegOff reg (off - fromIntegral (narrowS rep n))
340
341 -- Fold label(+/-)offset into a CmmLit where possible
342
343 cmmMachOpFold (MO_Add _) [CmmLit (CmmLabel lbl), CmmLit (CmmInt i rep)]
344   = CmmLit (CmmLabelOff lbl (fromIntegral (narrowU rep i)))
345 cmmMachOpFold (MO_Add _) [CmmLit (CmmInt i rep), CmmLit (CmmLabel lbl)]
346   = CmmLit (CmmLabelOff lbl (fromIntegral (narrowU rep i)))
347 cmmMachOpFold (MO_Sub _) [CmmLit (CmmLabel lbl), CmmLit (CmmInt i rep)]
348   = CmmLit (CmmLabelOff lbl (fromIntegral (negate (narrowU rep i))))
349
350
351 -- Comparison of literal with widened operand: perform the comparison
352 -- at the smaller width, as long as the literal is within range.
353
354 -- We can't do the reverse trick, when the operand is narrowed:
355 -- narrowing throws away bits from the operand, there's no way to do
356 -- the same comparison at the larger size.
357
358 #if i386_TARGET_ARCH || x86_64_TARGET_ARCH
359 -- powerPC NCG has a TODO for I8/I16 comparisons, so don't try
360
361 cmmMachOpFold cmp [CmmMachOp conv [x], CmmLit (CmmInt i _)]
362   |     -- if the operand is widened:
363     Just (rep, signed, narrow_fn) <- maybe_conversion conv,
364         -- and this is a comparison operation:
365     Just narrow_cmp <- maybe_comparison cmp rep signed,
366         -- and the literal fits in the smaller size:
367     i == narrow_fn rep i
368         -- then we can do the comparison at the smaller size
369   = cmmMachOpFold narrow_cmp [x, CmmLit (CmmInt i rep)]
370  where
371     maybe_conversion (MO_UU_Conv from to)
372         | to > from
373         = Just (from, False, narrowU)
374     maybe_conversion (MO_SS_Conv from to)
375         | to > from
376         = Just (from, True, narrowS)
377
378         -- don't attempt to apply this optimisation when the source
379         -- is a float; see #1916
380     maybe_conversion _ = Nothing
381     
382         -- careful (#2080): if the original comparison was signed, but
383         -- we were doing an unsigned widen, then we must do an
384         -- unsigned comparison at the smaller size.
385     maybe_comparison (MO_U_Gt _) rep _     = Just (MO_U_Gt rep)
386     maybe_comparison (MO_U_Ge _) rep _     = Just (MO_U_Ge rep)
387     maybe_comparison (MO_U_Lt _) rep _     = Just (MO_U_Lt rep)
388     maybe_comparison (MO_U_Le _) rep _     = Just (MO_U_Le rep)
389     maybe_comparison (MO_Eq   _) rep _     = Just (MO_Eq   rep)
390     maybe_comparison (MO_S_Gt _) rep True  = Just (MO_S_Gt rep)
391     maybe_comparison (MO_S_Ge _) rep True  = Just (MO_S_Ge rep)
392     maybe_comparison (MO_S_Lt _) rep True  = Just (MO_S_Lt rep)
393     maybe_comparison (MO_S_Le _) rep True  = Just (MO_S_Le rep)
394     maybe_comparison (MO_S_Gt _) rep False = Just (MO_U_Gt rep)
395     maybe_comparison (MO_S_Ge _) rep False = Just (MO_U_Ge rep)
396     maybe_comparison (MO_S_Lt _) rep False = Just (MO_U_Lt rep)
397     maybe_comparison (MO_S_Le _) rep False = Just (MO_U_Le rep)
398     maybe_comparison _ _ _ = Nothing
399
400 #endif
401
402 -- We can often do something with constants of 0 and 1 ...
403
404 cmmMachOpFold mop args@[x, y@(CmmLit (CmmInt 0 _))]
405   = case mop of
406         MO_Add   r -> x
407         MO_Sub   r -> x
408         MO_Mul   r -> y
409         MO_And   r -> y
410         MO_Or    r -> x
411         MO_Xor   r -> x
412         MO_Shl   r -> x
413         MO_S_Shr r -> x
414         MO_U_Shr r -> x
415         MO_Ne    r | isComparisonExpr x -> x
416         MO_Eq    r | Just x' <- maybeInvertCmmExpr x -> x'
417         MO_U_Gt  r | isComparisonExpr x -> x
418         MO_S_Gt  r | isComparisonExpr x -> x
419         MO_U_Lt  r | isComparisonExpr x -> CmmLit (CmmInt 0 wordWidth)
420         MO_S_Lt  r | isComparisonExpr x -> CmmLit (CmmInt 0 wordWidth)
421         MO_U_Ge  r | isComparisonExpr x -> CmmLit (CmmInt 1 wordWidth)
422         MO_S_Ge  r | isComparisonExpr x -> CmmLit (CmmInt 1 wordWidth)
423         MO_U_Le  r | Just x' <- maybeInvertCmmExpr x -> x'
424         MO_S_Le  r | Just x' <- maybeInvertCmmExpr x -> x'
425         other    -> CmmMachOp mop args
426
427 cmmMachOpFold mop args@[x, y@(CmmLit (CmmInt 1 rep))]
428   = case mop of
429         MO_Mul    r -> x
430         MO_S_Quot r -> x
431         MO_U_Quot r -> x
432         MO_S_Rem  r -> CmmLit (CmmInt 0 rep)
433         MO_U_Rem  r -> CmmLit (CmmInt 0 rep)
434         MO_Ne    r | Just x' <- maybeInvertCmmExpr x -> x'
435         MO_Eq    r | isComparisonExpr x -> x
436         MO_U_Lt  r | Just x' <- maybeInvertCmmExpr x -> x'
437         MO_S_Lt  r | Just x' <- maybeInvertCmmExpr x -> x'
438         MO_U_Gt  r | isComparisonExpr x -> CmmLit (CmmInt 0 wordWidth)
439         MO_S_Gt  r | isComparisonExpr x -> CmmLit (CmmInt 0 wordWidth)
440         MO_U_Le  r | isComparisonExpr x -> CmmLit (CmmInt 1 wordWidth)
441         MO_S_Le  r | isComparisonExpr x -> CmmLit (CmmInt 1 wordWidth)
442         MO_U_Ge  r | isComparisonExpr x -> x
443         MO_S_Ge  r | isComparisonExpr x -> x
444         other       -> CmmMachOp mop args
445
446 -- Now look for multiplication/division by powers of 2 (integers).
447
448 cmmMachOpFold mop args@[x, y@(CmmLit (CmmInt n _))]
449   = case mop of
450         MO_Mul rep
451            | Just p <- exactLog2 n ->
452                  cmmMachOpFold (MO_Shl rep) [x, CmmLit (CmmInt p rep)]
453         MO_U_Quot rep
454            | Just p <- exactLog2 n ->
455                  cmmMachOpFold (MO_U_Shr rep) [x, CmmLit (CmmInt p rep)]
456         MO_S_Quot rep
457            | Just p <- exactLog2 n, 
458              CmmReg _ <- x ->   -- We duplicate x below, hence require
459                                 -- it is a reg.  FIXME: remove this restriction.
460                 -- shift right is not the same as quot, because it rounds
461                 -- to minus infinity, whereasq quot rounds toward zero.
462                 -- To fix this up, we add one less than the divisor to the
463                 -- dividend if it is a negative number.
464                 --
465                 -- to avoid a test/jump, we use the following sequence:
466                 --      x1 = x >> word_size-1  (all 1s if -ve, all 0s if +ve)
467                 --      x2 = y & (divisor-1)
468                 --      result = (x+x2) >>= log2(divisor)
469                 -- this could be done a bit more simply using conditional moves,
470                 -- but we're processor independent here.
471                 --
472                 -- we optimise the divide by 2 case slightly, generating
473                 --      x1 = x >> word_size-1  (unsigned)
474                 --      return = (x + x1) >>= log2(divisor)
475                 let 
476                     bits = fromIntegral (widthInBits rep) - 1
477                     shr = if p == 1 then MO_U_Shr rep else MO_S_Shr rep
478                     x1 = CmmMachOp shr [x, CmmLit (CmmInt bits rep)]
479                     x2 = if p == 1 then x1 else
480                          CmmMachOp (MO_And rep) [x1, CmmLit (CmmInt (n-1) rep)]
481                     x3 = CmmMachOp (MO_Add rep) [x, x2]
482                 in
483                 cmmMachOpFold (MO_S_Shr rep) [x3, CmmLit (CmmInt p rep)]
484         other
485            -> unchanged
486     where
487        unchanged = CmmMachOp mop args
488
489 -- Anything else is just too hard.
490
491 cmmMachOpFold mop args = CmmMachOp mop args
492
493 -- -----------------------------------------------------------------------------
494 -- exactLog2
495
496 -- This algorithm for determining the $\log_2$ of exact powers of 2 comes
497 -- from GCC.  It requires bit manipulation primitives, and we use GHC
498 -- extensions.  Tough.
499 -- 
500 -- Used to be in MachInstrs --SDM.
501 -- ToDo: remove use of unboxery --SDM.
502
503 -- Unboxery removed in favor of FastInt; but is the function supposed to fail
504 -- on inputs >= 2147483648, or was that just an implementation artifact?
505 -- And is this speed-critical, or can we just use Integer operations
506 -- (including Data.Bits)?
507 --  --Isaac Dupree
508
509 exactLog2 :: Integer -> Maybe Integer
510 exactLog2 x_
511   = if (x_ <= 0 || x_ >= 2147483648) then
512        Nothing
513     else
514        case iUnbox (fromInteger x_) of { x ->
515        if (x `bitAndFastInt` negateFastInt x) /=# x then
516           Nothing
517        else
518           Just (toInteger (iBox (pow2 x)))
519        }
520   where
521     pow2 x | x ==# _ILIT(1) = _ILIT(0)
522            | otherwise = _ILIT(1) +# pow2 (x `shiftR_FastInt` _ILIT(1))
523
524
525 -- -----------------------------------------------------------------------------
526 -- Loopify for C
527
528 {-
529  This is a simple pass that replaces tail-recursive functions like this:
530
531    fac() {
532      ...
533      jump fac();
534    }
535
536  with this:
537
538   fac() {
539    L:
540      ...
541      goto L;
542   }
543
544   the latter generates better C code, because the C compiler treats it
545   like a loop, and brings full loop optimisation to bear.
546
547   In my measurements this makes little or no difference to anything
548   except factorial, but what the hell.
549 -}
550
551 cmmLoopifyForC :: RawCmmTop -> RawCmmTop
552 cmmLoopifyForC p@(CmmProc info entry_lbl
553                  (ListGraph blocks@(BasicBlock top_id _ : _)))
554   | null info = p  -- only if there's an info table, ignore case alts
555   | otherwise =  
556 --  pprTrace "jump_lbl" (ppr jump_lbl <+> ppr entry_lbl) $
557   CmmProc info entry_lbl (ListGraph blocks')
558   where blocks' = [ BasicBlock id (map do_stmt stmts)
559                   | BasicBlock id stmts <- blocks ]
560
561         do_stmt (CmmJump (CmmLit (CmmLabel lbl)) _) | lbl == jump_lbl
562                 = CmmBranch top_id
563         do_stmt stmt = stmt
564
565         jump_lbl | tablesNextToCode = entryLblToInfoLbl entry_lbl
566                  | otherwise        = entry_lbl
567
568 cmmLoopifyForC top = top
569
570 -- -----------------------------------------------------------------------------
571 -- Utils
572
573 isLit (CmmLit _) = True
574 isLit _          = False
575
576 isComparisonExpr :: CmmExpr -> Bool
577 isComparisonExpr (CmmMachOp op _) = isComparisonMachOp op
578 isComparisonExpr _other             = False
579
580 isPicReg (CmmReg (CmmGlobal PicBaseReg)) = True
581 isPicReg _ = False
582