Skip to content

Commit a2bf1af

Browse files
author
Andres Madrid Ucha
committed
Partial Executer: Early bailout for a basic block if we stop learning
Instead of looping until we hit the max visits per basic block, I implemented a way to keep track of how many new edges or values we've discovered while visiting each SCC. We will always get to a point, especially in self-loops were we stop knowing anything new. If that is the case I keep track of how many iterations have passed without knowning any new values. When the iterations without progress reach the check for staleness, we mark this SCC as reachable and move on with the rests. If a child of the parent is stale, with this solution, we just exit that child earlier but the rest of the parent's children will still be visited.
1 parent e603f2d commit a2bf1af

1 file changed

Lines changed: 75 additions & 5 deletions

File tree

llvm/lib/CheerpWriter/PartialExecuter.cpp

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ typedef llvm::DenseSet<std::pair<GlobalVariable*, uint32_t> > NewAlignmentData;
6969
namespace cheerp {
7070

7171
const uint32_t MAX_NUMBER_OF_VISITS_PER_BB = 100u;
72+
const uint32_t CHECK_STALE_FREQUENCY = 10u;
7273

7374
class FunctionData;
7475
class ModuleData;
@@ -882,11 +883,13 @@ class FunctionData
882883
{
883884
}
884885
};
886+
885887
llvm::Function& F;
886888
std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*>> existingEdges;
887889
typedef std::vector<Value*> VectorOfArgs;
888890

889891
llvm::DenseMap<const llvm::BasicBlock*, int> visitCounter;
892+
llvm::DenseMap<const llvm::BasicBlock*, int> iterationsWithoutProgress;
890893
llvm::DenseSet<std::pair<const llvm::BasicBlock*, const llvm::BasicBlock*> > visitedEdges;
891894
llvm::DenseMap<llvm::Instruction*, KnownValue> knownValues;
892895
ModuleData& moduleData;
@@ -966,15 +969,30 @@ class FunctionData
966969
currentEE->addAlignmentRequirement(moduleData.alignmentToBeBumped);
967970

