public static void OptimizeIf(Branch condition) { Node trueStart = condition.FloatUpToNeighbours(condition.TrueSuccessor); Node falseStart = condition.FloatUpToNeighbours(condition.FalseSuccessor); NodeCollection trueReachable = trueStart != null ? trueStart.GetReachableNodes() : NodeCollection.Empty; NodeCollection falseReachable = falseStart != null ? falseStart.GetReachableNodes() : NodeCollection.Empty; NodeCollection commonReachable = NodeCollection.Intersect(trueReachable, falseReachable); NodeCollection trueNodes = trueReachable.Clone(); trueNodes.RemoveRange(commonReachable); NodeCollection falseNodes = falseReachable.Clone(); falseNodes.RemoveRange(commonReachable); // Replace the basic block with condition node Node conditionParent = condition.Parent; int conditionIndex = condition.Index; ConditionalNode conditionalNode = new ConditionalNode(condition); conditionalNode.MoveTo(conditionParent, conditionIndex); // If there are no common nodes, let the 'true' block be the default if (commonReachable.Count > 0) { trueNodes.MoveTo(conditionalNode.TrueBody); } falseNodes.MoveTo(conditionalNode.FalseBody); // Optimize the created subtrees conditionalNode.TrueBody.OptimizeConditions(); conditionalNode.FalseBody.OptimizeConditions(); }
Ast.Expression MakeBranchCondition_Internal(Branch branch) { if (branch is SimpleBranch) { List<Ast.Expression> args = TransformExpressionArguments((ILExpression)((SimpleBranch)branch).BasicBlock.Body[0]); Ast.Expression arg1 = args.Count >= 1 ? args[0] : null; Ast.Expression arg2 = args.Count >= 2 ? args[1] : null; switch(((ILExpression)((SimpleBranch)branch).BasicBlock.Body[0]).OpCode.Code) { case Code.Brfalse: return new Ast.UnaryOperatorExpression(arg1, UnaryOperatorType.Not); case Code.Brtrue: return arg1; case Code.Beq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2); case Code.Bge: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2); case Code.Bge_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2); case Code.Bgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); case Code.Bgt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); case Code.Ble: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2); case Code.Ble_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2); case Code.Blt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); case Code.Blt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); case Code.Bne_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2); case Code.Leave: return new Ast.PrimitiveExpression(true, true.ToString()); default: throw new Exception("Bad opcode"); } } else if (branch is ShortCircuitBranch) { ShortCircuitBranch scBranch = (ShortCircuitBranch)branch; switch(scBranch.Operator) { case ShortCircuitOperator.LeftAndRight: return new BinaryOperatorExpression( MakeBranchCondition(scBranch.Left), BinaryOperatorType.LogicalAnd, MakeBranchCondition(scBranch.Right) ); case ShortCircuitOperator.LeftOrRight: return new BinaryOperatorExpression( MakeBranchCondition(scBranch.Left), BinaryOperatorType.LogicalOr, MakeBranchCondition(scBranch.Right) ); case ShortCircuitOperator.NotLeftAndRight: return new BinaryOperatorExpression( new UnaryOperatorExpression(MakeBranchCondition(scBranch.Left), UnaryOperatorType.Not), BinaryOperatorType.LogicalAnd, MakeBranchCondition(scBranch.Right) ); case ShortCircuitOperator.NotLeftOrRight: return new BinaryOperatorExpression( new UnaryOperatorExpression(MakeBranchCondition(scBranch.Left), UnaryOperatorType.Not), BinaryOperatorType.LogicalOr, MakeBranchCondition(scBranch.Right) ); default: throw new Exception("Bad operator"); } } else { throw new Exception("Bad type"); } }
Ast.Expression MakeBranchCondition(Branch branch) { return new ParenthesizedExpression(MakeBranchCondition_Internal(branch)); }
public ConditionalNode(Branch condition) { this.condition = condition; condition.MoveTo(this); trueBody.MoveTo(this); falseBody.MoveTo(this); }