Baseline Copy Elimination

The baseline compiler tries to avoid move instructions by:

Eliminating LOADs

A LOAD creates a copy edge from a local variable Li to a temporary variable Tj. The copy may be eliminated if Li and Tj do not interfere.

We assume that Tj is unmarked. Thus the LOAD is known to be the only DEF of Tj. So the only way Li and Tj could interfere is that there is a DEF Li during the livetime of Tj.

case a)
LOAD Li      DEF Tj <- USE Li
               |
               |
               X <---> DEF Li
               |
             USE Tj

Implementation: Every LOAD Li marks the created Tj as coalesced with Li (as LOCALVAR(i)). STORE Li and IINC Li remove the LOCALVAR(i) coalescing of any Tj that are alive at the point of the STORE/IINC.

Eliminating STOREs

A STORE creates a copy edge from a temporary variable Tj to a local variable Li. The copy may be eliminated if Tj and Li do not interfere.

We assume that Tj is unmarked. There are two ways Tj and Li can interfere:

b) is rather easy to check: The liferange of Tj is a single range within the basic block. Thus we only need to check if Tj is live at the latest DEF Li (the last STORE/IINC Li). If so, Tj and Li interfere.

Case c) is a little harder to check. The STORE Li we are trying to eliminate kills Li, so case c) can only arise if there is a USE Li somewhere after the single DEF Tj but before the STORE Li.

Li may be live along exception edges. Thus we must assume interference if there is an exception edge from an instruction during the lifetime of Tj.

case b)
              DEF Tj
               |
               X <----> DEF Li
               |
               |
STORE Li      USE Tj -> DEF Li

case c)
                           |
              DEF Tj <---> X
               |           |
               |          USE Li (LOAD Li or USE LOCALVAR(i))
             R |
               |
               |
STORE Li      USE Tj -> DEF Li

We know that there is no interference if all of the following conditions are true:

Eliminating DUPs

DUP elimination is done in the register allocator of the baseline compiler. If there is a copy from one temporary variable Ti to another Tj, and neither variable is marked as STACKVAR, LOCALVAR, or ARGVAR, then Ti and Tj can be coalesced, eliminating the copy instruction.

Since temporary variables may only have one DEF (see IntermediateRepresentation), and the DEF Tj is the copy instruction, there is no possibility of interference. (If Ti is allocated to a register, Ti and Tj must have the same value in the SAVEDVAR flag. <!> XXX elaborate this!)

If the allocator decides to coalesce Ti and Tj, Tj is marked as STCOPY, so when the liferange of (the variable formerly known as) Tj ends, the register allocator does not free the allocation of Tj, since Ti is still alive at this point.

before:

    DEF Ti
     |
     |
DUP  |----> DEF Tj
     |       |
     |       |
     |      USE Tj
     |
     |
    USE Ti

after:

    DEF Tij
     |
     |
     |
     |
     |
    USE Tij (STCOPY -- don't free!)
     |
     |
    USE Tij

cacaowiki: BaselineCopyElimination (last edited 2006-08-27 19:14:37 by EdwinSteiner)