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 "include/private/SkSLIRNode.h" 11 #include "src/sksl/SkSLAnalysis.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/SkSLIndexExpression.h" 16 #include "src/sksl/ir/SkSLSwizzle.h" 17 #include "src/sksl/ir/SkSLType.h" 18 19 #include <memory> 20 21 namespace SkSL { 22 IsTrivialExpression(const Expression & expr)23bool Analysis::IsTrivialExpression(const Expression& expr) { 24 switch (expr.kind()) { 25 case Expression::Kind::kLiteral: 26 case Expression::Kind::kVariableReference: 27 return true; 28 29 case Expression::Kind::kSwizzle: 30 // All swizzles are considered to be trivial. 31 return IsTrivialExpression(*expr.as<Swizzle>().base()); 32 33 case Expression::Kind::kFieldAccess: 34 // Accessing a field is trivial. 35 return IsTrivialExpression(*expr.as<FieldAccess>().base()); 36 37 case Expression::Kind::kIndex: { 38 // Accessing a constant array index is trivial. 39 const IndexExpression& inner = expr.as<IndexExpression>(); 40 return inner.index()->isIntLiteral() && IsTrivialExpression(*inner.base()); 41 } 42 case Expression::Kind::kConstructorArray: 43 case Expression::Kind::kConstructorStruct: 44 // Only consider small arrays/structs of compile-time-constants to be trivial. 45 return expr.type().slotCount() <= 4 && IsCompileTimeConstant(expr); 46 47 case Expression::Kind::kConstructorArrayCast: 48 case Expression::Kind::kConstructorMatrixResize: 49 // These operations require function calls in Metal, so they're never trivial. 50 return false; 51 52 case Expression::Kind::kConstructorCompound: 53 // Only compile-time-constant compound constructors are considered to be trivial. 54 return IsCompileTimeConstant(expr); 55 56 case Expression::Kind::kConstructorCompoundCast: 57 case Expression::Kind::kConstructorScalarCast: 58 case Expression::Kind::kConstructorSplat: 59 case Expression::Kind::kConstructorDiagonalMatrix: { 60 // Single-argument constructors are trivial when their inner expression is trivial. 61 SkASSERT(expr.asAnyConstructor().argumentSpan().size() == 1); 62 const Expression& inner = *expr.asAnyConstructor().argumentSpan().front(); 63 return IsTrivialExpression(inner); 64 } 65 default: 66 return false; 67 } 68 } 69 70 } // namespace SkSL 71