зеркало из https://github.com/mozilla/gecko-dev.git
273 строки
8.8 KiB
C++
273 строки
8.8 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
|
|
#define INCLUDE_EMITTER
|
|
#include "CpuInfo.h"
|
|
#include "Fundamentals.h"
|
|
#include "ControlNodes.h"
|
|
#include "Instruction.h"
|
|
#include "InstructionEmitter.h"
|
|
#include "Spilling.h"
|
|
|
|
|
|
void Spilling::
|
|
insertSpillCode(ControlNode** dfsList, Uint32 nNodes)
|
|
{
|
|
PRUint32 nVirtualRegisters = vRegManager.count();
|
|
FastBitSet currentLive(vRegManager.pool, nVirtualRegisters);
|
|
FastBitSet usedInThisInstruction(vRegManager.pool, nVirtualRegisters);
|
|
RegisterFifo grNeedLoad(nVirtualRegisters);
|
|
RegisterFifo fpNeedLoad(nVirtualRegisters);
|
|
|
|
for (PRInt32 n = nNodes - 1; n >= 0; n--)
|
|
{
|
|
PR_ASSERT(grNeedLoad.empty() & fpNeedLoad.empty());
|
|
ControlNode& node = *dfsList[n];
|
|
|
|
currentLive = node.liveAtEnd;
|
|
|
|
PRUint32 nGeneralAlive = 0;
|
|
PRUint32 nFloatingPointAlive = 0;
|
|
|
|
// Get the number of registers alive at the end of this node.
|
|
for (PRInt32 j = currentLive.firstOne(); j != -1; j = currentLive.nextOne(j))
|
|
{
|
|
VirtualRegister& vReg = vRegManager.getVirtualRegister(j);
|
|
if (vReg.spillInfo.willSpill)
|
|
{
|
|
currentLive.clear(j);
|
|
}
|
|
else
|
|
{
|
|
switch (vReg.getClass())
|
|
{
|
|
case vrcInteger:
|
|
nGeneralAlive++;
|
|
break;
|
|
case vrcFloatingPoint:
|
|
case vrcFixedPoint:
|
|
nFloatingPointAlive++;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// if(node.dfsNum == 8) printf("\n________Begin Node %d________\n", node.dfsNum);
|
|
|
|
InstructionList& instructions = node.getInstructions();
|
|
for (InstructionList::iterator i = instructions.end(); !instructions.done(i); i = instructions.retreat(i))
|
|
{
|
|
Instruction& instruction = instructions.get(i);
|
|
InstructionUse* useBegin = instruction.getInstructionUseBegin();
|
|
InstructionUse* useEnd = instruction.getInstructionUseEnd();
|
|
InstructionUse* usePtr;
|
|
InstructionDefine* defBegin = instruction.getInstructionDefineBegin();
|
|
InstructionDefine* defEnd = instruction.getInstructionDefineEnd();
|
|
InstructionDefine* defPtr;
|
|
|
|
// if(node.dfsNum == 8) { printf("\n");
|
|
// instruction.printPretty(stdout);
|
|
// printf("\n"); }
|
|
|
|
// Handle definitions
|
|
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
|
|
if (defPtr->isVirtualRegister())
|
|
{
|
|
VirtualRegister& vReg = defPtr->getVirtualRegister();
|
|
currentLive.clear(vReg.getRegisterIndex());
|
|
switch (vReg.getClass())
|
|
{
|
|
case vrcInteger:
|
|
nGeneralAlive--;
|
|
break;
|
|
case vrcFloatingPoint:
|
|
case vrcFixedPoint:
|
|
nFloatingPointAlive--;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Check for deaths
|
|
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
|
if (usePtr->isVirtualRegister())
|
|
{
|
|
VirtualRegister& vReg = usePtr->getVirtualRegister();
|
|
if (!currentLive.test(vReg.getRegisterIndex()))
|
|
// This is the last use of this register.
|
|
{
|
|
currentLive.set(vReg.getRegisterIndex());
|
|
switch (vReg.getClass())
|
|
{
|
|
case vrcInteger:
|
|
nGeneralAlive++;
|
|
while (/*(nGeneralAlive > NUMBER_OF_GREGISTERS) &&*/ !grNeedLoad.empty())
|
|
{
|
|
PRUint32 toLoad = grNeedLoad.get();
|
|
currentLive.clear(toLoad);
|
|
nGeneralAlive--;
|
|
|
|
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
|
|
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
|
|
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
|
|
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
|
|
nReg.releaseSelf();
|
|
}
|
|
break;
|
|
case vrcFloatingPoint:
|
|
case vrcFixedPoint:
|
|
nFloatingPointAlive++;
|
|
while (/*(nFloatingPointAlive > NUMBER_OF_FPREGISTERS) &&*/ !fpNeedLoad.empty())
|
|
{
|
|
PRUint32 toLoad = fpNeedLoad.get();
|
|
currentLive.clear(toLoad);
|
|
nFloatingPointAlive--;
|
|
|
|
VirtualRegister& nReg = vRegManager.getVirtualRegister(toLoad);
|
|
Instruction& lastUsingInstruction = *nReg.spillInfo.lastUsingInstruction;
|
|
emitter.emitLoadAfter(*lastUsingInstruction.getPrimitive(), lastUsingInstruction.getLinks().prev,
|
|
nReg.getAlias(), *nReg.equivalentRegister[vrcStackSlot]);
|
|
nReg.releaseSelf();
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle uses
|
|
for (usePtr = useBegin; usePtr < useEnd; usePtr++)
|
|
if (usePtr->isVirtualRegister())
|
|
{
|
|
VirtualRegister& vReg = usePtr->getVirtualRegister();
|
|
PRUint32 registerIndex = vReg.getRegisterIndex();
|
|
|
|
if (vReg.spillInfo.willSpill) {
|
|
#if defined(GENERATE_FOR_X86)
|
|
if (!instruction.switchUseToSpill((usePtr - useBegin), *vReg.equivalentRegister[vrcStackSlot]))
|
|
#endif
|
|
{
|
|
switch (vReg.getClass())
|
|
{
|
|
case vrcInteger:
|
|
if (!grNeedLoad.test(registerIndex))
|
|
{
|
|
grNeedLoad.put(registerIndex);
|
|
VirtualRegister& alias = vRegManager.newVirtualRegister(vrcInteger);
|
|
if (vReg.isPreColored())
|
|
alias.preColorRegister(vReg.getPreColor());
|
|
/* if (vReg.hasSpecialInterference) {
|
|
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
|
|
alias.specialInterference = vReg.specialInterference;
|
|
alias.hasSpecialInterference = true;
|
|
} */
|
|
vReg.setAlias(alias);
|
|
vReg.retainSelf();
|
|
}
|
|
break;
|
|
case vrcFloatingPoint:
|
|
case vrcFixedPoint:
|
|
if (!fpNeedLoad.test(registerIndex))
|
|
{
|
|
fpNeedLoad.put(registerIndex);
|
|
VirtualRegister& alias = vRegManager.newVirtualRegister(vReg.getClass());
|
|
if (vReg.isPreColored())
|
|
alias.preColorRegister(vReg.getPreColor());
|
|
/*if (vReg.hasSpecialInterference) {
|
|
alias.specialInterference.sizeTo(NUMBER_OF_REGISTERS);
|
|
alias.specialInterference = vReg.specialInterference;
|
|
alias.hasSpecialInterference = true;
|
|
} */
|
|
vReg.setAlias(alias);
|
|
vReg.retainSelf();
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
usePtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
|
|
usedInThisInstruction.set(registerIndex);
|
|
vReg.spillInfo.lastUsingInstruction = &instruction;
|
|
}
|
|
currentLive.clear(registerIndex);
|
|
} else { // will not spill
|
|
currentLive.set(registerIndex);
|
|
}
|
|
}
|
|
|
|
// Handle definitions
|
|
for (defPtr = defBegin; defPtr < defEnd; defPtr++)
|
|
if (defPtr->isVirtualRegister())
|
|
{
|
|
VirtualRegister& vReg = defPtr->getVirtualRegister();
|
|
|
|
if (vReg.spillInfo.willSpill)
|
|
#if defined(GENERATE_FOR_X86)
|
|
if (!instruction.switchDefineToSpill((defPtr - defBegin), *vReg.equivalentRegister[vrcStackSlot]))
|
|
#endif
|
|
{
|
|
if (usedInThisInstruction.test(vReg.getRegisterIndex()))
|
|
// this virtualRegister was used in this instruction and is also defined. We need to move
|
|
// this virtual register to its alias first and then save it to memory.
|
|
{
|
|
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
|
|
vReg.getAlias(), *vReg.equivalentRegister[vrcStackSlot]);
|
|
defPtr->getVirtualRegisterPtr().initialize(vReg.getAlias());
|
|
}
|
|
else
|
|
{
|
|
emitter.emitStoreAfter(*instruction.getPrimitive(), &instruction.getLinks(),
|
|
vReg, *vReg.equivalentRegister[vrcStackSlot]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
while (!grNeedLoad.empty())
|
|
{
|
|
PRUint32 nl = grNeedLoad.get();
|
|
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
|
|
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
|
|
|
|
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
|
|
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
|
|
nlReg.releaseSelf();
|
|
}
|
|
while (!fpNeedLoad.empty())
|
|
{
|
|
PRUint32 nl = fpNeedLoad.get();
|
|
VirtualRegister& nlReg = vRegManager.getVirtualRegister(nl);
|
|
Instruction& lastUse = *nlReg.spillInfo.lastUsingInstruction;
|
|
|
|
emitter.emitLoadAfter(*lastUse.getPrimitive(), lastUse.getLinks().prev,
|
|
nlReg.getAlias(), *nlReg.equivalentRegister[vrcStackSlot]);
|
|
nlReg.releaseSelf();
|
|
}
|
|
|
|
// if(node.dfsNum == 8) printf("\n________End Node %d________\n", node.dfsNum);
|
|
|
|
}
|
|
}
|