Re: property lists

Top Pagina
Bijlagen:
Bericht als e-mail
+ (text/plain)
Delete this message
Reply to this message
Auteur: Matthew Fluet
Datum:  
Aan: MLton
Onderwerp: Re: property lists

> > Second footnote: The live variable lists are updated during the simplify
> > phase when I verify that the all of the liveness information is correct.
> > Previously, I hadn't needed to do this, I just assumed that the values
> > filled in in backend.fun were correct. (Steve and I wrestled with this at
> > the end of the summer when we first added the liveness calculation to
> > backend.fun. It's correct, although in some cases it overly conservative,
> > claiming that variables are live into a block when they don't need to be.)
>
> Shoot. If you let me know where it's still conservative, I'll look into it.


Here's where I found some differences in the liveness calculations. These
programs were all run with -detect-overflow false to avoid all of the
overflow blocks. Unfortunately, I don't see a common error in these
cases.

regression/real.sml

This one is due to a missed CPS optimization:

fun L_1055(x_14390) = 
    case x_14390 of
      false => L_889
    | true => L_889


In MachineOutput, this became a Switch, which was optimized at translation
to a single jump to L_889. Thus, x_14390 (which became RI(0)) is no
longer live in.


benchmarks/barnes-hut.sml *

There were a number of differences in the liveness.

Here's the problematic CPS functions:

        fun L_376(x_17179, x_17180) = 
           let
          val x_16282 = Word32_fromInt(x_15515)
          val x_16283 = Word32_fromInt(x_17175)
          val x_16284 = Word32_andb(x_16282, x_16283)
          val x_16279 = MLton_eq(x_16284, global_82)
          fun L_700() = 
             let
            val x_16286 = Int_add(x_17179, global_12)
             in
            x_17180
             end
          fun L_699() = 
             let
            val x_16288 = Int_add(x_17179, global_12)
            val x_16289 = Word32_fromInt(env_126)
            val x_16290 = Word32_fromInt(x_16288)
            val x_16287 = Word32_lt(x_16290, global_79)
            fun L_703(x_16291) = 
               let
                  val x_16293 = Word32_toIntX(x_16291)
                  fun L_704() = 
                 let
                    val x_16295 = Word32_toIntX(x_16291)
                    val x_16296 = Int_add(x_17180, x_16295)
                    val x_16297 = Int_add(x_17179, global_12)
                 in
                    x_16296
                 end
                  fun L_705() = 
                 raise [global_24]
                  val x_16292 = Int_lt(x_16293, global_9)
               in
                  case x_16292 of
                false => L_704 | true => L_705
               end
            fun L_701() = 
               let
                  val x_16298 = Word32_arshift(x_16289, global_78)
               in
                  L_703(x_16298)
               end
            fun L_702() = 
               let
                  val x_16299 = Word32_arshift(x_16289, x_16290)
               in
                  L_703(x_16299)
               end
             in
            case x_16287 of
              false => L_701 | true => L_702
             end
           in
          case x_16279 of
            false => L_699 | true => L_700
           end


The basic issues seems to be with L_704, where barnes-hut.reg shows that
x_16297 is unused, but x_17179 is assigned to RI(5), and the backend
reports that RI(5) is live into L_704. This is propagated back and the
backend reports that L_703, L_702, and L_701 all have RI(5) live in.

The same error occurs with L_700, where x_16289 is unused.


benchmarks/mlyacc.sml

      fun L_7055() = 
     let
        val x_72292 = Array_length(data_36)
        fun L_7056() = 
           let
          val x_72293 = Array_sub(data_36, x_65181)
           in
          L_5885(x_72293)
           end
        fun L_7057() = 
           raise [global_39]
        val x_72291 = Int_geu(x_65181, x_72292)
     in
        case x_72291 of
          false => L_7056 | true => L_7057
     end


The variable x_72292 is assigned to RI(2), which is reported as live
into L_7056.


benchmarks/zern.sml

The CPS is a little bit big for this one, so here's the C backend output:

L_278:
/* live: L_278 [RI(3),RI(4),RI(1),RI(2)] */
    RI(5) = Int_sub(RI(3), 1);
    RI(6) = Int_add(RI(4), 1000000);
L_279:
/* live: L_279 [RI(5),RI(2),RI(1)] */
    RI(6) = Int_lt(RI(5), 0);
    BZ(RI(6), L_280)


Note that RI(4) shouldn't really be live into L_278, because
RI(6) = Int_add(RI(4), 1000000);
is dead code.

Here's the important part of the CPS:

fun L_279(x_5081, x_5082) = 
 let
   fun L_280() = ... (big function, neither x_5081 nor x_5082 is free) ...
   fun L_281() = 
    L_197(global_9)
   val x_5039 = Int_lt(x_5082, global_3)
 in
   case x_5039 of
    false => L_280 | true => L_281
 end
fun L_277() = L_279(x_5037, x_5036)
fun L_278() = 
 let
  val x_5075 = Int_sub(x_5036, global_5)
  val x_5076 = Int_add(x_5037, global_7)
 in
  L_279(x_5076, x_5075)
 end


The issue seems to be that x_5081 is really useless in L_279, but it
wasn't eliminated by the CPS shrinker. On the otherhand, the register
allocator established that x_5039 and x_5081 could share the same
pseudo-register.