From 01d65771c6802e80b17dd53f870170df51599458 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 16 Nov 2021 17:39:43 -0500 Subject: [PATCH 1/2] Remove some unnecessary slicing from generated Regex code When we're outputting code to match a "multi" (a sequence of multiple characters), we're currently issuing a Slice for the known tracked offset even if that offset is 0. We can skip that nop. --- .../gen/RegexGenerator.Emitter.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs index 734f3509f3843..52eaac5c9a2d4 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs @@ -1529,7 +1529,8 @@ void EmitOr() while (byteStr.Length >= sizeof(ulong)) { EmitOr(); - writer.Write($"global::System.Buffers.Binary.BinaryPrimitives.ReadUInt64LittleEndian(byteSpan.Slice({textSpanPos * sizeof(char)})) != 0x{BinaryPrimitives.ReadUInt64LittleEndian(byteStr):X}ul"); + string byteSpan = textSpanPos > 0 ? $"byteSpan.Slice({textSpanPos * sizeof(char)})" : "byteSpan"; + writer.Write($"global::System.Buffers.Binary.BinaryPrimitives.ReadUInt64LittleEndian({byteSpan}) != 0x{BinaryPrimitives.ReadUInt64LittleEndian(byteStr):X}ul"); textSpanPos += sizeof(ulong) / sizeof(char); byteStr = byteStr.Slice(sizeof(ulong)); } @@ -1537,7 +1538,8 @@ void EmitOr() while (byteStr.Length >= sizeof(uint)) { EmitOr(); - writer.Write($"global::System.Buffers.Binary.BinaryPrimitives.ReadUInt32LittleEndian(byteSpan.Slice({textSpanPos * sizeof(char)})) != 0x{BinaryPrimitives.ReadUInt32LittleEndian(byteStr):X}u"); + string byteSpan = textSpanPos > 0 ? $"byteSpan.Slice({textSpanPos * sizeof(char)})" : "byteSpan"; + writer.Write($"global::System.Buffers.Binary.BinaryPrimitives.ReadUInt32LittleEndian({byteSpan}) != 0x{BinaryPrimitives.ReadUInt32LittleEndian(byteStr):X}u"); textSpanPos += sizeof(uint) / sizeof(char); byteStr = byteStr.Slice(sizeof(uint)); } @@ -1565,7 +1567,8 @@ void EmitOr() // character-by-character while respecting the culture. if (!caseInsensitive) { - using (EmitBlock(writer, $"if (!global::System.MemoryExtensions.StartsWith({textSpanLocal}.Slice({textSpanPos}), {Literal(node.Str)}))")) + string sourceSpan = textSpanPos > 0 ? $"{textSpanLocal}.Slice({textSpanPos})" : textSpanLocal; + using (EmitBlock(writer, $"if (!global::System.MemoryExtensions.StartsWith({sourceSpan}, {Literal(node.Str)}))")) { writer.WriteLine($"goto {doneLabel};"); } From e5f319edc8f6e1f2deafaf232acf984b77bd4b20 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 16 Nov 2021 22:05:35 -0500 Subject: [PATCH 2/2] Address PR feedback --- .../gen/RegexGenerator.Emitter.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs index 52eaac5c9a2d4..46eb36b7fe511 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs @@ -1580,7 +1580,8 @@ void EmitOr() string i = NextLocalName("i"); using (EmitBlock(writer, $"for (int {i} = 0; {i} < {Literal(node.Str)}.Length; {i}++)")) { - using (EmitBlock(writer, $"if ({ToLower(hasTextInfo, options, $"{textSpanLocal}[{textSpanPos} + {i}]")} != {Literal(str)}[{i}])")) + string textSpanIndex = textSpanPos > 0 ? $"{i} + {textSpanPos}" : i; + using (EmitBlock(writer, $"if ({ToLower(hasTextInfo, options, $"{textSpanLocal}[{textSpanIndex}]")} != {Literal(str)}[{i}])")) { writer.WriteLine($"goto {doneLabel};"); }