Repository: dotnet/runtime
File: src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs (C#)

Code before:
                        // switch (currentBranch)
                        Ldloc(currentBranch);
                    }
                    Switch(labelMap);
                }

                // Successfully completed the alternate.
                MarkLabel(matchLabel);
                Debug.Assert(sliceStaticPos == 0);
            }

            // Tries to emit an alternation as a switch on the first character of each branch.
            // Returns true if the optimization was applied, false otherwise.
            bool TryEmitAlternationAsSwitch(RegexNode node, int childCount, bool isAtomic)
            {
                // Determine whether we can use switched branches.
                // We can't use switched branches if there's any possibility of backtracking into the alternation.
                bool canUseSwitchedBranches = isAtomic;
                if (!canUseSwitchedBranches)
                {
                    canUseSwitchedBranches = true;
                    for (int i = 0; i < childCount; i++)
                    {
                        if (analysis.MayBacktrack(node.Child(i)))
                        {
                            canUseSwitchedBranches = false;
                            break;
                        }
                    }
                }

                if (!canUseSwitchedBranches)
                {
                    return false;
                }

                // Detect whether every branch begins with one or more unique characters.
                const int SetCharsSize = 64; // arbitrary limit; we want it to be large enough to handle ignore-case of common sets, like hex, the latin alphabet, etc.
                Span<char> setChars = stackalloc char[SetCharsSize];
                var seenChars = new HashSet<char>();

                // Iterate through every branch, seeing if we can easily find a starting One, Multi, or small Set.
                // If we can, extract its starting char (or multiple in the case of a set), validate that all such
                // starting characters are unique relative to all the branches.
                for (int i = 0; i < childCount && canUseSwitchedBranches; i++)
                {
                    // Look for the guaranteed starting node that's a one, multi, set,
                    // or loop of one of those with at least one minimum iteration. We need to exclude notones.
                    if (node.Child(i).FindStartingLiteralNode(allowZeroWidth: false) is not RegexNode startingLiteralNode ||
                        startingLiteralNode.IsNotoneFamily)
                    {

Review comment (refactor):
@copilot, as you've created this separate TryEmitAlternationAsSwitch helper, instead of maintaining a canUseSwitchedBranches local, can you instead just return false anywhere you were setting it to false?

Code after:
                        // switch (currentBranch)
                        Ldloc(currentBranch);
                    }
                    Switch(labelMap);
                }

                // Successfully completed the alternate.
                MarkLabel(matchLabel);
                Debug.Assert(sliceStaticPos == 0);
            }

            // Tries to emit an alternation as a switch on the first character of each branch.
            // Returns true if the optimization was applied, false otherwise.
            bool TryEmitAlternationAsSwitch(RegexNode node, int childCount, bool isAtomic)
            {
                // We can't use switched branches if there's any possibility of backtracking into the alternation.
                if (!isAtomic)
                {
                    for (int i = 0; i < childCount; i++)
                    {
                        if (analysis.MayBacktrack(node.Child(i)))
                        {
                            return false;
                        }
                    }
                }

                // Detect whether every branch begins with one or more unique characters.
                if (!node.TryGetAlternationStartingChars(out HashSet<char>? seenChars))
                {
                    return false;
                }

                // Compute min/max to determine density for choosing IL switch vs comparisons
                int count = seenChars.Count;
                int minValue = int.MaxValue;
                int maxValue = int.MinValue;
                foreach (char c in seenChars)
                {
                    if (c < minValue) minValue = c;
                    if (c > maxValue) maxValue = c;
                }
                int range = maxValue - minValue + 1;

                // Use IL switch if dense enough (Roslyn's heuristic), otherwise use comparisons
                bool useILSwitch = count >= 3 && (double)count / range >= 0.5;

                // Emit switched branches.
                EmitSwitchedBranches(node, childCount, useILSwitch, minValue, range);
                return true;
            }