From c77a8f2cdfd26c894b39978228c2a1374e849ee3 Mon Sep 17 00:00:00 2001 From: BoyBaykiller Date: Sat, 13 Jun 2026 07:32:19 +0200 Subject: [PATCH 1/7] * process all sets at once * move return/throw block dedulplication to before tail merge * add partition impl, but don't use it yet --- src/coreclr/jit/fgopt.cpp | 233 +++++++++++++++++++------------------- 1 file changed, 115 insertions(+), 118 deletions(-) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 0fa08018b47007..b9ee2cb449f407 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -5056,6 +5056,38 @@ unsigned Compiler::fgMeasureIR() #endif // FEATURE_JIT_METHOD_PERF +template +void partition(Iterator first, Iterator last, Pred pred) +{ + while (true) + { + // Skip all left items which are already correct + while (first < last && pred(first)) + { + first++; + } + + if (first == last) + { + return first; + } + + // Predicate was false, the item is left but should be right! + // Find an item on the right which also needs swaping and swap them + do + { + --last; + if (first == last) + { + return first; + } + } while (!pred(last)); + + std::swap(*first, *last); + first++; + } +} + //------------------------------------------------------------------------ // fgHeadTailMerge: merge common sequences of statements in block predecessors/successors // @@ -5123,9 +5155,8 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) Statement* m_stmt; }; - ArrayStack predInfo(getAllocator(CMK_ArrayStack)); - ArrayStack matchedPredInfo(getAllocator(CMK_ArrayStack)); - ArrayStack retryBlocks(getAllocator(CMK_ArrayStack)); + jitstd::vector predInfo(getAllocator(CMK_ArrayStack)); + ArrayStack retryBlocks(getAllocator(CMK_ArrayStack)); auto tryRemoveAndFixFlow = [&](BasicBlock* emptyBlock, BasicBlock* newTarget) -> bool { assert(emptyBlock->isEmpty()); @@ -5154,13 +5185,15 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) // If return value is true, retry. // May also add to retryBlocks. // - auto tailMergePreds = [&](BasicBlock* commSucc) -> bool { + auto tailMergePreds = [&](BasicBlock* commSucc) -> int { + int optimizedCount = 0; + // Are there enough preds to make it interesting? // - if (predInfo.Height() < 2) + if (predInfo.size() < 2) { // Not enough preds to merge - return false; + return optimizedCount; } // If there are large numbers of viable preds, forgo trying to merge. @@ -5176,67 +5209,61 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) // multiple that avoids code-size regressions (measured via SPMI asmdiffs). // const int effectiveLimit = (commSucc != nullptr) ? mergeLimit : (4 * mergeLimit); - if (predInfo.Height() > effectiveLimit) + if (predInfo.size() > effectiveLimit) { // Too many preds to consider - return false; + return optimizedCount; } // Find a matching set of preds. Potentially O(N^2) tree comparisons. // - int i = 0; - while (i < (predInfo.Height() - 1)) + auto matchesEnd = predInfo.begin(); + while (matchesEnd < (predInfo.end() - 1)) { - matchedPredInfo.Reset(); - matchedPredInfo.Emplace(predInfo.TopRef(i)); - Statement* const baseStmt = predInfo.TopRef(i).m_stmt; - BasicBlock* const baseBlock = predInfo.TopRef(i).m_block; - - for (int j = i + 1; j < predInfo.Height(); j++) - { - BasicBlock* const otherBlock = predInfo.TopRef(j).m_block; + // Previous 'end' becomes new 'begin'. + auto matchesBegin = matchesEnd; + PredInfo candidateA = *matchesBegin; + // Find all matching candidates and partition them to + // be continous in memory at [matchesBegin, matchesEnd - 1] + // + matchesEnd = std::partition(matchesBegin + 1, predInfo.end(), [candidateA](PredInfo candidateB) { // Consider: bypass this for statements that can't cause exceptions. // - if (!BasicBlock::sameEHRegion(baseBlock, otherBlock)) + if (!BasicBlock::sameEHRegion(candidateA.m_block, candidateB.m_block)) { - continue; + return false; } - Statement* const otherStmt = predInfo.TopRef(j).m_stmt; - - // Consider: compute and cache hashes to make this faster - // - if (GenTree::Compare(baseStmt->GetRootNode(), otherStmt->GetRootNode())) - { - matchedPredInfo.Emplace(predInfo.TopRef(j)); - } - } + return GenTree::Compare(candidateA.m_stmt->GetRootNode(), candidateB.m_stmt->GetRootNode()); + }); - if (matchedPredInfo.Height() < 2) + int matchesCount = static_cast(std::distance(matchesBegin, matchesEnd)); + if (matchesCount < 2) { - // This pred didn't match any other. Check other preds for matches. - i++; continue; } + optimizedCount++; + madeChanges = true; + // We can move the identical last statements to commSucc, if it exists, // and all preds have matching last statements, and we're not changing EH behavior. // - bool const hasCommSucc = (commSucc != nullptr); - bool const predsInSameEHRegionAsSucc = hasCommSucc && BasicBlock::sameEHRegion(baseBlock, commSucc); - bool const canMergeAllPreds = hasCommSucc && (matchedPredInfo.Height() == (int)commSucc->countOfInEdges()); + bool const hasCommSucc = (commSucc != nullptr); + bool const predsInSameEHRegionAsSucc = + hasCommSucc && BasicBlock::sameEHRegion(candidateA.m_block, commSucc); + bool const canMergeAllPreds = hasCommSucc && (matchesCount == (int)commSucc->countOfInEdges()); bool const canMergeIntoSucc = predsInSameEHRegionAsSucc && canMergeAllPreds; if (canMergeIntoSucc) { - JITDUMP("All %d preds of " FMT_BB " end with the same tree, moving\n", matchedPredInfo.Height(), - commSucc->bbNum); - JITDUMPEXEC(gtDispStmt(matchedPredInfo.TopRef(0).m_stmt)); + JITDUMP("All %d preds of " FMT_BB " end with the same tree, moving\n", matchesCount, commSucc->bbNum); + JITDUMPEXEC(gtDispStmt(candidateA.m_stmt)); - for (int j = 0; j < matchedPredInfo.Height(); j++) + for (auto it = matchesBegin; it < matchesEnd; it++) { - PredInfo& info = matchedPredInfo.TopRef(j); + PredInfo info = *it; Statement* const stmt = info.m_stmt; BasicBlock* const predBlock = info.m_block; @@ -5246,22 +5273,16 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) { tryRemoveAndFixFlow(predBlock, commSucc); } - - // Add one of the matching stmts to block, and - // update its flags. - // - if (j == 0) - { - fgInsertStmtAtBeg(commSucc, stmt); - commSucc->CopyFlags(predBlock, BBF_COPY_PROPAGATE); - } - - madeChanges = true; } + // Add one of the matching stmts to commSucc, and update its flags. + fgInsertStmtAtBeg(commSucc, candidateA.m_stmt); + commSucc->CopyFlags(candidateA.m_block, BBF_COPY_PROPAGATE); + // It's worth retrying tail merge on this block. - // - return true; + retryBlocks.Push(commSucc); + + continue; } // All or a subset of preds have matching last stmt, we will cross-jump. @@ -5270,29 +5291,29 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) // if (predsInSameEHRegionAsSucc) { - JITDUMP("A subset of %d preds of " FMT_BB " end with the same tree\n", matchedPredInfo.Height(), - commSucc->bbNum); + JITDUMP("A subset of %d preds of " FMT_BB " end with the same tree\n", matchesCount, commSucc->bbNum); } else if (commSucc != nullptr) { JITDUMP("%s %d preds of " FMT_BB " end with the same tree but are in a different EH region\n", - canMergeAllPreds ? "All" : "A subset of", matchedPredInfo.Height(), commSucc->bbNum); + canMergeAllPreds ? "All" : "A subset of", matchesCount, commSucc->bbNum); } else { - JITDUMP("A set of %d return blocks end with the same tree\n", matchedPredInfo.Height()); + JITDUMP("A set of %d return blocks end with the same tree\n", matchesCount); } - JITDUMPEXEC(gtDispStmt(matchedPredInfo.TopRef(0).m_stmt)); + JITDUMPEXEC(gtDispStmt(candidateA.m_stmt)); BasicBlock* crossJumpVictim = nullptr; Statement* crossJumpStmt = nullptr; unsigned bestRank = UINT32_MAX; - for (PredInfo& info : matchedPredInfo.TopDownOrder()) + for (auto it = matchesBegin; it < matchesEnd; it++) { - Statement* const stmt = info.m_stmt; - BasicBlock* const predBlock = info.m_block; + PredInfo candidate = *it; + Statement* const stmt = candidate.m_stmt; + BasicBlock* const predBlock = candidate.m_block; // Never pick the init block as the victim as that would // cause us to add a predecessor to it, which is invalid. @@ -5357,17 +5378,17 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) // Do the cross jumping // - for (PredInfo& info : matchedPredInfo.TopDownOrder()) + for (auto it = matchesBegin; it < matchesEnd; it++) { - BasicBlock* const predBlock = info.m_block; - Statement* const stmt = info.m_stmt; + PredInfo candidate = *it; + BasicBlock* const predBlock = candidate.m_block; + Statement* const stmt = candidate.m_stmt; if (predBlock == crossJumpVictim) { continue; } - // remove the statement fgUnlinkStmt(predBlock, stmt); // Fix up the flow. @@ -5395,24 +5416,14 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) } } - // We changed things - // - madeChanges = true; - // We should try tail merging the cross jump target. - // - retryBlocks.Push(crossJumpTarget); - - // Continue trying to merge in the current block. - // This is a bit inefficient, we could remember how - // far we got through the pred list perhaps. - // - return true; + if (hasCommSucc) + { + retryBlocks.Push(crossJumpTarget); + } } - // We've looked at everything. - // - return false; + return optimizedCount; }; auto tailMerge = [&](BasicBlock* block) -> bool { @@ -5422,11 +5433,10 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) return false; } - predInfo.Reset(); - // Find the subset of preds that reach along non-critical edges // and populate predInfo. // + predInfo.clear(); for (BasicBlock* const predBlock : block->PredBlocks()) { if (predBlock->GetUniqueSucc() != block) @@ -5476,33 +5486,24 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) // We don't expect to see PHIs but watch for them anyways. // assert(!lastStmt->IsPhiDefnStmt()); - predInfo.Emplace(predBlock, lastStmt); - } - - return tailMergePreds(block); - }; - - auto iterateTailMerge = [&](BasicBlock* block) -> void { - int numOpts = 0; - - while (tailMerge(block)) - { - numOpts++; + predInfo.push_back(PredInfo{predBlock, lastStmt}); } + int numOpts = tailMergePreds(block); if (numOpts > 0) { JITDUMP("Did %d tail merges in " FMT_BB "\n", numOpts, block->bbNum); } - }; - ArrayStack retOrThrowBlocks(getAllocator(CMK_ArrayStack)); + return numOpts; + }; - // Visit each block + // Deduplicate RETURN/THROW blocks. + // This can enable tail-merging so do it first. // + predInfo.clear(); for (BasicBlock* const block : Blocks()) { - iterateTailMerge(block); if (block->isEmpty()) { continue; @@ -5510,7 +5511,7 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) if (block->KindIs(BBJ_THROW)) { - retOrThrowBlocks.Push(block); + predInfo.push_back(PredInfo{block, block->lastStmt()}); } else if (block->KindIs(BBJ_RETURN) && (block != genReturnBB)) { @@ -5527,31 +5528,27 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) } } - retOrThrowBlocks.Push(block); + predInfo.push_back(PredInfo{block, block->lastStmt()}); } } - - JITDUMP("Trying tail merge of return and throw blocks\n"); - do + int numOpts = tailMergePreds(nullptr); + if (numOpts > 0) { - predInfo.Reset(); - for (BasicBlock* const block : retOrThrowBlocks.BottomUpOrder()) - { - // If this block was already processed, skip it - // - if (!block->KindIs(BBJ_RETURN, BBJ_THROW) || block->isEmpty()) - { - continue; - } - predInfo.Push(PredInfo(block, block->lastStmt())); - } - } while (tailMergePreds(nullptr)); + JITDUMP("Deduplicated %d sets of return/throw blocks\n", numOpts); + } - // Work through any retries + // Visit each block // - while (retryBlocks.Height() > 0) + for (BasicBlock* const block : Blocks()) { - iterateTailMerge(retryBlocks.Pop()); + tailMerge(block); + + // Work through any retries + // + while (retryBlocks.Height() > 0) + { + tailMerge(retryBlocks.Pop()); + } } // Visit each block and try to merge first statements of successors. From a8dc6bc7cc83df172ea82c72cce25fab2460628e Mon Sep 17 00:00:00 2001 From: BoyBaykiller Date: Sat, 13 Jun 2026 16:29:49 +0200 Subject: [PATCH 2/7] * fix error C4018: '>': signed/unsigned mismatch --- src/coreclr/jit/fgopt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index b9ee2cb449f407..57a6cc2e6a5c60 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -5209,7 +5209,7 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) // multiple that avoids code-size regressions (measured via SPMI asmdiffs). // const int effectiveLimit = (commSucc != nullptr) ? mergeLimit : (4 * mergeLimit); - if (predInfo.size() > effectiveLimit) + if (predInfo.size() > static_cast(effectiveLimit)) { // Too many preds to consider return optimizedCount; From 5753921c60bbe847d98ef9e5dd50cd65899d11a0 Mon Sep 17 00:00:00 2001 From: BoyBaykiller Date: Sat, 13 Jun 2026 17:33:54 +0200 Subject: [PATCH 3/7] * use custom jitstd::partition * remove 'already processed' check as its no longer needed --- src/coreclr/jit/fgopt.cpp | 44 ++---------------------------- src/coreclr/jit/jitstd/algorithm.h | 35 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 57a6cc2e6a5c60..88bf6c91362139 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -7,7 +7,8 @@ #pragma hdrstop #endif -#include "lower.h" // for LowerRange() +#include "lower.h" // for LowerRange() +#include "jitstd/algorithm.h" // for partition() // Flowgraph Optimization @@ -5056,38 +5057,6 @@ unsigned Compiler::fgMeasureIR() #endif // FEATURE_JIT_METHOD_PERF -template -void partition(Iterator first, Iterator last, Pred pred) -{ - while (true) - { - // Skip all left items which are already correct - while (first < last && pred(first)) - { - first++; - } - - if (first == last) - { - return first; - } - - // Predicate was false, the item is left but should be right! - // Find an item on the right which also needs swaping and swap them - do - { - --last; - if (first == last) - { - return first; - } - } while (!pred(last)); - - std::swap(*first, *last); - first++; - } -} - //------------------------------------------------------------------------ // fgHeadTailMerge: merge common sequences of statements in block predecessors/successors // @@ -5227,7 +5196,7 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) // Find all matching candidates and partition them to // be continous in memory at [matchesBegin, matchesEnd - 1] // - matchesEnd = std::partition(matchesBegin + 1, predInfo.end(), [candidateA](PredInfo candidateB) { + matchesEnd = jitstd::partition(matchesBegin + 1, predInfo.end(), [candidateA](PredInfo candidateB) { // Consider: bypass this for statements that can't cause exceptions. // if (!BasicBlock::sameEHRegion(candidateA.m_block, candidateB.m_block)) @@ -5444,13 +5413,6 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) continue; } - // If this block was already processed, skip it - // - if (predBlock->isEmpty()) - { - continue; - } - Statement* lastStmt = predBlock->lastStmt(); // Block might be empty. diff --git a/src/coreclr/jit/jitstd/algorithm.h b/src/coreclr/jit/jitstd/algorithm.h index 3c1fc260068290..0fb913f74c1575 100644 --- a/src/coreclr/jit/jitstd/algorithm.h +++ b/src/coreclr/jit/jitstd/algorithm.h @@ -198,4 +198,39 @@ void sort(RandomAccessIterator first, RandomAccessIterator last, Less less) #endif // DEBUG } } + +// Reorders the elements in the range [first, last) in such a way that all elements for which the predicate returns true +// precede all elements for which predicate returns false. Relative order of the elements is not preserved. +// Returns the first element in the right group. Equivalent to std::partition. +template +Iterator partition(Iterator first, Iterator last, Pred pred) +{ + while (true) + { + // Skip all left items which are already correct + while (first < last && pred(*first)) + { + first++; + } + + if (first == last) + { + return first; + } + + // Predicate was false, the item is left but should be right! + // Find an item on the right which also needs swaping and swap them + do + { + --last; + if (first == last) + { + return first; + } + } while (!pred(*last)); + + std::swap(*first, *last); + first++; + } +} } From 56139e4b530ef30e5cfd68df4022389d04c54fcf Mon Sep 17 00:00:00 2001 From: BoyBaykiller Date: Sat, 13 Jun 2026 17:58:30 +0200 Subject: [PATCH 4/7] * dont use std::distance --- src/coreclr/jit/fgopt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 88bf6c91362139..69b9be85e30f0a 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -5207,7 +5207,7 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) return GenTree::Compare(candidateA.m_stmt->GetRootNode(), candidateB.m_stmt->GetRootNode()); }); - int matchesCount = static_cast(std::distance(matchesBegin, matchesEnd)); + int matchesCount = static_cast(matchesEnd - matchesBegin); if (matchesCount < 2) { continue; From 91edc353dcbbbba351ae0dd49495da2496737d5d Mon Sep 17 00:00:00 2001 From: BoyBaykiller Date: Sat, 13 Jun 2026 21:14:58 +0200 Subject: [PATCH 5/7] * try fix x86 tp --- src/coreclr/jit/fgopt.cpp | 16 ++++++++-------- src/coreclr/jit/jitstd/vector.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 69b9be85e30f0a..563fb3d8824aef 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -5196,7 +5196,7 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) // Find all matching candidates and partition them to // be continous in memory at [matchesBegin, matchesEnd - 1] // - matchesEnd = jitstd::partition(matchesBegin + 1, predInfo.end(), [candidateA](PredInfo candidateB) { + matchesEnd = std::partition(matchesBegin + 1, predInfo.end(), [candidateA](PredInfo candidateB) { // Consider: bypass this for statements that can't cause exceptions. // if (!BasicBlock::sameEHRegion(candidateA.m_block, candidateB.m_block)) @@ -5232,7 +5232,7 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) for (auto it = matchesBegin; it < matchesEnd; it++) { - PredInfo info = *it; + PredInfo& const info = *it; Statement* const stmt = info.m_stmt; BasicBlock* const predBlock = info.m_block; @@ -5280,9 +5280,9 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) for (auto it = matchesBegin; it < matchesEnd; it++) { - PredInfo candidate = *it; - Statement* const stmt = candidate.m_stmt; - BasicBlock* const predBlock = candidate.m_block; + PredInfo& const info = *it; + Statement* const stmt = info.m_stmt; + BasicBlock* const predBlock = info.m_block; // Never pick the init block as the victim as that would // cause us to add a predecessor to it, which is invalid. @@ -5349,9 +5349,9 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) // for (auto it = matchesBegin; it < matchesEnd; it++) { - PredInfo candidate = *it; - BasicBlock* const predBlock = candidate.m_block; - Statement* const stmt = candidate.m_stmt; + PredInfo& const info = *it; + BasicBlock* const predBlock = info.m_block; + Statement* const stmt = info.m_stmt; if (predBlock == crossJumpVictim) { diff --git a/src/coreclr/jit/jitstd/vector.h b/src/coreclr/jit/jitstd/vector.h index 17862714046504..1e059faa5d9ed9 100644 --- a/src/coreclr/jit/jitstd/vector.h +++ b/src/coreclr/jit/jitstd/vector.h @@ -33,7 +33,7 @@ class vector typedef T value_type; // nested classes - class iterator : public jitstd::iterator + class iterator : public jitstd::iterator { iterator(T* ptr); public: From 534ebffc815baeeadc56af4b22b35f01ddf09ffe Mon Sep 17 00:00:00 2001 From: BoyBaykiller Date: Sat, 13 Jun 2026 21:34:10 +0200 Subject: [PATCH 6/7] * fix 'const' position --- src/coreclr/jit/fgopt.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 563fb3d8824aef..d5e2e8cf9423a7 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -5232,7 +5232,7 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) for (auto it = matchesBegin; it < matchesEnd; it++) { - PredInfo& const info = *it; + const PredInfo& info = *it; Statement* const stmt = info.m_stmt; BasicBlock* const predBlock = info.m_block; @@ -5280,7 +5280,7 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) for (auto it = matchesBegin; it < matchesEnd; it++) { - PredInfo& const info = *it; + const PredInfo& info = *it; Statement* const stmt = info.m_stmt; BasicBlock* const predBlock = info.m_block; @@ -5349,7 +5349,7 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) // for (auto it = matchesBegin; it < matchesEnd; it++) { - PredInfo& const info = *it; + const PredInfo& info = *it; BasicBlock* const predBlock = info.m_block; Statement* const stmt = info.m_stmt; From 42a53d7705aeecca628361558027a622dd0b19a6 Mon Sep 17 00:00:00 2001 From: BoyBaykiller Date: Tue, 30 Jun 2026 01:02:48 +0200 Subject: [PATCH 7/7] * use custom partition again --- src/coreclr/jit/fgopt.cpp | 2 +- src/coreclr/jit/jitstd/vector.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index d5e2e8cf9423a7..7ab6a79b97e5bc 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -5196,7 +5196,7 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early) // Find all matching candidates and partition them to // be continous in memory at [matchesBegin, matchesEnd - 1] // - matchesEnd = std::partition(matchesBegin + 1, predInfo.end(), [candidateA](PredInfo candidateB) { + matchesEnd = partition(matchesBegin + 1, predInfo.end(), [candidateA](PredInfo candidateB) { // Consider: bypass this for statements that can't cause exceptions. // if (!BasicBlock::sameEHRegion(candidateA.m_block, candidateB.m_block)) diff --git a/src/coreclr/jit/jitstd/vector.h b/src/coreclr/jit/jitstd/vector.h index 1e059faa5d9ed9..17862714046504 100644 --- a/src/coreclr/jit/jitstd/vector.h +++ b/src/coreclr/jit/jitstd/vector.h @@ -33,7 +33,7 @@ class vector typedef T value_type; // nested classes - class iterator : public jitstd::iterator + class iterator : public jitstd::iterator { iterator(T* ptr); public: