Skip to content

Commit 1aa2fd8

Browse files
authored
Tweak regex source gen for single char repeater (#118137)
This doesn't help with perf, it just makes the generated code a bit cleaner. Instead of e.g. ```C# if ((uint)slice.Length < 20) { return false; // The input didn't match. } if (slice.Slice(0, 20).ContainsAnyExceptInRange('a', 'c')) { return false; // The input didn't match. } ``` we'll now get: ```C# if ((uint)slice.Length < 20 || slice.Slice(0, 20).ContainsAnyExceptInRange('a', 'c')) { return false; // The input didn't match. } ```
1 parent 26d4886 commit 1aa2fd8

File tree

1 file changed

+14
-8
lines changed

1 file changed

+14
-8
lines changed

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

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4181,13 +4181,6 @@ void EmitSingleCharRepeater(RegexNode node, bool emitLengthCheck = true)
41814181
}
41824182
else
41834183
{
4184-
// if ((uint)(sliceStaticPos + iterations - 1) >= (uint)slice.Length) goto doneLabel;
4185-
if (emitLengthCheck)
4186-
{
4187-
EmitSpanLengthCheck(iterations);
4188-
writer.WriteLine();
4189-
}
4190-
41914184
// If we're able to vectorize the search, do so. Otherwise, fall back to a loop.
41924185
// For the loop, we're validating that each char matches the target node.
41934186
// For Contains{Any}, we're looking for the first thing that _doesn't_ match the target node,
@@ -4196,13 +4189,26 @@ void EmitSingleCharRepeater(RegexNode node, bool emitLengthCheck = true)
41964189
{
41974190
string containsExpr = indexOfExpr.Replace("IndexOf", "Contains");
41984191

4199-
using (EmitBlock(writer, $"if ({sliceSpan}.Slice({sliceStaticPos}, {iterations}).{containsExpr})"))
4192+
string condition = $"{sliceSpan}.Slice({sliceStaticPos}, {iterations}).{containsExpr}";
4193+
if (emitLengthCheck)
4194+
{
4195+
condition = $"{SpanLengthCheck(iterations)} || {condition}";
4196+
}
4197+
4198+
using (EmitBlock(writer, $"if ({condition})"))
42004199
{
42014200
Goto(doneLabel);
42024201
}
42034202
}
42044203
else
42054204
{
4205+
// if ((uint)(sliceStaticPos + iterations - 1) >= (uint)slice.Length) goto doneLabel;
4206+
if (emitLengthCheck)
4207+
{
4208+
EmitSpanLengthCheck(iterations);
4209+
writer.WriteLine();
4210+
}
4211+
42064212
string repeaterSpan = "repeaterSlice"; // As this repeater doesn't wrap arbitrary node emits, this shouldn't conflict with anything
42074213
writer.WriteLine($"ReadOnlySpan<char> {repeaterSpan} = {sliceSpan}.Slice({sliceStaticPos}, {iterations});");
42084214

0 commit comments

Comments
 (0)