Skip to content

Commit

Permalink
List.contains - change in order to inline + typespecialize (#15726)
Browse files Browse the repository at this point in the history
  • Loading branch information
T-Gro authored Aug 2, 2023
1 parent 681069f commit b680d3c
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/FSharp.Core/list.fs
Original file line number Diff line number Diff line change
Expand Up @@ -453,10 +453,13 @@ module List =

[<CompiledName("Contains")>]
let inline contains value source =
let equalityCheck listElement =
value = listElement

let rec contains e xs1 =
match xs1 with
| [] -> false
| h1 :: t1 -> e = h1 || contains e t1
| h1 :: t1 -> equalityCheck h1 || contains e t1

contains value source

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,56 @@ module Inlining =
let ``StructUnion01_fs`` compilation =
compilation
|> verifyCompilation


[<Fact>]
let ``List contains inlining`` () =
Fsx """module Test
let data = [nanf |> float;5.0;infinity]
let found = data |> List.contains nan
"""
|> asExe
|> compile
(* This is the essential aspect of the IL we are interested in - doing a direct specialized 'ceq' on primitive values, and not going via a GenericEqualityIntrinsic call*)
|> verifyIL ["""
.method assembly static bool contains@1<a>(!!a e,
class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<float64> xs1) cil managed
{
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 4
.locals init (class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<float64> V_0,
class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<float64> V_1,
float64 V_2)
IL_0000: ldarg.1
IL_0001: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<float64>::get_TailOrNull()
IL_0006: brfalse.s IL_000a
IL_0008: br.s IL_000c
IL_000a: ldc.i4.0
IL_000b: ret
IL_000c: ldarg.1
IL_000d: stloc.0
IL_000e: ldloc.0
IL_000f: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<float64>::get_TailOrNull()
IL_0014: stloc.1
IL_0015: ldloc.0
IL_0016: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<float64>::get_HeadOrDefault()
IL_001b: stloc.2
IL_001c: ldc.r8 (00 00 00 00 00 00 F8 FF)
IL_0025: ldloc.2
IL_0026: ceq
IL_0028: brfalse.s IL_002c
IL_002a: ldc.i4.1
IL_002b: ret
IL_002c: ldarg.0
IL_002d: ldloc.1
IL_002e: starg.s xs1
IL_0030: starg.s e
IL_0032: br.s IL_0000
}"""]

Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,18 @@ type ListModule() =
let resultStr = List.contains "....." strList
Assert.False(resultStr)

// float List
let flList = [nan;infinity;5.0;-0.]
Assert.False(List.contains nan flList)
Assert.False(List.contains 4.99 flList)
Assert.True(List.contains infinity flList)
Assert.True(List.contains 0. flList)

let flTupleList = [(nan,"text");(5.0,"wait")]
Assert.False(List.contains (nan,"text") flTupleList)
Assert.False(List.contains (5.0,"text") flTupleList)
Assert.True(List.contains (5.0,"wait") flTupleList)

// empty List
let emptyList:int list = [ ]
let resultEpt = List.contains 4 emptyList
Expand Down

0 comments on commit b680d3c

Please sign in to comment.