benchmarking Poly/ML & floating point

Stephen Weeks MLton@sourcelight.com
Wed, 13 Sep 2000 11:46:43 -0700 (PDT)


> It didn't get run on any of the benchmarks.  But, I'm curious why the CPS
> translation of  List.map Real.!= l  generates that level of indirection.
> Is it because the representation decisions haven't been made yet and the
> compiler doesn't know whether a simple (i.e., int, char, etc. type) move
> will be appropriate for the eventual representation of booleans?

I'm not entirely sure what you mean by level of indirection, but I'll take a
stab at it.  As a reminder, here is the code.

(* SML *)
val _ =
   List.app
   (fn b => print(concat[Bool.toString b, "\n"]))
   (List.map Real.!= [(1.0, 2.0), (3.0, 3.0)])

(* CPS *)
...
val global_24 = true()
val global_4 = false()
...
	    fun loop_0(x_115, x_116) = 
	       let
		  fun L_12(x_117, x_118) = 
		     let
			val x_120 = #1 x_118
			val x_121 = #2 x_118
			val x_119 = Real_equal(x_120, x_121)
			fun L_13(x_122) = 
			   let
			      val x_123 = ::_2(x_115, x_122)
			   in
			      loop_0(x_123, x_117)
			   end
			fun L_14() = 
			   L_13(global_24)
			fun L_15() = 
			   L_13(global_4)
		     in
			case x_119 of
			  true => L_15 | false => L_14
		     end

I'm guessing that you're referring to labels L_14 and L_15, and that you would
rather see something like

	    fun loop_0(x_115, x_116) = 
	       let
		  fun L_12(x_117, x_118) = 
		     let
			val x_120 = #1 x_118
			val x_121 = #2 x_118
			val x_119 = Real_equal(x_120, x_121)
			val x_122 = Bool_not x_119 
                        val x_123 = ::_2(x_115, x_122)
                      in loop_0(x_123, x_117)
                      end

The reason that this doesn't happen is that there is no "not" primitive --
rather, not is defined in the basis library as

val not =
   fn true => false
    | false => true

So, all uses of not will turn into case statements.  As long as the result of
not is always used in a case, then the CPS shrinker will eliminate the not and
switch the branches on the case.  OTOH, examples like the above, where the
boolean result of not is stored will lead to the extra labels.  I guess we could 
add not as a primitive and have a slightly different optimization to switch the
case labels, but I don't know if it's worth the trouble.