mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
Added debug information. Fixed several bugs in the reconstruct loop function.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16895 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
#include "MSSchedule.h"
|
#include "MSSchedule.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Target/TargetSchedInfo.h"
|
#include "llvm/Target/TargetSchedInfo.h"
|
||||||
|
#include "../../Target/SparcV9/SparcV9Internals.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@@ -134,6 +135,7 @@ bool MSSchedule::resourcesFree(MSchedGraphNode *node, int cycle) {
|
|||||||
|
|
||||||
bool MSSchedule::constructKernel(int II) {
|
bool MSSchedule::constructKernel(int II) {
|
||||||
MSchedGraphNode *branchNode = 0;
|
MSchedGraphNode *branchNode = 0;
|
||||||
|
MSchedGraphNode *branchANode = 0;
|
||||||
|
|
||||||
int stageNum = (schedule.rbegin()->first)/ II;
|
int stageNum = (schedule.rbegin()->first)/ II;
|
||||||
DEBUG(std::cerr << "Number of Stages: " << stageNum << "\n");
|
DEBUG(std::cerr << "Number of Stages: " << stageNum << "\n");
|
||||||
@@ -146,7 +148,10 @@ bool MSSchedule::constructKernel(int II) {
|
|||||||
E = schedule[i].end(); I != E; ++I) {
|
E = schedule[i].end(); I != E; ++I) {
|
||||||
//Check if its a branch
|
//Check if its a branch
|
||||||
if((*I)->isBranch()) {
|
if((*I)->isBranch()) {
|
||||||
branchNode = *I;
|
if((*I)->getInst()->getOpcode() == V9::BA)
|
||||||
|
branchANode = *I;
|
||||||
|
else
|
||||||
|
branchNode = *I;
|
||||||
assert(count == 0 && "Branch can not be from a previous iteration");
|
assert(count == 0 && "Branch can not be from a previous iteration");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -160,7 +165,16 @@ bool MSSchedule::constructKernel(int II) {
|
|||||||
|
|
||||||
//Add Branch to the end
|
//Add Branch to the end
|
||||||
kernel.push_back(std::make_pair(branchNode, 0));
|
kernel.push_back(std::make_pair(branchNode, 0));
|
||||||
|
|
||||||
|
//Add Branch Always to the end
|
||||||
|
kernel.push_back(std::make_pair(branchANode, 0));
|
||||||
|
|
||||||
|
|
||||||
|
if(stageNum > 0)
|
||||||
|
maxStage = stageNum;
|
||||||
|
else
|
||||||
|
maxStage = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,6 +32,9 @@ namespace llvm {
|
|||||||
//Resulting kernel
|
//Resulting kernel
|
||||||
std::vector<std::pair<MSchedGraphNode*, int> > kernel;
|
std::vector<std::pair<MSchedGraphNode*, int> > kernel;
|
||||||
|
|
||||||
|
//Max stage count
|
||||||
|
int maxStage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MSSchedule(int num) : numIssue(num) {}
|
MSSchedule(int num) : numIssue(num) {}
|
||||||
MSSchedule() : numIssue(4) {}
|
MSSchedule() : numIssue(4) {}
|
||||||
@@ -40,7 +43,7 @@ namespace llvm {
|
|||||||
void clear() { schedule.clear(); resourceNumPerCycle.clear(); kernel.clear(); }
|
void clear() { schedule.clear(); resourceNumPerCycle.clear(); kernel.clear(); }
|
||||||
std::vector<std::pair<MSchedGraphNode*, int> >* getKernel() { return &kernel; }
|
std::vector<std::pair<MSchedGraphNode*, int> >* getKernel() { return &kernel; }
|
||||||
bool constructKernel(int II);
|
bool constructKernel(int II);
|
||||||
|
int getMaxStage() { return maxStage; }
|
||||||
|
|
||||||
|
|
||||||
//iterators
|
//iterators
|
||||||
|
@@ -91,7 +91,7 @@ MSchedGraph::MSchedGraph(const MachineBasicBlock *bb, const TargetMachine &targ)
|
|||||||
//Make sure BB is not null,
|
//Make sure BB is not null,
|
||||||
assert(BB != NULL && "Basic Block is null");
|
assert(BB != NULL && "Basic Block is null");
|
||||||
|
|
||||||
DEBUG(std::cerr << "Constructing graph for " << bb << "\n");
|
//DEBUG(std::cerr << "Constructing graph for " << bb << "\n");
|
||||||
|
|
||||||
//Create nodes and edges for this BB
|
//Create nodes and edges for this BB
|
||||||
buildNodesAndEdges();
|
buildNodesAndEdges();
|
||||||
|
@@ -123,14 +123,11 @@ bool ModuloSchedulingPass::runOnFunction(Function &F) {
|
|||||||
|
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
DEBUG(std::cerr << "Creating ModuloSchedGraph for each valid BasicBlock in" + F.getName() + "\n");
|
DEBUG(std::cerr << "Creating ModuloSchedGraph for each valid BasicBlock in " + F.getName() + "\n");
|
||||||
|
|
||||||
//Get MachineFunction
|
//Get MachineFunction
|
||||||
MachineFunction &MF = MachineFunction::get(&F);
|
MachineFunction &MF = MachineFunction::get(&F);
|
||||||
|
|
||||||
//Print out machine function
|
|
||||||
DEBUG(MF.print(std::cerr));
|
|
||||||
|
|
||||||
//Worklist
|
//Worklist
|
||||||
std::vector<MachineBasicBlock*> Worklist;
|
std::vector<MachineBasicBlock*> Worklist;
|
||||||
|
|
||||||
@@ -139,6 +136,7 @@ bool ModuloSchedulingPass::runOnFunction(Function &F) {
|
|||||||
if(MachineBBisValid(BI))
|
if(MachineBBisValid(BI))
|
||||||
Worklist.push_back(&*BI);
|
Worklist.push_back(&*BI);
|
||||||
|
|
||||||
|
DEBUG(if(Worklist.size() == 0) std::cerr << "No single basic block loops in function to ModuloSchedule\n");
|
||||||
|
|
||||||
//Iterate over the worklist and perform scheduling
|
//Iterate over the worklist and perform scheduling
|
||||||
for(std::vector<MachineBasicBlock*>::iterator BI = Worklist.begin(),
|
for(std::vector<MachineBasicBlock*>::iterator BI = Worklist.begin(),
|
||||||
@@ -150,7 +148,7 @@ bool ModuloSchedulingPass::runOnFunction(Function &F) {
|
|||||||
DEBUG(WriteGraphToFile(std::cerr, F.getName(), MSG));
|
DEBUG(WriteGraphToFile(std::cerr, F.getName(), MSG));
|
||||||
|
|
||||||
//Print out BB for debugging
|
//Print out BB for debugging
|
||||||
DEBUG((*BI)->print(std::cerr));
|
DEBUG(std::cerr << "ModuloScheduling BB: \n"; (*BI)->print(std::cerr));
|
||||||
|
|
||||||
//Calculate Resource II
|
//Calculate Resource II
|
||||||
int ResMII = calculateResMII(*BI);
|
int ResMII = calculateResMII(*BI);
|
||||||
@@ -213,7 +211,7 @@ bool ModuloSchedulingPass::runOnFunction(Function &F) {
|
|||||||
recurrenceList.clear();
|
recurrenceList.clear();
|
||||||
FinalNodeOrder.clear();
|
FinalNodeOrder.clear();
|
||||||
schedule.clear();
|
schedule.clear();
|
||||||
|
|
||||||
//Clean up. Nuke old MachineBB and llvmBB
|
//Clean up. Nuke old MachineBB and llvmBB
|
||||||
//BasicBlock *llvmBB = (BasicBlock*) (*BI)->getBasicBlock();
|
//BasicBlock *llvmBB = (BasicBlock*) (*BI)->getBasicBlock();
|
||||||
//Function *parent = (Function*) llvmBB->getParent();
|
//Function *parent = (Function*) llvmBB->getParent();
|
||||||
@@ -260,7 +258,6 @@ bool ModuloSchedulingPass::MachineBBisValid(const MachineBasicBlock *BI) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//ResMII is calculated by determining the usage count for each resource
|
//ResMII is calculated by determining the usage count for each resource
|
||||||
@@ -1021,11 +1018,22 @@ void ModuloSchedulingPass::orderNodes() {
|
|||||||
succIntersect(*CurrentSet, IntersectCurrent);
|
succIntersect(*CurrentSet, IntersectCurrent);
|
||||||
} //End if BOTTOM_DOWN
|
} //End if BOTTOM_DOWN
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "Current Intersection Size: " << IntersectCurrent.size() << "\n");
|
||||||
}
|
}
|
||||||
//End Wrapping while loop
|
//End Wrapping while loop
|
||||||
|
DEBUG(std::cerr << "Ending Size of Current Set: " << CurrentSet->size() << "\n");
|
||||||
}//End for over all sets of nodes
|
}//End for over all sets of nodes
|
||||||
|
|
||||||
|
//FIXME: As the algorithm stands it will NEVER add an instruction such as ba (with no
|
||||||
|
//data dependencies) to the final order. We add this manually. It will always be
|
||||||
|
//in the last set of S since its not part of a recurrence
|
||||||
|
//Loop over all the sets and place them in the final node order
|
||||||
|
std::vector<std::vector<MSchedGraphNode*> > ::reverse_iterator LastSet = partialOrder.rbegin();
|
||||||
|
for(std::vector<MSchedGraphNode*>::iterator CurrentNode = LastSet->begin(), LastNode = LastSet->end();
|
||||||
|
CurrentNode != LastNode; ++CurrentNode) {
|
||||||
|
if((*CurrentNode)->getInst()->getOpcode() == V9::BA)
|
||||||
|
FinalNodeOrder.push_back(*CurrentNode);
|
||||||
|
}
|
||||||
//Return final Order
|
//Return final Order
|
||||||
//return FinalNodeOrder;
|
//return FinalNodeOrder;
|
||||||
}
|
}
|
||||||
@@ -1080,8 +1088,15 @@ void ModuloSchedulingPass::computeSchedule() {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//WARNING: HACK! FIXME!!!!
|
//WARNING: HACK! FIXME!!!!
|
||||||
EarlyStart = II-1;
|
if((*I)->getInst()->getOpcode() == V9::BA) {
|
||||||
LateStart = II-1;
|
EarlyStart = II-1;
|
||||||
|
LateStart = II-1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
EarlyStart = II-1;
|
||||||
|
LateStart = II-1;
|
||||||
|
assert( (EarlyStart >= 0) && (LateStart >=0) && "EarlyStart and LateStart must be greater then 0");
|
||||||
|
}
|
||||||
hasPred = 1;
|
hasPred = 1;
|
||||||
hasSucc = 1;
|
hasSucc = 1;
|
||||||
}
|
}
|
||||||
@@ -1170,20 +1185,24 @@ bool ModuloSchedulingPass::scheduleNode(MSchedGraphNode *node,
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuloSchedulingPass::writePrologues(std::vector<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, std::vector<Value*> > > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation) {
|
void ModuloSchedulingPass::writePrologues(std::vector<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation) {
|
||||||
|
|
||||||
//Keep a map to easily know whats in the kernel
|
//Keep a map to easily know whats in the kernel
|
||||||
std::map<int, std::set<const MachineInstr*> > inKernel;
|
std::map<int, std::set<const MachineInstr*> > inKernel;
|
||||||
int maxStageCount = 0;
|
int maxStageCount = 0;
|
||||||
|
|
||||||
MSchedGraphNode *branch = 0;
|
MSchedGraphNode *branch = 0;
|
||||||
|
MSchedGraphNode *BAbranch = 0;
|
||||||
|
|
||||||
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
||||||
maxStageCount = std::max(maxStageCount, I->second);
|
maxStageCount = std::max(maxStageCount, I->second);
|
||||||
|
|
||||||
//Ignore the branch, we will handle this separately
|
//Ignore the branch, we will handle this separately
|
||||||
if(I->first->isBranch()) {
|
if(I->first->isBranch()) {
|
||||||
branch = I->first;
|
if (I->first->getInst()->getOpcode() == V9::BA)
|
||||||
|
BAbranch = I->first;
|
||||||
|
else
|
||||||
|
branch = I->first;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1204,27 +1223,30 @@ void ModuloSchedulingPass::writePrologues(std::vector<MachineBasicBlock *> &prol
|
|||||||
for(int j = 0; j <= i; ++j) {
|
for(int j = 0; j <= i; ++j) {
|
||||||
for(MachineBasicBlock::const_iterator MI = origBB->begin(), ME = origBB->end(); ME != MI; ++MI) {
|
for(MachineBasicBlock::const_iterator MI = origBB->begin(), ME = origBB->end(); ME != MI; ++MI) {
|
||||||
if(inKernel[j].count(&*MI)) {
|
if(inKernel[j].count(&*MI)) {
|
||||||
machineBB->push_back(MI->clone());
|
MachineInstr *instClone = MI->clone();
|
||||||
|
machineBB->push_back(instClone);
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "Cloning: " << *MI << "\n");
|
||||||
|
|
||||||
Instruction *tmp;
|
Instruction *tmp;
|
||||||
|
|
||||||
//After cloning, we may need to save the value that this instruction defines
|
//After cloning, we may need to save the value that this instruction defines
|
||||||
for(unsigned opNum=0; opNum < MI->getNumOperands(); ++opNum) {
|
for(unsigned opNum=0; opNum < MI->getNumOperands(); ++opNum) {
|
||||||
//get machine operand
|
//get machine operand
|
||||||
const MachineOperand &mOp = MI->getOperand(opNum);
|
const MachineOperand &mOp = instClone->getOperand(opNum);
|
||||||
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
|
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
|
||||||
|
|
||||||
|
|
||||||
//Check if this is a value we should save
|
//Check if this is a value we should save
|
||||||
if(valuesToSave.count(mOp.getVRegValue())) {
|
if(valuesToSave.count(mOp.getVRegValue())) {
|
||||||
//Save copy in tmpInstruction
|
//Save copy in tmpInstruction
|
||||||
tmp = new TmpInstruction(mOp.getVRegValue());
|
tmp = new TmpInstruction(mOp.getVRegValue());
|
||||||
|
|
||||||
DEBUG(std::cerr << "Value: " << mOp.getVRegValue() << " New Value: " << tmp << " Stage: " << i << "\n");
|
DEBUG(std::cerr << "Value: " << *(mOp.getVRegValue()) << " New Value: " << *tmp << " Stage: " << i << "\n");
|
||||||
newValues[mOp.getVRegValue()][i].push_back(tmp);
|
|
||||||
|
newValues[mOp.getVRegValue()][i]= tmp;
|
||||||
newValLocation[tmp] = machineBB;
|
newValLocation[tmp] = machineBB;
|
||||||
|
|
||||||
DEBUG(std::cerr << "Machine Instr Operands: " << mOp.getVRegValue() << ", 0, " << tmp << "\n");
|
DEBUG(std::cerr << "Machine Instr Operands: " << *(mOp.getVRegValue()) << ", 0, " << *tmp << "\n");
|
||||||
|
|
||||||
//Create machine instruction and put int machineBB
|
//Create machine instruction and put int machineBB
|
||||||
MachineInstr *saveValue = BuildMI(machineBB, V9::ORr, 3).addReg(mOp.getVRegValue()).addImm(0).addRegDef(tmp);
|
MachineInstr *saveValue = BuildMI(machineBB, V9::ORr, 3).addReg(mOp.getVRegValue()).addImm(0).addRegDef(tmp);
|
||||||
@@ -1232,6 +1254,18 @@ void ModuloSchedulingPass::writePrologues(std::vector<MachineBasicBlock *> &prol
|
|||||||
DEBUG(std::cerr << "Created new machine instr: " << *saveValue << "\n");
|
DEBUG(std::cerr << "Created new machine instr: " << *saveValue << "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//We may also need to update the value that we use if its from an earlier prologue
|
||||||
|
if(j != 0) {
|
||||||
|
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
||||||
|
if(newValues.count(mOp.getVRegValue()))
|
||||||
|
if(newValues[mOp.getVRegValue()].count(j-1)) {
|
||||||
|
DEBUG(std::cerr << "Replaced this value: " << mOp.getVRegValue() << " With:" << (newValues[mOp.getVRegValue()][i-1]) << "\n");
|
||||||
|
//Update the operand with the right value
|
||||||
|
instClone->getOperand(opNum).setValueReg(newValues[mOp.getVRegValue()][i-1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1240,6 +1274,9 @@ void ModuloSchedulingPass::writePrologues(std::vector<MachineBasicBlock *> &prol
|
|||||||
|
|
||||||
//Stick in branch at the end
|
//Stick in branch at the end
|
||||||
machineBB->push_back(branch->getInst()->clone());
|
machineBB->push_back(branch->getInst()->clone());
|
||||||
|
|
||||||
|
//Stick in BA branch at the end
|
||||||
|
machineBB->push_back(BAbranch->getInst()->clone());
|
||||||
|
|
||||||
(((MachineBasicBlock*)origBB)->getParent())->getBasicBlockList().push_back(machineBB);
|
(((MachineBasicBlock*)origBB)->getParent())->getBasicBlockList().push_back(machineBB);
|
||||||
prologues.push_back(machineBB);
|
prologues.push_back(machineBB);
|
||||||
@@ -1247,12 +1284,11 @@ void ModuloSchedulingPass::writePrologues(std::vector<MachineBasicBlock *> &prol
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuloSchedulingPass::writeEpilogues(std::vector<MachineBasicBlock *> &epilogues, const MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_epilogues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, std::vector<Value*> > > &newValues,std::map<Value*, MachineBasicBlock*> &newValLocation ) {
|
void ModuloSchedulingPass::writeEpilogues(std::vector<MachineBasicBlock *> &epilogues, const MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_epilogues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues,std::map<Value*, MachineBasicBlock*> &newValLocation, std::map<Value*, std::map<int, Value*> > &kernelPHIs ) {
|
||||||
|
|
||||||
std::map<int, std::set<const MachineInstr*> > inKernel;
|
std::map<int, std::set<const MachineInstr*> > inKernel;
|
||||||
int maxStageCount = 0;
|
|
||||||
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
||||||
maxStageCount = std::max(maxStageCount, I->second);
|
|
||||||
|
|
||||||
//Ignore the branch, we will handle this separately
|
//Ignore the branch, we will handle this separately
|
||||||
if(I->first->isBranch())
|
if(I->first->isBranch())
|
||||||
@@ -1264,62 +1300,80 @@ void ModuloSchedulingPass::writeEpilogues(std::vector<MachineBasicBlock *> &epil
|
|||||||
|
|
||||||
std::map<Value*, Value*> valPHIs;
|
std::map<Value*, Value*> valPHIs;
|
||||||
|
|
||||||
|
//some debug stuff, will remove later
|
||||||
|
DEBUG(for(std::map<Value*, std::map<int, Value*> >::iterator V = newValues.begin(), E = newValues.end(); V !=E; ++V) {
|
||||||
|
std::cerr << "Old Value: " << *(V->first) << "\n";
|
||||||
|
for(std::map<int, Value*>::iterator I = V->second.begin(), IE = V->second.end(); I != IE; ++I)
|
||||||
|
std::cerr << "Stage: " << I->first << " Value: " << *(I->second) << "\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
//some debug stuff, will remove later
|
||||||
|
DEBUG(for(std::map<Value*, std::map<int, Value*> >::iterator V = kernelPHIs.begin(), E = kernelPHIs.end(); V !=E; ++V) {
|
||||||
|
std::cerr << "Old Value: " << *(V->first) << "\n";
|
||||||
|
for(std::map<int, Value*>::iterator I = V->second.begin(), IE = V->second.end(); I != IE; ++I)
|
||||||
|
std::cerr << "Stage: " << I->first << " Value: " << *(I->second) << "\n";
|
||||||
|
});
|
||||||
|
|
||||||
//Now write the epilogues
|
//Now write the epilogues
|
||||||
for(int i = maxStageCount-1; i >= 0; --i) {
|
for(int i = schedule.getMaxStage()-1; i >= 0; --i) {
|
||||||
BasicBlock *llvmBB = new BasicBlock("EPILOGUE", (Function*) (origBB->getBasicBlock()->getParent()));
|
BasicBlock *llvmBB = new BasicBlock("EPILOGUE", (Function*) (origBB->getBasicBlock()->getParent()));
|
||||||
MachineBasicBlock *machineBB = new MachineBasicBlock(llvmBB);
|
MachineBasicBlock *machineBB = new MachineBasicBlock(llvmBB);
|
||||||
|
|
||||||
DEBUG(std::cerr << " i: " << i << "\n");
|
DEBUG(std::cerr << " Epilogue #: " << i << "\n");
|
||||||
|
|
||||||
//Spit out phi nodes
|
|
||||||
for(std::map<Value*, std::map<int, std::vector<Value*> > >::iterator V = newValues.begin(), E = newValues.end();
|
|
||||||
V != E; ++V) {
|
|
||||||
|
|
||||||
DEBUG(std::cerr << "Writing phi for" << *(V->first));
|
|
||||||
for(std::map<int, std::vector<Value*> >::iterator I = V->second.begin(), IE = V->second.end(); I != IE; ++I) {
|
|
||||||
if(I->first == i) {
|
|
||||||
DEBUG(std::cerr << "BLAH " << i << "\n");
|
|
||||||
|
|
||||||
//Vector must have two elements in it:
|
|
||||||
assert(I->second.size() == 2 && "Vector size should be two\n");
|
|
||||||
|
|
||||||
Instruction *tmp = new TmpInstruction(I->second[0]);
|
|
||||||
MachineInstr *saveValue = BuildMI(machineBB, V9::PHI, 3).addReg(I->second[0]).addReg(I->second[1]).addRegDef(tmp);
|
|
||||||
valPHIs[V->first] = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for(MachineBasicBlock::const_iterator MI = origBB->begin(), ME = origBB->end(); ME != MI; ++MI) {
|
|
||||||
for(int j=maxStageCount; j > i; --j) {
|
for(MachineBasicBlock::const_iterator MI = origBB->begin(), ME = origBB->end(); ME != MI; ++MI) {
|
||||||
|
for(int j=schedule.getMaxStage(); j > i; --j) {
|
||||||
if(inKernel[j].count(&*MI)) {
|
if(inKernel[j].count(&*MI)) {
|
||||||
DEBUG(std::cerr << "Cloning instruction " << *MI << "\n");
|
DEBUG(std::cerr << "Cloning instruction " << *MI << "\n");
|
||||||
MachineInstr *clone = MI->clone();
|
MachineInstr *clone = MI->clone();
|
||||||
|
|
||||||
//Update operands that need to use the result from the phi
|
//Update operands that need to use the result from the phi
|
||||||
for(unsigned i=0; i < clone->getNumOperands(); ++i) {
|
for(unsigned opNum=0; opNum < clone->getNumOperands(); ++opNum) {
|
||||||
//get machine operand
|
//get machine operand
|
||||||
const MachineOperand &mOp = clone->getOperand(i);
|
const MachineOperand &mOp = clone->getOperand(opNum);
|
||||||
|
|
||||||
|
//If this is the last instructions for the max iterations ago, don't update operands
|
||||||
|
if(j == schedule.getMaxStage() && (i == 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
if((mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse())) {
|
if((mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse())) {
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "Writing PHI for " << *(mOp.getVRegValue()) << "\n");
|
||||||
|
|
||||||
|
//Quickly write appropriate phis for this operand
|
||||||
|
if(newValues.count(mOp.getVRegValue())) {
|
||||||
|
if(newValues[mOp.getVRegValue()].count(i)) {
|
||||||
|
Instruction *tmp = new TmpInstruction(newValues[mOp.getVRegValue()][i]);
|
||||||
|
MachineInstr *saveValue = BuildMI(machineBB, V9::PHI, 3).addReg(newValues[mOp.getVRegValue()][i]).addReg(kernelPHIs[mOp.getVRegValue()][i]).addRegDef(tmp);
|
||||||
|
DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
|
||||||
|
valPHIs[mOp.getVRegValue()] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(valPHIs.count(mOp.getVRegValue())) {
|
if(valPHIs.count(mOp.getVRegValue())) {
|
||||||
//Update the operand in the cloned instruction
|
//Update the operand in the cloned instruction
|
||||||
clone->getOperand(i).setValueReg(valPHIs[mOp.getVRegValue()]);
|
clone->getOperand(opNum).setValueReg(valPHIs[mOp.getVRegValue()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
machineBB->push_back(clone);
|
machineBB->push_back(clone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(((MachineBasicBlock*)origBB)->getParent())->getBasicBlockList().push_back(machineBB);
|
(((MachineBasicBlock*)origBB)->getParent())->getBasicBlockList().push_back(machineBB);
|
||||||
epilogues.push_back(machineBB);
|
epilogues.push_back(machineBB);
|
||||||
llvm_epilogues.push_back(llvmBB);
|
llvm_epilogues.push_back(llvmBB);
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "EPILOGUE #" << i << "\n");
|
||||||
|
DEBUG(machineBB->print(std::cerr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuloSchedulingPass::writeKernel(BasicBlock *llvmBB, MachineBasicBlock *machineBB, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, std::vector<Value*> > > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation) {
|
void ModuloSchedulingPass::writeKernel(BasicBlock *llvmBB, MachineBasicBlock *machineBB, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation, std::map<Value*, std::map<int, Value*> > &kernelPHIs) {
|
||||||
|
|
||||||
//Keep track of operands that are read and saved from a previous iteration. The new clone
|
//Keep track of operands that are read and saved from a previous iteration. The new clone
|
||||||
//instruction will use the result of the phi instead.
|
//instruction will use the result of the phi instead.
|
||||||
@@ -1329,19 +1383,29 @@ void ModuloSchedulingPass::writeKernel(BasicBlock *llvmBB, MachineBasicBlock *ma
|
|||||||
//Create TmpInstructions for the final phis
|
//Create TmpInstructions for the final phis
|
||||||
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "Stage: " << I->second << " Inst: " << *(I->first->getInst()) << "\n";);
|
||||||
|
|
||||||
//Clone instruction
|
//Clone instruction
|
||||||
const MachineInstr *inst = I->first->getInst();
|
const MachineInstr *inst = I->first->getInst();
|
||||||
MachineInstr *instClone = inst->clone();
|
MachineInstr *instClone = inst->clone();
|
||||||
|
|
||||||
//If this instruction is from a previous iteration, update its operands
|
|
||||||
if(I->second > 0) {
|
|
||||||
//Loop over Machine Operands
|
|
||||||
const MachineInstr *inst = I->first->getInst();
|
|
||||||
for(unsigned i=0; i < inst->getNumOperands(); ++i) {
|
|
||||||
//get machine operand
|
|
||||||
const MachineOperand &mOp = inst->getOperand(i);
|
|
||||||
|
|
||||||
|
//Insert into machine basic block
|
||||||
|
machineBB->push_back(instClone);
|
||||||
|
|
||||||
|
|
||||||
|
//Loop over Machine Operands
|
||||||
|
for(unsigned i=0; i < inst->getNumOperands(); ++i) {
|
||||||
|
//get machine operand
|
||||||
|
const MachineOperand &mOp = inst->getOperand(i);
|
||||||
|
|
||||||
|
if(I->second != 0) {
|
||||||
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
||||||
|
|
||||||
|
//Check to see where this operand is defined if this instruction is from max stage
|
||||||
|
if(I->second == schedule.getMaxStage()) {
|
||||||
|
DEBUG(std::cerr << "VREG: " << *(mOp.getVRegValue()) << "\n");
|
||||||
|
}
|
||||||
|
|
||||||
//If its in the value saved, we need to create a temp instruction and use that instead
|
//If its in the value saved, we need to create a temp instruction and use that instead
|
||||||
if(valuesToSave.count(mOp.getVRegValue())) {
|
if(valuesToSave.count(mOp.getVRegValue())) {
|
||||||
TmpInstruction *tmp = new TmpInstruction(mOp.getVRegValue());
|
TmpInstruction *tmp = new TmpInstruction(mOp.getVRegValue());
|
||||||
@@ -1354,23 +1418,8 @@ void ModuloSchedulingPass::writeKernel(BasicBlock *llvmBB, MachineBasicBlock *ma
|
|||||||
newValLocation[tmp] = machineBB;
|
newValLocation[tmp] = machineBB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//Insert into machine basic block
|
if(I->second != schedule.getMaxStage()) {
|
||||||
machineBB->push_back(instClone);
|
|
||||||
|
|
||||||
}
|
|
||||||
//Otherwise we just check if we need to save a value or not
|
|
||||||
else {
|
|
||||||
//Insert into machine basic block
|
|
||||||
machineBB->push_back(instClone);
|
|
||||||
|
|
||||||
//Loop over Machine Operands
|
|
||||||
const MachineInstr *inst = I->first->getInst();
|
|
||||||
for(unsigned i=0; i < inst->getNumOperands(); ++i) {
|
|
||||||
//get machine operand
|
|
||||||
const MachineOperand &mOp = inst->getOperand(i);
|
|
||||||
|
|
||||||
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
|
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
|
||||||
if(valuesToSave.count(mOp.getVRegValue())) {
|
if(valuesToSave.count(mOp.getVRegValue())) {
|
||||||
|
|
||||||
@@ -1382,59 +1431,84 @@ void ModuloSchedulingPass::writeKernel(BasicBlock *llvmBB, MachineBasicBlock *ma
|
|||||||
//Save for future cleanup
|
//Save for future cleanup
|
||||||
kernelValue[mOp.getVRegValue()] = tmp;
|
kernelValue[mOp.getVRegValue()] = tmp;
|
||||||
newValLocation[tmp] = machineBB;
|
newValLocation[tmp] = machineBB;
|
||||||
|
kernelPHIs[mOp.getVRegValue()][schedule.getMaxStage()-1] = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Clean up by writing phis
|
DEBUG(std::cerr << "KERNEL before PHIs\n");
|
||||||
for(std::map<Value*, std::map<int, std::vector<Value*> > >::iterator V = newValues.begin(), E = newValues.end();
|
DEBUG(machineBB->print(std::cerr));
|
||||||
V != E; ++V) {
|
|
||||||
|
|
||||||
|
//Loop over each value we need to generate phis for
|
||||||
|
for(std::map<Value*, std::map<int, Value*> >::iterator V = newValues.begin(),
|
||||||
|
E = newValues.end(); V != E; ++V) {
|
||||||
|
|
||||||
|
|
||||||
DEBUG(std::cerr << "Writing phi for" << *(V->first));
|
DEBUG(std::cerr << "Writing phi for" << *(V->first));
|
||||||
|
DEBUG(std::cerr << "\nMap of Value* for this phi\n");
|
||||||
//FIXME
|
DEBUG(for(std::map<int, Value*>::iterator I = V->second.begin(),
|
||||||
int maxStage = 1;
|
IE = V->second.end(); I != IE; ++I) {
|
||||||
|
std::cerr << "Stage: " << I->first;
|
||||||
|
std::cerr << " Value: " << *(I->second) << "\n";
|
||||||
|
});
|
||||||
|
|
||||||
//Last phi
|
//If we only have one current iteration live, its safe to set lastPhi = to kernel value
|
||||||
Instruction *lastPHI = 0;
|
if(V->second.size() == 1) {
|
||||||
|
assert(kernelValue[V->first] != 0 && "Kernel value* must exist to create phi");
|
||||||
for(std::map<int, std::vector<Value*> >::iterator I = V->second.begin(), IE = V->second.end();
|
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(),V9::PHI, 3).addReg(V->second.begin()->second).addReg(kernelValue[V->first]).addRegDef(finalPHIValue[V->first]);
|
||||||
I != IE; ++I) {
|
DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
|
||||||
|
kernelPHIs[V->first][schedule.getMaxStage()-1] = kernelValue[V->first];
|
||||||
int stage = I->first;
|
|
||||||
|
|
||||||
DEBUG(std::cerr << "Stage: " << I->first << " vector size: " << I->second.size() << "\n");
|
|
||||||
|
|
||||||
//Assert if this vector is ever greater then 1. This should not happen
|
|
||||||
//FIXME: Get rid of vector if we convince ourselves this won't happn
|
|
||||||
assert(I->second.size() == 1 && "Vector of values should be of size \n");
|
|
||||||
|
|
||||||
//We must handle the first and last phi specially
|
|
||||||
if(stage == maxStage) {
|
|
||||||
//The resulting value must be the Value* we created earlier
|
|
||||||
assert(lastPHI != 0 && "Last phi is NULL!\n");
|
|
||||||
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(lastPHI).addReg(I->second[0]).addRegDef(finalPHIValue[V->first]);
|
|
||||||
I->second.push_back(finalPHIValue[V->first]);
|
|
||||||
}
|
|
||||||
else if(stage == 0) {
|
|
||||||
lastPHI = new TmpInstruction(I->second[0]);
|
|
||||||
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(kernelValue[V->first]).addReg(I->second[0]).addRegDef(lastPHI);
|
|
||||||
I->second.push_back(lastPHI);
|
|
||||||
newValLocation[lastPHI] = machineBB;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Instruction *tmp = new TmpInstruction(I->second[0]);
|
|
||||||
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(lastPHI).addReg(I->second[0]).addRegDef(tmp);
|
|
||||||
lastPHI = tmp;
|
|
||||||
I->second.push_back(lastPHI);
|
|
||||||
newValLocation[tmp] = machineBB;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
|
|
||||||
|
//Keep track of last phi created.
|
||||||
|
Instruction *lastPhi = 0;
|
||||||
|
|
||||||
|
unsigned count = 1;
|
||||||
|
//Loop over the the map backwards to generate phis
|
||||||
|
for(std::map<int, Value*>::reverse_iterator I = V->second.rbegin(), IE = V->second.rend();
|
||||||
|
I != IE; ++I) {
|
||||||
|
|
||||||
|
if(count < (V->second).size()) {
|
||||||
|
if(lastPhi == 0) {
|
||||||
|
lastPhi = new TmpInstruction(I->second);
|
||||||
|
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(kernelValue[V->first]).addReg(I->second).addRegDef(lastPhi);
|
||||||
|
DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
|
||||||
|
newValLocation[lastPhi] = machineBB;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Instruction *tmp = new TmpInstruction(I->second);
|
||||||
|
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(lastPhi).addReg(I->second).addRegDef(tmp);
|
||||||
|
DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
|
||||||
|
lastPhi = tmp;
|
||||||
|
kernelPHIs[V->first][I->first] = lastPhi;
|
||||||
|
newValLocation[lastPhi] = machineBB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Final phi value
|
||||||
|
else {
|
||||||
|
//The resulting value must be the Value* we created earlier
|
||||||
|
assert(lastPhi != 0 && "Last phi is NULL!\n");
|
||||||
|
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(lastPhi).addReg(I->second).addRegDef(finalPHIValue[V->first]);
|
||||||
|
DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
|
||||||
|
kernelPHIs[V->first][I->first] = finalPHIValue[V->first];
|
||||||
|
}
|
||||||
|
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "KERNEL after PHIs\n");
|
||||||
|
DEBUG(machineBB->print(std::cerr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ModuloSchedulingPass::removePHIs(const MachineBasicBlock *origBB, std::vector<MachineBasicBlock *> &prologues, std::vector<MachineBasicBlock *> &epilogues, MachineBasicBlock *kernelBB, std::map<Value*, MachineBasicBlock*> &newValLocation) {
|
void ModuloSchedulingPass::removePHIs(const MachineBasicBlock *origBB, std::vector<MachineBasicBlock *> &prologues, std::vector<MachineBasicBlock *> &epilogues, MachineBasicBlock *kernelBB, std::map<Value*, MachineBasicBlock*> &newValLocation) {
|
||||||
|
|
||||||
//Worklist to delete things
|
//Worklist to delete things
|
||||||
@@ -1535,6 +1609,7 @@ void ModuloSchedulingPass::removePHIs(const MachineBasicBlock *origBB, std::vect
|
|||||||
|
|
||||||
//Delete the phis
|
//Delete the phis
|
||||||
for(std::vector<std::pair<MachineBasicBlock*, MachineBasicBlock::iterator> >::iterator I = worklist.begin(), E = worklist.end(); I != E; ++I) {
|
for(std::vector<std::pair<MachineBasicBlock*, MachineBasicBlock::iterator> >::iterator I = worklist.begin(), E = worklist.end(); I != E; ++I) {
|
||||||
|
DEBUG(std::cerr << "Deleting PHI " << I->second << "\n");
|
||||||
I->first->erase(I->second);
|
I->first->erase(I->second);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1544,26 +1619,66 @@ void ModuloSchedulingPass::removePHIs(const MachineBasicBlock *origBB, std::vect
|
|||||||
|
|
||||||
void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "Reconstructing Loop\n");
|
||||||
|
|
||||||
//First find the value *'s that we need to "save"
|
//First find the value *'s that we need to "save"
|
||||||
std::map<const Value*, std::pair<const MSchedGraphNode*, int> > valuesToSave;
|
std::map<const Value*, std::pair<const MSchedGraphNode*, int> > valuesToSave;
|
||||||
|
|
||||||
|
//Keep track of instructions we have already seen and their stage because
|
||||||
|
//we don't want to "save" values if they are used in the kernel immediately
|
||||||
|
std::map<const MachineInstr*, int> lastInstrs;
|
||||||
|
|
||||||
//Loop over kernel and only look at instructions from a stage > 0
|
//Loop over kernel and only look at instructions from a stage > 0
|
||||||
//Look at its operands and save values *'s that are read
|
//Look at its operands and save values *'s that are read
|
||||||
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
||||||
|
|
||||||
if(I->second > 0) {
|
if(I->second !=0) {
|
||||||
//For this instruction, get the Value*'s that it reads and put them into the set.
|
//For this instruction, get the Value*'s that it reads and put them into the set.
|
||||||
//Assert if there is an operand of another type that we need to save
|
//Assert if there is an operand of another type that we need to save
|
||||||
const MachineInstr *inst = I->first->getInst();
|
const MachineInstr *inst = I->first->getInst();
|
||||||
|
lastInstrs[inst] = I->second;
|
||||||
|
|
||||||
for(unsigned i=0; i < inst->getNumOperands(); ++i) {
|
for(unsigned i=0; i < inst->getNumOperands(); ++i) {
|
||||||
//get machine operand
|
//get machine operand
|
||||||
const MachineOperand &mOp = inst->getOperand(i);
|
const MachineOperand &mOp = inst->getOperand(i);
|
||||||
|
|
||||||
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
||||||
//find the value in the map
|
//find the value in the map
|
||||||
if (const Value* srcI = mOp.getVRegValue())
|
if (const Value* srcI = mOp.getVRegValue()) {
|
||||||
valuesToSave[srcI] = std::make_pair(I->first, i);
|
|
||||||
|
//Before we declare this Value* one that we should save
|
||||||
|
//make sure its def is not of the same stage as this instruction
|
||||||
|
//because it will be consumed before its used
|
||||||
|
Instruction *defInst = (Instruction*) srcI;
|
||||||
|
|
||||||
|
//Should we save this value?
|
||||||
|
bool save = true;
|
||||||
|
|
||||||
|
//Get Machine code for this instruction, and loop backwards over the array
|
||||||
|
//to find the def
|
||||||
|
MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(defInst);
|
||||||
|
for (int j = tempMvec.size()-1; j >= 0; j--) {
|
||||||
|
MachineInstr *temp = tempMvec[j];
|
||||||
|
|
||||||
|
//Loop over instructions
|
||||||
|
for(unsigned opNum = 0; opNum < temp->getNumOperands(); ++opNum) {
|
||||||
|
MachineOperand &mDefOp = temp->getOperand(opNum);
|
||||||
|
|
||||||
|
if (mDefOp.getType() == MachineOperand::MO_VirtualRegister && mDefOp.isDef()) {
|
||||||
|
const Value* defVReg = mDefOp.getVRegValue();
|
||||||
|
if(defVReg == srcI) {
|
||||||
|
//Check if instruction has been seen already and is of same stage
|
||||||
|
if(lastInstrs.count(temp)) {
|
||||||
|
if(lastInstrs[temp] == I->second)
|
||||||
|
save = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(save)
|
||||||
|
valuesToSave[srcI] = std::make_pair(I->first, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mOp.getType() != MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
if(mOp.getType() != MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
||||||
@@ -1576,8 +1691,11 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
//The new loop will consist of one or more prologues, the kernel, and one or more epilogues.
|
//The new loop will consist of one or more prologues, the kernel, and one or more epilogues.
|
||||||
|
|
||||||
//Map to keep track of old to new values
|
//Map to keep track of old to new values
|
||||||
std::map<Value*, std::map<int, std::vector<Value*> > > newValues;
|
std::map<Value*, std::map<int, Value*> > newValues;
|
||||||
|
|
||||||
|
//Map to keep track of old to new values in kernel
|
||||||
|
std::map<Value*, std::map<int, Value*> > kernelPHIs;
|
||||||
|
|
||||||
//Another map to keep track of what machine basic blocks these new value*s are in since
|
//Another map to keep track of what machine basic blocks these new value*s are in since
|
||||||
//they have no llvm instruction equivalent
|
//they have no llvm instruction equivalent
|
||||||
std::map<Value*, MachineBasicBlock*> newValLocation;
|
std::map<Value*, MachineBasicBlock*> newValLocation;
|
||||||
@@ -1588,18 +1706,25 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
|
|
||||||
//Write prologue
|
//Write prologue
|
||||||
writePrologues(prologues, BB, llvm_prologues, valuesToSave, newValues, newValLocation);
|
writePrologues(prologues, BB, llvm_prologues, valuesToSave, newValues, newValLocation);
|
||||||
|
|
||||||
|
//Print out epilogues and prologue
|
||||||
|
DEBUG(for(std::vector<MachineBasicBlock*>::iterator I = prologues.begin(), E = prologues.end();
|
||||||
|
I != E; ++I) {
|
||||||
|
std::cerr << "PROLOGUE\n";
|
||||||
|
(*I)->print(std::cerr);
|
||||||
|
});
|
||||||
|
|
||||||
BasicBlock *llvmKernelBB = new BasicBlock("Kernel", (Function*) (BB->getBasicBlock()->getParent()));
|
BasicBlock *llvmKernelBB = new BasicBlock("Kernel", (Function*) (BB->getBasicBlock()->getParent()));
|
||||||
MachineBasicBlock *machineKernelBB = new MachineBasicBlock(llvmKernelBB);
|
MachineBasicBlock *machineKernelBB = new MachineBasicBlock(llvmKernelBB);
|
||||||
|
|
||||||
writeKernel(llvmKernelBB, machineKernelBB, valuesToSave, newValues, newValLocation);
|
|
||||||
(((MachineBasicBlock*)BB)->getParent())->getBasicBlockList().push_back(machineKernelBB);
|
(((MachineBasicBlock*)BB)->getParent())->getBasicBlockList().push_back(machineKernelBB);
|
||||||
|
writeKernel(llvmKernelBB, machineKernelBB, valuesToSave, newValues, newValLocation, kernelPHIs);
|
||||||
|
|
||||||
|
|
||||||
std::vector<MachineBasicBlock*> epilogues;
|
std::vector<MachineBasicBlock*> epilogues;
|
||||||
std::vector<BasicBlock*> llvm_epilogues;
|
std::vector<BasicBlock*> llvm_epilogues;
|
||||||
|
|
||||||
//Write epilogues
|
//Write epilogues
|
||||||
writeEpilogues(epilogues, BB, llvm_epilogues, valuesToSave, newValues, newValLocation);
|
writeEpilogues(epilogues, BB, llvm_epilogues, valuesToSave, newValues, newValLocation, kernelPHIs);
|
||||||
|
|
||||||
|
|
||||||
const TargetInstrInfo *TMI = target.getInstrInfo();
|
const TargetInstrInfo *TMI = target.getInstrInfo();
|
||||||
@@ -1650,11 +1775,11 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
//Push nop onto end of machine basic block
|
//Push nop onto end of machine basic block
|
||||||
BuildMI(prologues[I], V9::NOP, 0);
|
BuildMI(prologues[I], V9::NOP, 0);
|
||||||
|
|
||||||
//Now since I don't trust fall throughs, add a unconditional branch to the next prologue
|
//Add a unconditional branch to the next prologue
|
||||||
if(I != prologues.size()-1)
|
if(I != prologues.size()-1)
|
||||||
BuildMI(prologues[I], V9::BA, 1).addReg(llvm_prologues[I+1]);
|
BuildMI(prologues[I], V9::BA, 1).addPCDisp(llvm_prologues[I+1]);
|
||||||
else
|
else
|
||||||
BuildMI(prologues[I], V9::BA, 1).addReg(llvmKernelBB);
|
BuildMI(prologues[I], V9::BA, 1).addPCDisp(llvmKernelBB);
|
||||||
|
|
||||||
//Add one more nop!
|
//Add one more nop!
|
||||||
BuildMI(prologues[I], V9::NOP, 0);
|
BuildMI(prologues[I], V9::NOP, 0);
|
||||||
@@ -1693,7 +1818,8 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
BuildMI(machineKernelBB, V9::NOP, 0);
|
BuildMI(machineKernelBB, V9::NOP, 0);
|
||||||
|
|
||||||
//Add unconditional branch to first epilogue
|
//Add unconditional branch to first epilogue
|
||||||
BuildMI(machineKernelBB, V9::BA, 1).addReg(llvm_epilogues[0]);
|
BuildMI(machineKernelBB, V9::BA, 1).addPCDisp(llvm_epilogues[0]);
|
||||||
|
|
||||||
|
|
||||||
//Add kernel noop
|
//Add kernel noop
|
||||||
BuildMI(machineKernelBB, V9::NOP, 0);
|
BuildMI(machineKernelBB, V9::NOP, 0);
|
||||||
@@ -1703,7 +1829,7 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
|
|
||||||
//Now since I don't trust fall throughs, add a unconditional branch to the next prologue
|
//Now since I don't trust fall throughs, add a unconditional branch to the next prologue
|
||||||
if(I != epilogues.size()-1) {
|
if(I != epilogues.size()-1) {
|
||||||
BuildMI(epilogues[I], V9::BA, 1).addReg(llvm_epilogues[I+1]);
|
BuildMI(epilogues[I], V9::BA, 1).addPCDisp(llvm_epilogues[I+1]);
|
||||||
//Add unconditional branch to end of epilogue
|
//Add unconditional branch to end of epilogue
|
||||||
TerminatorInst *newBranch = new BranchInst(llvm_epilogues[I+1],
|
TerminatorInst *newBranch = new BranchInst(llvm_epilogues[I+1],
|
||||||
llvm_epilogues[I]);
|
llvm_epilogues[I]);
|
||||||
@@ -1715,7 +1841,7 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
MachineOpCode OC = inst->getOpcode();
|
MachineOpCode OC = inst->getOpcode();
|
||||||
if(TMI->isBranch(OC)) {
|
if(TMI->isBranch(OC)) {
|
||||||
branch = &*inst;
|
branch = &*inst;
|
||||||
DEBUG(std::cerr << *inst << "\n");
|
DEBUG(std::cerr << "Exit branch from loop" << *inst << "\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1724,7 +1850,7 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
MachineOperand &mOp = branch->getOperand(opNum);
|
MachineOperand &mOp = branch->getOperand(opNum);
|
||||||
|
|
||||||
if (mOp.getType() == MachineOperand::MO_PCRelativeDisp) {
|
if (mOp.getType() == MachineOperand::MO_PCRelativeDisp) {
|
||||||
BuildMI(epilogues[I], V9::BA, 1).addReg(mOp.getVRegValue());
|
BuildMI(epilogues[I], V9::BA, 1).addPCDisp(mOp.getVRegValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1835,7 +1961,7 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
DEBUG(std::cerr << "New Machine Function" << "\n");
|
DEBUG(std::cerr << "New Machine Function" << "\n");
|
||||||
DEBUG(std::cerr << BB->getParent() << "\n");
|
DEBUG(std::cerr << BB->getParent() << "\n");
|
||||||
|
|
||||||
BB->getParent()->getBasicBlockList().erase(BB);
|
//BB->getParent()->getBasicBlockList().erase(BB);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,19 +41,19 @@ namespace llvm {
|
|||||||
|
|
||||||
//Map that holds node to node attribute information
|
//Map that holds node to node attribute information
|
||||||
std::map<MSchedGraphNode*, MSNodeAttributes> nodeToAttributesMap;
|
std::map<MSchedGraphNode*, MSNodeAttributes> nodeToAttributesMap;
|
||||||
|
|
||||||
//Map to hold all reccurrences
|
//Map to hold all reccurrences
|
||||||
std::set<std::pair<int, std::vector<MSchedGraphNode*> > > recurrenceList;
|
std::set<std::pair<int, std::vector<MSchedGraphNode*> > > recurrenceList;
|
||||||
|
|
||||||
//Set of edges to ignore, stored as src node and index into vector of successors
|
//Set of edges to ignore, stored as src node and index into vector of successors
|
||||||
std::set<std::pair<MSchedGraphNode*, unsigned> > edgesToIgnore;
|
std::set<std::pair<MSchedGraphNode*, unsigned> > edgesToIgnore;
|
||||||
|
|
||||||
//Vector containing the partial order
|
//Vector containing the partial order
|
||||||
std::vector<std::vector<MSchedGraphNode*> > partialOrder;
|
std::vector<std::vector<MSchedGraphNode*> > partialOrder;
|
||||||
|
|
||||||
//Vector containing the final node order
|
//Vector containing the final node order
|
||||||
std::vector<MSchedGraphNode*> FinalNodeOrder;
|
std::vector<MSchedGraphNode*> FinalNodeOrder;
|
||||||
|
|
||||||
//Schedule table, key is the cycle number and the vector is resource, node pairs
|
//Schedule table, key is the cycle number and the vector is resource, node pairs
|
||||||
MSSchedule schedule;
|
MSSchedule schedule;
|
||||||
|
|
||||||
@@ -68,7 +68,6 @@ namespace llvm {
|
|||||||
|
|
||||||
bool ignoreEdge(MSchedGraphNode *srcNode, MSchedGraphNode *destNode);
|
bool ignoreEdge(MSchedGraphNode *srcNode, MSchedGraphNode *destNode);
|
||||||
|
|
||||||
|
|
||||||
int calculateASAP(MSchedGraphNode *node, int MII,MSchedGraphNode *destNode);
|
int calculateASAP(MSchedGraphNode *node, int MII,MSchedGraphNode *destNode);
|
||||||
int calculateALAP(MSchedGraphNode *node, int MII, int maxASAP, MSchedGraphNode *srcNode);
|
int calculateALAP(MSchedGraphNode *node, int MII, int maxASAP, MSchedGraphNode *srcNode);
|
||||||
|
|
||||||
@@ -93,12 +92,12 @@ namespace llvm {
|
|||||||
|
|
||||||
//void saveValue(const MachineInstr*, const std::set<Value*>&, std::vector<Value*>*);
|
//void saveValue(const MachineInstr*, const std::set<Value*>&, std::vector<Value*>*);
|
||||||
|
|
||||||
void writePrologues(std::vector<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, std::vector<Value*> > > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
void writePrologues(std::vector<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
||||||
|
|
||||||
void writeEpilogues(std::vector<MachineBasicBlock *> &epilogues, const MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_epilogues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave,std::map<Value*, std::map<int, std::vector<Value*> > > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
void writeEpilogues(std::vector<MachineBasicBlock *> &epilogues, const MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_epilogues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave,std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation, std::map<Value*, std::map<int, Value*> > &kernelPHIs);
|
||||||
|
|
||||||
|
|
||||||
void writeKernel(BasicBlock *llvmBB, MachineBasicBlock *machineBB, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, std::vector<Value*> > > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
void writeKernel(BasicBlock *llvmBB, MachineBasicBlock *machineBB, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation, std::map<Value*, std::map<int, Value*> > &kernelPHIs);
|
||||||
|
|
||||||
void removePHIs(const MachineBasicBlock *origBB, std::vector<MachineBasicBlock *> &prologues, std::vector<MachineBasicBlock *> &epilogues, MachineBasicBlock *kernelBB, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
void removePHIs(const MachineBasicBlock *origBB, std::vector<MachineBasicBlock *> &prologues, std::vector<MachineBasicBlock *> &epilogues, MachineBasicBlock *kernelBB, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
#include "MSSchedule.h"
|
#include "MSSchedule.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Target/TargetSchedInfo.h"
|
#include "llvm/Target/TargetSchedInfo.h"
|
||||||
|
#include "../../Target/SparcV9/SparcV9Internals.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@@ -134,6 +135,7 @@ bool MSSchedule::resourcesFree(MSchedGraphNode *node, int cycle) {
|
|||||||
|
|
||||||
bool MSSchedule::constructKernel(int II) {
|
bool MSSchedule::constructKernel(int II) {
|
||||||
MSchedGraphNode *branchNode = 0;
|
MSchedGraphNode *branchNode = 0;
|
||||||
|
MSchedGraphNode *branchANode = 0;
|
||||||
|
|
||||||
int stageNum = (schedule.rbegin()->first)/ II;
|
int stageNum = (schedule.rbegin()->first)/ II;
|
||||||
DEBUG(std::cerr << "Number of Stages: " << stageNum << "\n");
|
DEBUG(std::cerr << "Number of Stages: " << stageNum << "\n");
|
||||||
@@ -146,7 +148,10 @@ bool MSSchedule::constructKernel(int II) {
|
|||||||
E = schedule[i].end(); I != E; ++I) {
|
E = schedule[i].end(); I != E; ++I) {
|
||||||
//Check if its a branch
|
//Check if its a branch
|
||||||
if((*I)->isBranch()) {
|
if((*I)->isBranch()) {
|
||||||
branchNode = *I;
|
if((*I)->getInst()->getOpcode() == V9::BA)
|
||||||
|
branchANode = *I;
|
||||||
|
else
|
||||||
|
branchNode = *I;
|
||||||
assert(count == 0 && "Branch can not be from a previous iteration");
|
assert(count == 0 && "Branch can not be from a previous iteration");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -160,7 +165,16 @@ bool MSSchedule::constructKernel(int II) {
|
|||||||
|
|
||||||
//Add Branch to the end
|
//Add Branch to the end
|
||||||
kernel.push_back(std::make_pair(branchNode, 0));
|
kernel.push_back(std::make_pair(branchNode, 0));
|
||||||
|
|
||||||
|
//Add Branch Always to the end
|
||||||
|
kernel.push_back(std::make_pair(branchANode, 0));
|
||||||
|
|
||||||
|
|
||||||
|
if(stageNum > 0)
|
||||||
|
maxStage = stageNum;
|
||||||
|
else
|
||||||
|
maxStage = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,6 +32,9 @@ namespace llvm {
|
|||||||
//Resulting kernel
|
//Resulting kernel
|
||||||
std::vector<std::pair<MSchedGraphNode*, int> > kernel;
|
std::vector<std::pair<MSchedGraphNode*, int> > kernel;
|
||||||
|
|
||||||
|
//Max stage count
|
||||||
|
int maxStage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MSSchedule(int num) : numIssue(num) {}
|
MSSchedule(int num) : numIssue(num) {}
|
||||||
MSSchedule() : numIssue(4) {}
|
MSSchedule() : numIssue(4) {}
|
||||||
@@ -40,7 +43,7 @@ namespace llvm {
|
|||||||
void clear() { schedule.clear(); resourceNumPerCycle.clear(); kernel.clear(); }
|
void clear() { schedule.clear(); resourceNumPerCycle.clear(); kernel.clear(); }
|
||||||
std::vector<std::pair<MSchedGraphNode*, int> >* getKernel() { return &kernel; }
|
std::vector<std::pair<MSchedGraphNode*, int> >* getKernel() { return &kernel; }
|
||||||
bool constructKernel(int II);
|
bool constructKernel(int II);
|
||||||
|
int getMaxStage() { return maxStage; }
|
||||||
|
|
||||||
|
|
||||||
//iterators
|
//iterators
|
||||||
|
@@ -91,7 +91,7 @@ MSchedGraph::MSchedGraph(const MachineBasicBlock *bb, const TargetMachine &targ)
|
|||||||
//Make sure BB is not null,
|
//Make sure BB is not null,
|
||||||
assert(BB != NULL && "Basic Block is null");
|
assert(BB != NULL && "Basic Block is null");
|
||||||
|
|
||||||
DEBUG(std::cerr << "Constructing graph for " << bb << "\n");
|
//DEBUG(std::cerr << "Constructing graph for " << bb << "\n");
|
||||||
|
|
||||||
//Create nodes and edges for this BB
|
//Create nodes and edges for this BB
|
||||||
buildNodesAndEdges();
|
buildNodesAndEdges();
|
||||||
|
@@ -123,14 +123,11 @@ bool ModuloSchedulingPass::runOnFunction(Function &F) {
|
|||||||
|
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
DEBUG(std::cerr << "Creating ModuloSchedGraph for each valid BasicBlock in" + F.getName() + "\n");
|
DEBUG(std::cerr << "Creating ModuloSchedGraph for each valid BasicBlock in " + F.getName() + "\n");
|
||||||
|
|
||||||
//Get MachineFunction
|
//Get MachineFunction
|
||||||
MachineFunction &MF = MachineFunction::get(&F);
|
MachineFunction &MF = MachineFunction::get(&F);
|
||||||
|
|
||||||
//Print out machine function
|
|
||||||
DEBUG(MF.print(std::cerr));
|
|
||||||
|
|
||||||
//Worklist
|
//Worklist
|
||||||
std::vector<MachineBasicBlock*> Worklist;
|
std::vector<MachineBasicBlock*> Worklist;
|
||||||
|
|
||||||
@@ -139,6 +136,7 @@ bool ModuloSchedulingPass::runOnFunction(Function &F) {
|
|||||||
if(MachineBBisValid(BI))
|
if(MachineBBisValid(BI))
|
||||||
Worklist.push_back(&*BI);
|
Worklist.push_back(&*BI);
|
||||||
|
|
||||||
|
DEBUG(if(Worklist.size() == 0) std::cerr << "No single basic block loops in function to ModuloSchedule\n");
|
||||||
|
|
||||||
//Iterate over the worklist and perform scheduling
|
//Iterate over the worklist and perform scheduling
|
||||||
for(std::vector<MachineBasicBlock*>::iterator BI = Worklist.begin(),
|
for(std::vector<MachineBasicBlock*>::iterator BI = Worklist.begin(),
|
||||||
@@ -150,7 +148,7 @@ bool ModuloSchedulingPass::runOnFunction(Function &F) {
|
|||||||
DEBUG(WriteGraphToFile(std::cerr, F.getName(), MSG));
|
DEBUG(WriteGraphToFile(std::cerr, F.getName(), MSG));
|
||||||
|
|
||||||
//Print out BB for debugging
|
//Print out BB for debugging
|
||||||
DEBUG((*BI)->print(std::cerr));
|
DEBUG(std::cerr << "ModuloScheduling BB: \n"; (*BI)->print(std::cerr));
|
||||||
|
|
||||||
//Calculate Resource II
|
//Calculate Resource II
|
||||||
int ResMII = calculateResMII(*BI);
|
int ResMII = calculateResMII(*BI);
|
||||||
@@ -213,7 +211,7 @@ bool ModuloSchedulingPass::runOnFunction(Function &F) {
|
|||||||
recurrenceList.clear();
|
recurrenceList.clear();
|
||||||
FinalNodeOrder.clear();
|
FinalNodeOrder.clear();
|
||||||
schedule.clear();
|
schedule.clear();
|
||||||
|
|
||||||
//Clean up. Nuke old MachineBB and llvmBB
|
//Clean up. Nuke old MachineBB and llvmBB
|
||||||
//BasicBlock *llvmBB = (BasicBlock*) (*BI)->getBasicBlock();
|
//BasicBlock *llvmBB = (BasicBlock*) (*BI)->getBasicBlock();
|
||||||
//Function *parent = (Function*) llvmBB->getParent();
|
//Function *parent = (Function*) llvmBB->getParent();
|
||||||
@@ -260,7 +258,6 @@ bool ModuloSchedulingPass::MachineBBisValid(const MachineBasicBlock *BI) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//ResMII is calculated by determining the usage count for each resource
|
//ResMII is calculated by determining the usage count for each resource
|
||||||
@@ -1021,11 +1018,22 @@ void ModuloSchedulingPass::orderNodes() {
|
|||||||
succIntersect(*CurrentSet, IntersectCurrent);
|
succIntersect(*CurrentSet, IntersectCurrent);
|
||||||
} //End if BOTTOM_DOWN
|
} //End if BOTTOM_DOWN
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "Current Intersection Size: " << IntersectCurrent.size() << "\n");
|
||||||
}
|
}
|
||||||
//End Wrapping while loop
|
//End Wrapping while loop
|
||||||
|
DEBUG(std::cerr << "Ending Size of Current Set: " << CurrentSet->size() << "\n");
|
||||||
}//End for over all sets of nodes
|
}//End for over all sets of nodes
|
||||||
|
|
||||||
|
//FIXME: As the algorithm stands it will NEVER add an instruction such as ba (with no
|
||||||
|
//data dependencies) to the final order. We add this manually. It will always be
|
||||||
|
//in the last set of S since its not part of a recurrence
|
||||||
|
//Loop over all the sets and place them in the final node order
|
||||||
|
std::vector<std::vector<MSchedGraphNode*> > ::reverse_iterator LastSet = partialOrder.rbegin();
|
||||||
|
for(std::vector<MSchedGraphNode*>::iterator CurrentNode = LastSet->begin(), LastNode = LastSet->end();
|
||||||
|
CurrentNode != LastNode; ++CurrentNode) {
|
||||||
|
if((*CurrentNode)->getInst()->getOpcode() == V9::BA)
|
||||||
|
FinalNodeOrder.push_back(*CurrentNode);
|
||||||
|
}
|
||||||
//Return final Order
|
//Return final Order
|
||||||
//return FinalNodeOrder;
|
//return FinalNodeOrder;
|
||||||
}
|
}
|
||||||
@@ -1080,8 +1088,15 @@ void ModuloSchedulingPass::computeSchedule() {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//WARNING: HACK! FIXME!!!!
|
//WARNING: HACK! FIXME!!!!
|
||||||
EarlyStart = II-1;
|
if((*I)->getInst()->getOpcode() == V9::BA) {
|
||||||
LateStart = II-1;
|
EarlyStart = II-1;
|
||||||
|
LateStart = II-1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
EarlyStart = II-1;
|
||||||
|
LateStart = II-1;
|
||||||
|
assert( (EarlyStart >= 0) && (LateStart >=0) && "EarlyStart and LateStart must be greater then 0");
|
||||||
|
}
|
||||||
hasPred = 1;
|
hasPred = 1;
|
||||||
hasSucc = 1;
|
hasSucc = 1;
|
||||||
}
|
}
|
||||||
@@ -1170,20 +1185,24 @@ bool ModuloSchedulingPass::scheduleNode(MSchedGraphNode *node,
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuloSchedulingPass::writePrologues(std::vector<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, std::vector<Value*> > > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation) {
|
void ModuloSchedulingPass::writePrologues(std::vector<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation) {
|
||||||
|
|
||||||
//Keep a map to easily know whats in the kernel
|
//Keep a map to easily know whats in the kernel
|
||||||
std::map<int, std::set<const MachineInstr*> > inKernel;
|
std::map<int, std::set<const MachineInstr*> > inKernel;
|
||||||
int maxStageCount = 0;
|
int maxStageCount = 0;
|
||||||
|
|
||||||
MSchedGraphNode *branch = 0;
|
MSchedGraphNode *branch = 0;
|
||||||
|
MSchedGraphNode *BAbranch = 0;
|
||||||
|
|
||||||
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
||||||
maxStageCount = std::max(maxStageCount, I->second);
|
maxStageCount = std::max(maxStageCount, I->second);
|
||||||
|
|
||||||
//Ignore the branch, we will handle this separately
|
//Ignore the branch, we will handle this separately
|
||||||
if(I->first->isBranch()) {
|
if(I->first->isBranch()) {
|
||||||
branch = I->first;
|
if (I->first->getInst()->getOpcode() == V9::BA)
|
||||||
|
BAbranch = I->first;
|
||||||
|
else
|
||||||
|
branch = I->first;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1204,27 +1223,30 @@ void ModuloSchedulingPass::writePrologues(std::vector<MachineBasicBlock *> &prol
|
|||||||
for(int j = 0; j <= i; ++j) {
|
for(int j = 0; j <= i; ++j) {
|
||||||
for(MachineBasicBlock::const_iterator MI = origBB->begin(), ME = origBB->end(); ME != MI; ++MI) {
|
for(MachineBasicBlock::const_iterator MI = origBB->begin(), ME = origBB->end(); ME != MI; ++MI) {
|
||||||
if(inKernel[j].count(&*MI)) {
|
if(inKernel[j].count(&*MI)) {
|
||||||
machineBB->push_back(MI->clone());
|
MachineInstr *instClone = MI->clone();
|
||||||
|
machineBB->push_back(instClone);
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "Cloning: " << *MI << "\n");
|
||||||
|
|
||||||
Instruction *tmp;
|
Instruction *tmp;
|
||||||
|
|
||||||
//After cloning, we may need to save the value that this instruction defines
|
//After cloning, we may need to save the value that this instruction defines
|
||||||
for(unsigned opNum=0; opNum < MI->getNumOperands(); ++opNum) {
|
for(unsigned opNum=0; opNum < MI->getNumOperands(); ++opNum) {
|
||||||
//get machine operand
|
//get machine operand
|
||||||
const MachineOperand &mOp = MI->getOperand(opNum);
|
const MachineOperand &mOp = instClone->getOperand(opNum);
|
||||||
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
|
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
|
||||||
|
|
||||||
|
|
||||||
//Check if this is a value we should save
|
//Check if this is a value we should save
|
||||||
if(valuesToSave.count(mOp.getVRegValue())) {
|
if(valuesToSave.count(mOp.getVRegValue())) {
|
||||||
//Save copy in tmpInstruction
|
//Save copy in tmpInstruction
|
||||||
tmp = new TmpInstruction(mOp.getVRegValue());
|
tmp = new TmpInstruction(mOp.getVRegValue());
|
||||||
|
|
||||||
DEBUG(std::cerr << "Value: " << mOp.getVRegValue() << " New Value: " << tmp << " Stage: " << i << "\n");
|
DEBUG(std::cerr << "Value: " << *(mOp.getVRegValue()) << " New Value: " << *tmp << " Stage: " << i << "\n");
|
||||||
newValues[mOp.getVRegValue()][i].push_back(tmp);
|
|
||||||
|
newValues[mOp.getVRegValue()][i]= tmp;
|
||||||
newValLocation[tmp] = machineBB;
|
newValLocation[tmp] = machineBB;
|
||||||
|
|
||||||
DEBUG(std::cerr << "Machine Instr Operands: " << mOp.getVRegValue() << ", 0, " << tmp << "\n");
|
DEBUG(std::cerr << "Machine Instr Operands: " << *(mOp.getVRegValue()) << ", 0, " << *tmp << "\n");
|
||||||
|
|
||||||
//Create machine instruction and put int machineBB
|
//Create machine instruction and put int machineBB
|
||||||
MachineInstr *saveValue = BuildMI(machineBB, V9::ORr, 3).addReg(mOp.getVRegValue()).addImm(0).addRegDef(tmp);
|
MachineInstr *saveValue = BuildMI(machineBB, V9::ORr, 3).addReg(mOp.getVRegValue()).addImm(0).addRegDef(tmp);
|
||||||
@@ -1232,6 +1254,18 @@ void ModuloSchedulingPass::writePrologues(std::vector<MachineBasicBlock *> &prol
|
|||||||
DEBUG(std::cerr << "Created new machine instr: " << *saveValue << "\n");
|
DEBUG(std::cerr << "Created new machine instr: " << *saveValue << "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//We may also need to update the value that we use if its from an earlier prologue
|
||||||
|
if(j != 0) {
|
||||||
|
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
||||||
|
if(newValues.count(mOp.getVRegValue()))
|
||||||
|
if(newValues[mOp.getVRegValue()].count(j-1)) {
|
||||||
|
DEBUG(std::cerr << "Replaced this value: " << mOp.getVRegValue() << " With:" << (newValues[mOp.getVRegValue()][i-1]) << "\n");
|
||||||
|
//Update the operand with the right value
|
||||||
|
instClone->getOperand(opNum).setValueReg(newValues[mOp.getVRegValue()][i-1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1240,6 +1274,9 @@ void ModuloSchedulingPass::writePrologues(std::vector<MachineBasicBlock *> &prol
|
|||||||
|
|
||||||
//Stick in branch at the end
|
//Stick in branch at the end
|
||||||
machineBB->push_back(branch->getInst()->clone());
|
machineBB->push_back(branch->getInst()->clone());
|
||||||
|
|
||||||
|
//Stick in BA branch at the end
|
||||||
|
machineBB->push_back(BAbranch->getInst()->clone());
|
||||||
|
|
||||||
(((MachineBasicBlock*)origBB)->getParent())->getBasicBlockList().push_back(machineBB);
|
(((MachineBasicBlock*)origBB)->getParent())->getBasicBlockList().push_back(machineBB);
|
||||||
prologues.push_back(machineBB);
|
prologues.push_back(machineBB);
|
||||||
@@ -1247,12 +1284,11 @@ void ModuloSchedulingPass::writePrologues(std::vector<MachineBasicBlock *> &prol
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuloSchedulingPass::writeEpilogues(std::vector<MachineBasicBlock *> &epilogues, const MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_epilogues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, std::vector<Value*> > > &newValues,std::map<Value*, MachineBasicBlock*> &newValLocation ) {
|
void ModuloSchedulingPass::writeEpilogues(std::vector<MachineBasicBlock *> &epilogues, const MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_epilogues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues,std::map<Value*, MachineBasicBlock*> &newValLocation, std::map<Value*, std::map<int, Value*> > &kernelPHIs ) {
|
||||||
|
|
||||||
std::map<int, std::set<const MachineInstr*> > inKernel;
|
std::map<int, std::set<const MachineInstr*> > inKernel;
|
||||||
int maxStageCount = 0;
|
|
||||||
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
||||||
maxStageCount = std::max(maxStageCount, I->second);
|
|
||||||
|
|
||||||
//Ignore the branch, we will handle this separately
|
//Ignore the branch, we will handle this separately
|
||||||
if(I->first->isBranch())
|
if(I->first->isBranch())
|
||||||
@@ -1264,62 +1300,80 @@ void ModuloSchedulingPass::writeEpilogues(std::vector<MachineBasicBlock *> &epil
|
|||||||
|
|
||||||
std::map<Value*, Value*> valPHIs;
|
std::map<Value*, Value*> valPHIs;
|
||||||
|
|
||||||
|
//some debug stuff, will remove later
|
||||||
|
DEBUG(for(std::map<Value*, std::map<int, Value*> >::iterator V = newValues.begin(), E = newValues.end(); V !=E; ++V) {
|
||||||
|
std::cerr << "Old Value: " << *(V->first) << "\n";
|
||||||
|
for(std::map<int, Value*>::iterator I = V->second.begin(), IE = V->second.end(); I != IE; ++I)
|
||||||
|
std::cerr << "Stage: " << I->first << " Value: " << *(I->second) << "\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
//some debug stuff, will remove later
|
||||||
|
DEBUG(for(std::map<Value*, std::map<int, Value*> >::iterator V = kernelPHIs.begin(), E = kernelPHIs.end(); V !=E; ++V) {
|
||||||
|
std::cerr << "Old Value: " << *(V->first) << "\n";
|
||||||
|
for(std::map<int, Value*>::iterator I = V->second.begin(), IE = V->second.end(); I != IE; ++I)
|
||||||
|
std::cerr << "Stage: " << I->first << " Value: " << *(I->second) << "\n";
|
||||||
|
});
|
||||||
|
|
||||||
//Now write the epilogues
|
//Now write the epilogues
|
||||||
for(int i = maxStageCount-1; i >= 0; --i) {
|
for(int i = schedule.getMaxStage()-1; i >= 0; --i) {
|
||||||
BasicBlock *llvmBB = new BasicBlock("EPILOGUE", (Function*) (origBB->getBasicBlock()->getParent()));
|
BasicBlock *llvmBB = new BasicBlock("EPILOGUE", (Function*) (origBB->getBasicBlock()->getParent()));
|
||||||
MachineBasicBlock *machineBB = new MachineBasicBlock(llvmBB);
|
MachineBasicBlock *machineBB = new MachineBasicBlock(llvmBB);
|
||||||
|
|
||||||
DEBUG(std::cerr << " i: " << i << "\n");
|
DEBUG(std::cerr << " Epilogue #: " << i << "\n");
|
||||||
|
|
||||||
//Spit out phi nodes
|
|
||||||
for(std::map<Value*, std::map<int, std::vector<Value*> > >::iterator V = newValues.begin(), E = newValues.end();
|
|
||||||
V != E; ++V) {
|
|
||||||
|
|
||||||
DEBUG(std::cerr << "Writing phi for" << *(V->first));
|
|
||||||
for(std::map<int, std::vector<Value*> >::iterator I = V->second.begin(), IE = V->second.end(); I != IE; ++I) {
|
|
||||||
if(I->first == i) {
|
|
||||||
DEBUG(std::cerr << "BLAH " << i << "\n");
|
|
||||||
|
|
||||||
//Vector must have two elements in it:
|
|
||||||
assert(I->second.size() == 2 && "Vector size should be two\n");
|
|
||||||
|
|
||||||
Instruction *tmp = new TmpInstruction(I->second[0]);
|
|
||||||
MachineInstr *saveValue = BuildMI(machineBB, V9::PHI, 3).addReg(I->second[0]).addReg(I->second[1]).addRegDef(tmp);
|
|
||||||
valPHIs[V->first] = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for(MachineBasicBlock::const_iterator MI = origBB->begin(), ME = origBB->end(); ME != MI; ++MI) {
|
|
||||||
for(int j=maxStageCount; j > i; --j) {
|
for(MachineBasicBlock::const_iterator MI = origBB->begin(), ME = origBB->end(); ME != MI; ++MI) {
|
||||||
|
for(int j=schedule.getMaxStage(); j > i; --j) {
|
||||||
if(inKernel[j].count(&*MI)) {
|
if(inKernel[j].count(&*MI)) {
|
||||||
DEBUG(std::cerr << "Cloning instruction " << *MI << "\n");
|
DEBUG(std::cerr << "Cloning instruction " << *MI << "\n");
|
||||||
MachineInstr *clone = MI->clone();
|
MachineInstr *clone = MI->clone();
|
||||||
|
|
||||||
//Update operands that need to use the result from the phi
|
//Update operands that need to use the result from the phi
|
||||||
for(unsigned i=0; i < clone->getNumOperands(); ++i) {
|
for(unsigned opNum=0; opNum < clone->getNumOperands(); ++opNum) {
|
||||||
//get machine operand
|
//get machine operand
|
||||||
const MachineOperand &mOp = clone->getOperand(i);
|
const MachineOperand &mOp = clone->getOperand(opNum);
|
||||||
|
|
||||||
|
//If this is the last instructions for the max iterations ago, don't update operands
|
||||||
|
if(j == schedule.getMaxStage() && (i == 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
if((mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse())) {
|
if((mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse())) {
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "Writing PHI for " << *(mOp.getVRegValue()) << "\n");
|
||||||
|
|
||||||
|
//Quickly write appropriate phis for this operand
|
||||||
|
if(newValues.count(mOp.getVRegValue())) {
|
||||||
|
if(newValues[mOp.getVRegValue()].count(i)) {
|
||||||
|
Instruction *tmp = new TmpInstruction(newValues[mOp.getVRegValue()][i]);
|
||||||
|
MachineInstr *saveValue = BuildMI(machineBB, V9::PHI, 3).addReg(newValues[mOp.getVRegValue()][i]).addReg(kernelPHIs[mOp.getVRegValue()][i]).addRegDef(tmp);
|
||||||
|
DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
|
||||||
|
valPHIs[mOp.getVRegValue()] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(valPHIs.count(mOp.getVRegValue())) {
|
if(valPHIs.count(mOp.getVRegValue())) {
|
||||||
//Update the operand in the cloned instruction
|
//Update the operand in the cloned instruction
|
||||||
clone->getOperand(i).setValueReg(valPHIs[mOp.getVRegValue()]);
|
clone->getOperand(opNum).setValueReg(valPHIs[mOp.getVRegValue()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
machineBB->push_back(clone);
|
machineBB->push_back(clone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(((MachineBasicBlock*)origBB)->getParent())->getBasicBlockList().push_back(machineBB);
|
(((MachineBasicBlock*)origBB)->getParent())->getBasicBlockList().push_back(machineBB);
|
||||||
epilogues.push_back(machineBB);
|
epilogues.push_back(machineBB);
|
||||||
llvm_epilogues.push_back(llvmBB);
|
llvm_epilogues.push_back(llvmBB);
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "EPILOGUE #" << i << "\n");
|
||||||
|
DEBUG(machineBB->print(std::cerr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuloSchedulingPass::writeKernel(BasicBlock *llvmBB, MachineBasicBlock *machineBB, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, std::vector<Value*> > > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation) {
|
void ModuloSchedulingPass::writeKernel(BasicBlock *llvmBB, MachineBasicBlock *machineBB, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation, std::map<Value*, std::map<int, Value*> > &kernelPHIs) {
|
||||||
|
|
||||||
//Keep track of operands that are read and saved from a previous iteration. The new clone
|
//Keep track of operands that are read and saved from a previous iteration. The new clone
|
||||||
//instruction will use the result of the phi instead.
|
//instruction will use the result of the phi instead.
|
||||||
@@ -1329,19 +1383,29 @@ void ModuloSchedulingPass::writeKernel(BasicBlock *llvmBB, MachineBasicBlock *ma
|
|||||||
//Create TmpInstructions for the final phis
|
//Create TmpInstructions for the final phis
|
||||||
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "Stage: " << I->second << " Inst: " << *(I->first->getInst()) << "\n";);
|
||||||
|
|
||||||
//Clone instruction
|
//Clone instruction
|
||||||
const MachineInstr *inst = I->first->getInst();
|
const MachineInstr *inst = I->first->getInst();
|
||||||
MachineInstr *instClone = inst->clone();
|
MachineInstr *instClone = inst->clone();
|
||||||
|
|
||||||
//If this instruction is from a previous iteration, update its operands
|
|
||||||
if(I->second > 0) {
|
|
||||||
//Loop over Machine Operands
|
|
||||||
const MachineInstr *inst = I->first->getInst();
|
|
||||||
for(unsigned i=0; i < inst->getNumOperands(); ++i) {
|
|
||||||
//get machine operand
|
|
||||||
const MachineOperand &mOp = inst->getOperand(i);
|
|
||||||
|
|
||||||
|
//Insert into machine basic block
|
||||||
|
machineBB->push_back(instClone);
|
||||||
|
|
||||||
|
|
||||||
|
//Loop over Machine Operands
|
||||||
|
for(unsigned i=0; i < inst->getNumOperands(); ++i) {
|
||||||
|
//get machine operand
|
||||||
|
const MachineOperand &mOp = inst->getOperand(i);
|
||||||
|
|
||||||
|
if(I->second != 0) {
|
||||||
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
||||||
|
|
||||||
|
//Check to see where this operand is defined if this instruction is from max stage
|
||||||
|
if(I->second == schedule.getMaxStage()) {
|
||||||
|
DEBUG(std::cerr << "VREG: " << *(mOp.getVRegValue()) << "\n");
|
||||||
|
}
|
||||||
|
|
||||||
//If its in the value saved, we need to create a temp instruction and use that instead
|
//If its in the value saved, we need to create a temp instruction and use that instead
|
||||||
if(valuesToSave.count(mOp.getVRegValue())) {
|
if(valuesToSave.count(mOp.getVRegValue())) {
|
||||||
TmpInstruction *tmp = new TmpInstruction(mOp.getVRegValue());
|
TmpInstruction *tmp = new TmpInstruction(mOp.getVRegValue());
|
||||||
@@ -1354,23 +1418,8 @@ void ModuloSchedulingPass::writeKernel(BasicBlock *llvmBB, MachineBasicBlock *ma
|
|||||||
newValLocation[tmp] = machineBB;
|
newValLocation[tmp] = machineBB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
//Insert into machine basic block
|
if(I->second != schedule.getMaxStage()) {
|
||||||
machineBB->push_back(instClone);
|
|
||||||
|
|
||||||
}
|
|
||||||
//Otherwise we just check if we need to save a value or not
|
|
||||||
else {
|
|
||||||
//Insert into machine basic block
|
|
||||||
machineBB->push_back(instClone);
|
|
||||||
|
|
||||||
//Loop over Machine Operands
|
|
||||||
const MachineInstr *inst = I->first->getInst();
|
|
||||||
for(unsigned i=0; i < inst->getNumOperands(); ++i) {
|
|
||||||
//get machine operand
|
|
||||||
const MachineOperand &mOp = inst->getOperand(i);
|
|
||||||
|
|
||||||
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
|
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
|
||||||
if(valuesToSave.count(mOp.getVRegValue())) {
|
if(valuesToSave.count(mOp.getVRegValue())) {
|
||||||
|
|
||||||
@@ -1382,59 +1431,84 @@ void ModuloSchedulingPass::writeKernel(BasicBlock *llvmBB, MachineBasicBlock *ma
|
|||||||
//Save for future cleanup
|
//Save for future cleanup
|
||||||
kernelValue[mOp.getVRegValue()] = tmp;
|
kernelValue[mOp.getVRegValue()] = tmp;
|
||||||
newValLocation[tmp] = machineBB;
|
newValLocation[tmp] = machineBB;
|
||||||
|
kernelPHIs[mOp.getVRegValue()][schedule.getMaxStage()-1] = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Clean up by writing phis
|
DEBUG(std::cerr << "KERNEL before PHIs\n");
|
||||||
for(std::map<Value*, std::map<int, std::vector<Value*> > >::iterator V = newValues.begin(), E = newValues.end();
|
DEBUG(machineBB->print(std::cerr));
|
||||||
V != E; ++V) {
|
|
||||||
|
|
||||||
|
//Loop over each value we need to generate phis for
|
||||||
|
for(std::map<Value*, std::map<int, Value*> >::iterator V = newValues.begin(),
|
||||||
|
E = newValues.end(); V != E; ++V) {
|
||||||
|
|
||||||
|
|
||||||
DEBUG(std::cerr << "Writing phi for" << *(V->first));
|
DEBUG(std::cerr << "Writing phi for" << *(V->first));
|
||||||
|
DEBUG(std::cerr << "\nMap of Value* for this phi\n");
|
||||||
//FIXME
|
DEBUG(for(std::map<int, Value*>::iterator I = V->second.begin(),
|
||||||
int maxStage = 1;
|
IE = V->second.end(); I != IE; ++I) {
|
||||||
|
std::cerr << "Stage: " << I->first;
|
||||||
|
std::cerr << " Value: " << *(I->second) << "\n";
|
||||||
|
});
|
||||||
|
|
||||||
//Last phi
|
//If we only have one current iteration live, its safe to set lastPhi = to kernel value
|
||||||
Instruction *lastPHI = 0;
|
if(V->second.size() == 1) {
|
||||||
|
assert(kernelValue[V->first] != 0 && "Kernel value* must exist to create phi");
|
||||||
for(std::map<int, std::vector<Value*> >::iterator I = V->second.begin(), IE = V->second.end();
|
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(),V9::PHI, 3).addReg(V->second.begin()->second).addReg(kernelValue[V->first]).addRegDef(finalPHIValue[V->first]);
|
||||||
I != IE; ++I) {
|
DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
|
||||||
|
kernelPHIs[V->first][schedule.getMaxStage()-1] = kernelValue[V->first];
|
||||||
int stage = I->first;
|
|
||||||
|
|
||||||
DEBUG(std::cerr << "Stage: " << I->first << " vector size: " << I->second.size() << "\n");
|
|
||||||
|
|
||||||
//Assert if this vector is ever greater then 1. This should not happen
|
|
||||||
//FIXME: Get rid of vector if we convince ourselves this won't happn
|
|
||||||
assert(I->second.size() == 1 && "Vector of values should be of size \n");
|
|
||||||
|
|
||||||
//We must handle the first and last phi specially
|
|
||||||
if(stage == maxStage) {
|
|
||||||
//The resulting value must be the Value* we created earlier
|
|
||||||
assert(lastPHI != 0 && "Last phi is NULL!\n");
|
|
||||||
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(lastPHI).addReg(I->second[0]).addRegDef(finalPHIValue[V->first]);
|
|
||||||
I->second.push_back(finalPHIValue[V->first]);
|
|
||||||
}
|
|
||||||
else if(stage == 0) {
|
|
||||||
lastPHI = new TmpInstruction(I->second[0]);
|
|
||||||
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(kernelValue[V->first]).addReg(I->second[0]).addRegDef(lastPHI);
|
|
||||||
I->second.push_back(lastPHI);
|
|
||||||
newValLocation[lastPHI] = machineBB;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Instruction *tmp = new TmpInstruction(I->second[0]);
|
|
||||||
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(lastPHI).addReg(I->second[0]).addRegDef(tmp);
|
|
||||||
lastPHI = tmp;
|
|
||||||
I->second.push_back(lastPHI);
|
|
||||||
newValLocation[tmp] = machineBB;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
|
|
||||||
|
//Keep track of last phi created.
|
||||||
|
Instruction *lastPhi = 0;
|
||||||
|
|
||||||
|
unsigned count = 1;
|
||||||
|
//Loop over the the map backwards to generate phis
|
||||||
|
for(std::map<int, Value*>::reverse_iterator I = V->second.rbegin(), IE = V->second.rend();
|
||||||
|
I != IE; ++I) {
|
||||||
|
|
||||||
|
if(count < (V->second).size()) {
|
||||||
|
if(lastPhi == 0) {
|
||||||
|
lastPhi = new TmpInstruction(I->second);
|
||||||
|
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(kernelValue[V->first]).addReg(I->second).addRegDef(lastPhi);
|
||||||
|
DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
|
||||||
|
newValLocation[lastPhi] = machineBB;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Instruction *tmp = new TmpInstruction(I->second);
|
||||||
|
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(lastPhi).addReg(I->second).addRegDef(tmp);
|
||||||
|
DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
|
||||||
|
lastPhi = tmp;
|
||||||
|
kernelPHIs[V->first][I->first] = lastPhi;
|
||||||
|
newValLocation[lastPhi] = machineBB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Final phi value
|
||||||
|
else {
|
||||||
|
//The resulting value must be the Value* we created earlier
|
||||||
|
assert(lastPhi != 0 && "Last phi is NULL!\n");
|
||||||
|
MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(lastPhi).addReg(I->second).addRegDef(finalPHIValue[V->first]);
|
||||||
|
DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
|
||||||
|
kernelPHIs[V->first][I->first] = finalPHIValue[V->first];
|
||||||
|
}
|
||||||
|
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "KERNEL after PHIs\n");
|
||||||
|
DEBUG(machineBB->print(std::cerr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ModuloSchedulingPass::removePHIs(const MachineBasicBlock *origBB, std::vector<MachineBasicBlock *> &prologues, std::vector<MachineBasicBlock *> &epilogues, MachineBasicBlock *kernelBB, std::map<Value*, MachineBasicBlock*> &newValLocation) {
|
void ModuloSchedulingPass::removePHIs(const MachineBasicBlock *origBB, std::vector<MachineBasicBlock *> &prologues, std::vector<MachineBasicBlock *> &epilogues, MachineBasicBlock *kernelBB, std::map<Value*, MachineBasicBlock*> &newValLocation) {
|
||||||
|
|
||||||
//Worklist to delete things
|
//Worklist to delete things
|
||||||
@@ -1535,6 +1609,7 @@ void ModuloSchedulingPass::removePHIs(const MachineBasicBlock *origBB, std::vect
|
|||||||
|
|
||||||
//Delete the phis
|
//Delete the phis
|
||||||
for(std::vector<std::pair<MachineBasicBlock*, MachineBasicBlock::iterator> >::iterator I = worklist.begin(), E = worklist.end(); I != E; ++I) {
|
for(std::vector<std::pair<MachineBasicBlock*, MachineBasicBlock::iterator> >::iterator I = worklist.begin(), E = worklist.end(); I != E; ++I) {
|
||||||
|
DEBUG(std::cerr << "Deleting PHI " << I->second << "\n");
|
||||||
I->first->erase(I->second);
|
I->first->erase(I->second);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1544,26 +1619,66 @@ void ModuloSchedulingPass::removePHIs(const MachineBasicBlock *origBB, std::vect
|
|||||||
|
|
||||||
void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "Reconstructing Loop\n");
|
||||||
|
|
||||||
//First find the value *'s that we need to "save"
|
//First find the value *'s that we need to "save"
|
||||||
std::map<const Value*, std::pair<const MSchedGraphNode*, int> > valuesToSave;
|
std::map<const Value*, std::pair<const MSchedGraphNode*, int> > valuesToSave;
|
||||||
|
|
||||||
|
//Keep track of instructions we have already seen and their stage because
|
||||||
|
//we don't want to "save" values if they are used in the kernel immediately
|
||||||
|
std::map<const MachineInstr*, int> lastInstrs;
|
||||||
|
|
||||||
//Loop over kernel and only look at instructions from a stage > 0
|
//Loop over kernel and only look at instructions from a stage > 0
|
||||||
//Look at its operands and save values *'s that are read
|
//Look at its operands and save values *'s that are read
|
||||||
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
|
||||||
|
|
||||||
if(I->second > 0) {
|
if(I->second !=0) {
|
||||||
//For this instruction, get the Value*'s that it reads and put them into the set.
|
//For this instruction, get the Value*'s that it reads and put them into the set.
|
||||||
//Assert if there is an operand of another type that we need to save
|
//Assert if there is an operand of another type that we need to save
|
||||||
const MachineInstr *inst = I->first->getInst();
|
const MachineInstr *inst = I->first->getInst();
|
||||||
|
lastInstrs[inst] = I->second;
|
||||||
|
|
||||||
for(unsigned i=0; i < inst->getNumOperands(); ++i) {
|
for(unsigned i=0; i < inst->getNumOperands(); ++i) {
|
||||||
//get machine operand
|
//get machine operand
|
||||||
const MachineOperand &mOp = inst->getOperand(i);
|
const MachineOperand &mOp = inst->getOperand(i);
|
||||||
|
|
||||||
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
||||||
//find the value in the map
|
//find the value in the map
|
||||||
if (const Value* srcI = mOp.getVRegValue())
|
if (const Value* srcI = mOp.getVRegValue()) {
|
||||||
valuesToSave[srcI] = std::make_pair(I->first, i);
|
|
||||||
|
//Before we declare this Value* one that we should save
|
||||||
|
//make sure its def is not of the same stage as this instruction
|
||||||
|
//because it will be consumed before its used
|
||||||
|
Instruction *defInst = (Instruction*) srcI;
|
||||||
|
|
||||||
|
//Should we save this value?
|
||||||
|
bool save = true;
|
||||||
|
|
||||||
|
//Get Machine code for this instruction, and loop backwards over the array
|
||||||
|
//to find the def
|
||||||
|
MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(defInst);
|
||||||
|
for (int j = tempMvec.size()-1; j >= 0; j--) {
|
||||||
|
MachineInstr *temp = tempMvec[j];
|
||||||
|
|
||||||
|
//Loop over instructions
|
||||||
|
for(unsigned opNum = 0; opNum < temp->getNumOperands(); ++opNum) {
|
||||||
|
MachineOperand &mDefOp = temp->getOperand(opNum);
|
||||||
|
|
||||||
|
if (mDefOp.getType() == MachineOperand::MO_VirtualRegister && mDefOp.isDef()) {
|
||||||
|
const Value* defVReg = mDefOp.getVRegValue();
|
||||||
|
if(defVReg == srcI) {
|
||||||
|
//Check if instruction has been seen already and is of same stage
|
||||||
|
if(lastInstrs.count(temp)) {
|
||||||
|
if(lastInstrs[temp] == I->second)
|
||||||
|
save = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(save)
|
||||||
|
valuesToSave[srcI] = std::make_pair(I->first, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mOp.getType() != MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
if(mOp.getType() != MachineOperand::MO_VirtualRegister && mOp.isUse()) {
|
||||||
@@ -1576,8 +1691,11 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
//The new loop will consist of one or more prologues, the kernel, and one or more epilogues.
|
//The new loop will consist of one or more prologues, the kernel, and one or more epilogues.
|
||||||
|
|
||||||
//Map to keep track of old to new values
|
//Map to keep track of old to new values
|
||||||
std::map<Value*, std::map<int, std::vector<Value*> > > newValues;
|
std::map<Value*, std::map<int, Value*> > newValues;
|
||||||
|
|
||||||
|
//Map to keep track of old to new values in kernel
|
||||||
|
std::map<Value*, std::map<int, Value*> > kernelPHIs;
|
||||||
|
|
||||||
//Another map to keep track of what machine basic blocks these new value*s are in since
|
//Another map to keep track of what machine basic blocks these new value*s are in since
|
||||||
//they have no llvm instruction equivalent
|
//they have no llvm instruction equivalent
|
||||||
std::map<Value*, MachineBasicBlock*> newValLocation;
|
std::map<Value*, MachineBasicBlock*> newValLocation;
|
||||||
@@ -1588,18 +1706,25 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
|
|
||||||
//Write prologue
|
//Write prologue
|
||||||
writePrologues(prologues, BB, llvm_prologues, valuesToSave, newValues, newValLocation);
|
writePrologues(prologues, BB, llvm_prologues, valuesToSave, newValues, newValLocation);
|
||||||
|
|
||||||
|
//Print out epilogues and prologue
|
||||||
|
DEBUG(for(std::vector<MachineBasicBlock*>::iterator I = prologues.begin(), E = prologues.end();
|
||||||
|
I != E; ++I) {
|
||||||
|
std::cerr << "PROLOGUE\n";
|
||||||
|
(*I)->print(std::cerr);
|
||||||
|
});
|
||||||
|
|
||||||
BasicBlock *llvmKernelBB = new BasicBlock("Kernel", (Function*) (BB->getBasicBlock()->getParent()));
|
BasicBlock *llvmKernelBB = new BasicBlock("Kernel", (Function*) (BB->getBasicBlock()->getParent()));
|
||||||
MachineBasicBlock *machineKernelBB = new MachineBasicBlock(llvmKernelBB);
|
MachineBasicBlock *machineKernelBB = new MachineBasicBlock(llvmKernelBB);
|
||||||
|
|
||||||
writeKernel(llvmKernelBB, machineKernelBB, valuesToSave, newValues, newValLocation);
|
|
||||||
(((MachineBasicBlock*)BB)->getParent())->getBasicBlockList().push_back(machineKernelBB);
|
(((MachineBasicBlock*)BB)->getParent())->getBasicBlockList().push_back(machineKernelBB);
|
||||||
|
writeKernel(llvmKernelBB, machineKernelBB, valuesToSave, newValues, newValLocation, kernelPHIs);
|
||||||
|
|
||||||
|
|
||||||
std::vector<MachineBasicBlock*> epilogues;
|
std::vector<MachineBasicBlock*> epilogues;
|
||||||
std::vector<BasicBlock*> llvm_epilogues;
|
std::vector<BasicBlock*> llvm_epilogues;
|
||||||
|
|
||||||
//Write epilogues
|
//Write epilogues
|
||||||
writeEpilogues(epilogues, BB, llvm_epilogues, valuesToSave, newValues, newValLocation);
|
writeEpilogues(epilogues, BB, llvm_epilogues, valuesToSave, newValues, newValLocation, kernelPHIs);
|
||||||
|
|
||||||
|
|
||||||
const TargetInstrInfo *TMI = target.getInstrInfo();
|
const TargetInstrInfo *TMI = target.getInstrInfo();
|
||||||
@@ -1650,11 +1775,11 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
//Push nop onto end of machine basic block
|
//Push nop onto end of machine basic block
|
||||||
BuildMI(prologues[I], V9::NOP, 0);
|
BuildMI(prologues[I], V9::NOP, 0);
|
||||||
|
|
||||||
//Now since I don't trust fall throughs, add a unconditional branch to the next prologue
|
//Add a unconditional branch to the next prologue
|
||||||
if(I != prologues.size()-1)
|
if(I != prologues.size()-1)
|
||||||
BuildMI(prologues[I], V9::BA, 1).addReg(llvm_prologues[I+1]);
|
BuildMI(prologues[I], V9::BA, 1).addPCDisp(llvm_prologues[I+1]);
|
||||||
else
|
else
|
||||||
BuildMI(prologues[I], V9::BA, 1).addReg(llvmKernelBB);
|
BuildMI(prologues[I], V9::BA, 1).addPCDisp(llvmKernelBB);
|
||||||
|
|
||||||
//Add one more nop!
|
//Add one more nop!
|
||||||
BuildMI(prologues[I], V9::NOP, 0);
|
BuildMI(prologues[I], V9::NOP, 0);
|
||||||
@@ -1693,7 +1818,8 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
BuildMI(machineKernelBB, V9::NOP, 0);
|
BuildMI(machineKernelBB, V9::NOP, 0);
|
||||||
|
|
||||||
//Add unconditional branch to first epilogue
|
//Add unconditional branch to first epilogue
|
||||||
BuildMI(machineKernelBB, V9::BA, 1).addReg(llvm_epilogues[0]);
|
BuildMI(machineKernelBB, V9::BA, 1).addPCDisp(llvm_epilogues[0]);
|
||||||
|
|
||||||
|
|
||||||
//Add kernel noop
|
//Add kernel noop
|
||||||
BuildMI(machineKernelBB, V9::NOP, 0);
|
BuildMI(machineKernelBB, V9::NOP, 0);
|
||||||
@@ -1703,7 +1829,7 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
|
|
||||||
//Now since I don't trust fall throughs, add a unconditional branch to the next prologue
|
//Now since I don't trust fall throughs, add a unconditional branch to the next prologue
|
||||||
if(I != epilogues.size()-1) {
|
if(I != epilogues.size()-1) {
|
||||||
BuildMI(epilogues[I], V9::BA, 1).addReg(llvm_epilogues[I+1]);
|
BuildMI(epilogues[I], V9::BA, 1).addPCDisp(llvm_epilogues[I+1]);
|
||||||
//Add unconditional branch to end of epilogue
|
//Add unconditional branch to end of epilogue
|
||||||
TerminatorInst *newBranch = new BranchInst(llvm_epilogues[I+1],
|
TerminatorInst *newBranch = new BranchInst(llvm_epilogues[I+1],
|
||||||
llvm_epilogues[I]);
|
llvm_epilogues[I]);
|
||||||
@@ -1715,7 +1841,7 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
MachineOpCode OC = inst->getOpcode();
|
MachineOpCode OC = inst->getOpcode();
|
||||||
if(TMI->isBranch(OC)) {
|
if(TMI->isBranch(OC)) {
|
||||||
branch = &*inst;
|
branch = &*inst;
|
||||||
DEBUG(std::cerr << *inst << "\n");
|
DEBUG(std::cerr << "Exit branch from loop" << *inst << "\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1724,7 +1850,7 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
MachineOperand &mOp = branch->getOperand(opNum);
|
MachineOperand &mOp = branch->getOperand(opNum);
|
||||||
|
|
||||||
if (mOp.getType() == MachineOperand::MO_PCRelativeDisp) {
|
if (mOp.getType() == MachineOperand::MO_PCRelativeDisp) {
|
||||||
BuildMI(epilogues[I], V9::BA, 1).addReg(mOp.getVRegValue());
|
BuildMI(epilogues[I], V9::BA, 1).addPCDisp(mOp.getVRegValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1835,7 +1961,7 @@ void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
|
|||||||
DEBUG(std::cerr << "New Machine Function" << "\n");
|
DEBUG(std::cerr << "New Machine Function" << "\n");
|
||||||
DEBUG(std::cerr << BB->getParent() << "\n");
|
DEBUG(std::cerr << BB->getParent() << "\n");
|
||||||
|
|
||||||
BB->getParent()->getBasicBlockList().erase(BB);
|
//BB->getParent()->getBasicBlockList().erase(BB);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,19 +41,19 @@ namespace llvm {
|
|||||||
|
|
||||||
//Map that holds node to node attribute information
|
//Map that holds node to node attribute information
|
||||||
std::map<MSchedGraphNode*, MSNodeAttributes> nodeToAttributesMap;
|
std::map<MSchedGraphNode*, MSNodeAttributes> nodeToAttributesMap;
|
||||||
|
|
||||||
//Map to hold all reccurrences
|
//Map to hold all reccurrences
|
||||||
std::set<std::pair<int, std::vector<MSchedGraphNode*> > > recurrenceList;
|
std::set<std::pair<int, std::vector<MSchedGraphNode*> > > recurrenceList;
|
||||||
|
|
||||||
//Set of edges to ignore, stored as src node and index into vector of successors
|
//Set of edges to ignore, stored as src node and index into vector of successors
|
||||||
std::set<std::pair<MSchedGraphNode*, unsigned> > edgesToIgnore;
|
std::set<std::pair<MSchedGraphNode*, unsigned> > edgesToIgnore;
|
||||||
|
|
||||||
//Vector containing the partial order
|
//Vector containing the partial order
|
||||||
std::vector<std::vector<MSchedGraphNode*> > partialOrder;
|
std::vector<std::vector<MSchedGraphNode*> > partialOrder;
|
||||||
|
|
||||||
//Vector containing the final node order
|
//Vector containing the final node order
|
||||||
std::vector<MSchedGraphNode*> FinalNodeOrder;
|
std::vector<MSchedGraphNode*> FinalNodeOrder;
|
||||||
|
|
||||||
//Schedule table, key is the cycle number and the vector is resource, node pairs
|
//Schedule table, key is the cycle number and the vector is resource, node pairs
|
||||||
MSSchedule schedule;
|
MSSchedule schedule;
|
||||||
|
|
||||||
@@ -68,7 +68,6 @@ namespace llvm {
|
|||||||
|
|
||||||
bool ignoreEdge(MSchedGraphNode *srcNode, MSchedGraphNode *destNode);
|
bool ignoreEdge(MSchedGraphNode *srcNode, MSchedGraphNode *destNode);
|
||||||
|
|
||||||
|
|
||||||
int calculateASAP(MSchedGraphNode *node, int MII,MSchedGraphNode *destNode);
|
int calculateASAP(MSchedGraphNode *node, int MII,MSchedGraphNode *destNode);
|
||||||
int calculateALAP(MSchedGraphNode *node, int MII, int maxASAP, MSchedGraphNode *srcNode);
|
int calculateALAP(MSchedGraphNode *node, int MII, int maxASAP, MSchedGraphNode *srcNode);
|
||||||
|
|
||||||
@@ -93,12 +92,12 @@ namespace llvm {
|
|||||||
|
|
||||||
//void saveValue(const MachineInstr*, const std::set<Value*>&, std::vector<Value*>*);
|
//void saveValue(const MachineInstr*, const std::set<Value*>&, std::vector<Value*>*);
|
||||||
|
|
||||||
void writePrologues(std::vector<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, std::vector<Value*> > > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
void writePrologues(std::vector<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
||||||
|
|
||||||
void writeEpilogues(std::vector<MachineBasicBlock *> &epilogues, const MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_epilogues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave,std::map<Value*, std::map<int, std::vector<Value*> > > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
void writeEpilogues(std::vector<MachineBasicBlock *> &epilogues, const MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_epilogues, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave,std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation, std::map<Value*, std::map<int, Value*> > &kernelPHIs);
|
||||||
|
|
||||||
|
|
||||||
void writeKernel(BasicBlock *llvmBB, MachineBasicBlock *machineBB, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, std::vector<Value*> > > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
void writeKernel(BasicBlock *llvmBB, MachineBasicBlock *machineBB, std::map<const Value*, std::pair<const MSchedGraphNode*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation, std::map<Value*, std::map<int, Value*> > &kernelPHIs);
|
||||||
|
|
||||||
void removePHIs(const MachineBasicBlock *origBB, std::vector<MachineBasicBlock *> &prologues, std::vector<MachineBasicBlock *> &epilogues, MachineBasicBlock *kernelBB, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
void removePHIs(const MachineBasicBlock *origBB, std::vector<MachineBasicBlock *> &prologues, std::vector<MachineBasicBlock *> &epilogues, MachineBasicBlock *kernelBB, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user