Skip to content

cmmImplementSwitchPlans creates duplicate blocks

Given this c-- code *after* common block elimination and *before* cmmImplementSwitchPlans:

    ... 
cfzc:
   _sfh3::P64 = R1;
   _cfB7::I64 = %MO_UU_Conv_W32_W64(I32[I64[_sfh3::P64 - 1] - 4]);
   switch [0 .. 20] _cfB7::I64 {
     case 2 : goto cfAR;
     case 4 : goto cfAV;
     case 6 : goto cfAZ;
     default: goto cfAC;
   }
cfAZ:
   _sfh6::I64 = I64[_sfh3::P64 + 7];
   _sfgp::I64 = 1;
   goto sfgo;
cfAV:
   _sfh5::I64 = I64[_sfh3::P64 + 7];
   _sfgp::I64 = 1;
   goto sfgo;
cfAR:
   _sfh4::I64 = I64[_sfh3::P64 + 7];
   _sfgp::I64 = 1;
   goto sfgo;
sfgo:
  ... 

Everything is fine, the blocks cfAZ, cfAV and cfAR are all a little different.

But after cmmImplementSwitchPlans the code becomes:

    ...   
cfzc:
    _sfgl::I64 = I64[Sp + 24];
    _sfgn::P64 = P64[Sp + 16];
    _cfB7::I64 = %MO_UU_Conv_W32_W64(I32[I64[R1 - 1] - 4]);
    if (_cfB7::I64 < 5) goto ufBe; else goto ufBg;
ufBe:
    if (_cfB7::I64 < 4) goto ufBf; else goto cfAV;
ufBf:
    if (_cfB7::I64 != 2) goto cfAC; else goto cfAR;
cfAR:
    _sfgp::I64 = 1;
    goto sfgo;
cfAV:
    _sfgp::I64 = 1;
    goto sfgo;
ufBg:
    if (_cfB7::I64 != 6) goto cfAC; else goto cfAZ;
cfAZ:
    _sfgp::I64 = 1;
    goto sfgo;
sfgo:
    ... 

We can now see that cfAZ, cfAV and cfAR are code duplicates!

Now, https://github.com/ghc/ghc/blob/master/compiler/cmm/CmmPipeline.hs#L72 states

...
       ----------- Eliminate common blocks -------------------------------------
       g <- {-# SCC "elimCommonBlocks" #-}
            condPass Opt_CmmElimCommonBlocks elimCommonBlocks g
                          Opt_D_dump_cmm_cbe "Post common block elimination"

       -- Any work storing block Labels must be performed _after_
       -- elimCommonBlocks

       g <- {-# SCC "createSwitchPlans" #-}
            runUniqSM $ cmmImplementSwitchPlans dflags g
       dump Opt_D_dump_cmm_switch "Post switch plan" g
...

For some reason I don't understand cmmImplementSwitchPlans is run *after* elimCommonBlocks. Although it seems elimCommonBlocks can deal with the constructs introduced in cmmImplementSwitchPlans.

Trac metadata
Trac field Value
Version 8.0.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information