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

Breakpoints on pipeline stages #11957

Merged
merged 21 commits into from
Aug 17, 2021
Merged
Changes from 13 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
12 changes: 6 additions & 6 deletions src/fsharp/CompilerOptions.fs
Original file line number Diff line number Diff line change
@@ -382,7 +382,7 @@ let setFlag r n =
let SetOptimizeOff(tcConfigB: TcConfigBuilder) =
tcConfigB.optSettings <- { tcConfigB.optSettings with jitOptUser = Some false }
tcConfigB.optSettings <- { tcConfigB.optSettings with localOptUser = Some false }
tcConfigB.optSettings <- { tcConfigB.optSettings with crossModuleOptUser = Some false }
tcConfigB.optSettings <- { tcConfigB.optSettings with crossAssemblyOptimizationUser = Some false }
tcConfigB.optSettings <- { tcConfigB.optSettings with lambdaInlineThreshold = 0 }
tcConfigB.doDetuple <- false
tcConfigB.doTLR <- false
@@ -391,7 +391,7 @@ let SetOptimizeOff(tcConfigB: TcConfigBuilder) =
let SetOptimizeOn(tcConfigB: TcConfigBuilder) =
tcConfigB.optSettings <- { tcConfigB.optSettings with jitOptUser = Some true }
tcConfigB.optSettings <- { tcConfigB.optSettings with localOptUser = Some true }
tcConfigB.optSettings <- { tcConfigB.optSettings with crossModuleOptUser = Some true }
tcConfigB.optSettings <- { tcConfigB.optSettings with crossAssemblyOptimizationUser = Some true }
tcConfigB.optSettings <- { tcConfigB.optSettings with lambdaInlineThreshold = 6 }
tcConfigB.doDetuple <- true
tcConfigB.doTLR <- true
@@ -420,7 +420,7 @@ let localoptimizeSwitch (tcConfigB: TcConfigBuilder) switch =
tcConfigB.optSettings <- { tcConfigB.optSettings with localOptUser = Some (switch = OptionSwitch.On) }

let crossOptimizeSwitch (tcConfigB: TcConfigBuilder) switch =
tcConfigB.optSettings <- { tcConfigB.optSettings with crossModuleOptUser = Some (switch = OptionSwitch.On) }
tcConfigB.optSettings <- { tcConfigB.optSettings with crossAssemblyOptimizationUser = Some (switch = OptionSwitch.On) }

let splittingSwitch (tcConfigB: TcConfigBuilder) switch =
tcConfigB.optSettings <- { tcConfigB.optSettings with abstractBigTargets = switch = OptionSwitch.On }
@@ -540,7 +540,7 @@ let tagLangVersionValues = "{?|version|latest|preview}"
let PrintOptionInfo (tcConfigB:TcConfigBuilder) =
printfn " jitOptUser . . . . . . : %+A" tcConfigB.optSettings.jitOptUser
printfn " localOptUser . . . . . : %+A" tcConfigB.optSettings.localOptUser
printfn " crossModuleOptUser . . : %+A" tcConfigB.optSettings.crossModuleOptUser
printfn " crossAssemblyOptimizationUser . . : %+A" tcConfigB.optSettings.crossAssemblyOptimizationUser
printfn " lambdaInlineThreshold : %+A" tcConfigB.optSettings.lambdaInlineThreshold
printfn " ignoreSymStoreSeqPts . : %+A" tcConfigB.ignoreSymbolStoreSequencePoints
printfn " doDetuple . . . . . . : %+A" tcConfigB.doDetuple
@@ -1359,12 +1359,12 @@ let deprecatedFlagsFsc tcConfigB =

CompilerOption
("cross-optimize", tagNone,
OptionUnit (fun _ -> tcConfigB.optSettings <- { tcConfigB.optSettings with crossModuleOptUser = Some true }),
OptionUnit (fun _ -> tcConfigB.optSettings <- { tcConfigB.optSettings with crossAssemblyOptimizationUser = Some true }),
Some(DeprecatedCommandLineOptionNoDescription("--cross-optimize", rangeCmdArgs)), None)

