@@ -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 {
@@ -634,7 +634,7 @@ class PartialInterpreter : public llvm::Interpreter {
634634 {
635635 return (++functionCounters[F] > 0x1000 );
636636 }
637- void visitOuter (FunctionData& data, llvm::Instruction& I);
637+ void visitOuter (FunctionData& data, llvm::Instruction& I, bool & BBProgress );
638638 bool replaceKnownCEs ()
639639 {
640640 if (fullyKnownCEs.empty ())
@@ -789,7 +789,7 @@ static void removeEdgeBetweenBlocks(llvm::BasicBlock* from, llvm::BasicBlock* to
789789 }
790790}
791791
792- llvm::BasicBlock* PartialInterpreter::visitBasicBlock (FunctionData& data, llvm::BasicBlock& BB)
792+ llvm::BasicBlock* PartialInterpreter::visitBasicBlock (FunctionData& data, llvm::BasicBlock& BB, bool & BBProgress )
793793{
794794 ExecutionContext& executionContext = getTopCallFrame ();
795795 executionContext.CurBB = &BB;
@@ -800,7 +800,7 @@ llvm::BasicBlock* PartialInterpreter::visitBasicBlock(FunctionData& data, llvm::
800800 // Note that here we could also execute a Call, and that implies adding a CallFrame
801801 // executing there (possibly also in depth)
802802 // So getTopCallFrame() has to be called since it will possibly change
803- visitOuter (data, *getTopCallFrame ().CurInst ++);
803+ visitOuter (data, *getTopCallFrame ().CurInst ++, BBProgress );
804804 }
805805
806806 // Find (if there are enough information) the next BB to be visited
@@ -993,9 +993,10 @@ class FunctionData
993993 assert (currentEE);
994994 return *currentEE;
995995 }
996- void registerEdge (const llvm::BasicBlock* from, const llvm::BasicBlock* to)
996+ bool registerEdge (const llvm::BasicBlock* from, const llvm::BasicBlock* to)
997997 {
998- visitedEdges.insert ({from, to});
998+ auto [it, is_inserted] = visitedEdges.insert ({from, to});
999+ return is_inserted;
9991000 }
10001001 bool hasNoInfo (const VectorOfArgs& arguments) const
10011002 {
@@ -1181,29 +1182,36 @@ class FunctionData
11811182 {
11821183 knownValues[&I].everSkipped = true ;
11831184 }
1184- void registerValueForInst (llvm::Instruction& I, const GenericValue& GV, PartialInterpreter::BitMask strongBits)
1185+ bool registerValueForInst (llvm::Instruction& I, const GenericValue& GV, PartialInterpreter::BitMask strongBits)
11851186 {
11861187 // Only support integers for now, to simplify the handling of GVs
11871188 if (!I.getType ()->isIntegerTy ())
1188- return ;
1189+ return false ;
11891190 // Do not attempt tracking of partially known values
11901191 if (strongBits != PartialInterpreter::BitMask::ALL)
1191- return markInstSkipped (I);
1192+ {
1193+ markInstSkipped (I);
1194+ return false ;
1195+ }
11921196 auto it = knownValues.find (&I);
11931197 if (it == knownValues.end ())
11941198 {
11951199 // Never registered any value before, save the current one
11961200 knownValues[&I].value = GV;
1201+ return true ;
11971202 }
11981203 else if (it->second .everSkipped )
11991204 {
12001205 // Nothing we can do anymore
1206+ return false ;
12011207 }
12021208 else if (it->second .value .IntVal != GV.IntVal )
12031209 {
12041210 // Different value observed, bailout
12051211 it->second .everSkipped = true ;
1212+ return false ;
12061213 }
1214+ return false ;
12071215 }
12081216 void replaceKnownValues () const
12091217 {
@@ -1374,6 +1382,7 @@ class BasicBlockGroupNode
13741382 const DeterministicBBSet& blocks;
13751383 bool isMultiHead;
13761384 bool isReachable;
1385+ bool SCCProgress;
13771386 llvm::BasicBlock* start;
13781387 llvm::BasicBlock* from;
13791388 uint32_t currIter;
@@ -1401,7 +1410,7 @@ class BasicBlockGroupNode
14011410 void splitIntoSCCs (std::list<BasicBlockGroupNode>& queueToBePopulated, ReverseMapBBToGroup& blockToGroupMap);
14021411public:
14031412 BasicBlockGroupNode (FunctionData& data, BasicBlockGroupNode* parentBBGNode, const DeterministicBBSet& OWNEDblocks, llvm::BasicBlock* start = nullptr )
1404- : parentNode(parentBBGNode), data(data), ownedBlocks(OWNEDblocks), blocks(ownedBlocks), isMultiHead(false ), isReachable(parentNode == nullptr ), start(start), from(nullptr ), visitingAll(false )
1413+ : parentNode(parentBBGNode), data(data), ownedBlocks(OWNEDblocks), blocks(ownedBlocks), isMultiHead(false ), isReachable(parentNode == nullptr ), SCCProgress( false ), start(start), from(nullptr ), visitingAll(false )
14051414 {
14061415 if (start)
14071416 assert (start->getParent () == data.getFunction ());
@@ -1411,7 +1420,7 @@ class BasicBlockGroupNode
14111420 {
14121421 }
14131422 BasicBlockGroupNode (BasicBlockGroupNode& BBGNode)
1414- : parentNode(&BBGNode), data(BBGNode.data), blocks(BBGNode.blocks), isMultiHead(false ), isReachable(false ), start(nullptr ), from(nullptr ), visitingAll(false )
1423+ : parentNode(&BBGNode), data(BBGNode.data), blocks(BBGNode.blocks), isMultiHead(false ), isReachable(false ), SCCProgress( false ), start(nullptr ), from(nullptr ), visitingAll(false )
14151424 {
14161425 }
14171426 void addIncomingEdge (llvm::BasicBlock* comingFrom, uint32_t currIter, llvm::BasicBlock* target)
@@ -1442,13 +1451,13 @@ class BasicBlockGroupNode
14421451 // Do the visit of the BB, with 'from' (possibly nullptr if unknown) as predecessor
14431452 // Loop backs will be directed to another BBgroup
14441453 // The visit will return the set of reachable BBs, to be added into visitNext
1445- void runVisitBasicBlock (FunctionData& data, llvm::BasicBlock& BB, llvm::SmallVectorImpl<llvm::BasicBlock*>& visitNext)
1454+ void runVisitBasicBlock (FunctionData& data, llvm::BasicBlock& BB, llvm::SmallVectorImpl<llvm::BasicBlock*>& visitNext, bool & BBProgress )
14461455 {
14471456 assert (visitNext.empty ());
14481457
14491458 PartialInterpreter& interpreter = data.getInterpreter ();
14501459 interpreter.incomingBB = from;
1451- BasicBlock* ret = interpreter.visitBasicBlock (data, BB);
1460+ BasicBlock* ret = interpreter.visitBasicBlock (data, BB, BBProgress );
14521461
14531462 if (ret)
14541463 {
@@ -1509,10 +1518,11 @@ class BasicBlockGroupNode
15091518 registerEdge (bb, succ);
15101519 }
15111520 }
1512- void registerEdge (llvm::BasicBlock* from, llvm::BasicBlock* to)
1521+ bool registerEdge (llvm::BasicBlock* from, llvm::BasicBlock* to)
15131522 {
1514- data.registerEdge (from, to);
1523+ bool is_inserted = data.registerEdge (from, to);
15151524 notifySuccessor (from, currIter, to);
1525+ return is_inserted;
15161526 }
15171527 void cleanUp (llvm::BasicBlock* block)
15181528 {
@@ -1525,14 +1535,14 @@ class BasicBlockGroupNode
15251535 }
15261536 }
15271537 // Visit the tree of BasicBlockGroupNodes, starting from the root and visiting children depth-first
1528- void recursiveVisit ()
1538+ bool recursiveVisit ()
15291539 {
15301540 if (isMultiHead)
15311541 {
15321542 // There are multiple BasicBlock that are reacheable from outside
15331543 // --> Mark everything as reachable
15341544 visitAll ();
1535- return ;
1545+ return false ;
15361546 }
15371547 assert (start); // isReachable && !isMultiHead implies start being defined
15381548 currIter = data.getVisitCounter (start);
@@ -1543,7 +1553,7 @@ class BasicBlockGroupNode
15431553 // Since terminability is basically unprovable in general, we give up with the visit
15441554 // --> Mark everything as reachable
15451555 visitAll ();
1546- return ;
1556+ return false ;
15471557 }
15481558 if (parentNode)
15491559 {
@@ -1559,20 +1569,38 @@ class BasicBlockGroupNode
15591569
15601570 llvm::SmallVector<llvm::BasicBlock*, 4 > visitNext;
15611571
1562- // Do the actual visit for start, while populating visitNext
1563- runVisitBasicBlock (data, *start, visitNext);
1564- for (llvm::BasicBlock* succ : visitNext)
1565- registerEdge (start, succ);
1572+ bool BBProgress = false ;
1573+ runVisitBasicBlock (data, *start, visitNext, BBProgress);
1574+ for (llvm::BasicBlock* succ : visitNext){
1575+ if (registerEdge (start, succ)){
1576+ BBProgress = true ;
1577+ }
1578+ }
15661579
1567- // First has been already done
1580+ // The first SCC (start) has already been visited
1581+ // This updates SCCProgress in case progress was made while visiting the start
1582+ if (BBProgress)
1583+ SCCProgress = true ;
15681584 childrenNodes.pop_back ();
15691585 while (!childrenNodes.empty ())
15701586 {
15711587 auto & child = childrenNodes.back ();
15721588 if (child.isReachable )
1573- child.recursiveVisit ();
1589+ {
1590+ // If childrenNodes size is 1, that means that we are visiting the copy of all basic blocks in the curret set of SCC
1591+ // Because the copy is reachable, it means that we are in a loop
1592+ // 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
1593+ if (childrenNodes.size () == 1 && !SCCProgress)
1594+ {
1595+ visitAll ();
1596+ return false ;
1597+ }
1598+ if (child.recursiveVisit ())
1599+ SCCProgress = true ;
1600+ }
15741601 childrenNodes.pop_back ();
15751602 }
1603+ return BBProgress;
15761604 }
15771605};
15781606
@@ -1636,7 +1664,7 @@ void FunctionData::actualVisit()
16361664 groupData.recursiveVisit ();
16371665}
16381666
1639- void PartialInterpreter::visitOuter (FunctionData& data, llvm::Instruction& I)
1667+ void PartialInterpreter::visitOuter (FunctionData& data, llvm::Instruction& I, bool & BBProgress )
16401668{
16411669 if (PHINode* phi = dyn_cast<PHINode>(&I))
16421670 {
@@ -1650,6 +1678,7 @@ void PartialInterpreter::visitOuter(FunctionData& data, llvm::Instruction& I)
16501678 if (isValueComputed (incomingVal))
16511679 {
16521680 computedPhisValues.push_back ({phi, incomingVal});
1681+ BBProgress = true ;
16531682 return ;
16541683 }
16551684 }
@@ -1724,7 +1753,7 @@ void PartialInterpreter::visitOuter(FunctionData& data, llvm::Instruction& I)
17241753 getTopCallFrame ().CurBB = next;
17251754 getTopCallFrame ().CurInst = getTopCallFrame ().CurBB ->begin ();
17261755
1727- // Also here we have set the proper state for the execution so we can return
1756+ BBProgress = true ;
17281757 return ;
17291758 }
17301759 skip = true ;
@@ -1745,7 +1774,7 @@ void PartialInterpreter::visitOuter(FunctionData& data, llvm::Instruction& I)
17451774 }
17461775 // If we are here it means we have to actually perform the execution via Interpreter
17471776
1748- // Iff it's a call, set up the next stack frame
1777+ // If it's a call, set up the next stack frame
17491778 if (CallInst* CI = dyn_cast<CallInst>(&I))
17501779 {
17511780 const Function* calledFunc = dyn_cast_or_null<Function>(cast<CallInst>(I).getCalledFunction ());
@@ -1772,7 +1801,10 @@ void PartialInterpreter::visitOuter(FunctionData& data, llvm::Instruction& I)
17721801 BitMask strongBits = computeStronglyKnownBits (I.getOpcode (), I);
17731802
17741803 if (isInitialCallFrame ())
1775- data.registerValueForInst (I, getOperandValue (&I), strongBits);
1804+ {
1805+ if (data.registerValueForInst (I, getOperandValue (&I), strongBits))
1806+ BBProgress = true ;
1807+ }
17761808
17771809 if (!isa<CallInst>(I))
17781810 {
0 commit comments