Skip to content

Commit 233ed5a

Browse files
committed
optimize the TryEmitComparisonMethod and small opti and semantic compression
1 parent 5473b42 commit 233ed5a

2 files changed

Lines changed: 34 additions & 31 deletions

File tree

‎.vscode/settings.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"NETSTANDARD",
4444
"Newarr",
4545
"Newobj",
46+
"Oper",
4647
"outparameter",
4748
"shortcircuit",
4849
"stackchange",

‎src/FastExpressionCompiler/FastExpressionCompiler.cs‎

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5527,35 +5527,33 @@ private static MethodInfo FindBinaryOperandMethod(
55275527
private static bool TryEmitComparisonMethod(BinaryExpression expr, ILGenerator il, ref CompilerContext context, ParentFlags parent)
55285528
{
55295529
var method = expr.Method;
5530-
var parameters = method.GetParameters();
5531-
if (!TryEmit(expr.Left, il, ref context, ParentFlags.Call, parameters[0].ParameterType.IsByRef ? 0 : -1))
5530+
var pars = method.GetParameters();
5531+
var leftParamType = pars[0].ParameterType;
5532+
if (!TryEmit(expr.Left, il, ref context, ParentFlags.Call, leftParamType.IsByRef ? 0 : -1))
55325533
return false;
55335534

5534-
// Keep the evaluation stack empty while a nontrivial right operand
5535-
// may emit exception regions or jumps, just as for call arguments.
55365535
var right = expr.Right;
5537-
var spillLeft = !right.IsParamOrConstantOrDefault();
5536+
5537+
// Keep the evaluation stack empty while a nontrivial right operand may emit exception regions or jumps, just as for call arguments.
55385538
#if LIGHT_EXPRESSION
5539-
// A conversion chain may contain a custom IL emitter.
5540-
for (var operand = right; !spillLeft;)
5541-
{
5542-
if (operand.IsIntrinsic)
5543-
{
5544-
spillLeft = true;
5545-
break;
5546-
}
5547-
if (operand is not UnaryExpression convert || convert.NodeType != ExpressionType.Convert)
5548-
break;
5549-
operand = convert.Operand;
5550-
}
5539+
var rightMayBeComplex = false;
5540+
var rightOper = right;
5541+
while (!(rightMayBeComplex = rightOper.IsIntrinsic) && rightOper is UnaryExpression unExpr && unExpr.NodeType == ExpressionType.Convert)
5542+
rightOper = unExpr.Operand;
5543+
if (!rightMayBeComplex)
5544+
rightMayBeComplex = !rightOper.NodeType.IsParamOrConstantOrDefault();
5545+
#else
5546+
var rightMayBeComplex = !right.IsParamOrConstantOrDefault();
55515547
#endif
5552-
var leftVar = spillLeft ? EmitStoreLocalVariable(il, parameters[0].ParameterType) : -1;
5548+
// Storing left here for the complex right so that we restore left and right later after emitting the right (otherwise left may be lost on the evaluation stack)
5549+
var leftVar = rightMayBeComplex ? EmitStoreLocalVariable(il, leftParamType) : -1;
55535550

5554-
if (!TryEmit(expr.Right, il, ref context, ParentFlags.Call, parameters[1].ParameterType.IsByRef ? 1 : -1))
5551+
var rightParamType = pars[1].ParameterType;
5552+
if (!TryEmit(right, il, ref context, ParentFlags.Call, rightParamType.IsByRef ? 1 : -1))
55555553
return false;
55565554
if (leftVar != -1)
55575555
{
5558-
var rightVar = EmitStoreLocalVariable(il, parameters[1].ParameterType);
5556+
var rightVar = EmitStoreLocalVariable(il, rightParamType);
55595557
EmitLoadLocalVariable(il, leftVar);
55605558
EmitLoadLocalVariable(il, rightVar);
55615559
}
@@ -8043,10 +8041,13 @@ internal static bool IsReturnable(this Expression expr)
80438041
!IsBracedBlockLike(nodeType);
80448042
}
80458043

8046-
internal static Expression StripConvertRecursively(this Expression expr) =>
8047-
expr is UnaryExpression convert && convert.NodeType == ExpressionType.Convert
8048-
? StripConvertRecursively(convert.Operand)
8049-
: expr;
8044+
[MethodImpl((MethodImplOptions)256)]
8045+
internal static Expression StripConvertRecursively(this Expression expr)
8046+
{
8047+
while (expr is UnaryExpression unExpr && unExpr.NodeType == ExpressionType.Convert)
8048+
expr = unExpr.Operand;
8049+
return expr;
8050+
}
80508051

80518052
internal static bool IsComplexExpression(this Expression expr)
80528053
{
@@ -8062,13 +8063,14 @@ internal static bool IsConstantOrDefault(this Expression expr)
80628063
| nodeType == ExpressionType.Default;
80638064
}
80648065

8065-
internal static bool IsParamOrConstantOrDefault(this Expression expr)
8066-
{
8067-
var nodeType = StripConvertRecursively(expr).NodeType;
8068-
return nodeType == ExpressionType.Parameter
8069-
| nodeType == ExpressionType.Constant
8070-
| nodeType == ExpressionType.Default;
8071-
}
8066+
[MethodImpl((MethodImplOptions)256)]
8067+
internal static bool IsParamOrConstantOrDefault(this ExpressionType nodeType) =>
8068+
nodeType == ExpressionType.Parameter |
8069+
nodeType == ExpressionType.Constant |
8070+
nodeType == ExpressionType.Default;
8071+
8072+
internal static bool IsParamOrConstantOrDefault(this Expression expr) =>
8073+
StripConvertRecursively(expr).NodeType.IsParamOrConstantOrDefault();
80728074

80738075
internal static string GetCSharpName(this MemberInfo m)
80748076
{

0 commit comments

Comments
 (0)