Bug 496693 - NJ: comment and refactor DeadCodeFilter vs Assembler::gen interactions, r=edwsmith.

--HG--
extra : rebase_source : e675f824946d4a8bb83b2aed8ff1911c8b23caee
This commit is contained in:
Julian Seward 2009-07-13 11:50:42 -07:00
parent fe26342c84
commit 00243d2f8f
4 changed files with 64 additions and 53 deletions

View File

@ -309,7 +309,6 @@ js_InitJITLogController ( void )
if (strstr(tmf, "readlir")) bits |= LC_ReadLIR;
if (strstr(tmf, "aftersf_sp")) bits |= LC_AfterSF_SP;
if (strstr(tmf, "aftersf_rp")) bits |= LC_AfterSF_RP;
if (strstr(tmf, "afterdeadf")) bits |= LC_AfterDeadF;
if (strstr(tmf, "regalloc")) bits |= LC_RegAlloc;
if (strstr(tmf, "assembly")) bits |= LC_Assembly;
if (strstr(tmf, "nocodeaddrs")) bits |= LC_NoCodeAddrs;
@ -317,7 +316,7 @@ js_InitJITLogController ( void )
if (strstr(tmf, "full")) {
bits |= LC_TMMinimal | LC_TMTracer | LC_TMRecorder | LC_TMPatcher | LC_TMAbort |
LC_TMAbort | LC_TMStats | LC_TMRegexp | LC_Liveness | LC_ReadLIR |
LC_AfterSF_SP | LC_AfterSF_RP | LC_AfterDeadF | LC_RegAlloc | LC_Assembly;
LC_AfterSF_SP | LC_AfterSF_RP | LC_RegAlloc | LC_Assembly;
}
js_LogController.lcbits = bits;
@ -347,7 +346,6 @@ js_InitJITLogController ( void )
printf(" readlir show LIR as it enters the reader pipeline\n");
printf(" aftersf_sp show LIR after StackFilter(sp)\n");
printf(" aftersf_rp show LIR after StackFilter(rp)\n");
printf(" afterdeadf show LIR after DeadCodeFilter\n");
printf(" regalloc show regalloc details\n");
printf(" assembly show final aggregated assembly code\n");
printf(" nocodeaddrs don't show code addresses in assembly listings\n");

View File

