RyuJIT: Optimize simple comparisons into branchless expressions by EgorBo · Pull Request #32716 · dotnet/runtime (original) (raw)

This PR optimizes simple conditions (BBJ_COND + two BBJ_RETURN) into a single branchless BBJ_RETURN block
image

E.g.

The new codegen is branchless and is more compact. In theory, it can be slower in some benchmarks where we constantly take the same branch over and over and the branch-prediction + speculative execution may perform better but it seems GCC doesn't really care. If you want I can add a sort of "IsHotBlock" check (if it makes sense with the current PGO state)

Found 52 files with textual diffs.

Summary of Code Size diffs:
(Lower is better)

Total bytes of diff: -3419 (-0.01% of base)
    diff is an improvement.

Top file improvements (bytes):
        -933 : System.Private.CoreLib.dasm (-0.02% of base)
        -396 : Microsoft.CodeAnalysis.CSharp.dasm (-0.01% of base)
        -348 : System.Data.Common.dasm (-0.02% of base)
        -251 : System.Private.Xml.dasm (-0.01% of base)
        -126 : System.Linq.Parallel.dasm (-0.01% of base)
        -121 : System.Linq.Expressions.dasm (-0.02% of base)
        -115 : System.DirectoryServices.dasm (-0.03% of base)
         -86 : System.Reflection.MetadataLoadContext.dasm (-0.05% of base)
         -80 : System.Management.dasm (-0.02% of base)
         -75 : Newtonsoft.Json.dasm (-0.01% of base)
         -70 : System.Threading.Channels.dasm (-0.04% of base)
         -65 : System.Collections.dasm (-0.01% of base)
         -52 : Microsoft.CSharp.dasm (-0.02% of base)
         -50 : System.Net.WebSockets.WebSocketProtocol.dasm (-0.12% of base)
         -44 : System.ComponentModel.TypeConverter.dasm (-0.01% of base)
         -40 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (-0.00% of base)
         -39 : System.Security.Principal.Windows.dasm (-0.08% of base)
         -38 : Microsoft.CodeAnalysis.dasm (-0.00% of base)
         -35 : System.Reflection.Metadata.dasm (-0.01% of base)
         -32 : Microsoft.CodeAnalysis.VisualBasic.dasm (-0.00% of base)

52 total files with Code Size differences (52 improved, 0 regressed), 108 unchanged.

