Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Investigate.17607 #17613

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 21 additions & 16 deletions src/Compiler/Optimize/InnerLambdasToTopLevelFuncs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -217,28 +217,32 @@ 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
let arityM = Zmap.ofList valOrder fArities
#if DEBUG
if verboseTLR then DumpArity arityM
#endif
tlrS, topValS, arityM
tlrs, topVals, arityM

(* NOTES:
For constants,
Expand Down Expand Up @@ -760,7 +764,6 @@ let FlatEnvPacks g fclassM topValS declist (reqdItemsMap: Zmap<BindingGroupShari
let aenvExprFor v = exprForVal env.m (aenvFor v)

// build PackedReqdItems
let reqdTypars = env.reqdTypars
let aenvs = Zmap.values cmap
let pack = cmapPairs |> List.map (fun (v, aenv) -> mkInvisibleBind aenv (exprForVal env.m v))
let unpack =
Expand All @@ -785,7 +788,7 @@ let FlatEnvPacks g fclassM topValS declist (reqdItemsMap: Zmap<BindingGroupShari
dprintf "tlr: packEnv unpack =%s\n" (showL (listL bindingL unpack))

// result
(fc, { ep_etps = Zset.elements reqdTypars
(fc, { ep_etps = [] //Zset.elements env.reqdTypars
ep_aenvs = aenvs
ep_pack = pack
ep_unpack = unpack}), carrierMaps
Expand Down Expand Up @@ -996,6 +999,7 @@ module Pass4_RewriteAssembly =
fBind

let fHatNewBinding (shortRecBinds: Bindings) (TBind(f, b, letSeqPtOpt)) =
printfn $"fHatNewBinding: f:{f} b:{b}"
let wf = Zmap.force f penv.arityM ("fHatNewBinding - arityM", nameOfVal)
let fHat = Zmap.force f penv.fHatM ("fHatNewBinding - fHatM", nameOfVal)

Expand Down Expand Up @@ -1092,6 +1096,7 @@ module Pass4_RewriteAssembly =
/// At free vals, fixup 0-call if it is an arity-met constant.
/// Other cases rewrite structurally.
let rec TransExpr (penv: RewriteContext) (z: RewriteState) expr: Expr * RewriteState =

penv.stackGuard.Guard <| fun () ->

match expr with
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ module Inlining =
compilation
|> verifyCompilation

[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"Regression17607.fs"|])>]
let ``Mutually recursive inner let - regression 17607 - realsig off`` compilation =
compilation
|> withRealInternalSignatureOff
|> verifyCompilation

[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"Regression17607.fs"|])>]
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
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"StructUnion01.fs"|])>]
let ``StructUnion01_fs`` compilation =
Expand Down
Original file line number Diff line number Diff line change
@@ -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)


[<EntryPoint>]
let main argv =
fifth ()
Original file line number Diff line number Diff line change
@@ -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 '<StartupCode$assembly>'.$assembly
extends [runtime]System.Object
{
}






Loading