1 /* 2 * Copyright 2022 Google LLC 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "include/core/SkSpan.h" 9 #include "include/core/SkTypes.h" 10 #include "src/sksl/SkSLAnalysis.h" 11 #include "src/sksl/SkSLOperator.h" 12 #include "src/sksl/ir/SkSLConstructor.h" 13 #include "src/sksl/ir/SkSLExpression.h" 14 #include "src/sksl/ir/SkSLFieldAccess.h" 15 #include "src/sksl/ir/SkSLIRNode.h" 16 #include "src/sksl/ir/SkSLIndexExpression.h" 17 #include "src/sksl/ir/SkSLPrefixExpression.h" 18 #include "src/sksl/ir/SkSLSwizzle.h" 19 #include "src/sksl/ir/SkSLType.h" 20 21 #include <memory> 22 23 namespace SkSL { 24 IsTrivialExpression(const Expression & expr)25bool Analysis::IsTrivialExpression(const Expression& expr) { 26 switch (expr.kind()) { 27 case Expression::Kind::kLiteral: 28 case Expression::Kind::kVariableReference: 29 return true; 30 31 case Expression::Kind::kSwizzle: 32 // All swizzles are considered to be trivial. 33 return IsTrivialExpression(*expr.as<Swizzle>().base()); 34 35 case Expression::Kind::kPrefix: { 36 const PrefixExpression& prefix = expr.as<PrefixExpression>(); 37 switch (prefix.getOperator().kind()) { 38 case OperatorKind::PLUS: 39 case OperatorKind::MINUS: 40 case OperatorKind::LOGICALNOT: 41 case OperatorKind::BITWISENOT: 42 return IsTrivialExpression(*prefix.operand()); 43 44 default: 45 return false; 46 } 47 } 48 case Expression::Kind::kFieldAccess: 49 // Accessing a field is trivial. 50 return IsTrivialExpression(*expr.as<FieldAccess>().base()); 51 52 case Expression::Kind::kIndex: { 53 // Accessing a constant array index is trivial. 54 const IndexExpression& inner = expr.as<IndexExpression>(); 55 return inner.index()->isIntLiteral() && IsTrivialExpression(*inner.base()); 56 } 57 case Expression::Kind::kConstructorArray: 58 case Expression::Kind::kConstructorStruct: 59 // Only consider small arrays/structs of compile-time-constants to be trivial. 60 return expr.type().slotCount() <= 4 && IsCompileTimeConstant(expr); 61 62 case Expression::Kind::kConstructorArrayCast: 63 case Expression::Kind::kConstructorMatrixResize: 64 // These operations require function calls in Metal, so they're never trivial. 65 return false; 66 67 case Expression::Kind::kConstructorCompound: 68 // Only compile-time-constant compound constructors are considered to be trivial. 69 return IsCompileTimeConstant(expr); 70 71 case Expression::Kind::kConstructorCompoundCast: 72 case Expression::Kind::kConstructorScalarCast: 73 case Expression::Kind::kConstructorSplat: 74 case Expression::Kind::kConstructorDiagonalMatrix: { 75 // Single-argument constructors are trivial when their inner expression is trivial. 76 SkASSERT(expr.asAnyConstructor().argumentSpan().size() == 1); 77 const Expression& inner = *expr.asAnyConstructor().argumentSpan().front(); 78 return IsTrivialExpression(inner); 79 } 80 default: 81 return false; 82 } 83 } 84 85 } // namespace SkSL 86