protected virtual AstNode _Optimize(AstNodeExprBinop binary) { //Console.WriteLine("Optimize.AstNodeExprBinop: {0} {1} {2}", Binary.LeftNode, Binary.Operator, Binary.RightNode); var leftImm = binary.LeftNode as AstNodeExprImm; var rightImm = binary.RightNode as AstNodeExprImm; var leftType = binary.LeftNode.Type; var rightType = binary.RightNode.Type; var Operator = binary.Operator; if (leftType == rightType) { if (AstUtils.IsTypeFloat(leftType)) { var type = leftType; if (leftImm != null && rightImm != null) { var leftValue = Convert.ToDouble(leftImm.Value); var rightValue = Convert.ToDouble(rightImm.Value); switch (Operator) { case "+": return(new AstNodeExprImm(AstUtils.CastType(leftValue + rightValue, type))); case "-": return(new AstNodeExprImm(AstUtils.CastType(leftValue - rightValue, type))); case "*": return(new AstNodeExprImm(AstUtils.CastType(leftValue * rightValue, type))); case "/": return(new AstNodeExprImm(AstUtils.CastType(leftValue / rightValue, type))); } } else if (leftImm != null) { var leftValue = Convert.ToInt64(leftImm.Value); switch (Operator) { case "|": if (leftValue == 0) { return(binary.RightNode); } break; case "+": if (leftValue == 0) { return(binary.RightNode); } break; case "-": if (leftValue == 0) { return(new AstNodeExprUnop("-", binary.RightNode)); } break; case "*": //if (LeftValue == 0) return new AstNodeExprImm(AstUtils.CastType(0, Type)); if (leftValue == 1) { return(binary.RightNode); } break; case "/": //if (LeftValue == 0) return new AstNodeExprImm(AstUtils.CastType(0, Type)); break; } } else if (rightImm != null) { var rightValue = Convert.ToInt64(rightImm.Value); switch (Operator) { case "|": if (rightValue == 0) { return(binary.LeftNode); } break; case "+": if (rightValue == 0) { return(binary.LeftNode); } break; case "-": if (rightValue == 0) { return(binary.LeftNode); } break; case "*": if (rightValue == 1) { return(binary.LeftNode); } break; case "/": //if (LeftValue == 0) return new AstNodeExprImm(AstUtils.CastType(0, Type)); break; } } } else { var unop = binary.RightNode as AstNodeExprUnop; if (unop != null) { var rightUnary = unop; if (Operator == "+" || Operator == "-") { if (rightUnary.Operator == "-") { return(new AstNodeExprBinop(binary.LeftNode, Operator == "+" ? "-" : "+", rightUnary.RightNode)); } } } var type = leftType; // Can optimize just literal values. if (leftImm != null && rightImm != null) { if (AstUtils.IsTypeSigned(leftType)) { var leftValue = Convert.ToInt64(leftImm.Value); var rightValue = Convert.ToInt64(rightImm.Value); switch (Operator) { case "+": return(new AstNodeExprImm(AstUtils.CastType(leftValue + rightValue, type))); case "-": return(new AstNodeExprImm(AstUtils.CastType(leftValue - rightValue, type))); case "*": return(new AstNodeExprImm(AstUtils.CastType(leftValue * rightValue, type))); case "/": return(new AstNodeExprImm(AstUtils.CastType(leftValue / rightValue, type))); case "<<": return(new AstNodeExprImm(AstUtils.CastType(leftValue << (int)rightValue, type))); case ">>": return(new AstNodeExprImm(AstUtils.CastType(leftValue >> (int)rightValue, type))); } } else { var leftValue = Convert.ToUInt64(leftImm.Value); var rightValue = Convert.ToUInt64(rightImm.Value); // Optimize adding 0 switch (Operator) { case "+": return(new AstNodeExprImm(AstUtils.CastType(leftValue + rightValue, type))); case "-": return(new AstNodeExprImm(AstUtils.CastType(leftValue - rightValue, type))); case "*": return(new AstNodeExprImm(AstUtils.CastType(leftValue * rightValue, type))); case "/": return(new AstNodeExprImm(AstUtils.CastType(leftValue / rightValue, type))); case "<<": return(new AstNodeExprImm(AstUtils.CastType(leftValue << (int)rightValue, type))); case ">>": return(new AstNodeExprImm(AstUtils.CastType(leftValue >> (int)rightValue, type))); } } } else if (leftImm != null) { var leftValue = Convert.ToInt64(leftImm.Value); switch (Operator) { case "&": if (leftValue == 0) { return(new AstNodeExprImm(0)); } break; case "|": if (leftValue == 0) { return(binary.RightNode); } break; case "+": if (leftValue == 0) { return(binary.RightNode); } break; case "-": if (leftValue == 0) { return(new AstNodeExprUnop("-", binary.RightNode)); } break; case "*": //if (LeftValue == 0) return new AstNodeExprImm(AstUtils.CastType(0, Type)); if (leftValue == 1) { return(binary.RightNode); } break; case "/": //if (LeftValue == 0) return new AstNodeExprImm(AstUtils.CastType(0, Type)); break; } } else if (rightImm != null) { var rightValue = Convert.ToInt64(rightImm.Value); switch (Operator) { case "0": if (rightValue == 0) { return(new AstNodeExprImm(0)); } break; case "|": if (rightValue == 0) { return(binary.LeftNode); } break; case "+": if (rightValue == 0) { return(binary.LeftNode); } if (rightValue < 0) { return(new AstNodeExprBinop(binary.LeftNode, "-", new AstNodeExprImm(AstUtils.Negate(rightImm.Value)))); } break; case "-": if (rightValue == 0) { return(binary.LeftNode); } break; case "*": if (rightValue == 1) { return(binary.LeftNode); } break; case "/": //if (RightValue == 0) throw(new Exception("Can't divide by 0")); if (rightValue == 1) { return(binary.LeftNode); } break; } } } // !AstUtils.IsTypeFloat(LeftType) } // Special optimizations if ((leftType == typeof(uint) || leftType == typeof(int)) && rightType == typeof(int) && rightImm != null) { var rightValue = Convert.ToInt64(rightImm.Value); if (Operator == ">>" && rightValue == 0) { return(binary.LeftNode); } } return(binary); }
protected virtual AstNode _Optimize(AstNodeExprBinop Binary) { //Console.WriteLine("Optimize.AstNodeExprBinop: {0} {1} {2}", Binary.LeftNode, Binary.Operator, Binary.RightNode); var LeftImm = (Binary.LeftNode as AstNodeExprImm); var RightImm = (Binary.RightNode as AstNodeExprImm); var LeftType = Binary.LeftNode.Type; var RightType = Binary.RightNode.Type; var Operator = Binary.Operator; if ((LeftType == RightType)) { if (AstUtils.IsTypeFloat(LeftType)) { var Type = LeftType; if ((LeftImm != null) && (RightImm != null)) { var LeftValue = Convert.ToDouble(LeftImm.Value); var RightValue = Convert.ToDouble(RightImm.Value); switch (Operator) { case "+": return(new AstNodeExprImm(AstUtils.CastType(LeftValue + RightValue, Type))); case "-": return(new AstNodeExprImm(AstUtils.CastType(LeftValue - RightValue, Type))); case "*": return(new AstNodeExprImm(AstUtils.CastType(LeftValue * RightValue, Type))); case "/": return(new AstNodeExprImm(AstUtils.CastType(LeftValue / RightValue, Type))); } } else if (LeftImm != null) { var LeftValue = Convert.ToInt64(LeftImm.Value); switch (Operator) { case "|": if (LeftValue == 0) { return(Binary.RightNode); } break; case "+": if (LeftValue == 0) { return(Binary.RightNode); } break; case "-": if (LeftValue == 0) { return(new AstNodeExprUnop("-", Binary.RightNode)); } break; case "*": //if (LeftValue == 0) return new AstNodeExprImm(AstUtils.CastType(0, Type)); if (LeftValue == 1) { return(Binary.RightNode); } break; case "/": //if (LeftValue == 0) return new AstNodeExprImm(AstUtils.CastType(0, Type)); break; } } else if (RightImm != null) { var RightValue = Convert.ToInt64(RightImm.Value); switch (Operator) { case "|": if (RightValue == 0) { return(Binary.LeftNode); } break; case "+": if (RightValue == 0) { return(Binary.LeftNode); } break; case "-": if (RightValue == 0) { return(Binary.LeftNode); } break; case "*": if (RightValue == 1) { return(Binary.LeftNode); } break; case "/": //if (LeftValue == 0) return new AstNodeExprImm(AstUtils.CastType(0, Type)); break; } } } else { if (Binary.RightNode is AstNodeExprUnop) { var RightUnary = Binary.RightNode as AstNodeExprUnop; if (Operator == "+" || Operator == "-") { if (RightUnary.Operator == "-") { return(new AstNodeExprBinop(Binary.LeftNode, (Operator == "+") ? "-" : "+", RightUnary.RightNode)); } } } var Type = LeftType; // Can optimize just literal values. if ((LeftImm != null) && (RightImm != null)) { if (AstUtils.IsTypeSigned(LeftType)) { var LeftValue = Convert.ToInt64(LeftImm.Value); var RightValue = Convert.ToInt64(RightImm.Value); switch (Operator) { case "+": return(new AstNodeExprImm(AstUtils.CastType(LeftValue + RightValue, Type))); case "-": return(new AstNodeExprImm(AstUtils.CastType(LeftValue - RightValue, Type))); case "*": return(new AstNodeExprImm(AstUtils.CastType(LeftValue * RightValue, Type))); case "/": return(new AstNodeExprImm(AstUtils.CastType(LeftValue / RightValue, Type))); case "<<": return(new AstNodeExprImm(AstUtils.CastType(LeftValue << (int)RightValue, Type))); case ">>": return(new AstNodeExprImm(AstUtils.CastType(LeftValue >> (int)RightValue, Type))); } } else { var LeftValue = Convert.ToUInt64(LeftImm.Value); var RightValue = Convert.ToUInt64(RightImm.Value); // Optimize adding 0 switch (Operator) { case "+": return(new AstNodeExprImm(AstUtils.CastType(LeftValue + RightValue, Type))); case "-": return(new AstNodeExprImm(AstUtils.CastType(LeftValue - RightValue, Type))); case "*": return(new AstNodeExprImm(AstUtils.CastType(LeftValue * RightValue, Type))); case "/": return(new AstNodeExprImm(AstUtils.CastType(LeftValue / RightValue, Type))); case "<<": return(new AstNodeExprImm(AstUtils.CastType(LeftValue << (int)RightValue, Type))); case ">>": return(new AstNodeExprImm(AstUtils.CastType(LeftValue >> (int)RightValue, Type))); } } } else if (LeftImm != null) { var LeftValue = Convert.ToInt64(LeftImm.Value); switch (Operator) { case "&": if (LeftValue == 0) { return(new AstNodeExprImm(0)); } break; case "|": if (LeftValue == 0) { return(Binary.RightNode); } break; case "+": if (LeftValue == 0) { return(Binary.RightNode); } break; case "-": if (LeftValue == 0) { return(new AstNodeExprUnop("-", Binary.RightNode)); } break; case "*": //if (LeftValue == 0) return new AstNodeExprImm(AstUtils.CastType(0, Type)); if (LeftValue == 1) { return(Binary.RightNode); } break; case "/": //if (LeftValue == 0) return new AstNodeExprImm(AstUtils.CastType(0, Type)); break; } } else if (RightImm != null) { var RightValue = Convert.ToInt64(RightImm.Value); switch (Operator) { case "0": if (RightValue == 0) { return(new AstNodeExprImm(0)); } break; case "|": if (RightValue == 0) { return(Binary.LeftNode); } break; case "+": if (RightValue == 0) { return(Binary.LeftNode); } if (RightValue < 0) { return(new AstNodeExprBinop(Binary.LeftNode, "-", new AstNodeExprImm(AstUtils.Negate(RightImm.Value)))); } break; case "-": if (RightValue == 0) { return(Binary.LeftNode); } break; case "*": if (RightValue == 1) { return(Binary.LeftNode); } break; case "/": //if (RightValue == 0) throw(new Exception("Can't divide by 0")); if (RightValue == 1) { return(Binary.LeftNode); } break; } } } // !AstUtils.IsTypeFloat(LeftType) } // Special optimizations if ((LeftType == typeof(uint) || LeftType == typeof(int)) && RightType == typeof(int)) { if (RightImm != null) { var RightValue = Convert.ToInt64(RightImm.Value); if (Operator == ">>" && (RightValue == 0)) { return(Binary.LeftNode); } } } return(Binary); }