Skip to content

Commit

Permalink
Issue #47 fix a bug in edge set calculation.
Browse files Browse the repository at this point in the history
  • Loading branch information
lialan committed Sep 2, 2020
1 parent 5e3a250 commit 30431cb
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 38 deletions.
6 changes: 6 additions & 0 deletions lib/Target/EVM/EVMExpandFramePointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ bool EVMExpandFramePointer::handleStackPointer(MachineInstr *MI) {
// them remove MOVE
unsigned fmpReg = this->getNewRegister(MI);

LLVM_DEBUG({
dbgs() << "Expanding $sp to %"
<<Register::virtReg2Index(fmpReg) << " in instruction: ";
MI->dump();
});

BuildMI(*MBB, MI, DL, TII->get(EVM::PUSH32_r), fmpReg)
.addImm(ST->getStackPointer());
BuildMI(*MBB, MI, DL, TII->get(EVM::MSTORE_r))
Expand Down
127 changes: 89 additions & 38 deletions lib/Target/EVM/EVMStackAllocAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,32 +165,35 @@ void EdgeSets::computeEdgeSets(MachineFunction *MF) {
// First, assign each edge with a number:
collectEdges(MF);

// Insert a default edge set: NULL->Entry:

// Then, assign a new edge set for each of the edges
for (std::pair<unsigned, Edge> index : edgeIndex) {
edgeIndex2EdgeSet.insert({index.first, index.first});
}


// Criteria: Two MBBs share a same edge set if:
// 1. they have a common child.
// 2. they have a common parent.
for (MachineBasicBlock &MBB : *MF) {
LLVM_DEBUG({
dbgs() << " Processing MBB:" << MBB.getNumber() << "\n";
});
// we have more than one predecessors
if (std::distance(MBB.pred_begin(), MBB.pred_end()) > 1) {
// all predecessors belong to an edge set
MachineBasicBlock *first = *MBB.pred_begin();

MachineBasicBlock::pred_iterator iter = ++MBB.pred_begin();

while (iter != MBB.pred_end()) {
mergeEdgeSets({first, &MBB}, {*iter, &MBB});
mergeEdgeSets({first, &MBB}, {*iter++, &MBB});
}
}

if (std::distance(MBB.succ_begin(), MBB.succ_end()) > 1) {
// all sucessors belong to an edge set
MachineBasicBlock *first = *MBB.succ_begin();

MachineBasicBlock::pred_iterator iter = ++MBB.succ_begin();

while (iter != MBB.succ_end()) {
mergeEdgeSets({&MBB, first}, {&MBB, *iter++});
}
Expand Down Expand Up @@ -238,7 +241,6 @@ void EdgeSets::printEdge(Edge edge) const {

void EdgeSets::dump() const {
LLVM_DEBUG({
dbgs() << " Computed edge set: (size of edgesets: " << 0 << ")\n";
for (std::pair<unsigned, unsigned> it : edgeIndex2EdgeSet) {
// edge set Index : edge index
unsigned edgeId = it.first;
Expand Down Expand Up @@ -317,11 +319,20 @@ void EVMStackAlloc::beginOfBlockUpdates(MachineBasicBlock *MBB) {
if (MBB->pred_empty()) {
return;
}
LLVM_DEBUG({
dbgs() << " beginBlockUpdate for MBB" << MBB->getNumber() << ".\n";
});

MachineBasicBlock* Pred = *MBB->pred_begin();
EdgeSets::Edge edge = {Pred, MBB};
unsigned setIndex = edgeSets.getEdgeSetIndex(edge);

assert(edgeset2assignment.find(setIndex) != edgeset2assignment.end());

if (edgeset2assignment.find(setIndex) != edgeset2assignment.end()) {
// TODO
} else {

}
ActiveStack xStack = edgeset2assignment[setIndex].first;
MemorySlots memslots = edgeset2assignment[setIndex].second;

Expand Down Expand Up @@ -355,14 +366,12 @@ void EVMStackAlloc::beginOfBlockUpdates(MachineBasicBlock *MBB) {
}

// Now free up memory slots if its occupant is out of range
SlotIndex MBBBeginSlot = LIS->getMBBStartIdx(MBB);
for (size_t i = 0; i < memoryAssignment.size(); ++i) {
for (unsigned i = 0; i < memoryAssignment.size(); ++i) {
unsigned reg = memoryAssignment[i];
if (reg == 0) {
continue;
}
const LiveInterval &LI = LIS->getInterval(reg);
if (!LI.liveAt(MBBBeginSlot)) {
if (regIsDeadAtBeginningOfMBB(reg, MBB)) {
LLVM_DEBUG({
dbgs() << " Memslot: free up %" << Register::virtReg2Index(reg)
<< "\n";
Expand Down Expand Up @@ -425,28 +434,29 @@ void EVMStackAlloc::endOfBlockUpdates(MachineBasicBlock *MBB) {
for (MachineBasicBlock *NextMBB : MBB->successors()) {
unsigned edgeSetIndex = edgeSets.getEdgeSetIndex({MBB, NextMBB});

/*
if (edgeset2assignment.find(edgeSetIndex) != edgeset2assignment.end()) {
// We've already have an x stack assignment previously. so now we will
// need to arrange them so they are the same
ActiveStack &another = edgeset2assignment[edgeSetIndex].first;
MemorySlots memslots = edgeset2assignment[edgeSetIndex].second;
assert(another == xStack && "Two X Stack arrangements are different!");
assert(memslots == memoryAssignment && "Two memory arrangements are different!");
//consolidateXRegionForEdgeSet(edgetSetIndex);
}
*/

// TODO: merge edgeset
EdgeSetAssignment EA = {stack.getStackElements(), memoryAssignment};
edgeset2assignment.erase(edgeSetIndex);
edgeset2assignment[edgeSetIndex] = EA;
mergeEdgesetAssigments(edgeSetIndex, EA);
break;
}
}


void EVMStackAlloc::mergeEdgesetAssigments(unsigned edgeSetIndex, EdgeSetAssignment &EA) {
edgeset2assignment[edgeSetIndex] = EA;
/*
auto iter = edgeset2assignment.find(edgeSetIndex);
if (iter != edgeset2assignment.end()) {
// we have an existing edgeset assignment. merge EA with it.
EdgeSetAssignment &OldEA = iter->second;
MemorySlots newMem;
//edgeset2assignment[edgeSetIndex] = NewEA;
} else {
edgeset2assignment[edgeSetIndex] = EA;
}
*/
}

MachineInstr& EVMStackAlloc::tryToAnalyzeStackArgs(MachineBasicBlock *MBB) {
if (MBB != &MBB->getParent()->front()) {
return MBB->front();
Expand Down Expand Up @@ -524,7 +534,7 @@ MachineInstr& EVMStackAlloc::tryToAnalyzeStackArgs(MachineBasicBlock *MBB) {
<< " to LOCAL STACK.\n");
// update stack status
currentStackStatus.L.insert(reg);
} else if (liveIntervalWithinSameEdgeSet(reg)) {
} else if (false && liveIntervalWithinSameEdgeSet(reg)) {
regAssignments.insert(
std::pair<unsigned, StackAssignment>(reg, {X_STACK, 0}));
LLVM_DEBUG(dbgs() << " Allocating %"
Expand All @@ -545,11 +555,18 @@ MachineInstr& EVMStackAlloc::tryToAnalyzeStackArgs(MachineBasicBlock *MBB) {
regAssignments.insert(
std::pair<unsigned, StackAssignment>(reg, {NONSTACK, slot}));

unsigned depth = stack.findRegDepth(reg);
if (depth != 0) {
insertSwapBefore(depth, MI);
}
insertStoreToMemoryBefore(reg, MI, slot);

LLVM_DEBUG({
dbgs() << " Allocating %" << Register::virtReg2Index(reg)
<< " to memslot: " << slot << "\n";
});

// make sure we pop the right stack register.
unsigned pop_stackreg = stack.pop();
assert(reg == pop_stackreg);
}
Expand All @@ -566,6 +583,10 @@ MachineInstr& EVMStackAlloc::tryToAnalyzeStackArgs(MachineBasicBlock *MBB) {
void EVMStackAlloc::analyzeBasicBlock(MachineBasicBlock *MBB) {
LLVM_DEBUG({ dbgs() << " Analyzing MBB" << MBB->getNumber() << ":\n"; });

if (MBB->empty()) {
return;
}

// this will alter MBB, so we record begin MI instruction
stack.clear();

Expand All @@ -586,9 +607,7 @@ void EVMStackAlloc::analyzeBasicBlock(MachineBasicBlock *MBB) {
// First consume, then create
handleUses(MI);
handleDef(MI);

cleanUpDeadRegisters(MI);

stack.dump();
}

Expand All @@ -609,13 +628,25 @@ void EVMStackAlloc::cleanUpDeadRegisters(MachineInstr &MI) {

MachineBasicBlock::iterator insertPoint(MI);
insertPoint++;
MachineBasicBlock *MBB = MI.getParent();
for (MOPUseType mut : useTypes) {
unsigned depth = stack.findRegDepth(mut.second.reg);
if (depth != 0) {
insertSwapBefore(depth, *insertPoint);
}
insertPopBefore(*insertPoint);
if (mut.second.isLastUse) {
unsigned depth = stack.findRegDepth(mut.second.reg);

if (depth != 0) {
if (insertPoint == MBB->end()) {
insertSwapAfter(depth, MI);
} else {
insertSwapBefore(depth, *insertPoint);
}
}
if (insertPoint == MBB->end()) {
insertPopAfter(MI);
} else {
insertPopBefore(*insertPoint);
}
}
}
}

StackAssignment EVMStackAlloc::getStackAssignment(unsigned reg) const {
Expand Down Expand Up @@ -697,15 +728,17 @@ bool EVMStackAlloc::regIsLastUse(const MachineOperand &MOP) const {
const MachineInstr *MI = MOP.getParent();
const MachineBasicBlock *MBB = MI->getParent();
SlotIndex MISlot = LIS->getInstructionIndex(*MI).getRegSlot();
SlotIndex BBEndSlot = LIS->getMBBEndIdx(MBB);
SlotIndex BBEndSlot = LIS->getMBBEndIdx(&MBB->getParent()->back());

if (rangeContainsRegUses(reg, MISlot, BBEndSlot)) {
return false;
}

/*
if (sucessorsContainRegUses(reg, MBB)) {
return false;
}
*/

return true;
}
Expand Down Expand Up @@ -752,7 +785,7 @@ void EVMStackAlloc::handleDef(MachineInstr &MI) {

// If all uses are in a same edge set, send it to Transfer Stack
// This could greatly benefit from a stack machine specific optimization.
if (liveIntervalWithinSameEdgeSet(defReg)) {
if (false && liveIntervalWithinSameEdgeSet(defReg)) {
// it is a def register, so we only care about out-going edges.
regAssignments.insert(
std::pair<unsigned, StackAssignment>(defReg, {X_STACK, 0}));
Expand Down Expand Up @@ -821,6 +854,11 @@ bool EVMStackAlloc::liveIntervalWithinSameEdgeSet(unsigned defReg) {
}

unsigned EVMStackAlloc::calculateUseRegs(MachineInstr &MI, std::vector<MOPUseType> &useTypes) {
if (MI.getOpcode() == EVM::SAR_r) {
LLVM_DEBUG({
dbgs() << "found sar_r\n";
});
}
unsigned index = 0;
for (const MachineOperand &MOP : MI.explicit_uses()) {
if (!MOP.isReg()) {
Expand Down Expand Up @@ -974,6 +1012,8 @@ void EVMStackAlloc::insertStoreToMemoryBefore(unsigned reg, MachineInstr &MI,
}

void EVMStackAlloc::insertPopAfter(MachineInstr &MI) {
// TODO: this is buggy, we should only use it when the MI is the last
// instruction in the MBB.
MachineBasicBlock *MBB = MI.getParent();
MachineFunction &MF = *MBB->getParent();
MachineInstrBuilder pop = BuildMI(MF, MI.getDebugLoc(), TII->get(EVM::POP_r));
Expand All @@ -991,6 +1031,17 @@ void EVMStackAlloc::insertPopBefore(MachineInstr &MI) {
stack.pop();
}

void EVMStackAlloc::insertSwapAfter(unsigned index, MachineInstr &MI) {
// TODO: this is buggy, we should only use it when the MI is the last
// instruction in the MBB.
MachineBasicBlock *MBB = MI.getParent();
MachineInstrBuilder swap =
BuildMI(*MBB->getParent(), MI.getDebugLoc(), TII->get(EVM::SWAP_r))
.addImm(index);
MBB->insertAfter(MachineBasicBlock::iterator(MI), swap);
LIS->InsertMachineInstrInMaps(*swap);
stack.swap(index);
}

void EVMStackAlloc::insertSwapBefore(unsigned index, MachineInstr &MI) {
MachineBasicBlock *MBB = MI.getParent();
Expand Down Expand Up @@ -1122,6 +1173,7 @@ unsigned EVMStackAlloc::allocateXRegion(unsigned setIndex, unsigned reg) {
"Inserting duplicate element in X region.");

x_region.push_back(reg);
// TODO: we should arrange stack here.
stack.pushElementToXRegion();
return x_region.size();
}
Expand Down Expand Up @@ -1193,7 +1245,6 @@ void EVMStackAlloc::getXStackRegion(unsigned edgeSetIndex,
assert(edgeset2assignment.find(edgeSetIndex) != edgeset2assignment.end() &&
"Cannot find edgeset index!");
llvm_unreachable("not implemented");
//std::copy(edgeset2assignment.begin(), edgeset2assignment.end(), xRegion);
return;
}

Expand Down
2 changes: 2 additions & 0 deletions lib/Target/EVM/EVMStackAllocAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ class EVMStackAlloc : public MachineFunctionPass {
bool rangeContainsRegUses(unsigned reg, SlotIndex &begin,
SlotIndex &end) const;
bool sucessorsContainRegUses(unsigned reg, const MachineBasicBlock *MBB) const;
void mergeEdgesetAssigments(unsigned edgeSetIndex, EdgeSetAssignment &EA);

// the pass to analyze a single basicblock
MachineInstr &tryToAnalyzeStackArgs(MachineBasicBlock *MBB);
Expand Down Expand Up @@ -294,6 +295,7 @@ class EVMStackAlloc : public MachineFunctionPass {
void insertStoreToMemoryBefore(unsigned reg, MachineInstr &MI, unsigned memSlot);
void insertDupBefore(unsigned index, MachineInstr &MI);
void insertSwapBefore(unsigned index, MachineInstr &MI);
void insertSwapAfter(unsigned index, MachineInstr &MI);
void insertPopAfter(MachineInstr &MI);
void insertPopBefore(MachineInstr &MI);

Expand Down

0 comments on commit 30431cb

Please sign in to comment.