CompilerOption
("no-cross-optimize", tagNone,
OptionUnit (fun _ -> tcConfigB.optSettings <- { tcConfigB.optSettings with crossModuleOptUser = Some false }),
OptionUnit (fun _ -> tcConfigB.optSettings <- { tcConfigB.optSettings with crossAssemblyOptimizationUser = Some false }),
Some(DeprecatedCommandLineOptionNoDescription("--no-cross-optimize", rangeCmdArgs)), None)

CompilerOption
213 changes: 179 additions & 34 deletions src/fsharp/Optimizer.fs

Large diffs are not rendered by default.

41 changes: 30 additions & 11 deletions src/fsharp/Optimizer.fsi
Original file line number Diff line number Diff line change
@@ -10,20 +10,39 @@ open FSharp.Compiler.TypedTreeOps
open FSharp.Compiler.TypedTreePickle

type OptimizationSettings =
{ abstractBigTargets: bool
jitOptUser: bool option
localOptUser: bool option
crossModuleOptUser: bool option
bigTargetSize: int
veryBigExprSize: int
lambdaInlineThreshold: int
reportingPhase: bool
{
abstractBigTargets : bool

jitOptUser : bool option

localOptUser : bool option

debugPointsForPipeRight: bool option

crossAssemblyOptimizationUser : bool option

/// size after which we start chopping methods in two, though only at match targets
bigTargetSize : int

/// size after which we start enforcing splitting sub-expressions to new methods, to avoid hitting .NET IL limitations
veryBigExprSize : int

/// The size after which we don't inline
lambdaInlineThreshold : int

/// For unit testing
reportingPhase : bool

reportNoNeedToTailcall: bool
reportFunctionSizes: bool
reportHasEffect: bool
reportTotalSizes: bool

reportFunctionSizes : bool

reportHasEffect : bool

reportTotalSizes : bool
}


member jitOpt: unit -> bool

member localOpt: unit -> bool
27 changes: 26 additions & 1 deletion src/fsharp/SyntaxTreeOps.fs
Original file line number Diff line number Diff line change
@@ -760,4 +760,29 @@ let (|ParsedHashDirectiveArguments|) (input: ParsedHashDirectiveArgument list) =
(function
| ParsedHashDirectiveArgument.String (s, _, _) -> s
| ParsedHashDirectiveArgument.SourceIdentifier (_, v, _) -> v)
input
input

let (|SynBinOp|_|) input =
match input with
| SynExpr.App (ExprAtomicFlag.NonAtomic, false, SynExpr.App (ExprAtomicFlag.NonAtomic, true, SynExpr.Ident synId, x1, _m1), x2, _m2) ->
Some (synId, x1, x2)
| _ -> None

let (|SynPipeRight|_|) input =
match input with
| SynBinOp (synId, x1, x2) when synId.idText = "op_PipeRight" -> Some (x1, x2)
| _ -> None

let (|SynPipeRight2|_|) input =
match input with
| SynBinOp (synId, SynExpr.Paren(SynExpr.Tuple(false, [x1a; x1b], _, _), _, _, _), x2)
when synId.idText = "op_PipeRight2" ->
Some (x1a, x1b, x2)
| _ -> None

let (|SynPipeRight3|_|) input =
match input with
| SynBinOp (synId, SynExpr.Paren(SynExpr.Tuple(false, [x1a; x1b; x1c], _, _), _, _, _), x2)
when synId.idText = "op_PipeRight3" ->
Some (x1a, x1b, x1c, x2)
| _ -> None
9 changes: 8 additions & 1 deletion src/fsharp/SyntaxTreeOps.fsi
Original file line number Diff line number Diff line change
@@ -262,4 +262,11 @@ val noInferredTypars: SynValTyparDecls

val synExprContainsError: inpExpr:SynExpr -> bool

val ( |ParsedHashDirectiveArguments| ) : ParsedHashDirectiveArgument list -> string list
val ( |ParsedHashDirectiveArguments| ) : ParsedHashDirectiveArgument list -> string list

val (|SynPipeRight|_|): SynExpr -> (SynExpr * SynExpr) option

val (|SynPipeRight2|_|): SynExpr -> (SynExpr * SynExpr * SynExpr) option

val (|SynPipeRight3|_|): SynExpr -> (SynExpr * SynExpr * SynExpr * SynExpr) option

6 changes: 6 additions & 0 deletions src/fsharp/TcGlobals.fs
Original file line number Diff line number Diff line change
@@ -624,6 +624,9 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d

let v_reference_equality_inner_info = makeIntrinsicValRef(fslib_MFHashCompare_nleref, "PhysicalEqualityIntrinsic" , None , None , [vara], mk_rel_sig varaTy)

let v_piperight_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "op_PipeRight" , None , None , [vara; varb],([[varaTy];[varaTy --> varbTy]], varbTy))
let v_piperight2_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "op_PipeRight2" , None , None , [vara; varb; varc],([[varaTy; varbTy];[varaTy --> (varbTy --> varcTy)]], varcTy))
let v_piperight3_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "op_PipeRight3" , None , None , [vara; varb; varc; vard],([[varaTy; varbTy; varcTy];[varaTy --> (varbTy --> (varcTy --> vardTy))]], vardTy))
let v_bitwise_or_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "op_BitwiseOr" , None , None , [vara], mk_binop_ty varaTy)
let v_bitwise_and_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "op_BitwiseAnd" , None , None , [vara], mk_binop_ty varaTy)
let v_bitwise_xor_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "op_ExclusiveOr" , None , None , [vara], mk_binop_ty varaTy)
@@ -1298,6 +1301,9 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d

