Control Flow support for setting a merge point per thread

Required for simulations which do multiple simulation steps per control flow update and can diverge the tangle outside of the control flow and in this scenario need to set multiple merge points. A single merge point for the tangle is incorrect
This commit is contained in:
Jake Turner
2025-06-23 15:52:14 +01:00
parent e54e69650d
commit a6f6f31680
2 changed files with 51 additions and 1 deletions
+40 -1
View File
@@ -133,6 +133,18 @@ void Tangle::SetThreadExecutionPoint(ThreadIndex threadId, ExecutionPoint execPo
RDCASSERTMSG("Thread not found", threadId);
}
void Tangle::SetThreadMergePoint(ThreadIndex threadId, ExecutionPoint execPoint)
{
for(ThreadReference &threadRef : m_ThreadRefs)
{
if(threadRef.id == threadId)
{
threadRef.mergePoint = execPoint;
return;
}
}
}
void Tangle::SetThreadAlive(ThreadIndex threadId, bool value)
{
for(ThreadReference &threadRef : m_ThreadRefs)
@@ -197,6 +209,30 @@ void Tangle::PruneMergePoints(ExecutionPoint execPoint)
m_MergePoints.erase(index + 1, m_MergePoints.size() - index);
}
// Get the merge point from the threads in the tangle and add it to the merge point stack
void Tangle::AddMergePointFromThreads()
{
ExecutionPoint threadMergePoint = INVALID_EXECUTION_POINT;
size_t countNewMergePoints = 0;
for(ThreadReference &threadRef : m_ThreadRefs)
{
if(threadRef.mergePoint != INVALID_EXECUTION_POINT)
{
++countNewMergePoints;
if(threadMergePoint == INVALID_EXECUTION_POINT)
threadMergePoint = threadRef.mergePoint;
RDCASSERTEQUAL(threadMergePoint, threadRef.mergePoint);
threadRef.mergePoint = INVALID_EXECUTION_POINT;
}
}
if(threadMergePoint == INVALID_EXECUTION_POINT)
return;
RDCASSERTEQUAL(countNewMergePoints, m_ThreadRefs.size());
AddMergePoint(threadMergePoint);
}
// Define tangles to be entangled if the merge point stack of one tangle is contained within the other
bool Tangle::Entangled(const Tangle &other) const
{
@@ -236,7 +272,6 @@ TangleGroup ControlFlow::DivergeTangle(Tangle &tangle)
{
Tangle newTangle;
newTangle.SetId(GetNewTangleId());
newTangle.AddThreadReference(threadRef);
newTangle.SetMergePoints(tangle.GetMergePoints());
newTangle.SetFunctionReturnPoints(tangle.GetFunctionReturnPoints());
newTangle.SetDiverged(false);
@@ -244,12 +279,14 @@ TangleGroup ControlFlow::DivergeTangle(Tangle &tangle)
newTangle.SetActive(!tangle.IsConverged());
newTangle.SetAlive(true);
newTangle.SetStateChanged(true);
newTangle.AddThreadReference(threadRef);
newTangles.push_back(newTangle);
}
}
for(Tangle &newTangle : newTangles)
{
newTangle.AddMergePointFromThreads();
for(const ThreadReference &threadRef : newTangle.GetThreadRefs())
tangle.RemoveThreadReference(threadRef.id);
}
@@ -280,6 +317,8 @@ void ControlFlow::ProcessTangleDivergence()
tangle.CheckForDivergence();
if(tangle.IsDiverged())
newTangles.append(DivergeTangle(tangle));
else
tangle.AddMergePointFromThreads();
}
m_Tangles.append(newTangles);
+11
View File
@@ -45,6 +45,7 @@ const uint32_t INVALID_THREAD_INDEX = (uint32_t)-1;
struct ThreadReference
{
ExecutionPoint execPoint = INVALID_EXECUTION_POINT;
ExecutionPoint mergePoint = INVALID_EXECUTION_POINT;
ThreadIndex id = INVALID_THREAD_INDEX;
bool m_Alive = true;
};
@@ -69,12 +70,15 @@ public:
SetThreadAlive(threadId, false);
m_StateChanged = true;
}
void SetThreadMergePoint(ThreadIndex threadId, ExecutionPoint execPoint);
void AddMergePointFromThreads();
void AddMergePoint(ExecutionPoint execPoint)
{
// only add a new merge point
if(!m_MergePoints.contains(execPoint))
m_MergePoints.push_back(execPoint);
m_StateChanged = true;
ClearThreadMergePoints();
}
void AddFunctionReturnPoint(ExecutionPoint execPoint)
{
@@ -141,6 +145,11 @@ private:
m_StateChanged = true;
}
ExecutionPoint GetMergePoint() const { return m_MergePoints.back(); }
void ClearThreadMergePoints()
{
for(ThreadReference &threadRef : m_ThreadRefs)
threadRef.mergePoint = INVALID_EXECUTION_POINT;
}
void PopMergePoint(void)
{
m_MergePoints.pop_back();
@@ -151,11 +160,13 @@ private:
{
m_MergePoints.clear();
m_StateChanged = true;
ClearThreadMergePoints();
}
void SetMergePoints(const rdcarray<ExecutionPoint> &points)
{
m_MergePoints = points;
m_StateChanged = true;
ClearThreadMergePoints();
}
ExecutionPoint GetFunctionReturnPoint() const { return m_FunctionReturnPoints.back(); }
void PopFunctionReturnPoint(void)