@@ -301,7 +301,7 @@ class PartialInterpreter : public llvm::Interpreter {
301301 }
302302 return nullptr ;
303303 }
304- llvm::BasicBlock* visitBasicBlock (FunctionData& data, llvm::BasicBlock& BB);
304+ llvm::BasicBlock* visitBasicBlock (FunctionData& data, llvm::BasicBlock& BB, bool & BBProgress );
305305 explicit PartialInterpreter (std::unique_ptr<llvm::Module> M)
306306 : llvm::Interpreter(std::move(M), /* preExecute*/ false)
307307 {
@@ -631,7 +631,7 @@ class PartialInterpreter : public llvm::Interpreter {
631631 {
632632 return (++functionCounters[F] > 0x1000 );
633633 }
634- void visitOuter (FunctionData& data, llvm::Instruction& I);
634+ void visitOuter (FunctionData& data, llvm::Instruction& I, bool & BBProgress );
635635 bool replaceKnownCEs ()
636636 {
637637 if (fullyKnownCEs.empty ())
@@ -786,7 +786,7 @@ static void removeEdgeBetweenBlocks(llvm::BasicBlock* from, llvm::BasicBlock* to
786786 }
787787}
788788
789- llvm::BasicBlock* PartialInterpreter::visitBasicBlock (FunctionData& data, llvm::BasicBlock& BB)
789+ llvm::BasicBlock* PartialInterpreter::visitBasicBlock (FunctionData& data, llvm::BasicBlock& BB, bool & BBProgress )
790790{
791791 ExecutionContext& executionContext = getTopCallFrame ();
792792 executionContext.CurBB = &BB;
@@ -797,7 +797,7 @@ llvm::BasicBlock* PartialInterpreter::visitBasicBlock(FunctionData& data, llvm::
797797 // Note that here we could also execute a Call, and that implies adding a CallFrame
798798 // executing there (possibly also in depth)
799799 // So getTopCallFrame() has to be called since it will possibly change
800- visitOuter (data, *getTopCallFrame ().CurInst ++);
800+ visitOuter (data, *getTopCallFrame ().CurInst ++, BBProgress );
801801 }
802802
803803 // Find (if there are enough information) the next BB to be visited
@@ -990,9 +990,10 @@ class FunctionData
990990 assert (currentEE);
991991 return *currentEE;
992992 }
993- void registerEdge (const llvm::BasicBlock* from, const llvm::BasicBlock* to)
993+ bool registerEdge (const llvm::BasicBlock* from, const llvm::BasicBlock* to)
994994 {
995- visitedEdges.insert ({from, to});
995+ auto [it, is_inserted] = visitedEdges.insert ({from, to});
996+ return is_inserted;
996997 }
997998 bool hasNoInfo (const VectorOfArgs& arguments) const
998999 {
@@ -1178,29 +1179,36 @@ class FunctionData
11781179 {
11791180 knownValues[&I].everSkipped = true ;
11801181 }
1181- void registerValueForInst (llvm::Instruction& I, const GenericValue& GV, PartialInterpreter::BitMask strongBits)
1182+ bool registerValueForInst (llvm::Instruction& I, const GenericValue& GV, PartialInterpreter::BitMask strongBits)
11821183 {
11831184 // Only support integers for now, to simplify the handling of GVs
11841185 if (!I.getType ()->isIntegerTy ())
1185- return ;
1186+ return false ;
11861187 // Do not attempt tracking of partially known values
11871188 if (strongBits != PartialInterpreter::BitMask::ALL)
1188- return markInstSkipped (I);
1189+ {
1190+ markInstSkipped (I);
1191+ return false ;
1192+ }
11891193 auto it = knownValues.find (&I);
11901194 if (it == knownValues.end ())
11911195 {
11921196 // Never registered any value before, save the current one
11931197 knownValues[&I].value = GV;
1198+ return true ;
11941199 }
11951200 else if (it->second .everSkipped )
11961201 {
11971202 // Nothing we can do anymore
1203+ return false ;
11981204 }
11991205 else if (it->second .value .IntVal != GV.IntVal )
12001206 {
12011207 // Different value observed, bailout
12021208 it->second .everSkipped = true ;
1209+ return false ;
12031210 }
1211+ return false ;
12041212 }
12051213 void replaceKnownValues () const
12061214 {
@@ -1371,6 +1379,7 @@ class BasicBlockGroupNode
13711379 const DeterministicBBSet& blocks;
13721380 bool isMultiHead;
13731381 bool isReachable;
1382+ bool SCCProgress;
13741383 llvm::BasicBlock* start;
13751384 llvm::BasicBlock* from;
13761385 uint32_t currIter;
@@ -1398,7 +1407,7 @@ class BasicBlockGroupNode
13981407 void splitIntoSCCs (std::list<BasicBlockGroupNode>& queueToBePopulated, ReverseMapBBToGroup& blockToGroupMap);
13991408public:
14001409 BasicBlockGroupNode (FunctionData& data, BasicBlockGroupNode* parentBBGNode, const DeterministicBBSet& OWNEDblocks, llvm::BasicBlock* start = nullptr )
1401- : parentNode(parentBBGNode), data(data), ownedBlocks(OWNEDblocks), blocks(ownedBlocks), isMultiHead(false ), isReachable(parentNode == nullptr ), start(start), from(nullptr ), visitingAll(false )
1410+ : parentNode(parentBBGNode), data(data), ownedBlocks(OWNEDblocks), blocks(ownedBlocks), isMultiHead(false ), isReachable(parentNode == nullptr ), SCCProgress( false ), start(start), from(nullptr ), visitingAll(false )
14021411 {
14031412 if (start)
14041413 assert (start->getParent () == data.getFunction ());
@@ -1408,7 +1417,7 @@ class BasicBlockGroupNode
14081417 {
14091418 }
14101419 BasicBlockGroupNode (BasicBlockGroupNode& BBGNode)
1411- : parentNode(&BBGNode), data(BBGNode.data), blocks(BBGNode.blocks), isMultiHead(false ), isReachable(false ), start(nullptr ), from(nullptr ), visitingAll(false )
1420+ : parentNode(&BBGNode), data(BBGNode.data), blocks(BBGNode.blocks), isMultiHead(false ), isReachable(false ), SCCProgress( false ), start(nullptr ), from(nullptr ), visitingAll(false )
14121421 {
14131422 }
14141423 void addIncomingEdge (llvm::BasicBlock* comingFrom, uint32_t currIter, llvm::BasicBlock* target)
@@ -1439,13 +1448,13 @@ class BasicBlockGroupNode
14391448 // Do the visit of the BB, with 'from' (possibly nullptr if unknown) as predecessor
14401449 // Loop backs will be directed to another BBgroup
14411450 // The visit will return the set of reachable BBs, to be added into visitNext
1442- void runVisitBasicBlock (FunctionData& data, llvm::BasicBlock& BB, llvm::SmallVectorImpl<llvm::BasicBlock*>& visitNext)
1451+ void runVisitBasicBlock (FunctionData& data, llvm::BasicBlock& BB, llvm::SmallVectorImpl<llvm::BasicBlock*>& visitNext, bool & BBProgress )
14431452 {
14441453 assert (visitNext.empty ());
14451454
14461455 PartialInterpreter& interpreter = data.getInterpreter ();
14471456 interpreter.incomingBB = from;
1448- BasicBlock* ret = interpreter.visitBasicBlock (data, BB);
1457+ BasicBlock* ret = interpreter.visitBasicBlock (data, BB, BBProgress );
14491458
14501459 if (ret)
14511460 {
@@ -1506,10 +1515,11 @@ class BasicBlockGroupNode
15061515 registerEdge (bb, succ);
15071516 }
15081517 }
1509- void registerEdge (llvm::BasicBlock* from, llvm::BasicBlock* to)
1518+ bool registerEdge (llvm::BasicBlock* from, llvm::BasicBlock* to)
15101519 {
1511- data.registerEdge (from, to);
1520+ bool is_inserted = data.registerEdge (from, to);
15121521 notifySuccessor (from, currIter, to);
1522+ return is_inserted;
15131523 }
15141524 void cleanUp (llvm::BasicBlock* block)
15151525 {
@@ -1522,14 +1532,14 @@ class BasicBlockGroupNode
15221532 }
15231533 }
15241534 // Visit the tree of BasicBlockGroupNodes, starting from the root and visiting children depth-first
1525- void recursiveVisit ()
1535+ bool recursiveVisit ()
15261536 {
15271537 if (isMultiHead)
15281538 {
15291539 // There are multiple BasicBlock that are reacheable from outside
15301540 // --> Mark everything as reachable
15311541 visitAll ();
1532- return ;
1542+ return false ;
15331543 }
15341544 assert (start); // isReachable && !isMultiHead implies start being defined
15351545 currIter = data.getVisitCounter (start);
@@ -1540,7 +1550,7 @@ class BasicBlockGroupNode
15401550 // Since terminability is basically unprovable in general, we give up with the visit
15411551 // --> Mark everything as reachable
15421552 visitAll ();
1543- return ;
1553+ return false ;
15441554 }
15451555 if (parentNode)
15461556 {
@@ -1556,20 +1566,38 @@ class BasicBlockGroupNode
15561566
15571567 llvm::SmallVector<llvm::BasicBlock*, 4 > visitNext;
15581568
1559- // Do the actual visit for start, while populating visitNext
1560- runVisitBasicBlock (data, *start, visitNext);
1561- for (llvm::BasicBlock* succ : visitNext)
1562- registerEdge (start, succ);
1569+ bool BBProgress = false ;
1570+ runVisitBasicBlock (data, *start, visitNext, BBProgress);
1571+ for (llvm::BasicBlock* succ : visitNext){
1572+ if (registerEdge (start, succ)){
1573+ BBProgress = true ;
1574+ }
1575+ }
15631576
1564- // First has been already done
1577+ // The first SCC (start) has already been visited
1578+ // This updates SCCProgress in case progress was made while visiting the start
1579+ if (BBProgress)
1580+ SCCProgress = true ;
15651581 childrenNodes.pop_back ();
15661582 while (!childrenNodes.empty ())
15671583 {
15681584 auto & child = childrenNodes.back ();
15691585 if (child.isReachable )
1570- child.recursiveVisit ();
1586+ {
1587+ // If childrenNodes size is 1, that means that we are visiting the copy of all basic blocks in the curret set of SCC
1588+ // Because the copy is reachable, it means that we are in a loop
1589+ // By this point we have run and visit all the SCC of a parent. If no progress was found there is no point to continue with the loop
1590+ if (childrenNodes.size () == 1 && !SCCProgress)
1591+ {
1592+ visitAll ();
1593+ return false ;
1594+ }
1595+ if (child.recursiveVisit ())
1596+ SCCProgress = true ;
1597+ }
15711598 childrenNodes.pop_back ();
15721599 }
1600+ return BBProgress;
15731601 }
15741602};
15751603
@@ -1633,7 +1661,7 @@ void FunctionData::actualVisit()
16331661 groupData.recursiveVisit ();
16341662}
16351663
1636- void PartialInterpreter::visitOuter (FunctionData& data, llvm::Instruction& I)
1664+ void PartialInterpreter::visitOuter (FunctionData& data, llvm::Instruction& I, bool & BBProgress )
16371665{
16381666 if (PHINode* phi = dyn_cast<PHINode>(&I))
16391667 {
@@ -1647,6 +1675,7 @@ void PartialInterpreter::visitOuter(FunctionData& data, llvm::Instruction& I)
16471675 if (isValueComputed (incomingVal))
16481676 {
16491677 computedPhisValues.push_back ({phi, incomingVal});
1678+ BBProgress = true ;
16501679 return ;
16511680 }
16521681 }
@@ -1721,7 +1750,7 @@ void PartialInterpreter::visitOuter(FunctionData& data, llvm::Instruction& I)
17211750 getTopCallFrame ().CurBB = next;
17221751 getTopCallFrame ().CurInst = getTopCallFrame ().CurBB ->begin ();
17231752
1724- // Also here we have set the proper state for the execution so we can return
1753+ BBProgress = true ;
17251754 return ;
17261755 }
17271756 skip = true ;
@@ -1742,7 +1771,7 @@ void PartialInterpreter::visitOuter(FunctionData& data, llvm::Instruction& I)
17421771 }
17431772 // If we are here it means we have to actually perform the execution via Interpreter
17441773
1745- // Iff it's a call, set up the next stack frame
1774+ // If it's a call, set up the next stack frame
17461775 if (CallInst* CI = dyn_cast<CallInst>(&I))
17471776 forwardArgumentsToNextFrame (*CI);
17481777
@@ -1752,7 +1781,10 @@ void PartialInterpreter::visitOuter(FunctionData& data, llvm::Instruction& I)
17521781 BitMask strongBits = computeStronglyKnownBits (I.getOpcode (), I);
17531782
17541783 if (isInitialCallFrame ())
1755- data.registerValueForInst (I, getOperandValue (&I), strongBits);
1784+ {
1785+ if (data.registerValueForInst (I, getOperandValue (&I), strongBits))
1786+ BBProgress = true ;
1787+ }
17561788
17571789 if (!isa<CallInst>(I))
17581790 {
0 commit comments