@ -58,35 +58,6 @@ namespace nanojit
{
int UseSoftfloat = 0;
class DeadCodeFilter: public LirFilter
{
bool ignoreInstruction(LInsp ins)
{
LOpcode op = ins->opcode();
if (ins->isStore() ||
op == LIR_loop ||
op == LIR_label ||
op == LIR_live ||
op == LIR_start ||
ins->isRet()) {
return false;
}
return !ins->resv()->used;
}
public:
DeadCodeFilter(LirFilter *in) : LirFilter(in) {}
LInsp read() {
for (;;) {
LInsp i = in->read();
if (i->isGuard() || i->isBranch()
|| (i->isCall() && !i->isCse())
|| !ignoreInstruction(i))
return i;
}
}
};
#ifdef NJ_VERBOSE
class VerboseBlockReader: public LirFilter
{
@ -821,8 +792,7 @@ namespace nanojit
verbose_only(
ReverseLister *pp_init = NULL,
*pp_after_sf1 = NULL,
*pp_after_sf2 = NULL,
*pp_after_dead = NULL;
*pp_after_sf2 = NULL;
)
// set up backwards pipeline: assembler -> StackFilter -> LirReader
@ -858,20 +828,10 @@ namespace nanojit
verbose_only( if (_logc->lcbits & LC_AfterSF_RP) {
pp_after_sf2 = new ReverseLister(prev, gc, frag->lirbuf->names, _logc,
"After StoreFilter(rp)");
"After StoreFilter(rp) (final LIR)");
prev = pp_after_sf2;
})
// DEAD CODE FILTER
DeadCodeFilter deadfilter(prev);
prev = &deadfilter;
verbose_only( if (_logc->lcbits & LC_AfterDeadF) {
pp_after_dead = new ReverseLister(prev, gc, frag->lirbuf->names, _logc,
"After DeadFilter == Final LIR");
prev = pp_after_dead;
})
// end of pipeline
verbose_only(
VerboseBlockReader vbr(prev, this, frag->lirbuf->names);
@ -920,8 +880,7 @@ namespace nanojit
if (pp_init) delete pp_init;
if (pp_after_sf1) delete pp_after_sf1;
if (pp_after_sf2) delete pp_after_sf2;
if (pp_after_dead) delete pp_after_dead;
)
)
}
void Assembler::endAssembly(Fragment* frag, NInsList& loopJumps)
@ -1128,8 +1087,49 @@ namespace nanojit
InsList pending_lives(_gc);
for (LInsp ins = reader->read(); !ins->isop(LIR_start) && !error(); ins = reader->read())
for (LInsp ins = reader->read(); !ins->isop(LIR_start) && !error();
ins = reader->read())
{
/* What's going on here: we're visiting all the LIR nodes
in the buffer, working strictly backwards in
buffer-order, and generating machine instructions for
them as we go.
But we're not visiting all of them, only the ones that
made it through the filter pipeline that we're reading
from. For each visited node, we first determine
whether it's actually necessary, and if not skip it.
Otherwise we fall into the big switch, which calls a
target-specific routine to generate the required
instructions.
For each node, we need to decide whether we need to
generate any code. This is a rather subtle part of the
generation algorithm.
There are two categories:
"statement" nodes -- ones with side effects. Anything
that could change control flow or the state of memory.
These we must absolutely retain. That accounts for the
first part of the following disjunction for 'required'.
The rest are "value" nodes, which compute a value based
only on the operands to the node (and, in the case of
loads, the state of memory). It's safe to omit these
if the value(s) computed are not used later. Since
we're visiting nodes in reverse order, if some
previously visited (viz, later in the buffer ordering)
node uses the value computed by this node, then this
node will already have a register assigned to hold that
value. Hence we can consult the reservation to detect
whether the value is in fact used. That's the second
part of the disjunction.
*/
bool required = ins->isStmt() || ins->resv()->used;
if (!required)
continue;
LOpcode op = ins->opcode();
switch(op)
{

View File

@ -681,6 +681,20 @@ namespace nanojit
return isop(LIR_jt) || isop(LIR_jf) || isop(LIR_j);
}
// Return true if removal of 'ins' from a LIR fragment could
// possibly change the behaviour of that fragment, even if any
// value computed by 'ins' is not used later in the fragment.
// In other words, can 'ins' possible alter control flow or memory?
// Note, this assumes that loads will never fault and hence cannot
// affect the control flow.
bool isStmt() {
return isGuard() || isBranch() ||
(isCall() && !isCse()) ||
isStore() ||
isop(LIR_loop) || isop(LIR_label) || isop(LIR_live) ||
isRet();
}
void setTarget(LIns* t);
LIns* getTarget();

View File

@ -268,11 +268,10 @@ namespace nanojit {
and below, so that callers can use bits 16 and above for
themselves. */
// TODO: add entries for the writer pipeline
LC_Liveness = 1<<7, // (show LIR liveness analysis)
LC_ReadLIR = 1<<6, // As read from LirBuffer
LC_AfterSF_SP = 1<<5, // After StackFilter(sp)
LC_AfterSF_RP = 1<<4, // After StackFilter(rp)
LC_AfterDeadF = 1<<3, // After DeadFilter
LC_Liveness = 1<<6, // (show LIR liveness analysis)
LC_ReadLIR = 1<<5, // As read from LirBuffer
LC_AfterSF_SP = 1<<4, // After StackFilter(sp)
LC_AfterSF_RP = 1<<3, // After StackFilter(rp)
LC_RegAlloc = 1<<2, // stuff to do with reg alloc
LC_Assembly = 1<<1, // final assembly
LC_NoCodeAddrs = 1<<0 // (don't show code addresses on asm output)