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); }
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); }