968971
}
972+
969973
public:
970974
explicit FunctionData(llvm::Function& F, ModuleData& moduleData)
971975
: F(F), moduleData(moduleData), currentEE(nullptr)
972976
{
973977
}
978+
size_t countReplaceableInstructions() const
979+
{
980+
size_t count = 0;
981+
for (const auto& kv: knownValues) {
982+
if (!kv.second.everSkipped)
983+
count++;
984+
}
985+
return count;
986+
}
987+
size_t countVisitedEdges() const
988+
{
989+
return visitedEdges.size();
990+
}
974991
llvm::Function* getFunction()
975992
{
976993
return &F;
977994
}
995+
978996
uint32_t getVisitCounter(const llvm::BasicBlock* BB)
979997
{
980998
return visitCounter[BB];
@@ -983,6 +1001,18 @@ class FunctionData
9831001
{
9841002
visitCounter[BB]++;
9851003
}
1004+
uint32_t getIterationsWithoutProgress(const llvm::BasicBlock* BB)
1005+
{
1006+
return iterationsWithoutProgress[BB];
1007+
}
1008+
void incrementIterationsWithoutProgress(const llvm::BasicBlock* BB)
1009+
{
1010+
iterationsWithoutProgress[BB]++;
1011+
}
1012+
void resetIterationsWithoutProgress(const llvm::BasicBlock* BB)
1013+
{
1014+
iterationsWithoutProgress[BB] = 0;
1015+
}
9861016
PartialInterpreter& getInterpreter()
9871017
{
9881018
// currentEE will be non-null while visiting a Call Equivalent
@@ -1114,6 +1144,7 @@ class FunctionData
11141144
for (const FunctionData::VectorOfArgs& toBeVisited : callEquivalentQueue)
11151145
{
11161146
visitCounter.clear();
1147+
iterationsWithoutProgress.clear();
11171148
visitCallEquivalent(toBeVisited);
11181149
}
11191150
}
@@ -1373,6 +1404,8 @@ class BasicBlockGroupNode
13731404
llvm::BasicBlock* start;
13741405
llvm::BasicBlock* from;
13751406
uint32_t currIter;
1407+
size_t prevValues;
1408+
size_t prevEdges;
13761409
llvm::DenseMap<llvm::BasicBlock*, uint32_t> minVisitIndex;
13771410
// TODO(carlo): an optmization might be having from be a set<BasicBlock>, conserving the phi that are equals
13781411

@@ -1395,9 +1428,28 @@ class BasicBlockGroupNode
13951428
return set;
13961429
}
13971430
void splitIntoSCCs(std::list<BasicBlockGroupNode>& queueToBePopulated, ReverseMapBBToGroup& blockToGroupMap);
1431+
1432+
bool hasProgressed(size_t currValues, size_t currEdges)
1433+
{
1434+
if (currValues > prevValues || currEdges > prevEdges)
1435+
{
1436+
prevValues = currValues;
1437+
prevEdges = currEdges;
1438+
data.resetIterationsWithoutProgress(start);
1439+
return true;
1440+
}
1441+
data.incrementIterationsWithoutProgress(start);
1442+
return false;
1443+
}
1444+
bool hasStaled() const
1445+
{
1446+
return data.getIterationsWithoutProgress(start) >= CHECK_STALE_FREQUENCY;
1447+
}
1448+
13981449
public:
13991450
BasicBlockGroupNode(FunctionData& data, BasicBlockGroupNode* parentBBGNode, const DeterministicBBSet& OWNEDblocks, llvm::BasicBlock* start = nullptr)
1400-
: parentNode(parentBBGNode), data(data), ownedBlocks(OWNEDblocks), blocks(ownedBlocks), isMultiHead(false), isReachable(parentNode == nullptr), start(start), from(nullptr), visitingAll(false)
1451+
: parentNode(parentBBGNode), data(data), ownedBlocks(OWNEDblocks), blocks(ownedBlocks), isMultiHead(false), isReachable(parentNode == nullptr), start(start), from(nullptr), visitingAll(false),
1452+
prevValues(data.countReplaceableInstructions()), prevEdges(data.countVisitedEdges())
14011453
{
14021454
if (start)
14031455
assert(start->getParent() == data.getFunction());
@@ -1407,9 +1459,11 @@ class BasicBlockGroupNode
14071459
{
14081460
}
14091461
BasicBlockGroupNode(BasicBlockGroupNode& BBGNode)
1410-
: parentNode(&BBGNode), data(BBGNode.data), blocks(BBGNode.blocks), isMultiHead(false), isReachable(false), start(nullptr), from(nullptr), visitingAll(false)
1462+
: parentNode(&BBGNode), data(BBGNode.data), blocks(BBGNode.blocks), isMultiHead(false), isReachable(false), start(nullptr), from(nullptr), visitingAll(false),
1463+
prevValues(data.countReplaceableInstructions()), prevEdges(data.countVisitedEdges())
14111464
{
14121465
}
1466+
14131467
void addIncomingEdge(llvm::BasicBlock* comingFrom, uint32_t currIter, llvm::BasicBlock* target)
14141468
{
14151469
isReachable = true;
@@ -1550,15 +1604,31 @@ class BasicBlockGroupNode
15501604
}
15511605
}
15521606
data.incrementVisitCounter(start);
1553-
1607+
15541608
splitIntoSCCs(childrenNodes, reverseMappingBBToGroup); //These should be partially ordered with the last one possibly being the replica of the current one
1555-
1609+
15561610
llvm::SmallVector<llvm::BasicBlock*, 4> visitNext;
1557-
1611+
15581612
// Do the actual visit for start, while populating visitNext
15591613
runVisitBasicBlock(data, *start, visitNext);
15601614
for (llvm::BasicBlock* succ : visitNext)
15611615
registerEdge(start, succ);
1616+
1617+
1618+
if (currIter > 0)
1619+
{
1620+
size_t currentGlobalValues = data.countReplaceableInstructions();
1621+
size_t currentGlobalEdges = data.countVisitedEdges();
1622+
1623+
if (!hasProgressed(currentGlobalValues, currentGlobalEdges))
1624+
{
1625+
if (hasStaled())
1626+
{
1627+
visitAll();
1628+
return;
1629+
}
1630+
}
1631+
}
15621632

15631633
// First has been already done
15641634
childrenNodes.pop_back();

0 commit comments

Comments
 (0)