member val reference_equality_inner_vref = ValRefForIntrinsic v_reference_equality_inner_info

member val piperight_vref = ValRefForIntrinsic v_piperight_info
member val piperight2_vref = ValRefForIntrinsic v_piperight2_info
member val piperight3_vref = ValRefForIntrinsic v_piperight3_info
member val bitwise_or_vref = ValRefForIntrinsic v_bitwise_or_info
member val bitwise_and_vref = ValRefForIntrinsic v_bitwise_and_info
member val bitwise_xor_vref = ValRefForIntrinsic v_bitwise_xor_info
21 changes: 21 additions & 0 deletions src/fsharp/TypedTreeOps.fs
Original file line number Diff line number Diff line change
@@ -7663,6 +7663,27 @@ let (|DelegateInvokeExpr|_|) g expr =
Some(iref, fty, tyargs, f, args, m)
| _ -> None

let (|OpPipeRight|_|) g expr =
match expr with
| Expr.App (Expr.Val (vref, _, _), _, [_; resType], [xExpr; fExpr], m)
when valRefEq g vref g.piperight_vref ->
Some(resType, xExpr, fExpr, m)
| _ -> None

let (|OpPipeRight2|_|) g expr =
match expr with
| Expr.App (Expr.Val (vref, _, _), _, [_; _; resType], [Expr.Op (TOp.Tuple _, _, [arg1; arg2], _); fExpr], m)
when valRefEq g vref g.piperight2_vref ->
Some(resType, arg1, arg2, fExpr, m)
| _ -> None

let (|OpPipeRight3|_|) g expr =
match expr with
| Expr.App (Expr.Val (vref, _, _), _, [_; _; _; resType], [Expr.Op (TOp.Tuple _, _, [arg1; arg2; arg3], _); fExpr], m)
when valRefEq g vref g.piperight3_vref ->
Some(resType, arg1, arg2, arg3, fExpr, m)
| _ -> None

let rec MakeFSharpDelegateInvokeAndTryBetaReduce g (invokeRef, f, fty, tyargs, argsl: Expr list, m) =
match f with
| Expr.Let (bind, body, mlet, _) ->
17 changes: 16 additions & 1 deletion src/fsharp/TypedTreeOps.fsi
Original file line number Diff line number Diff line change
@@ -2508,4 +2508,19 @@ val (|ResumableCodeInvoke|_|):
g:TcGlobals ->
expr: Expr ->
(Expr * Expr * Expr list * range * (Expr * Expr list -> Expr)) option


