gecko-dev/ef/Compiler/RegisterAllocator/Liveness.cpp

182 строки
6.5 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):
*/
#include "Fundamentals.h"
#include "Liveness.h"
#include "FastBitSet.h"
#include "VirtualRegister.h"
#include "ControlGraph.h"
#include "Timer.h"
//
// Build the liveness analysis.
//
// The liveness is defined by the following data-flow equations:
// LiveIn(n) = LocalLive(n) U (LiveOut(n) - Killed(n)).
// LiveOut(n) = U LiveIn(s) (s a successor of n).
// where LocalLive(n) is the set of used registers in the block n, Killed(n) is the set of defined registers
// in the block n, LiveIn(n) is the set of live registers at the begining a the block n and LiveOut(n) is the
// set of live registers at the end of the block n.
//
// We will compute the liveness analysis in two stages:
// 1- Build LocalLive(n) (wich is an approximation of LiveIn(n)) and Killed(n) for each block n.
// 2- Perform a backward data-flow analysis to propagate the liveness information through the entire control-flow graph.
void Liveness::buildAcyclicLivenessAnalysis(const ControlGraph& /*controlGraph*/, const VirtualRegisterManager& /*vrManager*/)
{
trespass("not implemented");
}
//
// Build the sets LiveIn & LiveOut for each node of the given cyclic graph (controlGraph).
//
void Liveness::buildCyclicLivenessAnalysis(const ControlGraph& controlGraph, const VirtualRegisterManager& vrManager)
{
Uint32 nNodes = size = controlGraph.nNodes; // Number of nodes in this graph.
Uint32 nRegisters = vrManager.getSize(); // Number of allocated VirtualRegisters.
startTimer("liveness");
// Allocate and clear the sets LiveIn, LiveOut and Killed (Killed is a temporary,
// it is no longer needed after the liveness analysis).
liveIn = new(pool) FastBitSet[nNodes](pool, nRegisters);
liveOut = new(pool) FastBitSet[nNodes](pool, nRegisters);
FastBitSet* killed = new(pool) FastBitSet[nNodes](pool, nRegisters);
FastBitSet* usedByPhiNodes = new(pool) FastBitSet[nNodes](pool, nRegisters);
ControlNode** nodes = controlGraph.dfsList;
//
// First stage of the liveness analysis: Compute the sets LocalLive(stored in LiveIn) and Killed.
//
for (Uint32 n = 0; n < (nNodes - 1); n++) {
ControlNode& node = *nodes[n];
FastBitSet& currentLocalLive = liveIn[n];
FastBitSet& currentKilled = killed[n];
// If a Virtual Register is defined by a phi node then we add it to the set Killed. Add also the
// used VirtualRegister of this phi node in the set usedByPhiNodes.
DoublyLinkedList<PhiNode>& phiNodes = node.getPhiNodes();
for (DoublyLinkedList<PhiNode>::iterator p = phiNodes.begin(); !phiNodes.done(p); p = phiNodes.advance(p)) {
PhiNode& phiNode = phiNodes.get(p);
if (isStorableKind(phiNode.getKind())) {
currentKilled.set(phiNode.getVirtualRegisterAnnotation()->index);
// Walk the uses.
DataConsumer* consumers = phiNode.getInputsBegin();
Uint32 predecessorIndex = 0;
const DoublyLinkedList<ControlEdge>& predecessors = node.getPredecessors();
for (DoublyLinkedList<ControlEdge>::iterator e = predecessors.begin(); !predecessors.done(e); e = predecessors.advance(e)) {
VirtualRegister& usedRegister = *consumers[predecessorIndex++].getVariable().getVirtualRegisterAnnotation();
usedByPhiNodes[predecessors.get(e).getSource().dfsNum].set(usedRegister.index);
}
}
}
// Find the instructions contributions to the sets LocalLive and Killed.
InstructionList& instructions = node.getInstructions();
for (InstructionList::iterator i = instructions.begin(); !instructions.done(i); i = instructions.advance(i)) {
Instruction& instruction = instructions.get(i);
// If a VirtualRegister is 'used' before being 'defined' then we add it to set LocalLive.
InstructionUse* useEnd = instruction.getInstructionUseEnd();
for (InstructionUse* usePtr = instruction.getInstructionUseBegin(); usePtr < useEnd; usePtr++)
if (usePtr->isVirtualRegister()) {
VirtualRegisterIndex index = usePtr->getVirtualRegister().index;
if (!currentKilled.test(index))
currentLocalLive.set(index);
}
// If a Virtualregister is 'defined' then we add it to the set Killed.
InstructionDefine* defineEnd = instruction.getInstructionDefineEnd();
for (InstructionDefine* definePtr = instruction.getInstructionDefineBegin(); definePtr < defineEnd; definePtr++)
if (definePtr->isVirtualRegister())
currentKilled.set(definePtr->getVirtualRegister().index);
}
}
//
// Second stage of the liveness analysis: We propagate the LiveIn & LiveOut through the entire
// control-flow graph.
//
FastBitSet temp(pool, nRegisters);
bool changed;
do {
changed = false;
for (Int32 n = (nNodes - 2); n >= 0; n--) { // For all nodes in this graph (backward && end block not included).
ControlNode& node = *nodes[n];
FastBitSet& currentLiveIn = liveIn[n];
FastBitSet& currentLiveOut = liveOut[n];
Uint32 nSuccessors = node.nSuccessors();
if (nSuccessors != 0) {
temp = liveIn[node.nthSuccessor(0).getTarget().dfsNum];
for (Uint32 s = 1; s < nSuccessors; s++)
temp |= liveIn[node.nthSuccessor(s).getTarget().dfsNum];
} else
temp.clear();
ControlEdge* successorsEnd = node.getSuccessorsEnd();
for (ControlEdge* e = node.getSuccessorsBegin(); e < successorsEnd; e++)
temp |= liveIn[e->getTarget().dfsNum];
temp |= usedByPhiNodes[n];
if (currentLiveOut != temp) {
currentLiveOut = temp;
temp -= killed[n];
temp |= currentLiveIn;
if (currentLiveIn != temp) {
currentLiveIn = temp;
changed = true;
}
}
}
} while(changed);
stopTimer("liveness");
DEBUG_LOG_ONLY(printPretty(stdout));
}
#ifdef DEBUG_LOG
void Liveness::printPretty(FILE* f)
{
for (Uint32 n = 0; n < size; n++) {
fprintf(f, "Node %d: \n\tliveIn=", n);
liveIn[n].printPrettyOnes(f);
fprintf(f, "\tliveOut=");
liveOut[n].printPrettyOnes(f);
}
}
#endif // DEBUG_LOG