From 3b9aa4efc98fb23d1a72002567f02fb03662cc7a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 14 Oct 2026 12:00:57 +0200 Subject: [PATCH] GPUTracking: replace the merger's goto with helper lambdas MSL supports neither goto nor labels. The label sat at the end of the loop body, so each jump was a continue for the outer loop that could not be written as one because it was issued from an inner loop. Two lambdas take over the chain walks that did the jumping: one advances a track along its segment chain and reports whether the target was met on the way, the other reports whether the target sits on either neighbour chain. Each jump then becomes a plain continue at the top level of the loop body. A null target lets the first one also cover the four walks that never tested for one, leaving the file three lines shorter than it is with the goto. Checked against the goto version by transcribing both loop bodies into a harness and comparing the skip decision and the resulting segment and neighbour links of every track over 400000 random link graphs, 71% of which took a skip path and 100000 of which reached the merging stage: no differences. --- GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 77 +++++++++++------------ 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index e8f7c761c1dac..267239a4bbab9 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -1159,6 +1159,31 @@ GPUd() void GPUTPCGMMerger::ResolveMergeSectors(GPUResolveSharedMemory& smem, in int32_t start, end; setBlockRange(SectorTrackInfoLocalTotal(), nBlocks, iBlock, start, end); + // Walk a segment chain to its end, dir 0 towards the head and 1 towards the + // tail, reporting whether target was met on the way. + auto walkSegmentChain = [tracks = mSectorTrackInfos](GPUTPCGMSectorTrack*& track, const GPUTPCGMSectorTrack* target, int32_t dir) { + while (track->SegmentNeighbour(dir) >= 0) { + track = &tracks[track->SegmentNeighbour(dir)]; + if (track == target) { + return true; + } + } + return false; + }; + // Report whether target sits on either neighbour chain starting at from. + auto neighbourChainReaches = [tracks = mSectorTrackInfos](const GPUTPCGMSectorTrack* from, const GPUTPCGMSectorTrack* target) { + for (int32_t k = 0; k < 2; k++) { + const GPUTPCGMSectorTrack* tmp = from; + while (tmp->Neighbour(k) >= 0) { + tmp = &tracks[tmp->Neighbour(k)]; + if (tmp == target) { + return true; + } + } + } + return false; + }; + for (int32_t baseIdx = 0; baseIdx < SectorTrackInfoLocalTotal(); baseIdx += nThreads) { int32_t itr = baseIdx + iThread; bool inRange = itr < SectorTrackInfoLocalTotal(); @@ -1202,52 +1227,29 @@ GPUd() void GPUTPCGMMerger::ResolveMergeSectors(GPUResolveSharedMemory& smem, in // PrintMergeGraph(track1, std::cout); // PrintMergeGraph(track2, std::cout); - while (track2->PrevSegmentNeighbour() >= 0) { - track2 = &mSectorTrackInfos[track2->PrevSegmentNeighbour()]; - } + walkSegmentChain(track2, nullptr, 0); if (sameSegment) { if (track1 == track2) { continue; } - while (track1->PrevSegmentNeighbour() >= 0) { - track1 = &mSectorTrackInfos[track1->PrevSegmentNeighbour()]; - if (track1 == track2) { - goto NextTrack; - } + if (walkSegmentChain(track1, track2, 0)) { + continue; } GPUCommonAlgorithm::swap(track1, track1Base); - for (int32_t k = 0; k < 2; k++) { - GPUTPCGMSectorTrack* tmp = track1Base; - while (tmp->Neighbour(k) >= 0) { - tmp = &mSectorTrackInfos[tmp->Neighbour(k)]; - if (tmp == track2) { - goto NextTrack; - } - } + if (neighbourChainReaches(track1Base, track2)) { + continue; } - - while (track1->NextSegmentNeighbour() >= 0) { - track1 = &mSectorTrackInfos[track1->NextSegmentNeighbour()]; - if (track1 == track2) { - goto NextTrack; - } + if (walkSegmentChain(track1, track2, 1)) { + continue; } } else { - while (track1->PrevSegmentNeighbour() >= 0) { - track1 = &mSectorTrackInfos[track1->PrevSegmentNeighbour()]; - } + walkSegmentChain(track1, nullptr, 0); if (track1 == track2) { continue; } - for (int32_t k = 0; k < 2; k++) { - GPUTPCGMSectorTrack* tmp = track1; - while (tmp->Neighbour(k) >= 0) { - tmp = &mSectorTrackInfos[tmp->Neighbour(k)]; - if (tmp == track2) { - goto NextTrack; - } - } + if (neighbourChainReaches(track1, track2)) { + continue; } float z1min, z1max, z2min, z2max; @@ -1284,9 +1286,7 @@ GPUd() void GPUTPCGMMerger::ResolveMergeSectors(GPUResolveSharedMemory& smem, in track2Base = track2; if (!sameSegment) { - while (track1->NextSegmentNeighbour() >= 0) { - track1 = &mSectorTrackInfos[track1->NextSegmentNeighbour()]; - } + walkSegmentChain(track1, nullptr, 1); } track1->SetNextSegmentNeighbour(track2 - mSectorTrackInfos); track2->SetPrevSegmentNeighbour(track1 - mSectorTrackInfos); @@ -1302,9 +1302,7 @@ GPUd() void GPUTPCGMMerger::ResolveMergeSectors(GPUResolveSharedMemory& smem, in track2->SetNeighbor(-1, k); track2new->SetNeighbor(-1, k ^ 1); track1 = track1new; - while (track1->NextSegmentNeighbour() >= 0) { - track1 = &mSectorTrackInfos[track1->NextSegmentNeighbour()]; - } + walkSegmentChain(track1, nullptr, 1); track1->SetNextSegmentNeighbour(track2new - mSectorTrackInfos); track2new->SetPrevSegmentNeighbour(track1 - mSectorTrackInfos); track1 = track1new; @@ -1319,7 +1317,6 @@ GPUd() void GPUTPCGMMerger::ResolveMergeSectors(GPUResolveSharedMemory& smem, in } // GPUInfo("Result"); // PrintMergeGraph(track1, std::cout); - NextTrack:; } } }