[GHC] #11649: LLVM code generator produces mal-formed LLVM blocks

#11649: LLVM code generator produces mal-formed LLVM blocks
-------------------------------------+-------------------------------------
Reporter: bgamari | Owner:
Type: bug | Status: new
Priority: highest | Milestone: 8.0.1
Component: Compiler | Version: 8.0.1-rc2
(CodeGen) |
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: Compile-time
Unknown/Multiple | crash
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
It appears that the recent addition
(673efccb3b348e9daf23d9e65460691bbea8586e) 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,
{{{#!hs
lvl_rhSw
:: forall a_a99i.
GHC.Generics.U1 a_a99i -> GHC.Generics.U1 [a_a99i]
[GblId,
Arity=1,
Caf=NoCafRefs,
Str=DmdType

#11649: LLVM code generator produces mal-formed LLVM blocks
-------------------------------------+-------------------------------------
Reporter: bgamari | Owner:
Type: bug | Status: new
Priority: highest | Milestone: 8.0.1
Component: Compiler | Version: 8.0.1-rc2
(CodeGen) |
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Compile-time | Unknown/Multiple
crash | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
@@ -106,1 +106,1 @@
- Which arose from this Core,
+ Which arose from this Core (from `-ddump-simpl`),
New description:
It appears that the recent addition
(673efccb3b348e9daf23d9e65460691bbea8586e) 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,
{{{#!hs
lvl_rhSw
:: forall a_a99i.
GHC.Generics.U1 a_a99i -> GHC.Generics.U1 [a_a99i]
[GblId,
Arity=1,
Caf=NoCafRefs,
Str=DmdType

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by bgamari): I was strangely unable to reproduce this on x86_64 with LLVM 3.7 and 2b46fa060092537d93ba1b3b1a4c4b6fa607a5c6. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by bgamari): This simpler testcase reproduces the issue on ARM, {{{#!hs {-# LANGUAGE NoImplicitPrelude #-} module Test where import GHC.Base data U1 p = U1 instance Functor U1 where fmap f U1 = U1 instance Applicative U1 where pure _ = U1 U1 <*> U1 = U1 instance Alternative U1 where empty = U1 U1 <|> U1 = U1 }}} {{{ $ inplace/bin/ghc-stage1 Test.hs -O -fforce-recomp [1 of 1] Compiling Test ( Test.hs, Test.o ) Entry block to function must not have predecessors! label %cPR /home/ben/ghc/roots/llvm-3.7/bin/opt: /tmp/ghc26431_0/ghc_2.ll: error: input module is broken! `opt' failed in phase `LLVM Optimiser'. (Exit code: 1) }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by erikd): Not just a problem on Arm. Happens on x86_64 as well. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by erikd): * cc: erikd (added) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by bgamari): Explicitly defining `many _ = U1; some _ = U1` works around the issue. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by bgamari): Indeed if you compile with the native code generator you'll find that compilation succeeds as expected, but the resulting executable loops when you attempt to evaluate `some U1`. I suspect overriding `some` and `many` is the right thing to do in this particular case. That being said, apart from the `Generics` issue, there is clearly an LLVM code generator issue as well: we shouldn't be passing code to LLVM that it can't compile. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: #9043 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * related: => #9043 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: bgamari Type: bug | Status: new Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: #9043 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * owner: => bgamari -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: bgamari Type: bug | Status: new Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: #9043 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by erikd): From IRC: <bgamari> erikd, I think the best bet is to just examine the Cmm, look for procs whose entry blocks are self-referential and rewrite them, inserting an auxiliary block <bgamari> it's a bit of a hack, but I suspect it is a fix -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: erikd Type: bug | Status: new Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: #9043 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by erikd): * owner: bgamari => erikd Comment: I have something that compiles but doesn't work yet. I'll take this over, -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:11 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: erikd Type: bug | Status: patch Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: #9043 | Differential Rev(s): Phab:D1996 Wiki Page: | -------------------------------------+------------------------------------- Changes (by erikd): * status: new => patch * differential: => Phab:D1996 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:12 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks
-------------------------------------+-------------------------------------
Reporter: bgamari | Owner: erikd
Type: bug | Status: patch
Priority: highest | Milestone: 8.0.1
Component: Compiler | Version: 8.0.1-rc2
(CodeGen) |
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Compile-time | Unknown/Multiple
crash | Test Case:
Blocked By: | Blocking:
Related Tickets: #9043 | Differential Rev(s): Phab:D1996
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by Ben Gamari

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: erikd Type: bug | Status: closed Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: #9043 | Differential Rev(s): Phab:D1996 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: patch => closed * resolution: => fixed Comment: Merged to `ghc-8.0`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:14 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: erikd Type: bug | Status: closed Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: #9043 | Differential Rev(s): Phab:D1996 Wiki Page: | -------------------------------------+------------------------------------- Changes (by angerman): * cc: kavon, angerman (added) Comment: Yikes. This still seems to be the case with LLVM5. We should probably upstream a fix for this. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:15 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: erikd Type: bug | Status: closed Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: #9043 | Differential Rev(s): Phab:D1996 Wiki Page: | -------------------------------------+------------------------------------- Comment (by kavon): The entry block restriction isn't a bug in LLVM, it's just part of their IR design. I believe that not having any predecessors of the entry block simplifies some things related to computing dominators (plus, the way phi nodes work in LLVM makes it weird to write one for an entry block to merge incoming function arguments). A better fix for this issue would also include a way to avoid making a pass over the Cmm procedure to determine which global registers need allocas (which can only be declared in the entry block). Here's my proposal to solve both problems: For each CmmProc, after turning its Cmm blocks into LLVM blocks, we should generate a brand new entry basic block. This new entry block would include the allocas that we need for the function and then branch to the translated version of the original entry block. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:16 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11649: LLVM code generator produces mal-formed LLVM blocks -------------------------------------+------------------------------------- Reporter: bgamari | Owner: erikd Type: bug | Status: closed Priority: highest | Milestone: 8.0.1 Component: Compiler | Version: 8.0.1-rc2 (CodeGen) | Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash | Test Case: Blocked By: | Blocking: Related Tickets: #9043 | Differential Rev(s): Phab:D1996 Wiki Page: | -------------------------------------+------------------------------------- Comment (by angerman): That's a fantastic idea! I guess we could even name the initial block `entry`, and just allocate all the registers on the stack and just fall through into the first block. I'll give this a try with the `llvmng`. If this works, I might backport it to the `llvm` backend. It would also relinquish the need for the unique supply in the `LlvmM` I believe. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11649#comment:17 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC