Ejemplo n.º 1
0
        bool MatchFixedInitializer(List <ILNode> body, int i, out ILVariable pinnedVar, out ILExpression initValue, out int nextPos)
        {
            if (body[i].Match(ILCode.Stloc, out pinnedVar, out initValue) && pinnedVar.IsPinned && !IsNullOrZero(initValue))
            {
                initValue = (ILExpression)body[i];
                nextPos   = i + 1;
                HandleStringFixing(pinnedVar, body, ref nextPos, ref initValue);
                return(true);
            }
            ILCondition  ifStmt = body[i] as ILCondition;
            ILExpression arrayLoadingExpr;

            if (ifStmt != null && MatchFixedArrayInitializerCondition(ifStmt.Condition, out arrayLoadingExpr))
            {
                ILVariable   arrayVariable = (ILVariable)arrayLoadingExpr.Operand;
                ILExpression trueValue;
                if (ifStmt.TrueBlock != null && ifStmt.TrueBlock.Body.Count == 1 &&
                    ifStmt.TrueBlock.Body[0].Match(ILCode.Stloc, out pinnedVar, out trueValue) &&
                    pinnedVar.IsPinned && IsNullOrZero(trueValue))
                {
                    if (ifStmt.FalseBlock != null && ifStmt.FalseBlock.Body.Count == 1 && ifStmt.FalseBlock.Body[0] is ILFixedStatement)
                    {
                        ILFixedStatement fixedStmt = (ILFixedStatement)ifStmt.FalseBlock.Body[0];
                        ILVariable       stlocVar;
                        ILExpression     falseValue;
                        if (fixedStmt.Initializers.Count == 1 && fixedStmt.BodyBlock.Body.Count == 0 &&
                            fixedStmt.Initializers[0].Match(ILCode.Stloc, out stlocVar, out falseValue) && stlocVar == pinnedVar)
                        {
                            ILVariable loadedVariable;
                            if (falseValue.Code == ILCode.Ldelema &&
                                falseValue.Arguments[0].Match(ILCode.Ldloc, out loadedVariable) && loadedVariable == arrayVariable &&
                                IsNullOrZero(falseValue.Arguments[1]))
                            {
                                // OK, we detected the pattern for fixing an array.
                                // Now check whether the loading expression was a store ot a temp. var
                                // that can be eliminated.
                                if (arrayLoadingExpr.Code == ILCode.Stloc)
                                {
                                    ILInlining inlining = new ILInlining(method);
                                    if (inlining.numLdloc.GetOrDefault(arrayVariable) == 2 &&
                                        inlining.numStloc.GetOrDefault(arrayVariable) == 1 && inlining.numLdloca.GetOrDefault(arrayVariable) == 0)
                                    {
                                        arrayLoadingExpr = arrayLoadingExpr.Arguments[0];
                                    }
                                }
                                initValue = new ILExpression(ILCode.Stloc, pinnedVar, arrayLoadingExpr);
                                nextPos   = i + 1;
                                return(true);
                            }
                        }
                    }
                }
            }
            initValue = null;
            nextPos   = -1;
            return(false);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Reduce the nesting of conditions.
        /// It should be done on flat data that already had most gotos removed
        /// </summary>
        void ReduceIfNesting(ILNode node)
        {
            ILBlock block = node as ILBlock;

            if (block != null)
            {
                for (int i = 0; i < block.Body.Count; i++)
                {
                    ILCondition cond = block.Body[i] as ILCondition;
                    if (cond != null)
                    {
                        bool trueExits  = cond.TrueBlock.Body.LastOrDefault().IsUnconditionalControlFlow();
                        bool falseExits = cond.FalseBlock.Body.LastOrDefault().IsUnconditionalControlFlow();

                        if (trueExits)
                        {
                            // Move the false block after the condition
                            block.Body.InsertRange(i + 1, cond.FalseBlock.GetChildren());
                            cond.FalseBlock = new ILBlock();
                        }
                        else if (falseExits)
                        {
                            // Move the true block after the condition
                            block.Body.InsertRange(i + 1, cond.TrueBlock.GetChildren());
                            cond.TrueBlock = new ILBlock();
                        }

                        // Eliminate empty true block
                        if (!cond.TrueBlock.GetChildren().Any() && cond.FalseBlock.GetChildren().Any())
                        {
                            // Swap bodies
                            ILBlock tmp = cond.TrueBlock;
                            cond.TrueBlock  = cond.FalseBlock;
                            cond.FalseBlock = tmp;
                            cond.Condition  = new ILExpression(ILCode.LogicNot, null, cond.Condition);
                        }
                    }
                }
            }

            // We are changing the number of blocks so we use plain old recursion to get all blocks
            foreach (ILNode child in node.GetChildren())
            {
                if (child != null && !(child is ILExpression))
                {
                    ReduceIfNesting(child);
                }
            }
        }
Ejemplo n.º 3
0
        bool MatchFixedInitializer(List <ILNode> body, int i, out ILVariable pinnedVar, out ILExpression initValue, out int nextPos)
        {
            if (body[i].Match(ILCode.Stloc, out pinnedVar, out initValue) && pinnedVar.IsPinned && !IsNullOrZero(initValue))
            {
                initValue = (ILExpression)body[i];
                nextPos   = i + 1;
                HandleStringFixing(pinnedVar, body, ref nextPos, ref initValue);
                return(true);
            }
            ILCondition  ifStmt = body[i] as ILCondition;
            ILExpression arrayLoadingExpr;

            if (ifStmt != null && MatchFixedArrayInitializerCondition(ifStmt.Condition, out arrayLoadingExpr))
            {
                ILVariable   arrayVariable = (ILVariable)arrayLoadingExpr.Operand;
                ILExpression trueValue;
                if (ifStmt.TrueBlock != null && ifStmt.TrueBlock.Body.Count == 1 &&
                    ifStmt.TrueBlock.Body[0].Match(ILCode.Stloc, out pinnedVar, out trueValue) &&
                    pinnedVar.IsPinned && IsNullOrZero(trueValue))
                {
                    if (ifStmt.FalseBlock != null && ifStmt.FalseBlock.Body.Count == 1 && ifStmt.FalseBlock.Body[0] is ILFixedStatement)
                    {
                        ILFixedStatement fixedStmt = (ILFixedStatement)ifStmt.FalseBlock.Body[0];
                        ILVariable       stlocVar;
                        ILExpression     falseValue;
                        if (fixedStmt.Initializers.Count == 1 && fixedStmt.BodyBlock.Body.Count == 0 &&
                            fixedStmt.Initializers[0].Match(ILCode.Stloc, out stlocVar, out falseValue) && stlocVar == pinnedVar)
                        {
                            ILVariable loadedVariable;
                            if (falseValue.Code == ILCode.Ldelema &&
                                falseValue.Arguments[0].Match(ILCode.Ldloc, out loadedVariable) && loadedVariable == arrayVariable &&
                                IsNullOrZero(falseValue.Arguments[1]))
                            {
                                initValue = new ILExpression(ILCode.Stloc, pinnedVar, arrayLoadingExpr);
                                nextPos   = i + 1;
                                return(true);
                            }
                        }
                    }
                }
            }
            initValue = null;
            nextPos   = -1;
            return(false);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Get the first expression to be excecuted if the instruction pointer is at the start of the given node.
        /// Try blocks may not be entered in any way.  If possible, the try block is returned as the node to be executed.
        /// </summary>
        ILNode Enter(ILNode node, HashSet <ILNode> visitedNodes)
        {
            if (node == null)
            {
                throw new ArgumentNullException();
            }

            if (!visitedNodes.Add(node))
            {
                return(null);                 // Infinite loop
            }
            ILLabel label = node as ILLabel;

            if (label != null)
            {
                return(Exit(label, visitedNodes));
            }

            ILExpression expr = node as ILExpression;

            if (expr != null)
            {
                if (expr.Code == ILCode.Br || expr.Code == ILCode.Leave)
                {
                    ILLabel target = (ILLabel)expr.Operand;
                    // Early exit - same try-block
                    if (GetParents(expr).OfType <ILTryCatchBlock>().FirstOrDefault() == GetParents(target).OfType <ILTryCatchBlock>().FirstOrDefault())
                    {
                        return(Enter(target, visitedNodes));
                    }
                    // Make sure we are not entering any try-block
                    var srcTryBlocks = GetParents(expr).OfType <ILTryCatchBlock>().Reverse().ToList();
                    var dstTryBlocks = GetParents(target).OfType <ILTryCatchBlock>().Reverse().ToList();
                    // Skip blocks that we are already in
                    int i = 0;
                    while (i < srcTryBlocks.Count && i < dstTryBlocks.Count && srcTryBlocks[i] == dstTryBlocks[i])
                    {
                        i++;
                    }
                    if (i == dstTryBlocks.Count)
                    {
                        return(Enter(target, visitedNodes));
                    }
                    else
                    {
                        ILTryCatchBlock dstTryBlock = dstTryBlocks[i];
                        // Check that the goto points to the start
                        ILTryCatchBlock current = dstTryBlock;
                        while (current != null)
                        {
                            foreach (ILNode n in current.TryBlock.Body)
                            {
                                if (n is ILLabel)
                                {
                                    if (n == target)
                                    {
                                        return(dstTryBlock);
                                    }
                                }
                                else if (!n.Match(ILCode.Nop))
                                {
                                    current = n as ILTryCatchBlock;
                                    break;
                                }
                            }
                        }
                        return(null);
                    }
                }
                else if (expr.Code == ILCode.Nop)
                {
                    return(Exit(expr, visitedNodes));
                }
                else if (expr.Code == ILCode.LoopOrSwitchBreak)
                {
                    ILNode breakBlock = GetParents(expr).First(n => n is ILWhileLoop || n is ILSwitch);
                    return(Exit(breakBlock, new HashSet <ILNode>()
                    {
                        expr
                    }));
                }
                else if (expr.Code == ILCode.LoopContinue)
                {
                    ILNode continueBlock = GetParents(expr).First(n => n is ILWhileLoop);
                    return(Enter(continueBlock, new HashSet <ILNode>()
                    {
                        expr
                    }));
                }
                else
                {
                    return(expr);
                }
            }

            ILBlock block = node as ILBlock;

            if (block != null)
            {
                if (block.EntryGoto != null)
                {
                    return(Enter(block.EntryGoto, visitedNodes));
                }
                else if (block.Body.Count > 0)
                {
                    return(Enter(block.Body[0], visitedNodes));
                }
                else
                {
                    return(Exit(block, visitedNodes));
                }
            }

            ILCondition cond = node as ILCondition;

            if (cond != null)
            {
                return(cond.Condition);
            }

            ILWhileLoop loop = node as ILWhileLoop;

            if (loop != null)
            {
                if (loop.Condition != null)
                {
                    return(loop.Condition);
                }
                else
                {
                    return(Enter(loop.BodyBlock, visitedNodes));
                }
            }

            ILTryCatchBlock tryCatch = node as ILTryCatchBlock;

            if (tryCatch != null)
            {
                return(tryCatch);
            }

            ILSwitch ilSwitch = node as ILSwitch;

            if (ilSwitch != null)
            {
                return(ilSwitch.Condition);
            }

            throw new NotSupportedException(node.GetType().ToString());
        }
Ejemplo n.º 5
0
        List <ILNode> FindConditions(HashSet <ControlFlowNode> scope, ControlFlowNode entryNode)
        {
            List <ILNode> result = new List <ILNode>();

            // Do not modify entry data
            scope = new HashSet <ControlFlowNode>(scope);

            Stack <ControlFlowNode> agenda = new Stack <ControlFlowNode>();

            agenda.Push(entryNode);
            while (agenda.Count > 0)
            {
                ControlFlowNode node = agenda.Pop();

                // Find a block that represents a simple condition
                if (scope.Contains(node))
                {
                    ILBasicBlock block = (ILBasicBlock)node.UserData;

                    {
                        // Switch
                        ILLabel[]    caseLabels;
                        ILExpression switchArg;
                        ILLabel      fallLabel;
                        if (block.MatchLastAndBr(ILCode.Switch, out caseLabels, out switchArg, out fallLabel))
                        {
                            // Replace the switch code with ILSwitch
                            ILSwitch ilSwitch = new ILSwitch()
                            {
                                Condition = switchArg
                            };
                            block.Body.RemoveTail(ILCode.Switch, ILCode.Br);
                            block.Body.Add(ilSwitch);
                            block.Body.Add(new ILExpression(ILCode.Br, fallLabel));
                            result.Add(block);

                            // Remove the item so that it is not picked up as content
                            scope.RemoveOrThrow(node);

                            // Find the switch offset
                            int addValue = 0;
                            List <ILExpression> subArgs;
                            if (ilSwitch.Condition.Match(ILCode.Sub, out subArgs) && subArgs[1].Match(ILCode.Ldc_I4, out addValue))
                            {
                                ilSwitch.Condition = subArgs[0];
                            }

                            // Pull in code of cases
                            ControlFlowNode fallTarget = null;
                            labelToCfNode.TryGetValue(fallLabel, out fallTarget);

                            HashSet <ControlFlowNode> frontiers = new HashSet <ControlFlowNode>();
                            if (fallTarget != null)
                            {
                                frontiers.UnionWith(fallTarget.DominanceFrontier.Except(new [] { fallTarget }));
                            }

                            foreach (ILLabel condLabel in caseLabels)
                            {
                                ControlFlowNode condTarget = null;
                                labelToCfNode.TryGetValue(condLabel, out condTarget);
                                if (condTarget != null)
                                {
                                    frontiers.UnionWith(condTarget.DominanceFrontier.Except(new [] { condTarget }));
                                }
                            }

                            for (int i = 0; i < caseLabels.Length; i++)
                            {
                                ILLabel condLabel = caseLabels[i];

                                // Find or create new case block
                                ILSwitch.CaseBlock caseBlock = ilSwitch.CaseBlocks.FirstOrDefault(b => b.EntryGoto.Operand == condLabel);
                                if (caseBlock == null)
                                {
                                    caseBlock = new ILSwitch.CaseBlock()
                                    {
                                        Values    = new List <int>(),
                                        EntryGoto = new ILExpression(ILCode.Br, condLabel)
                                    };
                                    ilSwitch.CaseBlocks.Add(caseBlock);

                                    ControlFlowNode condTarget = null;
                                    labelToCfNode.TryGetValue(condLabel, out condTarget);
                                    if (condTarget != null && !frontiers.Contains(condTarget))
                                    {
                                        HashSet <ControlFlowNode> content = FindDominatedNodes(scope, condTarget);
                                        scope.ExceptWith(content);
                                        caseBlock.Body.AddRange(FindConditions(content, condTarget));
                                        // Add explicit break which should not be used by default, but the goto removal might decide to use it
                                        caseBlock.Body.Add(new ILBasicBlock()
                                        {
                                            Body =
                                            {
                                                new ILLabel()
                                                {
                                                    Name = "SwitchBreak_" + (nextLabelIndex++)
                                                },
                                                new ILExpression(ILCode.LoopOrSwitchBreak, null)
                                            }
                                        });
                                    }
                                }
                                caseBlock.Values.Add(i + addValue);
                            }

                            // Heuristis to determine if we want to use fallthough as default case
                            if (fallTarget != null && !frontiers.Contains(fallTarget))
                            {
                                HashSet <ControlFlowNode> content = FindDominatedNodes(scope, fallTarget);
                                if (content.Any())
                                {
                                    var caseBlock = new ILSwitch.CaseBlock()
                                    {
                                        EntryGoto = new ILExpression(ILCode.Br, fallLabel)
                                    };
                                    ilSwitch.CaseBlocks.Add(caseBlock);
                                    block.Body.RemoveTail(ILCode.Br);

                                    scope.ExceptWith(content);
                                    caseBlock.Body.AddRange(FindConditions(content, fallTarget));
                                    // Add explicit break which should not be used by default, but the goto removal might decide to use it
                                    caseBlock.Body.Add(new ILBasicBlock()
                                    {
                                        Body =
                                        {
                                            new ILLabel()
                                            {
                                                Name = "SwitchBreak_" + (nextLabelIndex++)
                                            },
                                            new ILExpression(ILCode.LoopOrSwitchBreak, null)
                                        }
                                    });
                                }
                            }
                        }

                        // Two-way branch
                        ILExpression condExpr;
                        ILLabel      trueLabel;
                        ILLabel      falseLabel;
                        if (block.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel))
                        {
                            // Swap bodies since that seems to be the usual C# order
                            ILLabel temp = trueLabel;
                            trueLabel  = falseLabel;
                            falseLabel = temp;
                            condExpr   = new ILExpression(ILCode.LogicNot, null, condExpr);

                            // Convert the brtrue to ILCondition
                            ILCondition ilCond = new ILCondition()
                            {
                                Condition = condExpr,
                                TrueBlock = new ILBlock()
                                {
                                    EntryGoto = new ILExpression(ILCode.Br, trueLabel)
                                },
                                FalseBlock = new ILBlock()
                                {
                                    EntryGoto = new ILExpression(ILCode.Br, falseLabel)
                                }
                            };
                            block.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
                            block.Body.Add(ilCond);
                            result.Add(block);

                            // Remove the item immediately so that it is not picked up as content
                            scope.RemoveOrThrow(node);

                            ControlFlowNode trueTarget = null;
                            labelToCfNode.TryGetValue(trueLabel, out trueTarget);
                            ControlFlowNode falseTarget = null;
                            labelToCfNode.TryGetValue(falseLabel, out falseTarget);

                            // Pull in the conditional code
                            if (trueTarget != null && HasSingleEdgeEnteringBlock(trueTarget))
                            {
                                HashSet <ControlFlowNode> content = FindDominatedNodes(scope, trueTarget);
                                scope.ExceptWith(content);
                                ilCond.TrueBlock.Body.AddRange(FindConditions(content, trueTarget));
                            }
                            if (falseTarget != null && HasSingleEdgeEnteringBlock(falseTarget))
                            {
                                HashSet <ControlFlowNode> content = FindDominatedNodes(scope, falseTarget);
                                scope.ExceptWith(content);
                                ilCond.FalseBlock.Body.AddRange(FindConditions(content, falseTarget));
                            }
                        }
                    }

                    // Add the node now so that we have good ordering
                    if (scope.Contains(node))
                    {
                        result.Add((ILNode)node.UserData);
                        scope.Remove(node);
                    }
                }

                // depth-first traversal of dominator tree
                for (int i = node.DominatorTreeChildren.Count - 1; i >= 0; i--)
                {
                    agenda.Push(node.DominatorTreeChildren[i]);
                }
            }

            // Add whatever is left
            foreach (var node in scope)
            {
                result.Add((ILNode)node.UserData);
            }

            return(result);
        }
Ejemplo n.º 6
0
        bool HandleStringFixing(ILVariable pinnedVar, List <ILNode> body, ref int pos, ref ILExpression fixedStmtInitializer)
        {
            // fixed (stloc(pinnedVar, ldloc(text))) {
            //   var1 = var2 = conv.i(ldloc(pinnedVar))
            //   if (logicnot(logicnot(var1))) {
            //     var2 = add(var1, call(RuntimeHelpers::get_OffsetToStringData))
            //   }
            //   stloc(ptrVar, var2)
            //   ...

            if (pos >= body.Count)
            {
                return(false);
            }

            ILVariable   var1, var2;
            ILExpression varAssignment, ptrInitialization;

            if (!(body[pos].Match(ILCode.Stloc, out var1, out varAssignment) && varAssignment.Match(ILCode.Stloc, out var2, out ptrInitialization)))
            {
                return(false);
            }
            if (!(var1.IsGenerated && var2.IsGenerated))
            {
                return(false);
            }
            if (ptrInitialization.Code == ILCode.Conv_I || ptrInitialization.Code == ILCode.Conv_U)
            {
                ptrInitialization = ptrInitialization.Arguments[0];
            }
            if (!ptrInitialization.MatchLdloc(pinnedVar))
            {
                return(false);
            }

            ILCondition ifStmt = body[pos + 1] as ILCondition;

            if (!(ifStmt != null && ifStmt.TrueBlock != null && ifStmt.TrueBlock.Body.Count == 1 && (ifStmt.FalseBlock == null || ifStmt.FalseBlock.Body.Count == 0)))
            {
                return(false);
            }
            if (!UnpackDoubleNegation(ifStmt.Condition).MatchLdloc(var1))
            {
                return(false);
            }
            ILVariable   assignedVar;
            ILExpression assignedExpr;

            if (!(ifStmt.TrueBlock.Body[0].Match(ILCode.Stloc, out assignedVar, out assignedExpr) && assignedVar == var2 && assignedExpr.Code == ILCode.Add))
            {
                return(false);
            }
            MethodReference calledMethod;

            if (!(assignedExpr.Arguments[0].MatchLdloc(var1) && assignedExpr.Arguments[1].Match(ILCode.Call, out calledMethod)))
            {
                return(false);
            }
            if (!(calledMethod.Name == "get_OffsetToStringData" && calledMethod.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers"))
            {
                return(false);
            }

            ILVariable pointerVar;

            if (body[pos + 2].Match(ILCode.Stloc, out pointerVar, out assignedExpr) && assignedExpr.MatchLdloc(var2))
            {
                pos += 3;
                fixedStmtInitializer.Operand = pointerVar;
                return(true);
            }
            return(false);
        }
Ejemplo n.º 7
0
        void CachedDelegateInitialization(ILBlock block, ref int i)
        {
            // if (logicnot(ldsfld(field))) {
            //     stsfld(field, newobj(Action::.ctor, ldnull(), ldftn(method)))
            // } else {
            // }
            // ...(..., ldsfld(field), ...)

            ILCondition c = block.Body[i] as ILCondition;

            if (c == null || c.Condition == null && c.TrueBlock == null || c.FalseBlock == null)
            {
                return;
            }
            if (!(c.TrueBlock.Body.Count == 1 && c.FalseBlock.Body.Count == 0))
            {
                return;
            }
            if (!c.Condition.Match(ILCode.LogicNot))
            {
                return;
            }
            ILExpression condition = c.Condition.Arguments.Single() as ILExpression;

            if (condition == null || condition.Code != ILCode.Ldsfld)
            {
                return;
            }
            FieldDefinition field = ((FieldReference)condition.Operand).ResolveWithinSameModule();             // field is defined in current assembly

            if (field == null || !field.IsCompilerGeneratedOrIsInCompilerGeneratedClass())
            {
                return;
            }
            ILExpression stsfld = c.TrueBlock.Body[0] as ILExpression;

            if (!(stsfld != null && stsfld.Code == ILCode.Stsfld && ((FieldReference)stsfld.Operand).ResolveWithinSameModule() == field))
            {
                return;
            }
            ILExpression newObj = stsfld.Arguments[0];

            if (!(newObj.Code == ILCode.Newobj && newObj.Arguments.Count == 2))
            {
                return;
            }
            if (newObj.Arguments[0].Code != ILCode.Ldnull)
            {
                return;
            }
            if (newObj.Arguments[1].Code != ILCode.Ldftn)
            {
                return;
            }
            MethodDefinition anonymousMethod = ((MethodReference)newObj.Arguments[1].Operand).ResolveWithinSameModule();             // method is defined in current assembly

            if (!Ast.Transforms.DelegateConstruction.IsAnonymousMethod(context, anonymousMethod))
            {
                return;
            }

            ILNode followingNode = block.Body.ElementAtOrDefault(i + 1);

            if (followingNode != null && followingNode.GetSelfAndChildrenRecursive <ILExpression>().Count(
                    e => e.Code == ILCode.Ldsfld && ((FieldReference)e.Operand).ResolveWithinSameModule() == field) == 1)
            {
                foreach (ILExpression parent in followingNode.GetSelfAndChildrenRecursive <ILExpression>())
                {
                    for (int j = 0; j < parent.Arguments.Count; j++)
                    {
                        if (parent.Arguments[j].Code == ILCode.Ldsfld && ((FieldReference)parent.Arguments[j].Operand).ResolveWithinSameModule() == field)
                        {
                            parent.Arguments[j] = newObj;
                            block.Body.RemoveAt(i);
                            i -= new ILInlining(method).InlineInto(block.Body, i, aggressive: true);
                            return;
                        }
                    }
                }
            }
        }
Ejemplo n.º 8
0
        void CachedDelegateInitializationWithLocal(ILBlock block, ref int i)
        {
            // if (logicnot(ldloc(v))) {
            //     stloc(v, newobj(Action::.ctor, ldloc(displayClass), ldftn(method)))
            // } else {
            // }
            // ...(..., ldloc(v), ...)

            ILCondition c = block.Body[i] as ILCondition;

            if (c == null || c.Condition == null && c.TrueBlock == null || c.FalseBlock == null)
            {
                return;
            }
            if (!(c.TrueBlock.Body.Count == 1 && c.FalseBlock.Body.Count == 0))
            {
                return;
            }
            if (!c.Condition.Match(ILCode.LogicNot))
            {
                return;
            }
            ILExpression condition = c.Condition.Arguments.Single() as ILExpression;

            if (condition == null || condition.Code != ILCode.Ldloc)
            {
                return;
            }
            ILVariable   v     = (ILVariable)condition.Operand;
            ILExpression stloc = c.TrueBlock.Body[0] as ILExpression;

            if (!(stloc != null && stloc.Code == ILCode.Stloc && (ILVariable)stloc.Operand == v))
            {
                return;
            }
            ILExpression newObj = stloc.Arguments[0];

            if (!(newObj.Code == ILCode.Newobj && newObj.Arguments.Count == 2))
            {
                return;
            }
            if (newObj.Arguments[0].Code != ILCode.Ldloc)
            {
                return;
            }
            if (newObj.Arguments[1].Code != ILCode.Ldftn)
            {
                return;
            }
            MethodDefinition anonymousMethod = ((MethodReference)newObj.Arguments[1].Operand).ResolveWithinSameModule();             // method is defined in current assembly

            if (!Ast.Transforms.DelegateConstruction.IsAnonymousMethod(context, anonymousMethod))
            {
                return;
            }

            ILNode followingNode = block.Body.ElementAtOrDefault(i + 1);

            if (followingNode != null && followingNode.GetSelfAndChildrenRecursive <ILExpression>().Count(
                    e => e.Code == ILCode.Ldloc && (ILVariable)e.Operand == v) == 1)
            {
                ILInlining inlining = new ILInlining(method);
                if (!(inlining.numLdloc.GetOrDefault(v) == 2 && inlining.numStloc.GetOrDefault(v) == 2 && inlining.numLdloca.GetOrDefault(v) == 0))
                {
                    return;
                }

                // Find the store instruction that initializes the local to null:
                foreach (ILBlock storeBlock in method.GetSelfAndChildrenRecursive <ILBlock>())
                {
                    for (int j = 0; j < storeBlock.Body.Count; j++)
                    {
                        ILVariable   storedVar;
                        ILExpression storedExpr;
                        if (storeBlock.Body[j].Match(ILCode.Stloc, out storedVar, out storedExpr) && storedVar == v && storedExpr.Match(ILCode.Ldnull))
                        {
                            // Remove the instruction
                            storeBlock.Body.RemoveAt(j);
                            if (storeBlock == block && j < i)
                            {
                                i--;
                            }
                            break;
                        }
                    }
                }

                block.Body[i] = stloc;                 // remove the 'if (v==null)'
                inlining      = new ILInlining(method);
                inlining.InlineIfPossible(block.Body, ref i);
            }
        }