Opened 8 years ago

Closed 6 years ago

#3552 closed bug (fixed)

Unreachable code in optimised CMM code

Reported by: simonpj Owned by:
Priority: normal Milestone: 7.2.1
Component: Compiler Version: 6.10.4
Keywords: Cc: ezyang
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


Ben found that GHC is gnerating some unreachable C-- code. While the NCG should handle that case, it's curious, so I'm recording it as a ticket to look at with the new codegen pipeline.

While working on the NCG I've come across this:

benl@mavericks:~/devel/ghc/ghc-head-incoming> inplace/bin/ghc-stage1 -c
rts/Updates.cmm -ddump-opt-cmm

==================== Optimised Cmm ====================
cp: _ch::I32 = I32[_cb::I32 + 4];
I32[_ch::I32] = _c6::I32;
I32[_cb::I32 + 4] = _ch::I32 + 4;
I32[_c6::I32 + 0] = stg_IND_OLDGEN_info;
jump (I32[Sp + 0]) ();
cq: goto cq;

The goto instruction at cq: is unreachable.

However, in nativeGen/RegAlloc/Linear/Main.hs we have:

{- from John Dias's patch 2008/10/16:
The linear-scan allocator sometimes allocates a block
before allocating one of its predecessors, which could lead to
inconsistent allocations. Make it so a block is only allocated
if a predecessor has set the "incoming" assignments for the block, or
if it's the procedure's entry block.

BL 2009/02: Careful. If the assignment for a block doesn't get set for
some reason then this function will loop. We should probably do some
more sanity checking to guard against this eventuality.

I'm in a situation where the linear allocator is looping because it's trying to wait for a predecessor of cq: to set the incoming register assignments, but that never happens because it's unreachable.

I don't know why it wasn't looping until now, maybe because i've wibbled some function and caused some previously undemanded computation to hit this loop.

Do we want the allocator to accept the above code, or just panic? Is this a bug in the Cmm code generator, or is there a good reason why there is an unreachable loop in this code?

Change History (5)

comment:1 Changed 8 years ago by simonmar

These unreachable blocks are left behind by the flattener, CgMonad.flattenCgStmts. Here's the comment:

  -- A label at the end of a function or fork: this label must not be reachable,
  -- but it might be referred to from another BB that also isn't reachable.
  -- Eliminating these has to be done with a dead-code analysis.  For now,
  -- we just make it into a well-formed block by adding a recursive jump.
  flatten [CgLabel id]
    = ( [CmmBranch id], [BasicBlock id [CmmBranch id]] )

I think it happens when you write something like

if (e) { ... } else { ... }

at the end of a C-- procedure, the code generation for this looks like (CmmParse.ifThenElse):

ifThenElse cond then_part else_part = do
     then_id <- code newLabelC
     join_id <- code newLabelC
     c <- cond
     emitCond c then_id
     stmtEC (CmmBranch join_id)
     code (labelC then_id)
     -- fall through to join
     code (labelC join_id)

So it leaves a join-point label at the end; it doesn't know whether the join point is reachable or not. Can this ticket be closed, or should we wait until the symptom that Ben described is also fixed?

All this is different in the new code generator, I imagine...

comment:2 Changed 7 years ago by igloo

Milestone: 6.14 branch6.14.1

comment:3 Changed 7 years ago by igloo


comment:4 Changed 7 years ago by igloo


comment:5 Changed 6 years ago by simonmar

Cc: ezyang added
Resolution: fixed
Status: newclosed
Type of failure: None/Unknown

Edward implemented "dead basic block elimination" that fixes this ticket I think.


Note: See TracTickets for help on using tickets.