manticore icon indicating copy to clipboard operation
manticore copied to clipboard

CPS inliner issue with recursive function being mapped

Open SimonAlling opened this issue 6 years ago • 1 comments

Greetings from Sweden and Chalmers University of Technology!

I may have found something when exploring parallel arrays in Manticore. Here is a piece of code that works perfectly fine:

fun f n = if n <= 0 then 0 else 1 + f (n - 1)
val xs = [ 1, 2, 3 ]
val _ = map f xs

Here is a similar program with a parallel array and PArray.map instead of a list and the regular map:

(* f same as before *)
val xs = PArray.fromRope (Rope.tabulateSequential (fn x => x) (1, 3))
val _ = PArray.map (fn x => f x) xs

That code also works. But watch what happens when I eta-reduce the mapped function:

val _ = PArray.map f xs

The code doesn't compile anymore:

$ pmlc eta.pml
***** Bogus CPS in Main after inline *****
** unbound variable f<11431>#4.4
** unbound variable f<11431>#4.4 in Apply
** unbound variable f<11431>#4.4
** unbound variable f<11431>#4.4 in Apply
broken CPS dumped to broken-CPS

The dumped file is 1.7 MB, but I can't really extract any useful information from it.

It also turns out that everything works fine if f is not recursive:

fun f n = if n <= 0 then 0 else 1
val xs = PArray.fromRope (Rope.tabulateSequential (fn x => x) (1, 3))
val _ = PArray.map f xs

I'm not an expert, but there seems to be something going on here. What do you think?

SimonAlling avatar Feb 22 '19 12:02 SimonAlling

This appears to be hitting on some bug in the expansive inliner that runs on the CPS IR.

A workaround for this right now would be to turn off that particular inliner by passing -Ccps.enable-inline=false to the compiler. Note that other function inlining will still happen in the compiler.

Thanks for the bug report! I've summarized the cases below for when we can get around to fixing this.

fun nonrecF x = x + 1

fun recF n = if n <= 0 then 0 else 1 + recF (n - 1)

val xs = PArray.fromRope (Rope.tabulateSequential (fn x => x) (1, 3))

(* broken *)
val _ = PArray.map recF xs

(* works if you eta-expand *)
(* val _ = PArray.map (fn x => recF x) xs *)

(* not an issue for non-recursive function *)
(* val _ = PArray.map nonrecF xs *)

kavon avatar Mar 08 '19 22:03 kavon