val (|OpPipeRight|_|):
g:TcGlobals ->
expr: Expr ->
(TType * Expr * Expr * range) option

val (|OpPipeRight2|_|):
g:TcGlobals ->
expr: Expr ->
(TType * Expr * Expr * Expr * range) option

val (|OpPipeRight3|_|):
g:TcGlobals ->
expr: Expr ->
(TType * Expr * Expr * Expr * Expr * range) option

30 changes: 30 additions & 0 deletions src/fsharp/service/FSharpParseFileResults.fs
Original file line number Diff line number Diff line change
@@ -534,6 +534,36 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput,
yield! checkRange e.Range
yield! walkExpr false e

// Always allow breakpoints on input and stages of x |> f1 |> f2 pipelines
| SynPipeRight _ ->
let rec loop e =
seq {
match e with
| SynPipeRight (xExpr, fExpr) ->
yield! checkRange fExpr.Range
yield! walkExpr false fExpr
yield! loop xExpr
| SynPipeRight2 (xExpr1, xExpr2, fExpr) ->
yield! checkRange fExpr.Range
yield! checkRange xExpr1.Range
yield! checkRange xExpr2.Range
yield! walkExpr false xExpr1
yield! walkExpr false xExpr2
yield! walkExpr false fExpr
| SynPipeRight3 (xExpr1, xExpr2, xExpr3, fExpr) ->
yield! checkRange fExpr.Range
yield! checkRange xExpr1.Range
yield! checkRange xExpr2.Range
yield! checkRange xExpr3.Range
yield! walkExpr false xExpr1
yield! walkExpr false xExpr2
yield! walkExpr false xExpr3
yield! walkExpr false fExpr
| _ ->
yield! checkRange e.Range
yield! walkExpr false e
}
yield! loop expr
| SynExpr.NamedIndexedPropertySet (_, e1, e2, _)
| SynExpr.DotSet (e1, _, e2, _)
| SynExpr.Set (e1, e2, _)
3 changes: 2 additions & 1 deletion src/fsharp/symbols/Exprs.fs
Original file line number Diff line number Diff line change
@@ -401,7 +401,8 @@ module FSharpExprConvert =
// tail recursive
ConvExprLinear cenv env e2 (contF << (fun e2R -> E.Sequential(e1R, e2R)))

| Expr.Sequential (x0, x1, ThenDoSeq, _, _) -> E.Sequential(ConvExpr cenv env x0, ConvExpr cenv env x1)
| Expr.Sequential (x0, x1, ThenDoSeq, _, _) ->
E.Sequential(ConvExpr cenv env x0, ConvExpr cenv env x1) |> contF

| ModuleValueOrMemberUse cenv.g (vref, vFlags, _f, _fty, tyargs, curriedArgs) when (nonNil tyargs || nonNil curriedArgs) && vref.IsMemberOrModuleBinding ->
ConvModuleValueOrMemberUseLinear cenv env (expr, vref, vFlags, tyargs, curriedArgs) contF
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0
// Copyright (c) Microsoft Corporation. All rights reserved.


@@ -13,7 +13,7 @@
.assembly extern FSharp.Core
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 4:4:3:0
.ver 5:0:0:0
}
.assembly AsyncExpressionSteppingTest1
{
@@ -29,20 +29,20 @@
}
.mresource public FSharpSignatureData.AsyncExpressionSteppingTest1
{
// Offset: 0x00000000 Length: 0x0000026C
// Offset: 0x00000000 Length: 0x00000260
}
.mresource public FSharpOptimizationData.AsyncExpressionSteppingTest1
{
// Offset: 0x00000270 Length: 0x000000B1
// Offset: 0x00000268 Length: 0x000000B1
}
.module AsyncExpressionSteppingTest1.dll
// MVID: {5AF5DDAE-6394-B5D4-A745-0383AEDDF55A}
// MVID: {6116A45A-6394-B5D4-A745-03835AA41661}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x02880000
// Image base: 0x07170000


