Skip to content

LLVM code generator produces mal-formed LLVM blocks

It appears that the recent addition (673efccb) of some instances for types in GHC.Generics has uncovered a bug in the LLVM code generator (at least on ARM). libraries/base/GHC/Generics.hs fails to compile with,

Entry block to function must not have predecessors!
label %cjGw
/home/ben/ghc/roots/llvm-3.7/bin/opt: libraries/base/GHC/Generics.ll: error: input module is broken!

The problematic block in question appears to be,

define internal ghccc void @rhSw_info$def(i32* noalias nocapture %Base_Arg, i32* noalias nocapture %Sp_Arg, i32* noal
ias nocapture %Hp_Arg, i32 %R1_Arg, i32 %R2_Arg, i32 %R3_Arg, i32 %R4_Arg, i32 %SpLim_Arg) align 4 nounwind prefix <{
i32, i32, i32}><{i32 65541, i32 0, i32 15}>
{
clpH:
  br label %clpH
}

Which arose from this Cmm,

==================== Post control-flow optimisations ====================
2016-02-26 10:39:28.656744 UTC


[section ""data" . lvl_rhSw_closure" {
     lvl_rhSw_closure:
         const lvl_rhSw_info;
 },
 lvl_rhSw_entry() //  []
         { info_tbl: [(clpH,
                       label: lvl_rhSw_info
                       rep:HeapRep static { Fun {arity: 1 fun_type: ArgSpec 5} })]
           stack_info: arg_space: 0 updfr_space: Nothing
         }
     {offset
       clpH:
           goto clpH;   // CmmBranch
     }
 }]

Which arose from this input Cmm,

==================== Cmm produced by new codegen ====================
2016-02-26 10:39:28.611641 UTC

[section ""data" . lvl_rhSw_closure" {
     lvl_rhSw_closure:
         const lvl_rhSw_info;
 },
 lvl_rhSw_entry() //  [R2]
         { info_tbl: [(clpD,
                       label: lvl_rhSw_info
                       rep:HeapRep static { Fun {arity: 1 fun_type: ArgSpec 5} })]
           stack_info: arg_space: 4 updfr_space: Just 4
         }
     {offset
       clpD:
           _shWa::P32 = R2;   // CmmAssign
           goto clpz;   // CmmBranch
       clpz:
           if ((old + 0) - <highSp> < SpLim) goto clpE; else goto clpF;   // CmmCondBranch
       clpE:
           R2 = _shWa::P32;   // CmmAssign
           R1 = lvl_rhSw_closure;   // CmmAssign
           call (stg_gc_fun)(R2, R1) args: 4, res: 0, upd: 4;   // CmmCall
       clpF:
           goto clpy;   // CmmBranch
       clpy:
           goto shWb;   // CmmBranch
       shWb:
           goto clpH;   // CmmBranch
       clpH:
           goto shWb;   // CmmBranch
     }
 }]

Which arose from this STG,

lvl_rhSw
  :: forall a_a99i.
     GHC.Generics.U1 a_a99i -> GHC.Generics.U1 [a_a99i]
[GblId,
 Arity=1,
 Caf=NoCafRefs,
 Str=DmdType <L,U>x,
 Unf=OtherCon []] =
    sat-only \r [eta_shWa]
        let-no-escape {
          some_v_shWb [Occ=LoopBreaker] :: GHC.Generics.U1 [a12_a99i]
          [LclId, Str=DmdType b] =
              NO_CCS[] \u [] some_v_shWb;
        } in  some_v_shWb;

Which arose from this Core (from -ddump-simpl),

lvl_rhSw :: forall a_a99i. U1 a_a99i -> U1 [a_a99i]
[GblId, Arity=1, Caf=NoCafRefs, Str=DmdType <L,U>x]
lvl_rhSw =
  \ (@ a12_a99i) _ [Occ=Dead] ->
    letrec {
      some_v_a99l [Occ=LoopBreaker] :: U1 [a12_a99i]
      [LclId, Str=DmdType b]
      some_v_a99l = some_v_a99l; } in
    some_v_a99l

Which is apparently the body of the some implementation in the Alternative instance for GHC.Generics.U1.

Edited by Ben Gamari
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information