Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2a74fec

Browse files
dsymeKevinRansom
authored andcommitted
[CompilerPerf] Fix 5136: LAddrOf is a constant and {x with ...} respects byrefness of x (dotnet#5148)
* LAddrOf is a constant* fix mistake* update baseline* update perf* remove extra copy when match on byref to struct* update baseline* fix merge* fix build
1 parentb6b7ff9 commit2a74fec

File tree

13 files changed

+796
-762
lines changed

13 files changed

+796
-762
lines changed

‎src/fsharp/Optimizer.fs‎

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,9 +1186,9 @@ let IsTyFuncValRefExpr = function
11861186
|_->false
11871187

11881188
/// Type applications of existing functions are always simple constants, with the exception of F# 'type functions'
1189-
/// REVIEW: we could also include any under-applied application here.
11901189
let recIsSmallConstExpr x=
11911190
match xwith
1191+
| Expr.Op(TOp.LValueOp(LAddrOf_,_),[],[],_)->true// &x is always a constant
11921192
| Expr.Val(v,_,_m)->not v.IsMutable
11931193
| Expr.App(fe,_,_tyargs, args,_)-> isNil args&&not(IsTyFuncValRefExpr fe)&& IsSmallConstExpr fe
11941194
|_->false
@@ -1202,11 +1202,29 @@ let ValueOfExpr expr =
12021202
// Dead binding elimination
12031203
//-------------------------------------------------------------------------
12041204

1205+
// Allow discard of "let v = *byref" if "v" is unused anywhere. The read effect
1206+
// can be discarded because it is always assumed that reading byref pointers (without using
1207+
// the value of the read) doesn't raise exceptions or cause other "interesting" side effects.
1208+
//
1209+
// This allows discarding the implicit deref when matching on struct unions, e.g.
1210+
//
1211+
// [<Struct; NoComparison; NoEquality>]
1212+
// type SingleRec =
1213+
// | SingleUnion of int
1214+
// member x.Next = let (SingleUnion i) = x in SingleUnion (i+1)
1215+
//
1216+
// See https://github.com/Microsoft/visualfsharp/issues/5136
1217+
letIsDiscardableEffectExpr expr=
1218+
match exprwith
1219+
| Expr.Op(TOp.LValueOp(LByrefGet_,_),[],[],_)->true
1220+
|_->false
1221+
1222+
/// Checks is a value binding is non-discardable
12051223
letValueIsUsedOrHasEffect cenv fvs(b:Binding,binfo)=
12061224
letv= b.Var
12071225
not(cenv.settings.EliminateUnusedBindings())||
12081226
Option.isSome v.MemberInfo||
1209-
binfo.HasEffect||
1227+
(binfo.HasEffect&&not(IsDiscardableEffectExpr b.Expr))||
12101228
v.IsFixed||
12111229
Zset.contains v(fvs())
12121230

@@ -1276,7 +1294,7 @@ and OpHasEffect g m op =
12761294
| TOp.ValFieldGet rfref-> rfref.RecdField.IsMutable||(TryFindTyconRefBoolAttribute g Range.range0 g.attrib_AllowNullLiteralAttribute rfref.TyconRef= Sometrue)
12771295
| TOp.ValFieldGetAddr(rfref,_readonly)-> rfref.RecdField.IsMutable
12781296
| TOp.UnionCaseFieldGetAddr_->false// union case fields are immutable
1279-
| TOp.LValueOp(LAddrOf_,lv)->lv.IsMutable
1297+
| TOp.LValueOp(LAddrOf_,_)->false// addresses of values are always constants
12801298
| TOp.UnionCaseFieldSet_
12811299
| TOp.ExnFieldSet_
12821300
| TOp.Coerce
@@ -1856,7 +1874,7 @@ and OptimizeInterfaceImpl cenv env baseValOpt (ty, overrides) =
18561874

18571875
andOptimizeExprOp cenv env(op,tyargs,args,m)=
18581876

1859-
(* Special cases*)
1877+
// Special cases
18601878
match op, tyargs, argswith
18611879
| TOp.Coerce,[toty;fromty],[e]->
18621880
lete',einfo= OptimizeExpr cenv env e
@@ -1868,26 +1886,38 @@ and OptimizeExprOp cenv env (op, tyargs, args, m) =
18681886
HasEffect=true
18691887
MightMakeCriticalTailcall=false
18701888
Info=UnknownValue}
1871-
(* Handle addresses*)
1889+
1890+
// Handle address-of
18721891
| TOp.LValueOp((LAddrOf_as lop), lv),_,_->
1873-
lete,_= OptimizeExpr cenv env(exprForValRef m lv)
1874-
letop'=
1875-
matchewith
1892+
letnewVal,_= OptimizeExpr cenv env(exprForValRef m lv)
1893+
letnewOp=
1894+
matchnewValwith
18761895
// Do not optimize if it's a top level static binding.
18771896
| Expr.Val(v,_,_)whennot v.IsCompiledAsTopLevel-> TOp.LValueOp(lop, v)
18781897
|_-> op
1879-
Expr.Op(op', tyargs, args, m),
1898+
letnewExpr= Expr.Op(newOp, tyargs, args, m)
1899+
newExpr,
18801900
{ TotalSize=1
18811901
FunctionSize=1
1882-
HasEffect= OpHasEffect cenv.g mop'
1902+
HasEffect= OpHasEffect cenv.g mnewOp
18831903
MightMakeCriticalTailcall=false
1884-
Info= UnknownValue}
1885-
(* Handle these as special cases since mutables are allowed inside their bodies*)
1886-
| TOp.While(spWhile, marker),_,[Expr.Lambda(_,_,_,[_], e1,_,_);Expr.Lambda(_,_,_,[_], e2,_,_)]-> OptimizeWhileLoop cenv{ envwith inLoop=true}(spWhile, marker, e1, e2, m)
1887-
| TOp.For(spStart, dir),_,[Expr.Lambda(_,_,_,[_], e1,_,_);Expr.Lambda(_,_,_,[_], e2,_,_);Expr.Lambda(_,_,_,[v], e3,_,_)]-> OptimizeFastIntegerForLoop cenv{ envwith inLoop=true}(spStart, v, e1, dir, e2, e3, m)
1888-
| TOp.TryFinally(spTry, spFinally),[resty],[Expr.Lambda(_,_,_,[_], e1,_,_); Expr.Lambda(_,_,_,[_], e2,_,_)]-> OptimizeTryFinally cenv env(spTry, spFinally, e1, e2, m, resty)
1889-
| TOp.TryCatch(spTry, spWith),[resty],[Expr.Lambda(_,_,_,[_], e1,_,_); Expr.Lambda(_,_,_,[vf], ef,_,_); Expr.Lambda(_,_,_,[vh], eh,_,_)]-> OptimizeTryCatch cenv env(e1, vf, ef, vh, eh, m, resty, spTry, spWith)
1890-
| TOp.TraitCall(traitInfo),[], args-> OptimizeTraitCall cenv env(traitInfo, args, m)
1904+
Info= ValueOfExpr newExpr}
1905+
1906+
// Handle these as special cases since mutables are allowed inside their bodies
1907+
| TOp.While(spWhile, marker),_,[Expr.Lambda(_,_,_,[_], e1,_,_);Expr.Lambda(_,_,_,[_], e2,_,_)]->
1908+
OptimizeWhileLoop cenv{ envwith inLoop=true}(spWhile, marker, e1, e2, m)
1909+
1910+
| TOp.For(spStart, dir),_,[Expr.Lambda(_,_,_,[_], e1,_,_);Expr.Lambda(_,_,_,[_], e2,_,_);Expr.Lambda(_,_,_,[v], e3,_,_)]->
1911+
OptimizeFastIntegerForLoop cenv{ envwith inLoop=true}(spStart, v, e1, dir, e2, e3, m)
1912+
1913+
| TOp.TryFinally(spTry, spFinally),[resty],[Expr.Lambda(_,_,_,[_], e1,_,_); Expr.Lambda(_,_,_,[_], e2,_,_)]->
1914+
OptimizeTryFinally cenv env(spTry, spFinally, e1, e2, m, resty)
1915+
1916+
| TOp.TryCatch(spTry, spWith),[resty],[Expr.Lambda(_,_,_,[_], e1,_,_); Expr.Lambda(_,_,_,[vf], ef,_,_); Expr.Lambda(_,_,_,[vh], eh,_,_)]->
1917+
OptimizeTryCatch cenv env(e1, vf, ef, vh, eh, m, resty, spTry, spWith)
1918+
1919+
| TOp.TraitCall(traitInfo),[], args->
1920+
OptimizeTraitCall cenv env(traitInfo, args, m)
18911921

