Joseph F. Ryan wrote: > Benjamin Goldberg wrote: >> Joseph Ryan wrote: >>> Benjamin Goldberg wrote: [snip] >>>> Hmm... If imcc is smart enough, (or perhaps I should say, when the >>>> flow control is simple/clear enough) it should be able to see when a >>>> value is pushed onto the stack, and later popped off, when there are >>>> enough registers free that we could have stored it in a spare >>>> register instead of on the stack. That is, a sort of register >>>> *un*spilling. >>> >>> Doesn't IMCC already do this? > > I think I misunderstood you. However, I still don't see this would be > helpful.
If someone's code emits something like: save $P1 restore $P2 Then IMCC should be able to optimize that to: $P<temp> = $P1 $P2 = $P<temp> True, a human writing code wouldn't do a save/restore like that, but a naive compiler might (the 'save' being the last instruction of one of <language>'s opcodes, and the 'restore' being the first instruction of the next of one of <language>'s opcodes). And I'd rather we make imcc smart enough to make such code fast, than have to make my compiler smarter. > How would IMCC know which save/restore are associated with > "the" stack, and which are "normal" save/restore? (i.e., associated > with parameters/results from a subroutine) Unless I'm missing > something, you'd have to between those two sets of use... That's why I said, "when the control flow is simple/clear enough" ... The following isn't the only way to do it, merely the first that comes to mind, and I *could* be quite mistaken about whether or not it would work. We can analyze each basic block, and try and figure out how much it changes the stack -- how many items from the stack it will pop, and how many it will push. We can say "unknown" for these if we have to, if it's beyond our ability to analyse. Also, code can make assertions, saying that even though we're doing this weird sequence of pushes and pops, (e.g., doing saves in one loop, followed by restores in another loop), that it will always pop a total of X, and push a total of Y. For each stretch of ops, repeatedly scan for a save op, then look for the following restore op. If we *know* that the value that was just saved wasn't popped off the stack by the ops and blocks in between (we should know this due to the analysis we just did), then we can replace that save...restore pair with $P<temp> = $P1...$P2 = $P<temp>. Note that no differentiation needs to be made about whether a save/restore is for a subroutine argument/return value, or a "normal" save/restore. We only count *how many* saves/restores occur. -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}