diff --git a/src/Compiler/Optimize/InnerLambdasToTopLevelFuncs.fs b/src/Compiler/Optimize/InnerLambdasToTopLevelFuncs.fs index f03db8f5e6f..480c98e95ec 100644 --- a/src/Compiler/Optimize/InnerLambdasToTopLevelFuncs.fs +++ b/src/Compiler/Optimize/InnerLambdasToTopLevelFuncs.fs @@ -196,8 +196,8 @@ module Pass1_DetermineTLRAndArities = let arity = Operators.min nFormals nMaxApplied if atTopLevel then Some (f, arity) - elif g.realsig then - None + //elif g.realsig then + // None else if arity<>0 || not (isNil tps) then Some (f, arity) else @@ -217,20 +217,24 @@ module Pass1_DetermineTLRAndArities = let DetermineTLRAndArities g expr = let xinfo = GetUsageInfoOfImplFile g expr - let fArities = Zmap.chooseL (SelectTLRVals g xinfo) xinfo.Defns - let fArities = List.filter (fst >> IsValueRecursionFree xinfo) fArities - // Do not TLR v if it is bound under a shouldinline defn - // There is simply no point - the original value will be duplicated and TLR'd anyway - let rejectS = GetValsBoundUnderShouldInline xinfo - let fArities = List.filter (fun (v, _) -> not (Zset.contains v rejectS)) fArities - (*-*) - let tlrS = Zset.ofList valOrder (List.map fst fArities) - let topValS = xinfo.TopLevelBindings (* genuinely top level *) - let topValS = Zset.filter (IsMandatoryNonTopLevel g >> not) topValS (* restrict *) + let rejects = GetValsBoundUnderShouldInline xinfo + let fArities = + xinfo.Defns + |> Zmap.chooseL (SelectTLRVals g xinfo) + |> List.filter (fst >> IsValueRecursionFree xinfo) + // Do not TLR v if it is bound under a shouldinline defn + // There is simply no point - the original value will be duplicated and TLR'd anyway + |> List.filter (fun (v, _) -> not (Zset.contains v rejects)) + + let tlrs = Zset.ofList valOrder (List.map fst fArities) + let topVals = + xinfo.TopLevelBindings // genuinely top level *) + |> Zset.filter (IsMandatoryNonTopLevel g >> not) // restrict + #if DEBUG (* REPORT MISSED CASES *) if verboseTLR then - let missed = Zset.diff xinfo.TopLevelBindings tlrS + let missed = Zset.diff xinfo.TopLevelBindings tlrs missed |> Zset.iter (fun v -> dprintf "TopLevel but not TLR = %s\n" v.LogicalName) (* REPORT OVER *) #endif @@ -238,7 +242,7 @@ module Pass1_DetermineTLRAndArities = #if DEBUG if verboseTLR then DumpArity arityM #endif - tlrS, topValS, arityM + tlrs, topVals, arityM (* NOTES: For constants, @@ -760,7 +764,6 @@ let FlatEnvPacks g fclassM topValS declist (reqdItemsMap: Zmap List.map (fun (v, aenv) -> mkInvisibleBind aenv (exprForVal env.m v)) let unpack = @@ -785,7 +788,7 @@ let FlatEnvPacks g fclassM topValS declist (reqdItemsMap: Zmap match expr with diff --git a/src/Compiler/TypedTree/TypedTreeBasics.fs b/src/Compiler/TypedTree/TypedTreeBasics.fs index 582d6767d7e..9101c33f322 100644 --- a/src/Compiler/TypedTree/TypedTreeBasics.fs +++ b/src/Compiler/TypedTree/TypedTreeBasics.fs @@ -196,7 +196,7 @@ let mkTyparTy (tp:Typar) = // For fresh type variables clear the StaticReq when copying because the requirement will be re-established through the // process of type inference. -let copyTypar clearStaticReq (tp: Typar) = +let copyTypar clearStaticReq (tp: Typar) = let optData = tp.typar_opt_data |> Option.map (fun tg -> { typar_il_name = tg.typar_il_name; typar_xmldoc = tg.typar_xmldoc; typar_constraints = tg.typar_constraints; typar_attribs = tg.typar_attribs; typar_is_contravariant = tg.typar_is_contravariant }) let flags = if clearStaticReq then tp.typar_flags.WithStaticReq(TyparStaticReq.None) else tp.typar_flags Typar.New { typar_id = tp.typar_id diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Inlining.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Inlining.fs index d226b4dc25f..27480c84e27 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Inlining.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Inlining.fs @@ -34,6 +34,18 @@ module Inlining = |> getCompilation |> verifyCompilation + [] + let ``Mutually recursive inner let - regression 17607 - realsig off`` compilation = + compilation + |> withRealInternalSignatureOff + |> verifyCompilation + + [] + let ``Mutually recursive inner let - regression 17607 - real sig on`` compilation = + compilation + |> withRealInternalSignatureOn + |> verifyCompilation + // SOURCE=StructUnion01.fs SCFLAGS="-a --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd StructUnion01.dll" # StructUnion01.fs [] let ``StructUnion01_fs`` compilation = diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Regression17607.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Regression17607.fs new file mode 100644 index 00000000000..515819c19af --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Regression17607.fs @@ -0,0 +1,31 @@ +open System +open System.Diagnostics + + +// Will create a tail il instruction and force a tail call. This is will become +// a fast tail call on unix x64 as the caller and callee have equal stack size +let fifth() = + let rec fifthMethodFirstCallee(iterationCount, firstArg: int) = + if iterationCount = 0 then + 100 + else if iterationCount % 2 = 0 then + fifthMethodSecondCallee(iterationCount - 1, firstArg) + else + fifthMethodFirstCallee(iterationCount - 1, firstArg) + + and fifthMethodSecondCallee(iterationCount, firstArg) = + if iterationCount = 0 then + 101 + else if iterationCount % 2 = 0 then + fifthMethodSecondCallee(iterationCount - 1, firstArg) + else + fifthMethodFirstCallee(iterationCount - 1, firstArg) + + + + fifthMethodFirstCallee(1000000, 158_423) + + +[] +let main argv = + fifth () \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Regression17607.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Regression17607.fs.il.bsl new file mode 100644 index 00000000000..0b2e90bbfe9 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Regression17607.fs.il.bsl @@ -0,0 +1,142 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + + + + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module assembly.exe + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .method assembly static int32 fifthMethodFirstCallee@8(int32 iterationCount, + int32 firstArg) cil managed + { + + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: brtrue.s IL_0007 + + IL_0004: ldc.i4.s 100 + IL_0006: ret + + IL_0007: nop + IL_0008: ldarg.0 + IL_0009: ldc.i4.2 + IL_000a: rem + IL_000b: brtrue.s IL_0019 + + IL_000d: ldarg.0 + IL_000e: ldc.i4.1 + IL_000f: sub + IL_0010: ldarg.1 + IL_0011: tail. + IL_0013: call int32 assembly::fifthMethodSecondCallee@16(int32, + int32) + IL_0018: ret + + IL_0019: ldarg.0 + IL_001a: ldc.i4.1 + IL_001b: sub + IL_001c: ldarg.1 + IL_001d: starg.s firstArg + IL_001f: starg.s iterationCount + IL_0021: br.s IL_0000 + } + + .method assembly static int32 fifthMethodSecondCallee@16(int32 iterationCount, + int32 firstArg) cil managed + { + + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: brtrue.s IL_0007 + + IL_0004: ldc.i4.s 101 + IL_0006: ret + + IL_0007: nop + IL_0008: ldarg.0 + IL_0009: ldc.i4.2 + IL_000a: rem + IL_000b: brtrue.s IL_0017 + + IL_000d: ldarg.0 + IL_000e: ldc.i4.1 + IL_000f: sub + IL_0010: ldarg.1 + IL_0011: starg.s firstArg + IL_0013: starg.s iterationCount + IL_0015: br.s IL_0000 + + IL_0017: ldarg.0 + IL_0018: ldc.i4.1 + IL_0019: sub + IL_001a: ldarg.1 + IL_001b: tail. + IL_001d: call int32 assembly::fifthMethodFirstCallee@8(int32, + int32) + IL_0022: ret + } + + .method public static int32 fifth() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4 0xf4240 + IL_0005: ldc.i4 0x26ad7 + IL_000a: tail. + IL_000c: call int32 assembly::fifthMethodFirstCallee@8(int32, + int32) + IL_0011: ret + } + + .method public static int32 main(string[] argv) cil managed + { + .entrypoint + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.EntryPointAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: tail. + IL_0002: call int32 assembly::fifth() + IL_0007: ret + } + +} + +.class private abstract auto ansi sealed ''.$assembly + extends [runtime]System.Object +{ +} + + + + + +