Top method improvements (bytes):
         -50 (-2.38% of base) : System.Net.WebSockets.WebSocketProtocol.dasm - <WaitForServerToCloseConnectionAsync>d__64:MoveNext():this
         -36 (-2.81% of base) : System.Private.CoreLib.dasm - System.Globalization.CompareInfo:Compare(System.String,System.String,int):int:this (2 methods)
         -32 (-8.82% of base) : System.Private.CoreLib.dasm - System.Collections.Generic.Comparer`1[Vector`1][System.Numerics.Vector`1[System.Single]]:System.Collections.IComparer.Compare(System.Object,System.Object):int:this
         -22 (-7.97% of base) : System.Data.Common.dasm - System.Data.DataColumn:CompareValueTo(int,System.Object,bool):bool:this
         -22 (-17.60% of base) : System.Private.CoreLib.dasm - System.Globalization.HijriCalendar:GetDaysInMonth(int,int,int):int:this
         -20 (-2.74% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Serialization.JsonSerializerInternalReader:SetPropertyValue(Newtonsoft.Json.Serialization.JsonProperty,Newtonsoft.Json.JsonConverter,Newtonsoft.Json.Serialization.JsonContainerContract,Newtonsoft.Json.Serialization.JsonProperty,Newtonsoft.Json.JsonReader,System.Object):bool:this
         -20 (-2.99% of base) : System.Private.CoreLib.dasm - System.DateTimeParse:MatchTimeMark(byref,System.Globalization.DateTimeFormatInfo,byref):bool
         -19 (-4.22% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.Semantics.ExpressionBinder:CompareTypes(Microsoft.CSharp.RuntimeBinder.Semantics.TypeArray,Microsoft.CSharp.RuntimeBinder.Semantics.TypeArray):int
         -19 (-7.36% of base) : System.Private.CoreLib.dasm - System.DefaultBinder:FindMostSpecificMethod(System.Reflection.MethodBase,System.Int32[],System.Type,System.Reflection.MethodBase,System.Int32[],System.Type,System.Type[],System.Object[]):int
         -19 (-6.53% of base) : System.Private.CoreLib.dasm - System.Collections.Generic.Comparer`1[Double][System.Double]:System.Collections.IComparer.Compare(System.Object,System.Object):int:this
         -19 (-7.66% of base) : System.Reflection.MetadataLoadContext.dasm - System.DefaultBinder:FindMostSpecificMethod(System.Reflection.MethodBase,System.Int32[],System.Type,System.Reflection.MethodBase,System.Int32[],System.Type,System.Type[],System.Object[]):int
         -18 (-3.48% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CodeGen.StackOptimizerPass1:IsNestedLocalOfCompoundOperator(Microsoft.CodeAnalysis.CSharp.Symbols.LocalSymbol,Microsoft.CodeAnalysis.CSharp.BoundSequence):bool:this
         -18 (-1.26% of base) : System.Private.CoreLib.dasm - System.Globalization.CompareInfo:IndexOf(System.String,System.String,int,int,int):int:this (2 methods)
         -18 (-1.81% of base) : System.Private.CoreLib.dasm - System.String:LastIndexOf(System.String,int,int,int):int:this
         -18 (-6.25% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.CustomMarshalers.EnumVariantViewOfEnumerator:Next(int,System.Object[],long):int:this
         -18 (-3.99% of base) : System.Private.Xml.dasm - System.Xml.Schema.SchemaCollectionCompiler:IsGroupBaseFromGroupBase(System.Xml.Schema.XmlSchemaGroupBase,System.Xml.Schema.XmlSchemaGroupBase,bool):bool:this
         -16 (-3.77% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.Symbols.SourceMemberContainerTypeSymbol:DoOperatorsPair(Microsoft.CodeAnalysis.CSharp.Symbols.MethodSymbol,Microsoft.CodeAnalysis.CSharp.Symbols.MethodSymbol):bool
         -15 (-2.50% of base) : System.Data.Common.dasm - System.Data.Common.DateTimeOffsetStorage:CompareValueTo(int,System.Object):int:this
         -14 (-6.90% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.ConversionsBase:HasImplicitConversionFromDelegate(Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol,Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol,byref):bool:this
         -14 (-5.34% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.Symbols.AssemblySymbol:PerformIVTCheck(System.Collections.Immutable.ImmutableArray`1[Byte],Microsoft.CodeAnalysis.AssemblyIdentity):int:this

Top method improvements (percentages):
          -5 (-31.25% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.ThreeStateHelpers:ToThreeState(bool):ubyte
          -4 (-30.77% of base) : System.Private.CoreLib.dasm - System.Convert:ToInt32(bool):int
          -4 (-30.77% of base) : System.Private.CoreLib.dasm - System.Convert:ToUInt32(bool):int
          -4 (-30.77% of base) : System.Private.CoreLib.dasm - System.Convert:ToUInt16(bool):ushort
          -4 (-30.77% of base) : System.Private.CoreLib.dasm - System.Convert:ToByte(bool):ubyte
          -4 (-30.77% of base) : System.Private.CoreLib.dasm - System.Convert:ToInt16(bool):short
          -4 (-30.77% of base) : System.Private.CoreLib.dasm - System.Convert:ToSByte(bool):byte
          -4 (-30.77% of base) : System.Private.Xml.dasm - System.Xml.Xsl.XPathConvert:NotZero(int):int
          -4 (-28.57% of base) : System.Private.CoreLib.dasm - System.Boolean:GetHashCode():int:this
          -4 (-28.57% of base) : System.Private.CoreLib.dasm - System.Threading.SpinWait:get_NextSpinWillYield():bool:this
          -5 (-27.78% of base) : Microsoft.CodeAnalysis.dasm - VersionResourceSerializer:get_FileType():int:this
          -9 (-27.27% of base) : System.Linq.Expressions.dasm - System.Linq.Expressions.Compiler.LambdaCompiler:EmitExpressionStart(System.Linq.Expressions.Expression):int:this
          -4 (-26.67% of base) : Microsoft.CSharp.dasm - BinOpFullSig:isLifted():bool:this
          -4 (-26.67% of base) : Microsoft.CSharp.dasm - UnaOpFullSig:isLifted():bool:this
          -4 (-26.67% of base) : System.ComponentModel.Composition.dasm - System.ComponentModel.Composition.ImportAttribute:System.ComponentModel.Composition.IAttributedImport.get_Cardinality():int:this
          -4 (-26.67% of base) : System.ComponentModel.TypeConverter.dasm - FilterCacheItem:IsValid(System.ComponentModel.Design.ITypeDescriptorFilterService):bool:this
          -4 (-26.67% of base) : System.Data.Common.dasm - System.Data.LookupNode:DependsOn(System.Data.DataColumn):bool:this
          -8 (-26.67% of base) : System.Data.Common.dasm - System.Data.Common.ADP:SrcCompare(System.String,System.String):int
          -8 (-26.67% of base) : System.Data.OleDb.dasm - System.Data.Common.ADP:SrcCompare(System.String,System.String):int
          -8 (-26.67% of base) : System.Diagnostics.TraceSource.dasm - System.Diagnostics.BooleanSwitch:get_Enabled():bool:this

406 total methods with Code Size differences (406 improved, 0 regressed), 304680 unchanged.

and the jit-diff already looks promising, I think the GT_ASG ones should produce even bigger diffs.