forked from OSchip/llvm-project
Move sparc-specific livevar code into lib/Target/Sparc
llvm-svn: 10733
This commit is contained in:
parent
bb6fa4b327
commit
4ee36320f4
|
@ -0,0 +1,230 @@
|
|||
//===-- BBLiveVar.cpp - Live Variable Analysis for a BasicBlock -----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is a wrapper class for BasicBlock which is used by live var analysis.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "BBLiveVar.h"
|
||||
#include "llvm/CodeGen/FunctionLiveVarInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include "Support/SetOperations.h"
|
||||
#include "../SparcInternals.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
BBLiveVar::BBLiveVar(const BasicBlock &bb, MachineBasicBlock &mbb, unsigned id)
|
||||
: BB(bb), MBB(mbb), POID(id) {
|
||||
InSetChanged = OutSetChanged = false;
|
||||
|
||||
calcDefUseSets();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// calculates def and use sets for each BB
|
||||
// There are two passes over operands of a machine instruction. This is
|
||||
// because, we can have instructions like V = V + 1, since we no longer
|
||||
// assume single definition.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void BBLiveVar::calcDefUseSets() {
|
||||
// iterate over all the machine instructions in BB
|
||||
for (MachineBasicBlock::const_reverse_iterator MII = MBB.rbegin(),
|
||||
MIE = MBB.rend(); MII != MIE; ++MII) {
|
||||
const MachineInstr *MI = *MII;
|
||||
|
||||
if (DEBUG_LV >= LV_DEBUG_Verbose) {
|
||||
std::cerr << " *Iterating over machine instr ";
|
||||
MI->dump();
|
||||
std::cerr << "\n";
|
||||
}
|
||||
|
||||
// iterate over MI operands to find defs
|
||||
for (MachineInstr::const_val_op_iterator OpI = MI->begin(), OpE = MI->end();
|
||||
OpI != OpE; ++OpI)
|
||||
if (OpI.isDef()) // add to Defs if this operand is a def
|
||||
addDef(*OpI);
|
||||
|
||||
// do for implicit operands as well
|
||||
for (unsigned i = 0; i < MI->getNumImplicitRefs(); ++i)
|
||||
if (MI->getImplicitOp(i).isDef())
|
||||
addDef(MI->getImplicitRef(i));
|
||||
|
||||
// iterate over MI operands to find uses
|
||||
for (MachineInstr::const_val_op_iterator OpI = MI->begin(), OpE = MI->end();
|
||||
OpI != OpE; ++OpI) {
|
||||
const Value *Op = *OpI;
|
||||
|
||||
if (isa<BasicBlock>(Op))
|
||||
continue; // don't process labels
|
||||
|
||||
if (OpI.isUse()) { // add to Uses only if this operand is a use
|
||||
//
|
||||
// *** WARNING: The following code for handling dummy PHI machine
|
||||
// instructions is untested. The previous code was broken and I
|
||||
// fixed it, but it turned out to be unused as long as Phi
|
||||
// elimination is performed during instruction selection.
|
||||
//
|
||||
// Put Phi operands in UseSet for the incoming edge, not node.
|
||||
// They must not "hide" later defs, and must be handled specially
|
||||
// during set propagation over the CFG.
|
||||
if (MI->getOpCode() == V9::PHI) { // for a phi node
|
||||
const Value *ArgVal = Op;
|
||||
const BasicBlock *PredBB = cast<BasicBlock>(*++OpI); // next ptr is BB
|
||||
|
||||
PredToEdgeInSetMap[PredBB].insert(ArgVal);
|
||||
|
||||
if (DEBUG_LV >= LV_DEBUG_Verbose)
|
||||
std::cerr << " - phi operand " << RAV(ArgVal) << " came from BB "
|
||||
<< RAV(PredBB) << "\n";
|
||||
} // if( IsPhi )
|
||||
else {
|
||||
// It is not a Phi use: add to regular use set and remove later defs.
|
||||
addUse(Op);
|
||||
}
|
||||
} // if a use
|
||||
} // for all operands
|
||||
|
||||
// do for implicit operands as well
|
||||
for (unsigned i = 0; i < MI->getNumImplicitRefs(); ++i) {
|
||||
assert(MI->getOpCode() != V9::PHI && "Phi cannot have implicit operands");
|
||||
const Value *Op = MI->getImplicitRef(i);
|
||||
|
||||
if (Op->getType() == Type::LabelTy) // don't process labels
|
||||
continue;
|
||||
|
||||
if (MI->getImplicitOp(i).isUse())
|
||||
addUse(Op);
|
||||
}
|
||||
} // for all machine instructions
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// To add an operand which is a def
|
||||
//-----------------------------------------------------------------------------
|
||||
void BBLiveVar::addDef(const Value *Op) {
|
||||
DefSet.insert(Op); // operand is a def - so add to def set
|
||||
InSet.erase(Op); // this definition kills any later uses
|
||||
InSetChanged = true;
|
||||
|
||||
if (DEBUG_LV >= LV_DEBUG_Verbose) std::cerr << " +Def: " << RAV(Op) << "\n";
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// To add an operand which is a use
|
||||
//-----------------------------------------------------------------------------
|
||||
void BBLiveVar::addUse(const Value *Op) {
|
||||
InSet.insert(Op); // An operand is a use - so add to use set
|
||||
DefSet.erase(Op); // remove if there is a def below this use
|
||||
InSetChanged = true;
|
||||
|
||||
if (DEBUG_LV >= LV_DEBUG_Verbose) std::cerr << " Use: " << RAV(Op) << "\n";
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Applies the transfer function to a basic block to produce the InSet using
|
||||
// the OutSet.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool BBLiveVar::applyTransferFunc() {
|
||||
// IMPORTANT: caller should check whether the OutSet changed
|
||||
// (else no point in calling)
|
||||
|
||||
ValueSet OutMinusDef = set_difference(OutSet, DefSet);
|
||||
InSetChanged = set_union(InSet, OutMinusDef);
|
||||
|
||||
OutSetChanged = false; // no change to OutSet since transf func applied
|
||||
return InSetChanged;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// calculates Out set using In sets of the successors
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool BBLiveVar::setPropagate(ValueSet *OutSet, const ValueSet *InSet,
|
||||
const BasicBlock *PredBB) {
|
||||
bool Changed = false;
|
||||
|
||||
// merge all members of InSet into OutSet of the predecessor
|
||||
for (ValueSet::const_iterator InIt = InSet->begin(), InE = InSet->end();
|
||||
InIt != InE; ++InIt)
|
||||
if ((OutSet->insert(*InIt)).second)
|
||||
Changed = true;
|
||||
|
||||
//
|
||||
//**** WARNING: The following code for handling dummy PHI machine
|
||||
// instructions is untested. See explanation above.
|
||||
//
|
||||
// then merge all members of the EdgeInSet for the predecessor into the OutSet
|
||||
const ValueSet& EdgeInSet = PredToEdgeInSetMap[PredBB];
|
||||
for (ValueSet::const_iterator InIt = EdgeInSet.begin(), InE = EdgeInSet.end();
|
||||
InIt != InE; ++InIt)
|
||||
if ((OutSet->insert(*InIt)).second)
|
||||
Changed = true;
|
||||
//
|
||||
//****
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// propagates in set to OutSets of PREDECESSORs
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool BBLiveVar::applyFlowFunc(hash_map<const BasicBlock*,
|
||||
BBLiveVar*> &BBLiveVarInfo) {
|
||||
// IMPORTANT: caller should check whether inset changed
|
||||
// (else no point in calling)
|
||||
|
||||
// If this BB changed any OutSets of preds whose POID is lower, than we need
|
||||
// another iteration...
|
||||
//
|
||||
bool needAnotherIt = false;
|
||||
|
||||
for (pred_const_iterator PI = pred_begin(&BB), PE = pred_end(&BB);
|
||||
PI != PE ; ++PI) {
|
||||
BBLiveVar *PredLVBB = BBLiveVarInfo[*PI];
|
||||
|
||||
// do set union
|
||||
if (setPropagate(&PredLVBB->OutSet, &InSet, *PI)) {
|
||||
PredLVBB->OutSetChanged = true;
|
||||
|
||||
// if the predec POID is lower than mine
|
||||
if (PredLVBB->getPOId() <= POID)
|
||||
needAnotherIt = true;
|
||||
}
|
||||
} // for
|
||||
|
||||
return needAnotherIt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----------------- Methods For Debugging (Printing) -----------------
|
||||
|
||||
void BBLiveVar::printAllSets() const {
|
||||
std::cerr << " Defs: "; printSet(DefSet); std::cerr << "\n";
|
||||
std::cerr << " In: "; printSet(InSet); std::cerr << "\n";
|
||||
std::cerr << " Out: "; printSet(OutSet); std::cerr << "\n";
|
||||
}
|
||||
|
||||
void BBLiveVar::printInOutSets() const {
|
||||
std::cerr << " In: "; printSet(InSet); std::cerr << "\n";
|
||||
std::cerr << " Out: "; printSet(OutSet); std::cerr << "\n";
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
|
@ -0,0 +1,90 @@
|
|||
//===-- BBLiveVar.h - Live Variable Analysis for a BasicBlock ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is a BasicBlock annotation class that is used by live var analysis to
|
||||
// hold data flow information for a basic block.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LIVE_VAR_BB_H
|
||||
#define LIVE_VAR_BB_H
|
||||
|
||||
#include "llvm/CodeGen/ValueSet.h"
|
||||
#include "Support/hash_map"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class BasicBlock;
|
||||
class Value;
|
||||
class MachineBasicBlock;
|
||||
|
||||
enum LiveVarDebugLevel_t {
|
||||
LV_DEBUG_None,
|
||||
LV_DEBUG_Normal,
|
||||
LV_DEBUG_Instr,
|
||||
LV_DEBUG_Verbose
|
||||
};
|
||||
|
||||
extern LiveVarDebugLevel_t DEBUG_LV;
|
||||
|
||||
class BBLiveVar {
|
||||
const BasicBlock &BB; // pointer to BasicBlock
|
||||
MachineBasicBlock &MBB; // Pointer to MachineBasicBlock
|
||||
unsigned POID; // Post-Order ID
|
||||
|
||||
ValueSet DefSet; // Def set (with no preceding uses) for LV analysis
|
||||
ValueSet InSet, OutSet; // In & Out for LV analysis
|
||||
bool InSetChanged, OutSetChanged; // set if the InSet/OutSet is modified
|
||||
|
||||
// map that contains PredBB -> Phi arguments
|
||||
// coming in on that edge. such uses have to be
|
||||
// treated differently from ordinary uses.
|
||||
hash_map<const BasicBlock *, ValueSet> PredToEdgeInSetMap;
|
||||
|
||||
// method to propagate an InSet to OutSet of a predecessor
|
||||
bool setPropagate(ValueSet *OutSetOfPred,
|
||||
const ValueSet *InSetOfThisBB,
|
||||
const BasicBlock *PredBB);
|
||||
|
||||
// To add an operand which is a def
|
||||
void addDef(const Value *Op);
|
||||
|
||||
// To add an operand which is a use
|
||||
void addUse(const Value *Op);
|
||||
|
||||
void calcDefUseSets(); // calculates the Def & Use sets for this BB
|
||||
public:
|
||||
|
||||
BBLiveVar(const BasicBlock &BB, MachineBasicBlock &MBB, unsigned POID);
|
||||
|
||||
inline bool isInSetChanged() const { return InSetChanged; }
|
||||
inline bool isOutSetChanged() const { return OutSetChanged; }
|
||||
|
||||
MachineBasicBlock &getMachineBasicBlock() const { return MBB; }
|
||||
|
||||
inline unsigned getPOId() const { return POID; }
|
||||
|
||||
bool applyTransferFunc(); // calcultes the In in terms of Out
|
||||
|
||||
// calculates Out set using In sets of the predecessors
|
||||
bool applyFlowFunc(hash_map<const BasicBlock*, BBLiveVar*> &BBLiveVarInfo);
|
||||
|
||||
inline const ValueSet &getOutSet() const { return OutSet; }
|
||||
inline ValueSet &getOutSet() { return OutSet; }
|
||||
|
||||
inline const ValueSet &getInSet() const { return InSet; }
|
||||
inline ValueSet &getInSet() { return InSet; }
|
||||
|
||||
void printAllSets() const; // for printing Def/In/Out sets
|
||||
void printInOutSets() const; // for printing In/Out sets
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,322 @@
|
|||
//===-- FunctionLiveVarInfo.cpp - Live Variable Analysis for a Function ---===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is the interface to function level live variable information that is
|
||||
// provided by live variable analysis.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/CodeGen/FunctionLiveVarInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include "Support/PostOrderIterator.h"
|
||||
#include "Support/SetOperations.h"
|
||||
#include "Support/CommandLine.h"
|
||||
#include "BBLiveVar.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
static RegisterAnalysis<FunctionLiveVarInfo>
|
||||
X("livevar", "Live Variable Analysis");
|
||||
|
||||
LiveVarDebugLevel_t DEBUG_LV;
|
||||
|
||||
static cl::opt<LiveVarDebugLevel_t, true>
|
||||
DEBUG_LV_opt("dlivevar", cl::Hidden, cl::location(DEBUG_LV),
|
||||
cl::desc("enable live-variable debugging information"),
|
||||
cl::values(
|
||||
clEnumValN(LV_DEBUG_None , "n", "disable debug output"),
|
||||
clEnumValN(LV_DEBUG_Normal , "y", "enable debug output"),
|
||||
clEnumValN(LV_DEBUG_Instr, "i", "print live-var sets before/after "
|
||||
"every machine instrn"),
|
||||
clEnumValN(LV_DEBUG_Verbose, "v", "print def, use sets for every instrn also"),
|
||||
0));
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Accessor Functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// gets OutSet of a BB
|
||||
const ValueSet &FunctionLiveVarInfo::getOutSetOfBB(const BasicBlock *BB) const {
|
||||
return BBLiveVarInfo.find(BB)->second->getOutSet();
|
||||
}
|
||||
ValueSet &FunctionLiveVarInfo::getOutSetOfBB(const BasicBlock *BB) {
|
||||
return BBLiveVarInfo[BB]->getOutSet();
|
||||
}
|
||||
|
||||
// gets InSet of a BB
|
||||
const ValueSet &FunctionLiveVarInfo::getInSetOfBB(const BasicBlock *BB) const {
|
||||
return BBLiveVarInfo.find(BB)->second->getInSet();
|
||||
}
|
||||
ValueSet &FunctionLiveVarInfo::getInSetOfBB(const BasicBlock *BB) {
|
||||
return BBLiveVarInfo[BB]->getInSet();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Performs live var analysis for a function
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool FunctionLiveVarInfo::runOnFunction(Function &F) {
|
||||
M = &F;
|
||||
if (DEBUG_LV) std::cerr << "Analysing live variables ...\n";
|
||||
|
||||
// create and initialize all the BBLiveVars of the CFG
|
||||
constructBBs(M);
|
||||
|
||||
unsigned int iter=0;
|
||||
while (doSingleBackwardPass(M, iter++))
|
||||
; // Iterate until we are done.
|
||||
|
||||
if (DEBUG_LV) std::cerr << "Live Variable Analysis complete!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructs BBLiveVars and init Def and In sets
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FunctionLiveVarInfo::constructBBs(const Function *F) {
|
||||
unsigned POId = 0; // Reverse Depth-first Order ID
|
||||
std::map<const BasicBlock*, unsigned> PONumbering;
|
||||
|
||||
for (po_iterator<const Function*> BBI = po_begin(M), BBE = po_end(M);
|
||||
BBI != BBE; ++BBI)
|
||||
PONumbering[*BBI] = POId++;
|
||||
|
||||
MachineFunction &MF = MachineFunction::get(F);
|
||||
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
|
||||
const BasicBlock &BB = *I->getBasicBlock(); // get the current BB
|
||||
if (DEBUG_LV) std::cerr << " For BB " << RAV(BB) << ":\n";
|
||||
|
||||
BBLiveVar *LVBB;
|
||||
std::map<const BasicBlock*, unsigned>::iterator POI = PONumbering.find(&BB);
|
||||
if (POI != PONumbering.end()) {
|
||||
// create a new BBLiveVar
|
||||
LVBB = new BBLiveVar(BB, *I, POId);
|
||||
} else {
|
||||
// The PO iterator does not discover unreachable blocks, but the random
|
||||
// iterator later may access these blocks. We must make sure to
|
||||
// initialize unreachable blocks as well. However, LV info is not correct
|
||||
// for those blocks (they are not analyzed)
|
||||
//
|
||||
LVBB = new BBLiveVar(BB, *I, ++POId);
|
||||
}
|
||||
BBLiveVarInfo[&BB] = LVBB;
|
||||
|
||||
if (DEBUG_LV)
|
||||
LVBB->printAllSets();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// do one backward pass over the CFG (for iterative analysis)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool FunctionLiveVarInfo::doSingleBackwardPass(const Function *M,
|
||||
unsigned iter) {
|
||||
if (DEBUG_LV) std::cerr << "\n After Backward Pass " << iter << "...\n";
|
||||
|
||||
bool NeedAnotherIteration = false;
|
||||
for (po_iterator<const Function*> BBI = po_begin(M), BBE = po_end(M);
|
||||
BBI != BBE; ++BBI) {
|
||||
BBLiveVar *LVBB = BBLiveVarInfo[*BBI];
|
||||
assert(LVBB && "BasicBlock information not set for block!");
|
||||
|
||||
if (DEBUG_LV) std::cerr << " For BB " << (*BBI)->getName() << ":\n";
|
||||
|
||||
// InSets are initialized to "GenSet". Recompute only if OutSet changed.
|
||||
if(LVBB->isOutSetChanged())
|
||||
LVBB->applyTransferFunc(); // apply the Tran Func to calc InSet
|
||||
|
||||
// OutSets are initialized to EMPTY. Recompute on first iter or if InSet
|
||||
// changed.
|
||||
if (iter == 0 || LVBB->isInSetChanged()) // to calc Outsets of preds
|
||||
NeedAnotherIteration |= LVBB->applyFlowFunc(BBLiveVarInfo);
|
||||
|
||||
if (DEBUG_LV) LVBB->printInOutSets();
|
||||
}
|
||||
|
||||
// true if we need to reiterate over the CFG
|
||||
return NeedAnotherIteration;
|
||||
}
|
||||
|
||||
|
||||
void FunctionLiveVarInfo::releaseMemory() {
|
||||
// First remove all BBLiveVars created in constructBBs().
|
||||
if (M) {
|
||||
for (Function::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
|
||||
delete BBLiveVarInfo[I];
|
||||
BBLiveVarInfo.clear();
|
||||
}
|
||||
M = 0;
|
||||
|
||||
// Then delete all objects of type ValueSet created in calcLiveVarSetsForBB
|
||||
// and entered into MInst2LVSetBI and MInst2LVSetAI (these are caches
|
||||
// to return ValueSet's before/after a machine instruction quickly).
|
||||
// We do not need to free up ValueSets in MInst2LVSetAI because it holds
|
||||
// pointers to the same sets as in MInst2LVSetBI (for all instructions
|
||||
// except the last one in a BB) or in BBLiveVar (for the last instruction).
|
||||
//
|
||||
for (hash_map<const MachineInstr*, ValueSet*>::iterator
|
||||
MI = MInst2LVSetBI.begin(),
|
||||
ME = MInst2LVSetBI.end(); MI != ME; ++MI)
|
||||
delete MI->second; // delete all ValueSets in MInst2LVSetBI
|
||||
|
||||
MInst2LVSetBI.clear();
|
||||
MInst2LVSetAI.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Following functions will give the LiveVar info for any machine instr in
|
||||
// a function. It should be called after a call to analyze().
|
||||
//
|
||||
// These functions calculate live var info for all the machine instrs in a
|
||||
// BB when LVInfo for one inst is requested. Hence, this function is useful
|
||||
// when live var info is required for many (or all) instructions in a basic
|
||||
// block. Also, the arguments to this function does not require specific
|
||||
// iterators.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gives live variable information before a machine instruction
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const ValueSet &
|
||||
FunctionLiveVarInfo::getLiveVarSetBeforeMInst(const MachineInstr *MI,
|
||||
const BasicBlock *BB) {
|
||||
ValueSet* &LVSet = MInst2LVSetBI[MI]; // ref. to map entry
|
||||
if (LVSet == NULL && BB != NULL) { // if not found and BB provided
|
||||
calcLiveVarSetsForBB(BB); // calc LVSet for all instrs in BB
|
||||
assert(LVSet != NULL);
|
||||
}
|
||||
return *LVSet;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gives live variable information after a machine instruction
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const ValueSet &
|
||||
FunctionLiveVarInfo::getLiveVarSetAfterMInst(const MachineInstr *MI,
|
||||
const BasicBlock *BB) {
|
||||
|
||||
ValueSet* &LVSet = MInst2LVSetAI[MI]; // ref. to map entry
|
||||
if (LVSet == NULL && BB != NULL) { // if not found and BB provided
|
||||
calcLiveVarSetsForBB(BB); // calc LVSet for all instrs in BB
|
||||
assert(LVSet != NULL);
|
||||
}
|
||||
return *LVSet;
|
||||
}
|
||||
|
||||
// This function applies a machine instr to a live var set (accepts OutSet) and
|
||||
// makes necessary changes to it (produces InSet). Note that two for loops are
|
||||
// used to first kill all defs and then to add all uses. This is because there
|
||||
// can be instructions like Val = Val + 1 since we allow multiple defs to a
|
||||
// machine instruction operand.
|
||||
//
|
||||
static void applyTranferFuncForMInst(ValueSet &LVS, const MachineInstr *MInst) {
|
||||
for (MachineInstr::const_val_op_iterator OpI = MInst->begin(),
|
||||
OpE = MInst->end(); OpI != OpE; ++OpI) {
|
||||
if (OpI.isDef()) // kill if this operand is a def
|
||||
LVS.erase(*OpI); // this definition kills any uses
|
||||
}
|
||||
|
||||
// do for implicit operands as well
|
||||
for (unsigned i=0; i < MInst->getNumImplicitRefs(); ++i) {
|
||||
if (MInst->getImplicitOp(i).isDef())
|
||||
LVS.erase(MInst->getImplicitRef(i));
|
||||
}
|
||||
|
||||
for (MachineInstr::const_val_op_iterator OpI = MInst->begin(),
|
||||
OpE = MInst->end(); OpI != OpE; ++OpI) {
|
||||
if (!isa<BasicBlock>(*OpI)) // don't process labels
|
||||
// add only if this operand is a use
|
||||
if (OpI.isUse())
|
||||
LVS.insert(*OpI); // An operand is a use - so add to use set
|
||||
}
|
||||
|
||||
// do for implicit operands as well
|
||||
for (unsigned i = 0, e = MInst->getNumImplicitRefs(); i != e; ++i)
|
||||
if (MInst->getImplicitOp(i).isUse())
|
||||
LVS.insert(MInst->getImplicitRef(i));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This method calculates the live variable information for all the
|
||||
// instructions in a basic block and enter the newly constructed live
|
||||
// variable sets into a the caches (MInst2LVSetAI, MInst2LVSetBI)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FunctionLiveVarInfo::calcLiveVarSetsForBB(const BasicBlock *BB) {
|
||||
BBLiveVar *BBLV = BBLiveVarInfo[BB];
|
||||
assert(BBLV && "BBLiveVar annotation doesn't exist?");
|
||||
const MachineBasicBlock &MIVec = BBLV->getMachineBasicBlock();
|
||||
const MachineFunction &MF = MachineFunction::get(M);
|
||||
const TargetMachine &TM = MF.getTarget();
|
||||
|
||||
if (DEBUG_LV >= LV_DEBUG_Instr)
|
||||
std::cerr << "\n======For BB " << BB->getName()
|
||||
<< ": Live var sets for instructions======\n";
|
||||
|
||||
ValueSet *SetAI = &getOutSetOfBB(BB); // init SetAI with OutSet
|
||||
ValueSet CurSet(*SetAI); // CurSet now contains OutSet
|
||||
|
||||
// iterate over all the machine instructions in BB
|
||||
for (MachineBasicBlock::const_reverse_iterator MII = MIVec.rbegin(),
|
||||
MIE = MIVec.rend(); MII != MIE; ++MII) {
|
||||
// MI is cur machine inst
|
||||
const MachineInstr *MI = *MII;
|
||||
|
||||
MInst2LVSetAI[MI] = SetAI; // record in After Inst map
|
||||
|
||||
applyTranferFuncForMInst(CurSet, MI); // apply the transfer Func
|
||||
ValueSet *NewSet = new ValueSet(CurSet); // create a new set with a copy
|
||||
// of the set after T/F
|
||||
MInst2LVSetBI[MI] = NewSet; // record in Before Inst map
|
||||
|
||||
// If the current machine instruction has delay slots, mark values
|
||||
// used by this instruction as live before and after each delay slot
|
||||
// instruction (After(MI) is the same as Before(MI+1) except for last MI).
|
||||
if (unsigned DS = TM.getInstrInfo().getNumDelaySlots(MI->getOpCode())) {
|
||||
MachineBasicBlock::const_iterator fwdMII = MII.base(); // ptr to *next* MI
|
||||
for (unsigned i = 0; i < DS; ++i, ++fwdMII) {
|
||||
assert(fwdMII != MIVec.end() && "Missing instruction in delay slot?");
|
||||
MachineInstr* DelaySlotMI = *fwdMII;
|
||||
if (! TM.getInstrInfo().isNop(DelaySlotMI->getOpCode())) {
|
||||
set_union(*MInst2LVSetBI[DelaySlotMI], *NewSet);
|
||||
if (i+1 == DS)
|
||||
set_union(*MInst2LVSetAI[DelaySlotMI], *NewSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_LV >= LV_DEBUG_Instr) {
|
||||
std::cerr << "\nLive var sets before/after instruction " << *MI;
|
||||
std::cerr << " Before: "; printSet(*NewSet); std::cerr << "\n";
|
||||
std::cerr << " After : "; printSet(*SetAI); std::cerr << "\n";
|
||||
}
|
||||
|
||||
// SetAI will be used in the next iteration
|
||||
SetAI = NewSet;
|
||||
}
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
|
@ -0,0 +1,14 @@
|
|||
##===- lib/Target/Sparc/LiveVar/Makefile -------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file was developed by the LLVM research group and is distributed under
|
||||
# the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL = ../../../..
|
||||
LIBRARYNAME = livevar
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FIXME: Eliminate this file.
|
||||
|
||||
#include "llvm/CodeGen/ValueSet.h"
|
||||
#include "llvm/Value.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
std::ostream &operator<<(std::ostream &O, RAV V) { // func to print a Value
|
||||
const Value &v = V.V;
|
||||
if (v.hasName())
|
||||
return O << (void*)&v << "(" << v.getName() << ") ";
|
||||
else if (isa<Constant>(v))
|
||||
return O << (void*)&v << "(" << v << ") ";
|
||||
else
|
||||
return O << (void*)&v << " ";
|
||||
}
|
||||
|
||||
void printSet(const ValueSet &S) {
|
||||
for (ValueSet::const_iterator I = S.begin(), E = S.end(); I != E; ++I)
|
||||
std::cerr << RAV(*I);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
|
@ -8,7 +8,7 @@
|
|||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../../..
|
||||
LIBRARYNAME = sparc
|
||||
DIRS = InstrSelection RegAlloc
|
||||
DIRS = InstrSelection RegAlloc LiveVar
|
||||
|
||||
ExtraSource = Sparc.burm.cpp
|
||||
|
||||
|
|
Loading…
Reference in New Issue