18921922
// This code hooks arr.Length. The idea is to ensure loops end up in the "same shape"as the forms of loops that the .NET JIT
18931923
// guarantees to optimize.
@@ -1906,20 +1936,20 @@ and OptimizeExprOp cenv env (op, tyargs, args, m) =
19061936
| TOp.ILAsm([],[ty]),_,[a]when typeEquiv cenv.g(tyOfExpr cenv.g a) ty-> OptimizeExpr cenv env a
19071937

19081938
|_->
1909-
(*Reductions*)
1910-
letargs',arginfos= OptimizeExprsThenConsiderSplits cenv env args
1911-
letknownValue=
1912-
match op, arginfoswith
1913-
| TOp.ValFieldGet(rf),[e1info]-> TryOptimizeRecordFieldGet cenv env(e1info, rf, tyargs, m)
1914-
| TOp.TupleFieldGet(tupInfo, n),[e1info]-> TryOptimizeTupleFieldGet cenv env(tupInfo, e1info, tyargs, n, m)
1915-
| TOp.UnionCaseFieldGet(cspec, n),[e1info]-> TryOptimizeUnionCaseGet cenv env(e1info, cspec, tyargs, n, m)
1916-
|_-> None
1917-
match knownValuewith
1918-
| Some valu->
1919-
match TryOptimizeVal cenv env(false, valu, m)with
1920-
| Some res-> OptimizeExpr cenv env res(* discard e1 since guard ensures it has no effects*)
1921-
| None-> OptimizeExprOpFallback cenv env(op, tyargs, args', m) arginfos valu
1922-
| None-> OptimizeExprOpFallback cenv env(op, tyargs, args', m) arginfos UnknownValue
1939+
//Reductions
1940+
letargs',arginfos= OptimizeExprsThenConsiderSplits cenv env args
1941+
letknownValue=
1942+
match op, arginfoswith
1943+
| TOp.ValFieldGet(rf),[e1info]-> TryOptimizeRecordFieldGet cenv env(e1info, rf, tyargs, m)
1944+
| TOp.TupleFieldGet(tupInfo, n),[e1info]-> TryOptimizeTupleFieldGet cenv env(tupInfo, e1info, tyargs, n, m)
1945+
| TOp.UnionCaseFieldGet(cspec, n),[e1info]-> TryOptimizeUnionCaseGet cenv env(e1info, cspec, tyargs, n, m)
1946+
|_-> None
1947+
match knownValuewith
1948+
| Some valu->
1949+
match TryOptimizeVal cenv env(false, valu, m)with
1950+
| Some res-> OptimizeExpr cenv env res(* discard e1 since guard ensures it has no effects*)
1951+
| None-> OptimizeExprOpFallback cenv env(op, tyargs, args', m) arginfos valu
1952+
| None-> OptimizeExprOpFallback cenv env(op, tyargs, args', m) arginfos UnknownValue
19231953

19241954

19251955
andOptimizeExprOpFallback cenv env(op,tyargs,args',m)arginfos valu=

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp