@@ -1764,7 +1764,15 @@ let TryDetectQueryQuoteAndRun cenv (expr:Expr) =
17641764//printfn "Not eliminating because no Run found"
17651765 None
17661766
1767-
1767+ let IsSystemStringConcatOverload ( methRef : ILMethodRef ) =
1768+ methRef.Name= " Concat" && methRef.DeclaringTypeRef.FullName= " System.String" &&
1769+ methRef.ReturnType.BasicQualifiedName= " System.String" &&
1770+ methRef.ArgTypes|> List.forall( fun ilty -> ilty.BasicQualifiedName= " System.String" )
1771+
1772+ let IsSystemStringConcatArray ( methRef : ILMethodRef ) =
1773+ methRef.Name= " Concat" && methRef.DeclaringTypeRef.FullName= " System.String" &&
1774+ methRef.ReturnType.BasicQualifiedName= " System.String" &&
1775+ methRef.ArgTypes.Length= 1 && methRef.ArgTypes.Head.BasicQualifiedName= " System.String[]"
17681776
17691777//-------------------------------------------------------------------------
17701778// The traversal
@@ -1824,7 +1832,6 @@ let rec OptimizeExpr cenv (env:IncrementalOptimizationEnv) expr =
18241832assert ( " unexpected reclink" = " " )
18251833 failwith" Unexpected reclink"
18261834
1827-
18281835//-------------------------------------------------------------------------
18291836// Optimize/analyze an object expression
18301837//-------------------------------------------------------------------------
@@ -1874,9 +1881,54 @@ and OptimizeInterfaceImpl cenv env baseValOpt (ty, overrides) =
18741881 Info= UnknownValue}
18751882
18761883//-------------------------------------------------------------------------
1877- //Optimize/analyze an application of an intrinsic operator to arguments
1884+ //Make and optimize String.Concat calls
18781885//-------------------------------------------------------------------------
18791886
1887+ and MakeOptimizedSystemStringConcatCall cenv env m args =
1888+ let rec optimizeArg e accArgs =
1889+ match e, accArgswith
1890+ | Expr.Op( TOp.ILCall(_, _, _, _, _, _, _, methRef, _, _, _), _, [ Expr.Op( TOp.Array, _, args, _) ], _), _ when IsSystemStringConcatArray methRef->
1891+ optimizeArgs args accArgs
1892+
1893+ | Expr.Op( TOp.ILCall(_, _, _, _, _, _, _, methRef, _, _, _), _, args, _), _ when IsSystemStringConcatOverload methRef->
1894+ optimizeArgs args accArgs
1895+
1896+ // Optimize string constants, e.g. "1" + "2" will turn into "12"
1897+ | Expr.Const( Const.String str1, _, _), Expr.Const( Const.String str2, _, _) :: accArgs->
1898+ mkString cenv.g m( str1+ str2) :: accArgs
1899+
1900+ | arg, _ -> arg:: accArgs
1901+
1902+ and optimizeArgs args accArgs =
1903+ ( args, accArgs)
1904+ ||> List.foldBack( fun arg accArgs -> optimizeArg arg accArgs)
1905+
1906+ let args = optimizeArgs args[]
1907+
1908+ let e =
1909+ match argswith
1910+ | [ arg] ->
1911+ arg
1912+ | [ arg1; arg2] ->
1913+ mkStaticCall_ String_ Concat2 cenv.g m arg1 arg2
1914+ | [ arg1; arg2; arg3] ->
1915+ mkStaticCall_ String_ Concat3 cenv.g m arg1 arg2 arg3
1916+ | [ arg1; arg2; arg3; arg4] ->
1917+ mkStaticCall_ String_ Concat4 cenv.g m arg1 arg2 arg3 arg4
1918+ | args->
1919+ let arg = mkArray( cenv.g.string_ ty, args, m)
1920+ mkStaticCall_ String_ Concat_ Array cenv.g m arg
1921+
1922+ match ewith
1923+ | Expr.Op( TOp.ILCall(_, _, _, _, _, _, _, methRef, _, _, _) as op, tyargs, args, m) when IsSystemStringConcatOverload methRef|| IsSystemStringConcatArray methRef->
1924+ OptimizeExprOpReductions cenv env( op, tyargs, args, m)
1925+ | _ ->
1926+ OptimizeExpr cenv env e
1927+
1928+ //-------------------------------------------------------------------------
1929+ // Optimize/analyze an application of an intrinsic operator to arguments
1930+ //-------------------------------------------------------------------------
1931+
18801932and OptimizeExprOp cenv env ( op , tyargs , args , m ) =
18811933
18821934// Special cases
@@ -1940,22 +1992,30 @@ and OptimizeExprOp cenv env (op, tyargs, args, m) =
19401992// if the types match up.
19411993| TOp.ILAsm([], [ ty]), _, [ a] when typeEquiv cenv.g( tyOfExpr cenv.g a) ty-> OptimizeExpr cenv env a
19421994
1943- | _ ->
1944- // Reductions
1945- let args ' , arginfos = OptimizeExprsThenConsiderSplits cenv env args
1946- let knownValue =
1947- match op, arginfoswith
1948- | TOp.ValFieldGet( rf), [ e1info] -> TryOptimizeRecordFieldGet cenv env( e1info, rf, tyargs, m)
1949- | TOp.TupleFieldGet( tupInfo, n), [ e1info] -> TryOptimizeTupleFieldGet cenv env( tupInfo, e1info, tyargs, n, m)
1950- | TOp.UnionCaseFieldGet( cspec, n), [ e1info] -> TryOptimizeUnionCaseGet cenv env( e1info, cspec, tyargs, n, m)
1951- | _ -> None
1952- match knownValuewith
1953- | Some valu->
1954- match TryOptimizeVal cenv env( false , valu, m) with
1955- | Some res-> OptimizeExpr cenv env res(* discard e1 since guard ensures it has no effects*)
1956- | None-> OptimizeExprOpFallback cenv env( op, tyargs, args', m) arginfos valu
1957- | None-> OptimizeExprOpFallback cenv env( op, tyargs, args', m) arginfos UnknownValue
1995+ // Optimize calls when concatenating strings, e.g. "1" + "2" + "3" + "4" .. etc.
1996+ | TOp.ILCall(_, _, _, _, _, _, _, methRef, _, _, _), _, [ Expr.Op( TOp.Array, _, args, _) ] when IsSystemStringConcatArray methRef->
1997+ MakeOptimizedSystemStringConcatCall cenv env m args
1998+ | TOp.ILCall(_, _, _, _, _, _, _, methRef, _, _, _), _, argswhen IsSystemStringConcatOverload methRef->
1999+ MakeOptimizedSystemStringConcatCall cenv env m args
19582000
2001+ | _ ->
2002+ // Reductions
2003+ OptimizeExprOpReductions cenv env( op, tyargs, args, m)
2004+
2005+ and OptimizeExprOpReductions cenv env ( op , tyargs , args , m ) =
2006+ let args ' , arginfos = OptimizeExprsThenConsiderSplits cenv env args
2007+ let knownValue =
2008+ match op, arginfoswith
2009+ | TOp.ValFieldGet( rf), [ e1info] -> TryOptimizeRecordFieldGet cenv env( e1info, rf, tyargs, m)
2010+ | TOp.TupleFieldGet( tupInfo, n), [ e1info] -> TryOptimizeTupleFieldGet cenv env( tupInfo, e1info, tyargs, n, m)
2011+ | TOp.UnionCaseFieldGet( cspec, n), [ e1info] -> TryOptimizeUnionCaseGet cenv env( e1info, cspec, tyargs, n, m)
2012+ | _ -> None
2013+ match knownValuewith
2014+ | Some valu->
2015+ match TryOptimizeVal cenv env( false , valu, m) with
2016+ | Some res-> OptimizeExpr cenv env res(* discard e1 since guard ensures it has no effects*)
2017+ | None-> OptimizeExprOpFallback cenv env( op, tyargs, args', m) arginfos valu
2018+ | None-> OptimizeExprOpFallback cenv env( op, tyargs, args', m) arginfos UnknownValue
19592019
19602020and OptimizeExprOpFallback cenv env ( op , tyargs , args' , m ) arginfos valu =
19612021// The generic case - we may collect information, but the construction/projection doesn't disappear
@@ -2682,7 +2742,7 @@ and TryInlineApplication cenv env finfo (tyargs: TType list, args: Expr list, m)
26822742// Inlining: beta reducing
26832743let expr ' = MakeApplicationAndBetaReduce cenv.g( f2', f2ty, [ tyargs], args', m)
26842744// Inlining: reoptimizing
2685- Some( OptimizeExpr cenv{ envwith dontInline= Zset.add lambdaId env.dontInline} expr')
2745+ Some( OptimizeExpr cenv{ envwith dontInline= Zset.add lambdaId env.dontInline} expr')
26862746
26872747| _ -> None
26882748