RewriteRepeatedAssignToSwizzled.cpp (2766B)
1 // 2 // Copyright 2018 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // RewriteRepeatedAssignToSwizzled.cpp: Rewrite expressions that assign an assignment to a swizzled 7 // vector, like: 8 // v.x = z = expression; 9 // to: 10 // z = expression; 11 // v.x = z; 12 // 13 // Note that this doesn't handle some corner cases: expressions nested inside other expressions, 14 // inside loop headers, or inside if conditions. 15 16 #include "compiler/translator/tree_ops/gl/RewriteRepeatedAssignToSwizzled.h" 17 18 #include "compiler/translator/tree_util/IntermNode_util.h" 19 #include "compiler/translator/tree_util/IntermTraverse.h" 20 21 namespace sh 22 { 23 24 namespace 25 { 26 27 class RewriteAssignToSwizzledTraverser : public TIntermTraverser 28 { 29 public: 30 [[nodiscard]] static bool rewrite(TCompiler *compiler, TIntermBlock *root); 31 32 private: 33 RewriteAssignToSwizzledTraverser(); 34 35 bool visitBinary(Visit, TIntermBinary *node) override; 36 37 void nextIteration(); 38 39 bool didRewrite() { return mDidRewrite; } 40 41 bool mDidRewrite; 42 }; 43 44 // static 45 bool RewriteAssignToSwizzledTraverser::rewrite(TCompiler *compiler, TIntermBlock *root) 46 { 47 RewriteAssignToSwizzledTraverser rewrite; 48 do 49 { 50 rewrite.nextIteration(); 51 root->traverse(&rewrite); 52 if (!rewrite.updateTree(compiler, root)) 53 { 54 return false; 55 } 56 } while (rewrite.didRewrite()); 57 58 return true; 59 } 60 61 RewriteAssignToSwizzledTraverser::RewriteAssignToSwizzledTraverser() 62 : TIntermTraverser(true, false, false), mDidRewrite(false) 63 {} 64 65 void RewriteAssignToSwizzledTraverser::nextIteration() 66 { 67 mDidRewrite = false; 68 } 69 70 bool RewriteAssignToSwizzledTraverser::visitBinary(Visit, TIntermBinary *node) 71 { 72 TIntermBinary *rightBinary = node->getRight()->getAsBinaryNode(); 73 TIntermBlock *parentBlock = getParentNode()->getAsBlock(); 74 if (parentBlock && node->isAssignment() && node->getLeft()->getAsSwizzleNode() && rightBinary && 75 rightBinary->isAssignment()) 76 { 77 TIntermSequence replacements; 78 replacements.push_back(rightBinary); 79 TIntermTyped *rightAssignmentTargetCopy = rightBinary->getLeft()->deepCopy(); 80 TIntermBinary *lastAssign = 81 new TIntermBinary(EOpAssign, node->getLeft(), rightAssignmentTargetCopy); 82 replacements.push_back(lastAssign); 83 mMultiReplacements.emplace_back(parentBlock, node, std::move(replacements)); 84 mDidRewrite = true; 85 return false; 86 } 87 return true; 88 } 89 90 } // anonymous namespace 91 92 bool RewriteRepeatedAssignToSwizzled(TCompiler *compiler, TIntermBlock *root) 93 { 94 return RewriteAssignToSwizzledTraverser::rewrite(compiler, root); 95 } 96 97 } // namespace sh