Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(746)

Side by Side Diff: src/sksl/SkSLIRGenerator.cpp

Issue 2489673002: added constant folding & branch elimination to skslc (Closed)
Patch Set: minor cleanups Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkSLIRGenerator.h" 8 #include "SkSLIRGenerator.h"
9 9
10 #include "limits.h" 10 #include "limits.h"
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 if (!ifTrue) { 239 if (!ifTrue) {
240 return nullptr; 240 return nullptr;
241 } 241 }
242 std::unique_ptr<Statement> ifFalse; 242 std::unique_ptr<Statement> ifFalse;
243 if (s.fIfFalse) { 243 if (s.fIfFalse) {
244 ifFalse = this->convertStatement(*s.fIfFalse); 244 ifFalse = this->convertStatement(*s.fIfFalse);
245 if (!ifFalse) { 245 if (!ifFalse) {
246 return nullptr; 246 return nullptr;
247 } 247 }
248 } 248 }
249 if (test->fKind == Expression::kBoolLiteral_Kind) {
250 // static boolean value, fold down to a single branch
251 if (((BoolLiteral&) *test).fValue) {
252 return ifTrue;
253 } else if (s.fIfFalse) {
254 return ifFalse;
255 } else {
256 // False & no else clause. Not an error, so don't return null!
257 return std::unique_ptr<Statement>(new Block(s.fPosition, { }, fSymbo lTable));
258 }
259 }
249 return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(tes t), 260 return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(tes t),
250 std::move(ifTrue), std::mo ve(ifFalse))); 261 std::move(ifTrue), std::mo ve(ifFalse)));
251 } 262 }
252 263
253 std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) { 264 std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) {
254 AutoLoopLevel level(this); 265 AutoLoopLevel level(this);
255 AutoSymbolTable table(this); 266 AutoSymbolTable table(this);
256 std::unique_ptr<Statement> initializer; 267 std::unique_ptr<Statement> initializer;
257 if (f.fInitializer) { 268 if (f.fInitializer) {
258 initializer = this->convertStatement(*f.fInitializer); 269 initializer = this->convertStatement(*f.fInitializer);
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
787 } 798 }
788 return false; 799 return false;
789 } 800 }
790 if (tryFlipped) { 801 if (tryFlipped) {
791 return determine_binary_type(context, op, right, left, outRightType, out LeftType, 802 return determine_binary_type(context, op, right, left, outRightType, out LeftType,
792 outResultType, false); 803 outResultType, false);
793 } 804 }
794 return false; 805 return false;
795 } 806 }
796 807
808 /**
809 * If both operands are compile-time constants and can be folded, returns an exp ression representing
810 * the folded value. Otherwise, returns null.
811 */
812 std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
813 Token::Kind op,
814 const Expression& right) {
815 if (left.fKind == Expression::kBoolLiteral_Kind &&
816 right.fKind == Expression::kBoolLiteral_Kind) {
817 bool leftVal = ((BoolLiteral&) left).fValue;
818 bool rightVal = ((BoolLiteral&) right).fValue;
819 bool result;
820 switch (op) {
821 case Token::LOGICALAND: result = leftVal && rightVal; break;
822 case Token::LOGICALOR: result = leftVal || rightVal; break;
823 case Token::LOGICALXOR: result = leftVal ^ rightVal; break;
824 default: return nullptr;
825 }
826 return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fPosit ion, result));
827 }
828 #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fPosition, \
829 leftVal o p rightVal))
830 if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression: :kIntLiteral_Kind) {
831 int64_t leftVal = ((IntLiteral&) left).fValue;
dogben 2016/11/09 15:35:36 Assuming integer overflow is well-defined in SkSL,
ethannicholas 2016/11/09 16:36:21 In GLSL ES, integer precision varies. It is allowe
832 int64_t rightVal = ((IntLiteral&) right).fValue;
833 switch (op) {
834 case Token::PLUS: return RESULT(Int, +);
835 case Token::MINUS: return RESULT(Int, -);
836 case Token::STAR: return RESULT(Int, *);
837 case Token::SLASH: return RESULT(Int, /);
838 case Token::PERCENT: return RESULT(Int, %);
839 case Token::BITWISEAND: return RESULT(Int, &);
840 case Token::BITWISEOR: return RESULT(Int, |);
841 case Token::BITWISEXOR: return RESULT(Int, ^);
842 case Token::SHL: return RESULT(Int, <<);
843 case Token::SHR: return RESULT(Int, >>);
844 case Token::EQEQ: return RESULT(Bool, ==);
845 case Token::NEQ: return RESULT(Bool, !=);
846 case Token::GT: return RESULT(Bool, >);
847 case Token::GTEQ: return RESULT(Bool, >=);
848 case Token::LT: return RESULT(Bool, <);
849 case Token::LTEQ: return RESULT(Bool, <=);
850 default: return nullptr;
851 }
852 }
853 if (left.fKind == Expression::kFloatLiteral_Kind &&
854 right.fKind == Expression::kFloatLiteral_Kind) {
855 double leftVal = ((FloatLiteral&) left).fValue;
dogben 2016/11/09 15:35:36 Same as above, except I don't feel that strongly a
ethannicholas 2016/11/09 16:36:21 Floating point's range is allowed to be as small a
856 double rightVal = ((FloatLiteral&) right).fValue;
857 switch (op) {
858 case Token::PLUS: return RESULT(Float, +);
859 case Token::MINUS: return RESULT(Float, -);
860 case Token::STAR: return RESULT(Float, *);
861 case Token::SLASH: return RESULT(Float, /);
862 case Token::EQEQ: return RESULT(Bool, ==);
863 case Token::NEQ: return RESULT(Bool, !=);
864 case Token::GT: return RESULT(Bool, >);
865 case Token::GTEQ: return RESULT(Bool, >=);
866 case Token::LT: return RESULT(Bool, <);
867 case Token::LTEQ: return RESULT(Bool, <=);
868 default: return nullptr;
869 }
870 }
871 #undef RESULT
872 return nullptr;
873 }
874
797 std::unique_ptr<Expression> IRGenerator::convertBinaryExpression( 875 std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
798 const ASTBinaryExpre ssion& expression) { 876 const ASTBinaryExpre ssion& expression) {
799 std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft ); 877 std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft );
800 if (!left) { 878 if (!left) {
801 return nullptr; 879 return nullptr;
802 } 880 }
803 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRig ht); 881 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRig ht);
804 if (!right) { 882 if (!right) {
805 return nullptr; 883 return nullptr;
806 } 884 }
807 const Type* leftType; 885 const Type* leftType;
808 const Type* rightType; 886 const Type* rightType;
809 const Type* resultType; 887 const Type* resultType;
810 if (!determine_binary_type(fContext, expression.fOperator, left->fType, righ t->fType, &leftType, 888 if (!determine_binary_type(fContext, expression.fOperator, left->fType, righ t->fType, &leftType,
811 &rightType, &resultType, !is_assignment(expressio n.fOperator))) { 889 &rightType, &resultType, !is_assignment(expressio n.fOperator))) {
812 fErrors.error(expression.fPosition, "type mismatch: '" + 890 fErrors.error(expression.fPosition, "type mismatch: '" +
813 Token::OperatorName(expression.fOper ator) + 891 Token::OperatorName(expression.fOper ator) +
814 "' cannot operate on '" + left->fTyp e.fName + 892 "' cannot operate on '" + left->fTyp e.fName +
815 "', '" + right->fType.fName + "'"); 893 "', '" + right->fType.fName + "'");
816 return nullptr; 894 return nullptr;
817 } 895 }
818 if (is_assignment(expression.fOperator)) { 896 if (is_assignment(expression.fOperator)) {
819 this->markWrittenTo(*left); 897 this->markWrittenTo(*left);
820 } 898 }
821 left = this->coerce(std::move(left), *leftType); 899 left = this->coerce(std::move(left), *leftType);
822 right = this->coerce(std::move(right), *rightType); 900 right = this->coerce(std::move(right), *rightType);
823 if (!left || !right) { 901 if (!left || !right) {
824 return nullptr; 902 return nullptr;
825 } 903 }
826 return std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition , 904 std::unique_ptr<Expression> result = this->constantFold(*left.get(), express ion.fOperator,
827 std::move(left), 905 *right.get());
828 expression.fOperator , 906 if (!result) {
829 std::move(right), 907 result = std::unique_ptr<Expression>(new BinaryExpression(expression.fPo sition,
830 *resultType)); 908 std::move(left ),
909 expression.fOp erator,
910 std::move(righ t),
911 *resultType));
912 }
913 return result;
831 } 914 }
832 915
833 std::unique_ptr<Expression> IRGenerator::convertTernaryExpression( 916 std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
834 const ASTTernaryExpre ssion& expression) { 917 const ASTTernaryExpre ssion& expression) {
835 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*exp ression.fTest), 918 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*exp ression.fTest),
836 *fContext.fBool_Type); 919 *fContext.fBool_Type);
837 if (!test) { 920 if (!test) {
838 return nullptr; 921 return nullptr;
839 } 922 }
840 std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIf True); 923 std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIf True);
(...skipping 10 matching lines...) Expand all
851 if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fT ype, &trueType, 934 if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fT ype, &trueType,
852 &falseType, &resultType, true)) { 935 &falseType, &resultType, true)) {
853 fErrors.error(expression.fPosition, "ternary operator result mismatch: ' " + 936 fErrors.error(expression.fPosition, "ternary operator result mismatch: ' " +
854 ifTrue->fType.fName + "', '" + 937 ifTrue->fType.fName + "', '" +
855 ifFalse->fType.fName + "'"); 938 ifFalse->fType.fName + "'");
856 return nullptr; 939 return nullptr;
857 } 940 }
858 ASSERT(trueType == falseType); 941 ASSERT(trueType == falseType);
859 ifTrue = this->coerce(std::move(ifTrue), *trueType); 942 ifTrue = this->coerce(std::move(ifTrue), *trueType);
860 ifFalse = this->coerce(std::move(ifFalse), *falseType); 943 ifFalse = this->coerce(std::move(ifFalse), *falseType);
944 if (test->fKind == Expression::kBoolLiteral_Kind) {
945 // static boolean test, just return one of the branches
946 if (((BoolLiteral&) *test).fValue) {
947 return ifTrue;
948 } else {
949 return ifFalse;
950 }
951 }
861 return std::unique_ptr<Expression>(new TernaryExpression(expression.fPositio n, 952 return std::unique_ptr<Expression>(new TernaryExpression(expression.fPositio n,
862 std::move(test), 953 std::move(test),
863 std::move(ifTrue), 954 std::move(ifTrue),
864 std::move(ifFalse)) ); 955 std::move(ifFalse)) );
865 } 956 }
866 957
867 std::unique_ptr<Expression> IRGenerator::call(Position position, 958 std::unique_ptr<Expression> IRGenerator::call(Position position,
868 const FunctionDeclaration& functio n, 959 const FunctionDeclaration& functio n,
869 std::vector<std::unique_ptr<Expres sion>> arguments) { 960 std::vector<std::unique_ptr<Expres sion>> arguments) {
870 if (function.fParameters.size() != arguments.size()) { 961 if (function.fParameters.size() != arguments.size()) {
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
1119 } 1210 }
1120 this->markWrittenTo(*base); 1211 this->markWrittenTo(*base);
1121 break; 1212 break;
1122 case Token::LOGICALNOT: 1213 case Token::LOGICALNOT:
1123 if (base->fType != *fContext.fBool_Type) { 1214 if (base->fType != *fContext.fBool_Type) {
1124 fErrors.error(expression.fPosition, 1215 fErrors.error(expression.fPosition,
1125 "'" + Token::OperatorName(expression.fOperator) + 1216 "'" + Token::OperatorName(expression.fOperator) +
1126 "' cannot operate on '" + base->fType.description( ) + "'"); 1217 "' cannot operate on '" + base->fType.description( ) + "'");
1127 return nullptr; 1218 return nullptr;
1128 } 1219 }
1220 if (base->fKind == Expression::kBoolLiteral_Kind) {
1221 return std::unique_ptr<Expression>(new BoolLiteral(fContext, bas e->fPosition,
1222 !((BoolLitera l&) *base).fValue));
1223 }
1129 break; 1224 break;
1130 case Token::BITWISENOT: 1225 case Token::BITWISENOT:
1131 if (base->fType != *fContext.fInt_Type) { 1226 if (base->fType != *fContext.fInt_Type) {
1132 fErrors.error(expression.fPosition, 1227 fErrors.error(expression.fPosition,
1133 "'" + Token::OperatorName(expression.fOperator) + 1228 "'" + Token::OperatorName(expression.fOperator) +
1134 "' cannot operate on '" + base->fType.description( ) + "'"); 1229 "' cannot operate on '" + base->fType.description( ) + "'");
1135 return nullptr; 1230 return nullptr;
1136 } 1231 }
1137 break; 1232 break;
1138 default: 1233 default:
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
1358 case Expression::kIndex_Kind: 1453 case Expression::kIndex_Kind:
1359 this->markWrittenTo(*((IndexExpression&) expr).fBase); 1454 this->markWrittenTo(*((IndexExpression&) expr).fBase);
1360 break; 1455 break;
1361 default: 1456 default:
1362 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio n() + "'"); 1457 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio n() + "'");
1363 break; 1458 break;
1364 } 1459 }
1365 } 1460 }
1366 1461
1367 } 1462 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698