mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 06:35:42 +00:00
Bug 496693 - NJ: comment and refactor DeadCodeFilter vs Assembler::gen interactions, r=edwsmith.
--HG-- extra : rebase_source : e675f824946d4a8bb83b2aed8ff1911c8b23caee
This commit is contained in:
parent
fe26342c84
commit
00243d2f8f
@ -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");
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user