private bool ForwardLabelsAllowLeaving()
        {
            bool madeChanges = false;

            SmallDictionary <object, LabelInfo> .KeyCollection labels = _labelInfos.Keys;

            bool done;

            do
            {
                done = true;

                foreach (object label in labels)
                {
                    LabelInfo labelInfo = _labelInfos[label];
                    if (labelInfo.targetOfConditionalBranches)
                    {
                        // only unconditional labels can be forwarded as a leave
                        continue;
                    }

                    BasicBlock targetBlock = labelInfo.bb;

                    Debug.Assert(!IsSpecialEndHandlerBlock(targetBlock));

                    if (targetBlock.HasNoRegularInstructions)
                    {
                        BasicBlock targetsTarget = null;
                        switch (targetBlock.BranchCode)
                        {
                        case ILOpCode.Br:
                            targetsTarget = targetBlock.BranchBlock;
                            break;

                        case ILOpCode.Nop:
                            targetsTarget = targetBlock.NextBlock;
                            break;
                        }

                        if ((targetsTarget != null) && (targetsTarget != targetBlock))
                        {
                            ExceptionHandlerScope currentHandler = targetBlock.EnclosingHandler;
                            ExceptionHandlerScope newHandler     = targetsTarget.EnclosingHandler;

                            // can skip the jump if it is in the same try scope
                            if (CanMoveLabelToAnotherHandler(currentHandler, newHandler))
                            {
                                _labelInfos[label] = labelInfo.WithNewTarget(targetsTarget);
                                madeChanges        = true;

                                // since we modified at least one label we want to try again.
                                done = false;
                            }
                        }
                    }
                }
            } while (!done);

            return(madeChanges);
        }
        private bool ForwardLabelsNoLeaving()
        {
            bool madeChanges = false;

            SmallDictionary <object, LabelInfo> .KeyCollection labels = _labelInfos.Keys;

            bool done;

            do
            {
                done = true;

                foreach (object label in labels)
                {
                    LabelInfo  labelInfo   = _labelInfos[label];
                    BasicBlock targetBlock = labelInfo.bb;

                    Debug.Assert(!IsSpecialEndHandlerBlock(targetBlock));

                    if (targetBlock.HasNoRegularInstructions)
                    {
                        BasicBlock targetsTarget = null;
                        switch (targetBlock.BranchCode)
                        {
                        case ILOpCode.Br:
                            targetsTarget = targetBlock.BranchBlock;
                            break;

                        case ILOpCode.Nop:
                            targetsTarget = targetBlock.NextBlock;
                            break;
                        }

                        if ((targetsTarget != null) && (targetsTarget != targetBlock))
                        {
                            ExceptionHandlerScope currentHandler = targetBlock.EnclosingHandler;
                            ExceptionHandlerScope newHandler     = targetsTarget.EnclosingHandler;

                            // forward the label if can be done without leaving current handler
                            if (currentHandler == newHandler)
                            {
                                _labelInfos[label] = labelInfo.WithNewTarget(targetsTarget);
                                madeChanges        = true;

                                // since we modified at least one label we want to try again.
                                done = false;
                            }
                        }
                    }
                }
            } while (!done);

            return(madeChanges);
        }
Exemple #3
0
            private bool TryOptimizeSameAsNext(BasicBlock next, ref int delta)
            {
                if (next.HasNoRegularInstructions &&
                    next.BranchCode == this.BranchCode &&
                    next.BranchBlock.Start == this.BranchBlock.Start)
                {
                    if (next.EnclosingHandler == this.EnclosingHandler)
                    {
                        int diff = this.BranchCode.Size() + this.BranchCode.GetBranchOperandSize();
                        delta -= diff;
                        this.SetBranch(null, ILOpCode.Nop);

                        // If current block has no regular instructions the resulting block is a trivial noop
                        // TryOptimizeBranchOverUncondBranch relies on an invariant that
                        // trivial blocks are not targeted by branches,
                        // make sure we are not breaking this condition.
                        if (this.HasNoRegularInstructions)
                        {
                            SmallDictionary <object, LabelInfo> labelInfos            = builder._labelInfos;
                            SmallDictionary <object, LabelInfo> .KeyCollection labels = labelInfos.Keys;
                            foreach (object label in labels)
                            {
                                LabelInfo info = labelInfos[label];
                                if (info.bb == this)
                                {
                                    // move the label from "this" to "next"
                                    labelInfos[label] = info.WithNewTarget(next);
                                }
                            }
                        }

                        return(true);
                    }
                }

                return(false);
            }