Allow static compilation of Arrays in a fashion similar to lists.
Motivation
The situation for lists
Currently if we write a top level static list like foo = [1,2,3,4] :: [Int]
the individual cons cells (and values) are floated out.
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
foo7
foo7 = I# 1#
...
-- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0}
foo3
foo3 = : foo4 []
-- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0}
foo2
foo2 = : foo5 foo3
...
This is good! The whole list is fully evaluated at compile time and ends up as a bunch of static data in the executable.
.section .data
.globl M_foo3_closure
M_foo3_closure:
.quad ghczmprim_GHCziTypes_ZC_con_info
.quad M_foo4_closure+1
.quad ghczmprim_GHCziTypes_ZMZN_closure+1
.quad 3
...
.globl M_foo_closure
M_foo_closure:
.quad ghczmprim_GHCziTypes_ZC_con_info
.quad M_foo7_closure+1
.quad M_foo1_closure+2
.quad 3
Arrays
In any array backed data structure however, if we write "foo = fromList [1,2,3,4] :: Vector Int" we either end up with the fully evaluated list in the executable or excessive amounts of code. Either way it leads to work and allocations being performed which should be done at compile time.
For example this is additional code on top of the list for fromList [1,2,3,4] :: Vector Int
at -O2
Click to show core output
Rec {
-- RHS size: {terms: 196, types: 205, coercions: 76, joins: 0/7}
foo_$s$wfoldlM_loop2
foo_$s$wfoldlM_loop2
= \ sc_s4n0
sc1_s4mX
sc2_s4mY
sc3_s4mW
sc4_s4mV
sc5_s4mU
sc6_s4mT ->
let {
y_a3mD
y_a3mD = +# sc3_s4mW 1# } in
case <# sc5_s4mU y_a3mD of {
__DEFAULT ->
case writeArray#
(sc4_s4mV `cast` <Co:5>)
(+# sc6_s4mT sc3_s4mW)
(I# sc1_s4mX)
(sc_s4n0 `cast` <Co:4>)
of s'#_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop3
(s'#_a3Wh `cast` <Co:3>) sc2_s4mY y_a3mD sc4_s4mV sc5_s4mU sc6_s4mT
};
1# ->
case <=# sc5_s4mU 1# of {
__DEFAULT ->
let {
y2_a3mN
y2_a3mN = -# y_a3mD sc5_s4mU } in
case <=# sc5_s4mU y2_a3mN of {
__DEFAULT ->
let {
n#_a3TR
n#_a3TR = *# 2# sc5_s4mU } in
case newArray# n#_a3TR uninitialised (sc_s4n0 `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc4_s4mV `cast` <Co:5>) sc6_s4mT ipv1_a3TX 0# sc5_s4mU ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc3_s4mW (I# sc1_s4mX) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop3
(s'#1_a3Wh `cast` <Co:3>)
sc2_s4mY
y_a3mD
(ipv1_a3TX `cast` <Co:4>)
n#_a3TR
0#
}
}
};
1# ->
let {
n#_a3TR
n#_a3TR = +# sc5_s4mU y2_a3mN } in
case newArray# n#_a3TR uninitialised (sc_s4n0 `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc4_s4mV `cast` <Co:5>) sc6_s4mT ipv1_a3TX 0# sc5_s4mU ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc3_s4mW (I# sc1_s4mX) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop3
(s'#1_a3Wh `cast` <Co:3>)
sc2_s4mY
y_a3mD
(ipv1_a3TX `cast` <Co:4>)
n#_a3TR
0#
}
}
}
};
1# ->
let {
y2_a3mT
y2_a3mT = -# y_a3mD sc5_s4mU } in
case <=# 1# y2_a3mT of {
__DEFAULT ->
let {
n#_a3TR
n#_a3TR = +# sc5_s4mU 1# } in
case newArray# n#_a3TR uninitialised (sc_s4n0 `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc4_s4mV `cast` <Co:5>) sc6_s4mT ipv1_a3TX 0# sc5_s4mU ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc3_s4mW (I# sc1_s4mX) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop3
(s'#1_a3Wh `cast` <Co:3>)
sc2_s4mY
y_a3mD
(ipv1_a3TX `cast` <Co:4>)
n#_a3TR
0#
}
}
};
1# ->
let {
n#_a3TR
n#_a3TR = +# sc5_s4mU y2_a3mT } in
case newArray# n#_a3TR uninitialised (sc_s4n0 `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc4_s4mV `cast` <Co:5>) sc6_s4mT ipv1_a3TX 0# sc5_s4mU ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc3_s4mW (I# sc1_s4mX) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop3
(s'#1_a3Wh `cast` <Co:3>)
sc2_s4mY
y_a3mD
(ipv1_a3TX `cast` <Co:4>)
n#_a3TR
0#
}
}
}
}
}
}
-- RHS size: {terms: 202, types: 206, coercions: 76, joins: 0/7}
foo_$s$wfoldlM_loop1
foo_$s$wfoldlM_loop1
= \ sc_s4md
sc1_s4m9
sc2_s4ma
sc3_s4mb
sc4_s4m8
sc5_s4m7
sc6_s4m6
sc7_s4m5 ->
let {
y_a3mD
y_a3mD = +# sc4_s4m8 1# } in
case <# sc6_s4m6 y_a3mD of {
__DEFAULT ->
case writeArray#
(sc5_s4m7 `cast` <Co:5>)
(+# sc7_s4m5 sc4_s4m8)
(I# sc1_s4m9)
(sc_s4md `cast` <Co:4>)
of s'#_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop2
(s'#_a3Wh `cast` <Co:3>)
sc2_s4ma
sc3_s4mb
y_a3mD
sc5_s4m7
sc6_s4m6
sc7_s4m5
};
1# ->
case <=# sc6_s4m6 1# of {
__DEFAULT ->
let {
y2_a3mN
y2_a3mN = -# y_a3mD sc6_s4m6 } in
case <=# sc6_s4m6 y2_a3mN of {
__DEFAULT ->
let {
n#_a3TR
n#_a3TR = *# 2# sc6_s4m6 } in
case newArray# n#_a3TR uninitialised (sc_s4md `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc5_s4m7 `cast` <Co:5>) sc7_s4m5 ipv1_a3TX 0# sc6_s4m6 ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc4_s4m8 (I# sc1_s4m9) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop2
(s'#1_a3Wh `cast` <Co:3>)
sc2_s4ma
sc3_s4mb
y_a3mD
(ipv1_a3TX `cast` <Co:4>)
n#_a3TR
0#
}
}
};
1# ->
let {
n#_a3TR
n#_a3TR = +# sc6_s4m6 y2_a3mN } in
case newArray# n#_a3TR uninitialised (sc_s4md `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc5_s4m7 `cast` <Co:5>) sc7_s4m5 ipv1_a3TX 0# sc6_s4m6 ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc4_s4m8 (I# sc1_s4m9) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop2
(s'#1_a3Wh `cast` <Co:3>)
sc2_s4ma
sc3_s4mb
y_a3mD
(ipv1_a3TX `cast` <Co:4>)
n#_a3TR
0#
}
}
}
};
1# ->
let {
y2_a3mT
y2_a3mT = -# y_a3mD sc6_s4m6 } in
case <=# 1# y2_a3mT of {
__DEFAULT ->
let {
n#_a3TR
n#_a3TR = +# sc6_s4m6 1# } in
case newArray# n#_a3TR uninitialised (sc_s4md `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc5_s4m7 `cast` <Co:5>) sc7_s4m5 ipv1_a3TX 0# sc6_s4m6 ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc4_s4m8 (I# sc1_s4m9) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop2
(s'#1_a3Wh `cast` <Co:3>)
sc2_s4ma
sc3_s4mb
y_a3mD
(ipv1_a3TX `cast` <Co:4>)
n#_a3TR
0#
}
}
};
1# ->
let {
n#_a3TR
n#_a3TR = +# sc6_s4m6 y2_a3mT } in
case newArray# n#_a3TR uninitialised (sc_s4md `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc5_s4m7 `cast` <Co:5>) sc7_s4m5 ipv1_a3TX 0# sc6_s4m6 ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc4_s4m8 (I# sc1_s4m9) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop2
(s'#1_a3Wh `cast` <Co:3>)
sc2_s4ma
sc3_s4mb
y_a3mD
(ipv1_a3TX `cast` <Co:4>)
n#_a3TR
0#
}
}
}
}
}
}
-- RHS size: {terms: 208, types: 207, coercions: 76, joins: 0/7}
foo_$s$wfoldlM_loop
foo_$s$wfoldlM_loop
= \ sc_s4m3
sc1_s4lY
sc2_s4lZ
sc3_s4m0
sc4_s4m1
sc5_s4lX
sc6_s4lW
sc7_s4lU
sc8_s4lT ->
let {
y_a3mD
y_a3mD = +# sc5_s4lX 1# } in
case <# sc7_s4lU y_a3mD of {
__DEFAULT ->
case writeArray#
(sc6_s4lW `cast` <Co:5>)
(+# sc8_s4lT sc5_s4lX)
(I# sc1_s4lY)
(sc_s4m3 `cast` <Co:4>)
of s'#_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop1
(s'#_a3Wh `cast` <Co:3>)
sc2_s4lZ
sc3_s4m0
sc4_s4m1
y_a3mD
sc6_s4lW
sc7_s4lU
sc8_s4lT
};
1# ->
case <=# sc7_s4lU 1# of {
__DEFAULT ->
let {
y2_a3mN
y2_a3mN = -# y_a3mD sc7_s4lU } in
case <=# sc7_s4lU y2_a3mN of {
__DEFAULT ->
let {
n#_a3TR
n#_a3TR = *# 2# sc7_s4lU } in
case newArray# n#_a3TR uninitialised (sc_s4m3 `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc6_s4lW `cast` <Co:5>) sc8_s4lT ipv1_a3TX 0# sc7_s4lU ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc5_s4lX (I# sc1_s4lY) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop1
(s'#1_a3Wh `cast` <Co:3>)
sc2_s4lZ
sc3_s4m0
sc4_s4m1
y_a3mD
(ipv1_a3TX `cast` <Co:4>)
n#_a3TR
0#
}
}
};
1# ->
let {
n#_a3TR
n#_a3TR = +# sc7_s4lU y2_a3mN } in
case newArray# n#_a3TR uninitialised (sc_s4m3 `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc6_s4lW `cast` <Co:5>) sc8_s4lT ipv1_a3TX 0# sc7_s4lU ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc5_s4lX (I# sc1_s4lY) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop1
(s'#1_a3Wh `cast` <Co:3>)
sc2_s4lZ
sc3_s4m0
sc4_s4m1
y_a3mD
(ipv1_a3TX `cast` <Co:4>)
n#_a3TR
0#
}
}
}
};
1# ->
let {
y2_a3mT
y2_a3mT = -# y_a3mD sc7_s4lU } in
case <=# 1# y2_a3mT of {
__DEFAULT ->
let {
n#_a3TR
n#_a3TR = +# sc7_s4lU 1# } in
case newArray# n#_a3TR uninitialised (sc_s4m3 `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc6_s4lW `cast` <Co:5>) sc8_s4lT ipv1_a3TX 0# sc7_s4lU ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc5_s4lX (I# sc1_s4lY) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop1
(s'#1_a3Wh `cast` <Co:3>)
sc2_s4lZ
sc3_s4m0
sc4_s4m1
y_a3mD
(ipv1_a3TX `cast` <Co:4>)
n#_a3TR
0#
}
}
};
1# ->
let {
n#_a3TR
n#_a3TR = +# sc7_s4lU y2_a3mT } in
case newArray# n#_a3TR uninitialised (sc_s4m3 `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc6_s4lW `cast` <Co:5>) sc8_s4lT ipv1_a3TX 0# sc7_s4lU ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc5_s4lX (I# sc1_s4lY) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
foo_$s$wfoldlM_loop1
(s'#1_a3Wh `cast` <Co:3>)
sc2_s4lZ
sc3_s4m0
sc4_s4m1
y_a3mD
(ipv1_a3TX `cast` <Co:4>)
n#_a3TR
0#
}
}
}
}
}
}
-- RHS size: {terms: 200, types: 209, coercions: 76, joins: 0/7}
foo_$s$wfoldlM_loop3
foo_$s$wfoldlM_loop3
= \ sc_s4nI sc1_s4nG sc2_s4nF sc3_s4nE sc4_s4nD sc5_s4nC ->
let {
y_a3mD
y_a3mD = +# sc2_s4nF 1# } in
case <# sc4_s4nD y_a3mD of {
__DEFAULT ->
case writeArray#
(sc3_s4nE `cast` <Co:5>)
(+# sc5_s4nC sc2_s4nF)
(I# sc1_s4nG)
(sc_s4nI `cast` <Co:4>)
of s'#_a3Wh
{ __DEFAULT ->
$wfoldlM_loop_r4vW
SPEC sc5_s4nC sc4_s4nD sc3_s4nE y_a3mD [] (s'#_a3Wh `cast` <Co:3>)
};
1# ->
case <=# sc4_s4nD 1# of {
__DEFAULT ->
let {
y2_a3mN
y2_a3mN = -# y_a3mD sc4_s4nD } in
case <=# sc4_s4nD y2_a3mN of {
__DEFAULT ->
let {
n#_a3TR
n#_a3TR = *# 2# sc4_s4nD } in
case newArray# n#_a3TR uninitialised (sc_s4nI `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc3_s4nE `cast` <Co:5>) sc5_s4nC ipv1_a3TX 0# sc4_s4nD ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc2_s4nF (I# sc1_s4nG) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
$wfoldlM_loop_r4vW
SPEC
0#
n#_a3TR
(ipv1_a3TX `cast` <Co:4>)
y_a3mD
[]
(s'#1_a3Wh `cast` <Co:3>)
}
}
};
1# ->
let {
n#_a3TR
n#_a3TR = +# sc4_s4nD y2_a3mN } in
case newArray# n#_a3TR uninitialised (sc_s4nI `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc3_s4nE `cast` <Co:5>) sc5_s4nC ipv1_a3TX 0# sc4_s4nD ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc2_s4nF (I# sc1_s4nG) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
$wfoldlM_loop_r4vW
SPEC
0#
n#_a3TR
(ipv1_a3TX `cast` <Co:4>)
y_a3mD
[]
(s'#1_a3Wh `cast` <Co:3>)
}
}
}
};
1# ->
let {
y2_a3mT
y2_a3mT = -# y_a3mD sc4_s4nD } in
case <=# 1# y2_a3mT of {
__DEFAULT ->
let {
n#_a3TR
n#_a3TR = +# sc4_s4nD 1# } in
case newArray# n#_a3TR uninitialised (sc_s4nI `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc3_s4nE `cast` <Co:5>) sc5_s4nC ipv1_a3TX 0# sc4_s4nD ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc2_s4nF (I# sc1_s4nG) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
$wfoldlM_loop_r4vW
SPEC
0#
n#_a3TR
(ipv1_a3TX `cast` <Co:4>)
y_a3mD
[]
(s'#1_a3Wh `cast` <Co:3>)
}
}
};
1# ->
let {
n#_a3TR
n#_a3TR = +# sc4_s4nD y2_a3mT } in
case newArray# n#_a3TR uninitialised (sc_s4nI `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(sc3_s4nE `cast` <Co:5>) sc5_s4nC ipv1_a3TX 0# sc4_s4nD ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX sc2_s4nF (I# sc1_s4nG) s'#_a3Uk
of s'#1_a3Wh
{ __DEFAULT ->
$wfoldlM_loop_r4vW
SPEC
0#
n#_a3TR
(ipv1_a3TX `cast` <Co:4>)
y_a3mD
[]
(s'#1_a3Wh `cast` <Co:3>)
}
}
}
}
}
}
-- RHS size: {terms: 214, types: 242, coercions: 106, joins: 0/7}
$wfoldlM_loop_r4vW
$wfoldlM_loop_r4vW
= \ w_s4aq ww_s4az ww1_s4aA ww2_s4aB ww3_s4aG w1_s4as w2_s4at ->
case w_s4aq of { __DEFAULT ->
case w1_s4as of {
[] ->
case unsafeFreezeArray#
(ww2_s4aB `cast` <Co:5>) (w2_s4at `cast` <Co:22>)
of
{ (# ipv_a3yP, ipv1_a3yQ #) ->
(# ipv_a3yP `cast` <Co:3>, Vector ww_s4az ww3_s4aG ipv1_a3yQ #)
};
: x_a3l6 xs1_a3l7 ->
let {
y_a3mD
y_a3mD = +# ww3_s4aG 1# } in
case <# ww1_s4aA y_a3mD of {
__DEFAULT ->
case writeArray#
(ww2_s4aB `cast` <Co:5>)
(+# ww_s4az ww3_s4aG)
x_a3l6
(w2_s4at `cast` <Co:4>)
of s'#_a3Wh
{ __DEFAULT ->
$wfoldlM_loop_r4vW
SPEC
ww_s4az
ww1_s4aA
ww2_s4aB
y_a3mD
xs1_a3l7
(s'#_a3Wh `cast` <Co:3>)
};
1# ->
case <=# ww1_s4aA 1# of {
__DEFAULT ->
let {
y2_a3mN
y2_a3mN = -# y_a3mD ww1_s4aA } in
case <=# ww1_s4aA y2_a3mN of {
__DEFAULT ->
let {
n#_a3TR
n#_a3TR = *# 2# ww1_s4aA } in
case newArray# n#_a3TR uninitialised (w2_s4at `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(ww2_s4aB `cast` <Co:5>) ww_s4az ipv1_a3TX 0# ww1_s4aA ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX ww3_s4aG x_a3l6 s'#_a3Uk of s'#1_a3Wh
{ __DEFAULT ->
$wfoldlM_loop_r4vW
SPEC
0#
n#_a3TR
(ipv1_a3TX `cast` <Co:4>)
y_a3mD
xs1_a3l7
(s'#1_a3Wh `cast` <Co:3>)
}
}
};
1# ->
let {
n#_a3TR
n#_a3TR = +# ww1_s4aA y2_a3mN } in
case newArray# n#_a3TR uninitialised (w2_s4at `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(ww2_s4aB `cast` <Co:5>) ww_s4az ipv1_a3TX 0# ww1_s4aA ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX ww3_s4aG x_a3l6 s'#_a3Uk of s'#1_a3Wh
{ __DEFAULT ->
$wfoldlM_loop_r4vW
SPEC
0#
n#_a3TR
(ipv1_a3TX `cast` <Co:4>)
y_a3mD
xs1_a3l7
(s'#1_a3Wh `cast` <Co:3>)
}
}
}
};
1# ->
let {
y2_a3mT
y2_a3mT = -# y_a3mD ww1_s4aA } in
case <=# 1# y2_a3mT of {
__DEFAULT ->
let {
n#_a3TR
n#_a3TR = +# ww1_s4aA 1# } in
case newArray# n#_a3TR uninitialised (w2_s4at `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(ww2_s4aB `cast` <Co:5>) ww_s4az ipv1_a3TX 0# ww1_s4aA ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX ww3_s4aG x_a3l6 s'#_a3Uk of s'#1_a3Wh
{ __DEFAULT ->
$wfoldlM_loop_r4vW
SPEC
0#
n#_a3TR
(ipv1_a3TX `cast` <Co:4>)
y_a3mD
xs1_a3l7
(s'#1_a3Wh `cast` <Co:3>)
}
}
};
1# ->
let {
n#_a3TR
n#_a3TR = +# ww1_s4aA y2_a3mT } in
case newArray# n#_a3TR uninitialised (w2_s4at `cast` <Co:4>) of
{ (# ipv_a3TW, ipv1_a3TX #) ->
case copyMutableArray#
(ww2_s4aB `cast` <Co:5>) ww_s4az ipv1_a3TX 0# ww1_s4aA ipv_a3TW
of s'#_a3Uk
{ __DEFAULT ->
case writeArray# ipv1_a3TX ww3_s4aG x_a3l6 s'#_a3Uk of s'#1_a3Wh
{ __DEFAULT ->
$wfoldlM_loop_r4vW
SPEC
0#
n#_a3TR
(ipv1_a3TX `cast` <Co:4>)
y_a3mD
xs1_a3l7
(s'#1_a3Wh `cast` <Co:3>)
}
}
}
}
}
}
}
}
end Rec }
-- RHS size: {terms: 17, types: 30, coercions: 95, joins: 0/0}
foo1
foo1
= \ s1_a1VO ->
case newArray# 0# uninitialised (s1_a1VO `cast` <Co:20>) of
{ (# ipv_a3B5, ipv1_a3B6 #) ->
foo_$s$wfoldlM_loop
(ipv_a3B5 `cast` <Co:22>)
1#
2#
3#
4#
0#
(ipv1_a3B6 `cast` <Co:53>)
0#
0#
}
-- RHS size: {terms: 5, types: 33, coercions: 0, joins: 0/0}
foo
foo
= case runRW# foo1 of { (# ipv1_a23t, ipv2_a23u #) -> ipv2_a23u }
It's quite excessive for generating what boils down to an Array of 4 elements known ahead of time.
Proposal
Ideally GHC would have something like these magic functions to instantiate statically known arrays at compile time.
mkStaticArray# :: [a] -> Array# a
mkSmallStaticArray# :: [a] -> SmallArray# a
Which when the list is static will simply allocate the Array in the .data
section just like we do for lists.
In particular a static list would be any list for which we:
- Can compile all elements to a pointer known at compile time.
- Know the length ahead of time.
This is however fragile as weither or not a list is static could (and likely would) change often based on GHC versions and optimization flags used.
An alternative might be to have "best effort" functions instead.
newSmallStaticArray# :: Int# -> [a] -> State# d -> (#State# d, SmallMutableArray# d a#)
With the idea being that semantically it's equal to fromListN
but any static elements will be preallocated. So if the whole list is static we will not have any compile time allocation at all, but code would not randomly fail to compile.
I do not have a concrete implementation plan. I'm sure there are also hurdles to overcome I didn't even think of. But the current situation is unsatisfying.