// =============== CLASS MEMBERS DECLARATION ===================
@@ -83,7 +83,7 @@
// Code size 62 (0x3e)
.maxstack 8
.language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
.line 6,6 : 17,32 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\CodeGen\\EmittedIL\\AsyncExpressionStepping\\AsyncExpressionSteppingTest1.fs'
.line 6,6 : 17,32 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\AsyncExpressionStepping\\AsyncExpressionSteppingTest1.fs'
IL_0000: ldstr "hello"
IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::.ctor(string)
IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine<class [FSharp.Core]Microsoft.FSharp.Core.Unit>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<!!0,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit>)
@@ -140,11 +140,12 @@
{
// Code size 18 (0x12)
.maxstack 5
.locals init ([0] class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<class [FSharp.Core]Microsoft.FSharp.Core.Unit> V_0,
.locals init ([0] class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<class [FSharp.Core]Microsoft.FSharp.Core.Unit> 'Pipe #1 input',
[1] class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<class [FSharp.Core]Microsoft.FSharp.Core.Unit> V_1)
.line 10,10 : 13,43 ''
.line 10,10 : 13,17 ''
IL_0000: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<class [FSharp.Core]Microsoft.FSharp.Core.Unit> AsyncExpressionSteppingTest1/AsyncExpressionSteppingTest1::f1()
IL_0005: stloc.0
.line 10,10 : 21,43 ''
IL_0006: ldloc.0
IL_0007: stloc.1
IL_0008: ldloc.1
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0
// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0
// Copyright (c) Microsoft Corporation. All rights reserved.


@@ -13,7 +13,7 @@
.assembly extern FSharp.Core
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 4:4:3:0
.ver 5:0:0:0
}
.assembly AsyncExpressionSteppingTest2
{
@@ -29,20 +29,20 @@
}
.mresource public FSharpSignatureData.AsyncExpressionSteppingTest2
{
// Offset: 0x00000000 Length: 0x0000026C
// Offset: 0x00000000 Length: 0x00000260
}
.mresource public FSharpOptimizationData.AsyncExpressionSteppingTest2
{
// Offset: 0x00000270 Length: 0x000000B1
// Offset: 0x00000268 Length: 0x000000B1
}
.module AsyncExpressionSteppingTest2.dll
// MVID: {5AF5DDAE-6394-D499-A745-0383AEDDF55A}
// MVID: {6116A45A-6394-D499-A745-03835AA41661}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x04520000
// Image base: 0x051E0000


// =============== CLASS MEMBERS DECLARATION ===================
@@ -80,7 +80,7 @@
// Code size 15 (0xf)
.maxstack 8
.language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
.line 6,6 : 23,29 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\CodeGen\\EmittedIL\\AsyncExpressionStepping\\AsyncExpressionSteppingTest2.fs'
.line 6,6 : 23,29 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\AsyncExpressionStepping\\AsyncExpressionSteppingTest2.fs'
IL_0000: ldarg.0
IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1<int32> AsyncExpressionSteppingTest2/AsyncExpressionSteppingTest2/'f2@6-1'::x
IL_0006: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::op_Dereference<int32>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1<!!0>)
@@ -237,11 +237,12 @@
{
// Code size 18 (0x12)
.maxstack 5
.locals init ([0] class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<class [FSharp.Core]Microsoft.FSharp.Core.Unit> V_0,
.locals init ([0] class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<class [FSharp.Core]Microsoft.FSharp.Core.Unit> 'Pipe #1 input',
[1] class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<class [FSharp.Core]Microsoft.FSharp.Core.Unit> V_1)
.line 11,11 : 13,43 ''
.line 11,11 : 13,17 ''
IL_0000: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1<class [FSharp.Core]Microsoft.FSharp.Core.Unit> AsyncExpressionSteppingTest2/AsyncExpressionSteppingTest2::f2()
IL_0005: stloc.0
.line 11,11 : 21,43 ''
IL_0006: ldloc.0
IL_0007: stloc.1
IL_0008: ldloc.1
Loading