Skip to content

Commit

Permalink
Added optimize equality switch. Figuring out rules for equality optim…
Browse files Browse the repository at this point in the history
…izations. Thank you Don.
  • Loading branch information
TIHan committed Jan 18, 2019
1 parent d161754 commit d8e2f38
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 9 deletions.
7 changes: 7 additions & 0 deletions src/fsharp/CompileOptions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,11 @@ let SetOptimizeOn(tcConfigB : TcConfigBuilder) =
let SetOptimizeSwitch (tcConfigB : TcConfigBuilder) switch =
if (switch = OptionSwitch.On) then SetOptimizeOn(tcConfigB) else SetOptimizeOff(tcConfigB)

let SetSpecificOptimizeSwitch (tcConfigB : TcConfigBuilder) n switch =
match n with
| "equality" -> tcConfigB.optSettings <- { tcConfigB.optSettings with optimizeComparisonLogic = (switch = OptionSwitch.On) }
| _ -> failwithf "dodgy flag %s" n

let SetTailcallSwitch (tcConfigB : TcConfigBuilder) switch =
tcConfigB.emitTailcalls <- (switch = OptionSwitch.On)

Expand Down Expand Up @@ -696,6 +701,8 @@ let codeGenerationFlags isFsi (tcConfigB : TcConfigBuilder) =
let codegen =
[CompilerOption("optimize", tagNone, OptionSwitch (SetOptimizeSwitch tcConfigB) , None,
Some (FSComp.SR.optsOptimize()))
CompilerOption("optimize", tagNone, OptionStringListSwitch (SetSpecificOptimizeSwitch tcConfigB) , None,
Some (FSComp.SR.optsOptimize()))
CompilerOption("tailcalls", tagNone, OptionSwitch (SetTailcallSwitch tcConfigB), None,
Some (FSComp.SR.optsTailcalls()))
CompilerOption("deterministic", tagNone, OptionSwitch (SetDeterministicSwitch tcConfigB), None,
Expand Down
35 changes: 27 additions & 8 deletions src/fsharp/Optimizer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ type OptimizationSettings =
jitOptUser : bool option
localOptUser : bool option
crossModuleOptUser : bool option
optimizeComparisonLogic : bool
/// 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
Expand All @@ -278,6 +279,7 @@ type OptimizationSettings =
{ abstractBigTargets = false
jitOptUser = None
localOptUser = None
optimizeComparisonLogic = false
/// size after which we start chopping methods in two, though only at match targets
bigTargetSize = 100
/// size after which we start enforcing splitting sub-expressions to new methods, to avoid hitting .NET IL limitations
Expand Down Expand Up @@ -2476,7 +2478,30 @@ and DevirtualizeApplication cenv env (vref:ValRef) ty tyargs args m =
and DevirtualizeGenericEqualityIntrinsic cenv env receiver arg m =
let call = mkCall_IEquatableT_Equals cenv.g m receiver arg
OptimizeExpr cenv env call


/// Check if a type 'ty' implements 'IEquatable<ty>'
and IsIEquatableTy cenv m ty =
let searchTy = mkAppTy cenv.g.system_GenericIEquatable_tcref [ty]
ExistsInEntireHierarchyOfType (fun t -> typeEquiv cenv.g t searchTy) cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes ty

/// Check if a type 'ty' implements 'IStructuralEquatable'
and IsIStructuralEquatableTy cenv m ty =
let searchTy = mkAppTy cenv.g.tcref_System_IStructuralEquatable []
ExistsInEntireHierarchyOfType (fun t -> typeEquiv cenv.g t searchTy) cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes ty

/// Check if a type 'ty' is a structural F# type with default structural equality semantics
and IsGeneratedHashAndEqualsTy g ty =
isAnonRecdTy g ty ||
(isAppTy g ty &&
(let tcref = tcrefOfAppTy g ty
tcref.GeneratedHashAndEqualsValues.IsSome && tcref.GeneratedHashAndEqualsWithComparerValues.IsSome))

/// Check if we can (perhaps optimistically) convert the reduced optimization of 'a = b' to '(a :> IEquatable).Equals(b)'
and CanOptimizeGenericEqualityIntrinsicToIEquatableEquals cenv m ty =
IsIEquatableTy cenv m ty &&
not (isAnyTupleTy cenv.g ty) &&
(IsGeneratedHashAndEqualsTy cenv.g ty || (cenv.settings.optimizeComparisonLogic && not (IsIStructuralEquatableTy cenv m ty)))

and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
match f, tyargs, args with

Expand Down Expand Up @@ -2672,14 +2697,8 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) =
MightMakeCriticalTailcall = false
Info=UnknownValue})

| Expr.Val(v, _, _), [_], [receiver; arg] when valRefEq cenv.g v cenv.g.generic_equality_per_inner_vref ->
//let receiverTy = tyOfExpr cenv.g receiver
//match tryAppTy cenv.g receiverTy with
//| ValueSome(tcref, _) when tcref.TypeContents.tcaug_hash_and_equals_withc.IsNone ->
| Expr.Val(v, _, _), [_], [receiver; arg] when valRefEq cenv.g v cenv.g.generic_equality_per_inner_vref && CanOptimizeGenericEqualityIntrinsicToIEquatableEquals cenv m (tyOfExpr cenv.g receiver) ->
Some(DevirtualizeGenericEqualityIntrinsic cenv env receiver arg m)
//| _ ->
// if isAnonRecdTy cenv.g receiverTy then Some(DevirtualizeGenericEqualityIntrinsic cenv env receiver arg m)
// else None

| _ -> None

Expand Down
1 change: 1 addition & 0 deletions src/fsharp/Optimizer.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type OptimizationSettings =
jitOptUser : bool option
localOptUser : bool option
crossModuleOptUser : bool option
optimizeComparisonLogic : bool
bigTargetSize : int
veryBigExprSize : int
lambdaInlineThreshold : int
Expand Down
2 changes: 1 addition & 1 deletion src/fsharp/range.fs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ type range(code1:int64, code2: int64) =

member r.ToShortString() = sprintf "(%d,%d--%d,%d)" r.StartLine r.StartColumn r.EndLine r.EndColumn

// override r.Equals(obj) = match obj with :? range as r2 -> code1 = r2.Code1 && code2 = r2.Code2 | _ -> false
override r.Equals(obj) = match obj with :? range as r2 -> code1 = r2.Code1 && code2 = r2.Code2 | _ -> false

override r.GetHashCode() = hash code1 + hash code2

Expand Down

0 comments on commit d8e2f38

Please sign in to comment.