RSSA backend
Matthew Fluet
fluet@CS.Cornell.EDU
Thu, 17 Jan 2002 13:00:20 -0500 (EST)
> Agreed. This is wrong because the backend inserts some code for conts
> and handlers that defines the formals at the beginning of the block.
> I checked in a change that makes the live for cont and handler blocks
> the liveNoFormals. Maybe that's good enough.
I also made CReturn and Runtime kinds liveNoFormals. The key is that the
x86 codegen thinks of liveness as being a property of labels, which occur
before "arguments". So, with a CReturn, the destination operand (if any)
is not live at the label; it becomes live after the label when we assign
to it. What is live (implicitly) is a temporary location holding the
return result (which, in turn, is never really used because all CReturns
become fall thus in code layout and moves all occur in place).
That solves most of the pseudo-register discrepencies between MACHINE and
X86 versions of liveness. The main remaining one are the selects down a
value carrying branch of a case statement that aren't used; e.g.:
L_80 ()
case x_126 of
ClosedStream_0 => L_73
| Io_0 => L_74
| SysErr_0 => L_75
| Subscript_0 => L_76
| Fail_0 => L_77
| Size_0 => L_78
| Overflow => L_79
L_77 (x_125)
print_0 (global_40)
x_125 is not used anywhere else in the program.
(This case doesn't actually crop up in the main branch, because knownCase
collapses this case with the one "above" it, where the Fail argument is
used, but it demonstrates the problem.)
This becomes:
L_80 {kind = Jump, live = (SU(4), SU(0), RP(11), SP(8))}:
SwitchIP (RP(11), L_211, L_210)
L_210 {kind = Jump, live = (SU(4), SU(0), RP(11), SP(8))}:
Switch (OI(RP(11),0), [(0, L_209), (1, L_208)], None)
L_209 {kind = Jump, live = (SU(4), SU(0), RP(11), SP(8))}:
RP(19) = OP(RP(11),4)
Goto L_77
L_77 {kind = Jump, live = (SU(4), SU(0), SP(8))}:
RP(20) = GP(17)
Goto print_0
RP(11) is considered live into L_209, because it's used in the select;
after a minor ammount of dead code elimination that eliminates the select,
RP(11) is no longer live into L_209, and that's fixed up by a second round
of liveness verification.
Anyways, I guess this isn't really a "problem" with MACHINE, because the
liveness is correct for the given program. It's only after some
optimization that the liveness changes. But, it might be worth running a
quick remove unused equivalent on RSSA to eliminate these.
With -native-live-stack true, there is a lot to fix up, but it mostly
seems related to the fact that so far I haven't tried to give initial
liveness information to Array allocations. Because limit checks always
appear at array allocations, everything live is stack allocated, so we saw
no problems with -native-live-stack false. When it is true, I need to
introduce the array initialization loops, which don't have any liveness
info associated with them, but really have everything that is live at the
limit check live across them as well; with the possible exception of the
array length, which might not be live at the loop exit.
Options are to
1. leave the array allocation loop labels with empty liveness sets at
translation; it is filled in by the x86 codegen liveness analysis
2. pass the live set from the entry to the translation of the statements;
because array allocation will always be the first statement in
a block, this live set is "right" for the array loop
3. give the MACHINE Array statement a live field
4. make the array initialization loops explicit in MACHINE; I guess this
would be an insertArrayInitializations after insertSignalChecks
I think we eventually want 4, which solves all the problems at once.
2 is easy enough for right now. 3 doesn't seem worth the effort,
particularly if we eventually implement 4.