[GHC] #14989: "Each block should be reachable from only one ProcPoint" compiling `integer` with `-fllvm`

GHC ghc-devs at haskell.org
Sat Mar 31 14:19:53 UTC 2018


#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


More information about the ghc-tickets mailing list