/// <summary> /// Group input into a set of blocks that can be later arbitraliby schufled. /// The method adds necessary branches to make control flow between blocks /// explicit and thus order independent. /// </summary> void SplitToMovableBlocks(ILBlock block) { // Remve no-ops // TODO: Assign the no-op range to someting block.Body = block.Body.Where(n => !(n is ILExpression && ((ILExpression)n).OpCode == OpCodes.Nop)).ToList(); List<ILNode> moveableBlocks = new List<ILNode>(); ILMoveableBlock moveableBlock = new ILMoveableBlock() { OriginalOrder = (nextBlockIndex++) }; moveableBlocks.Add(moveableBlock); block.EntryPoint = new ILLabel() { Name = "Block_" + moveableBlock.OriginalOrder }; moveableBlock.Body.Add(block.EntryPoint); if (block.Body.Count > 0) { moveableBlock.Body.Add(block.Body[0]); for (int i = 1; i < block.Body.Count; i++) { ILNode lastNode = block.Body[i - 1]; ILNode currNode = block.Body[i]; // Insert split if ((currNode is ILLabel && !(lastNode is ILLabel)) || lastNode is ILTryCatchBlock || currNode is ILTryCatchBlock || (lastNode is ILExpression) && ((ILExpression)lastNode).OpCode.IsBranch() || (currNode is ILExpression) && ((ILExpression)currNode).OpCode.IsBranch()) { ILBlock lastBlock = moveableBlock; moveableBlock = new ILMoveableBlock() { OriginalOrder = (nextBlockIndex++) }; moveableBlocks.Add(moveableBlock); // Explicit branch from one block to other // (unless the last expression was unconditional branch) if (!(lastNode is ILExpression) || ((ILExpression)lastNode).OpCode.CanFallThough()) { ILLabel blockLabel = new ILLabel() { Name = "Block_" + moveableBlock.OriginalOrder }; lastBlock.Body.Add(new ILExpression(OpCodes.Br, blockLabel)); moveableBlock.Body.Add(blockLabel); } } moveableBlock.Body.Add(currNode); } } block.Body = moveableBlocks; return; }
/* public enum ShortCircuitOperator { LeftAndRight, LeftOrRight, NotLeftAndRight, NotLeftOrRight, } static bool TryOptimizeShortCircuit(Node head) { if ((head is BasicBlock) && (head as BasicBlock).BranchBasicBlock != null && (head as BasicBlock).FallThroughBasicBlock != null) { head.Parent.MergeChilds<SimpleBranch>(head); return true; } Branch top = head as Branch; if (top == null) return false; Branch left = head.FloatUpToNeighbours(top.TrueSuccessor) as Branch; Branch right = head.FloatUpToNeighbours(top.FalseSuccessor) as Branch; // A & B if (left != null && left.Predecessors.Count == 1 && left.FalseSuccessor == top.FalseSuccessor) { ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, left); scBranch.Operator = ShortCircuitOperator.LeftAndRight; return true; } // ~A | B if (left != null && left.Predecessors.Count == 1 && left.TrueSuccessor == top.FalseSuccessor) { ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, left); scBranch.Operator = ShortCircuitOperator.NotLeftOrRight; return true; } // A | B if (right != null && right.Predecessors.Count == 1 && right.TrueSuccessor == top.TrueSuccessor) { ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, right); scBranch.Operator = ShortCircuitOperator.LeftOrRight; return true; } // ~A & B if (right != null && right.Predecessors.Count == 1 && right.FalseSuccessor == top.TrueSuccessor) { ShortCircuitBranch scBranch = top.Parent.MergeChilds<ShortCircuitBranch>(top, right); scBranch.Operator = ShortCircuitOperator.NotLeftAndRight; return true; } return false; } */ void OrderNodes(ILBlock ast) { // Order movable nodes var blocks = ast.GetSelfAndChildrenRecursive<ILBlock>().Where(b => !(b is ILMoveableBlock)).ToList(); ILMoveableBlock first = new ILMoveableBlock() { OriginalOrder = -1 }; foreach(ILBlock block in blocks) { block.Body = block.Body.OrderBy(n => (n.GetSelfAndChildrenRecursive<ILMoveableBlock>().FirstOrDefault() ?? first).OriginalOrder).ToList(); } }