TiarkRompf / virtualization-lms-core

A Framework for Runtime Code Generation and Compiled DSLs
http://scala-lms.github.com
BSD 3-Clause "New" or "Revised" License
324 stars 91 forks source link

Fat Struct optimizations are incorrect #90

Open manojo opened 9 years ago

manojo commented 9 years ago

See https://gist.github.com/manojo/2e378e7128b13c84f29e for runnable test case.

Suppose we want to generate code for a certain struct Box[T], with the constructor def mkBox[T: Manifest](t: Rep[T]); Rep[Box[T]]. Given the following code:

val someCond: Rep[Boolean] = //dynamic condition
if (someCond) mkBox(2)
else if (someCond) mkBox(7)
else mkBox(0)

If mixed in with the optimisation StructFatExpOptCommon, the generated code contains compile-time errors. Also, the generated code contains only one test for someCond: in the positive branch for that condition, both computations mkBox(2) and mkBox(7) are inlined. This is not desirable in general, and therefore should not be a default "optimisation". Consider a more real-life case:

val someCond: Rep[Boolean] = ...
val anOption: Rep[Option[Int]] = if (someCond) /* complex computation yielding Some */ else None
if (anOption.isDefined) anOption 
else {
   if (someCond) /* complex computation2 yielding Some */
   else None
}

We only want the complex computation 2 to be inlined in the failure branch of the anOption. Using StructFatExpOptCommon we will arrive at a similar problem as above, effectively breaking the semantics of Option.

I am not fully confident in understanding StructExpFat and IfThenElseFat to propose a solution myself, unfortunately.