
#14989: "Each block should be reachable from only one ProcPoint" compiling `integer` with `-fllvm` -------------------------------------+------------------------------------- Reporter: sgraf | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.5 Resolution: | Keywords: Operating System: Windows | Architecture: x86_64 Type of failure: Compile-time | (amd64) crash or panic | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by sgraf): I blame common block elimination. This is the output post sink assignments: {{{ ... c2m1: // global call (I64[R1])(R1) returns to c2m0, args: 8, res: 8, upd: 8; c2m0: // global switch [1 .. 2] (R1 & 7) { case 1 : goto u2mH; case 2 : goto c2m5; } ... c2mi: // global call (I64[R1])(R1) returns to c2mg, args: 8, res: 8, upd: 8; c2mg: // global switch [1 .. 2] (R1 & 7) { case 1 : goto u2mI; case 2 : goto c2mt; } ... c2mu: // global call (I64[R1])(R1) returns to c2mr, args: 8, res: 8, upd: 8; c2mr: // global switch [1 .. 2] (R1 & 7) { case 1 : goto c2mA; case 2 : goto u2mJ; } u2mJ: // global Sp = Sp + 8; goto c2mE; ... u2mI: // global Sp = Sp + 8; goto c2mE; u2mH: // global Sp = Sp + 8; goto c2mE; c2mE: // global call Main.$wfail_info() args: 8, res: 0, upd: 8; }}} And this is post common block elimination 2: {{{ ... c2m1: // global call (I64[R1])(R1) returns to c2m0, args: 8, res: 8, upd: 8; c2m0: // global switch [1 .. 2] (R1 & 7) { case 1 : goto u2mJ; case 2 : goto c2m5; } ... c2mi: // global call (I64[R1])(R1) returns to c2mg, args: 8, res: 8, upd: 8; c2mg: // global switch [1 .. 2] (R1 & 7) { case 1 : goto u2mJ; case 2 : goto c2mt; } ... c2mu: // global call (I64[R1])(R1) returns to c2mr, args: 8, res: 8, upd: 8; c2mr: // global switch [1 .. 2] (R1 & 7) { case 1 : goto c2mA; case 2 : goto u2mJ; } ... u2mJ: // global Sp = Sp + 8; goto c2mE; c2mE: // global call Main.$wfail_info() args: 8, res: 0, upd: 8; }}} The non-proc-point blocks u2m* have been merged into a single block u2MJ, which should have become a proc point in turn, because c2m{0,g,r} are multiple proc points (they are continuations) the block now "belongs" to. This is essentially diamond control flow introduced by the merging of blocks. {{{ c2m0 c2mg c2mr | | | u2mJ u2mI u2mH \ | / c2mE ===> c2m0 c2mg c2mr \ | / u2mJ | c2mE }}} In SSA world, this could entail inserting new Phi functions into the merged block, which corresponds to our notion of proc points, if I understand right. I find the parallels to SSA form very helpful. To stay in that analogy, c2mE was a proc point before common block elimination, but is no longer, because the dominance frontier of defs visible in c2m* changed from c2mE to u2mJ. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14989#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler