Skip to content

Commit 53ed08b

Browse files
authored
Simplify code emitted for single char repeater (#62322)
Rather than outputting an if block per unrolled iteration, just output a clause for each iteration as part of a single if block. We already do this for concatenations, but we don't yet for standalone repeaters.
1 parent 42224c6 commit 53ed08b

File tree

1 file changed

+27
-10
lines changed

1 file changed

+27
-10
lines changed

src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2483,25 +2483,42 @@ void EmitSingleCharFixedRepeater(RegexNode node, bool emitLengthCheck = true)
24832483
return;
24842484
}
24852485

2486-
// if ((uint)(textSpanPos + iterations - 1) >= (uint)textSpan.Length) goto doneLabel;
2487-
if (emitLengthCheck)
2488-
{
2489-
EmitSpanLengthCheck(iterations);
2490-
}
2491-
24922486
if (iterations <= MaxUnrollSize)
24932487
{
2494-
// if (textSpan[textSpanPos] != c1 ||
2488+
// if ((uint)(textSpanPos + iterations - 1) >= (uint)textSpan.Length ||
2489+
// textSpan[textSpanPos] != c1 ||
24952490
// textSpan[textSpanPos + 1] != c2 ||
24962491
// ...)
2497-
// goto doneLabel;
2498-
for (int i = 0; i < iterations; i++)
2492+
// {
2493+
// goto doneLabel;
2494+
// }
2495+
writer.Write($"if (");
2496+
if (emitLengthCheck)
24992497
{
2500-
EmitSingleChar(node, emitLengthCheck: false);
2498+
writer.WriteLine($"{SpanLengthCheck(iterations)} ||");
2499+
writer.Write(" ");
2500+
}
2501+
EmitSingleChar(node, emitLengthCheck: false, clauseOnly: true);
2502+
for (int i = 1; i < iterations; i++)
2503+
{
2504+
writer.WriteLine(" ||");
2505+
writer.Write(" ");
2506+
EmitSingleChar(node, emitLengthCheck: false, clauseOnly: true);
2507+
}
2508+
writer.WriteLine(")");
2509+
using (EmitBlock(writer, null))
2510+
{
2511+
writer.WriteLine($"goto {doneLabel};");
25012512
}
25022513
}
25032514
else
25042515
{
2516+
// if ((uint)(textSpanPos + iterations - 1) >= (uint)textSpan.Length) goto doneLabel;
2517+
if (emitLengthCheck)
2518+
{
2519+
EmitSpanLengthCheck(iterations);
2520+
}
2521+
25052522
string spanLocal = "slice"; // As this repeater doesn't wrap arbitrary node emits, this shouldn't conflict with anything
25062523
writer.WriteLine($"global::System.ReadOnlySpan<char> {spanLocal} = {textSpanLocal}.Slice({textSpanPos}, {iterations});");
25072524
string i = ReserveName("charrepeater_iteration");

0 commit comments

Comments
 (0)