Browse Source

Create short circuit logical expressions as left associative

pull/100/head
David Srbecký 15 years ago
parent
commit
1a64d56b5a
  1. 30
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  2. 6
      ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
  3. 7
      ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

30
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -410,16 +410,16 @@ namespace ICSharpCode.Decompiler.ILAst @@ -410,16 +410,16 @@ namespace ICSharpCode.Decompiler.ILAst
} else if (retType == typeSystem.Boolean && trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal)) {
// It can be expressed as logical expression
if (leftBoolVal != 0) {
newExpr = new ILExpression(ILCode.LogicOr, null, condExpr, falseExpr);
newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, condExpr, falseExpr);
} else {
newExpr = new ILExpression(ILCode.LogicAnd, null, new ILExpression(ILCode.LogicNot, null, condExpr), falseExpr);
newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, new ILExpression(ILCode.LogicNot, null, condExpr), falseExpr);
}
} else if (retType == typeSystem.Boolean && falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal)) {
// It can be expressed as logical expression
if (rightBoolVal != 0) {
newExpr = new ILExpression(ILCode.LogicOr, null, new ILExpression(ILCode.LogicNot, null, condExpr), trueExpr);
newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, new ILExpression(ILCode.LogicNot, null, condExpr), trueExpr);
} else {
newExpr = new ILExpression(ILCode.LogicAnd, null, condExpr, trueExpr);
newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, condExpr, trueExpr);
}
} else {
// Ternary operator tends to create long complicated return statements
@ -429,6 +429,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -429,6 +429,7 @@ namespace ICSharpCode.Decompiler.ILAst
// Create ternary expression
newExpr = new ILExpression(ILCode.TernaryOp, null, condExpr, trueExpr, falseExpr);
}
head.Body[head.Body.Count - 1] = new ILExpression(opCode, trueLocVar, newExpr);
head.FallthoughGoto = trueFall != null ? new ILExpression(ILCode.Br, trueFall) : null;
@ -519,11 +520,13 @@ namespace ICSharpCode.Decompiler.ILAst @@ -519,11 +520,13 @@ namespace ICSharpCode.Decompiler.ILAst
(otherLablel == nextFalseLabel || otherLablel == nextTrueLablel))
{
// Create short cicuit branch
ILExpression logicExpr;
if (otherLablel == nextFalseLabel) {
head.Body[head.Body.Count - 1] = new ILExpression(ILCode.Brtrue, nextTrueLablel, new ILExpression(ILCode.LogicAnd, null, negate ? new ILExpression(ILCode.LogicNot, null, condExpr) : condExpr, nextCondExpr));
logicExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, negate ? new ILExpression(ILCode.LogicNot, null, condExpr) : condExpr, nextCondExpr);
} else {
head.Body[head.Body.Count - 1] = new ILExpression(ILCode.Brtrue, nextTrueLablel, new ILExpression(ILCode.LogicOr, null, negate ? condExpr : new ILExpression(ILCode.LogicNot, null, condExpr), nextCondExpr));
logicExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, negate ? condExpr : new ILExpression(ILCode.LogicNot, null, condExpr), nextCondExpr);
}
head.Body[head.Body.Count - 1] = new ILExpression(ILCode.Brtrue, nextTrueLablel, logicExpr);
head.FallthoughGoto = new ILExpression(ILCode.Br, nextFalseLabel);
// Remove the inlined branch from scope
@ -538,6 +541,21 @@ namespace ICSharpCode.Decompiler.ILAst @@ -538,6 +541,21 @@ namespace ICSharpCode.Decompiler.ILAst
return false;
}
ILExpression MakeLeftAssociativeShortCircuit(ILCode code, ILExpression left, ILExpression right)
{
// Assuming that the inputs are already left associative
if (right.Match(code)) {
// Find the leftmost logical expression
ILExpression current = right;
while(current.Arguments[0].Match(code))
current = current.Arguments[0];
current.Arguments[0] = new ILExpression(code, null, left, current.Arguments[0]);
return right;
} else {
return new ILExpression(code, null, left, right);
}
}
void DuplicateReturnStatements(ILBlock method)
{
Dictionary<ILLabel, ILNode> nextSibling = new Dictionary<ILLabel, ILNode>();

6
ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

@ -281,6 +281,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -281,6 +281,9 @@ namespace ICSharpCode.Decompiler.ILAst
public ILExpression(ILCode code, object operand, List<ILExpression> args)
{
if (operand is ILExpression)
throw new ArgumentException("operand");
this.Code = code;
this.Operand = operand;
this.Arguments = new List<ILExpression>(args);
@ -289,6 +292,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -289,6 +292,9 @@ namespace ICSharpCode.Decompiler.ILAst
public ILExpression(ILCode code, object operand, params ILExpression[] args)
{
if (operand is ILExpression)
throw new ArgumentException("operand");
this.Code = code;
this.Operand = operand;
this.Arguments = new List<ILExpression>(args);

7
ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

@ -55,10 +55,11 @@ namespace ICSharpCode.Decompiler.ILAst @@ -55,10 +55,11 @@ namespace ICSharpCode.Decompiler.ILAst
static bool SimplifyLdObjAndStObj(List<ILNode> body, ILExpression expr, int pos)
{
bool modified = false;
if (expr.Code == ILCode.Initobj) {
expr.Code = ILCode.Stobj;
expr.Arguments.Add(new ILExpression(ILCode.DefaultValue, expr.Operand));
return true;
modified = true;
}
ILExpression arg, arg2;
TypeReference type;
@ -84,9 +85,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -84,9 +85,9 @@ namespace ICSharpCode.Decompiler.ILAst
arg.Arguments.Add(arg2);
arg.ILRanges.AddRange(expr.ILRanges);
body[pos] = arg;
return true;
modified = true;
}
return false;
return modified;
}
#region CachedDelegateInitialization

Loading…
Cancel
Save