1 // 2 // Copyright (c) 2002-2014 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 7 #include "compiler/translator/LoopInfo.h" 8 9 namespace 10 { 11 12 int EvaluateIntConstant(TIntermConstantUnion *node) 13 { 14 ASSERT(node && node->getUnionArrayPointer()); 15 return node->getIConst(0); 16 } 17 18 int GetLoopIntIncrement(TIntermLoop *node) 19 { 20 TIntermNode *expr = node->getExpression(); 21 // for expression has one of the following forms: 22 // loop_index++ 23 // loop_index-- 24 // loop_index += constant_expression 25 // loop_index -= constant_expression 26 // ++loop_index 27 // --loop_index 28 // The last two forms are not specified in the spec, but I am assuming 29 // its an oversight. 30 TIntermUnary *unOp = expr->getAsUnaryNode(); 31 TIntermBinary *binOp = unOp ? NULL : expr->getAsBinaryNode(); 32 33 TOperator op = EOpNull; 34 TIntermConstantUnion *incrementNode = NULL; 35 if (unOp) 36 { 37 op = unOp->getOp(); 38 } 39 else if (binOp) 40 { 41 op = binOp->getOp(); 42 ASSERT(binOp->getRight()); 43 incrementNode = binOp->getRight()->getAsConstantUnion(); 44 ASSERT(incrementNode); 45 } 46 47 int increment = 0; 48 // The operator is one of: ++ -- += -=. 49 switch (op) 50 { 51 case EOpPostIncrement: 52 case EOpPreIncrement: 53 ASSERT(unOp && !binOp); 54 increment = 1; 55 break; 56 case EOpPostDecrement: 57 case EOpPreDecrement: 58 ASSERT(unOp && !binOp); 59 increment = -1; 60 break; 61 case EOpAddAssign: 62 ASSERT(!unOp && binOp); 63 increment = EvaluateIntConstant(incrementNode); 64 break; 65 case EOpSubAssign: 66 ASSERT(!unOp && binOp); 67 increment = - EvaluateIntConstant(incrementNode); 68 break; 69 default: 70 UNREACHABLE(); 71 } 72 73 return increment; 74 } 75 76 } // namespace anonymous 77 78 TLoopIndexInfo::TLoopIndexInfo() 79 : mId(-1), 80 mType(EbtVoid), 81 mInitValue(0), 82 mStopValue(0), 83 mIncrementValue(0), 84 mOp(EOpNull), 85 mCurrentValue(0) 86 { 87 } 88 89 void TLoopIndexInfo::fillInfo(TIntermLoop *node) 90 { 91 if (node == NULL) 92 return; 93 94 // Here we assume all the operations are valid, because the loop node is 95 // already validated in ValidateLimitations. 96 TIntermSequence *declSeq = 97 node->getInit()->getAsAggregate()->getSequence(); 98 TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); 99 TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); 100 101 mId = symbol->getId(); 102 mType = symbol->getBasicType(); 103 104 if (mType == EbtInt) 105 { 106 TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion(); 107 mInitValue = EvaluateIntConstant(initNode); 108 mCurrentValue = mInitValue; 109 mIncrementValue = GetLoopIntIncrement(node); 110 111 TIntermBinary* binOp = node->getCondition()->getAsBinaryNode(); 112 mStopValue = EvaluateIntConstant( 113 binOp->getRight()->getAsConstantUnion()); 114 mOp = binOp->getOp(); 115 } 116 } 117 118 bool TLoopIndexInfo::satisfiesLoopCondition() const 119 { 120 // Relational operator is one of: > >= < <= == or !=. 121 switch (mOp) 122 { 123 case EOpEqual: 124 return (mCurrentValue == mStopValue); 125 case EOpNotEqual: 126 return (mCurrentValue != mStopValue); 127 case EOpLessThan: 128 return (mCurrentValue < mStopValue); 129 case EOpGreaterThan: 130 return (mCurrentValue > mStopValue); 131 case EOpLessThanEqual: 132 return (mCurrentValue <= mStopValue); 133 case EOpGreaterThanEqual: 134 return (mCurrentValue >= mStopValue); 135 default: 136 UNREACHABLE(); 137 return false; 138 } 139 } 140 141 TLoopInfo::TLoopInfo() 142 : loop(NULL) 143 { 144 } 145 146 TLoopInfo::TLoopInfo(TIntermLoop *node) 147 : loop(node) 148 { 149 index.fillInfo(node); 150 } 151 152 TIntermLoop *TLoopStack::findLoop(TIntermSymbol *symbol) 153 { 154 if (!symbol) 155 return NULL; 156 for (iterator iter = begin(); iter != end(); ++iter) 157 { 158 if (iter->index.getId() == symbol->getId()) 159 return iter->loop; 160 } 161 return NULL; 162 } 163 164 TLoopIndexInfo *TLoopStack::getIndexInfo(TIntermSymbol *symbol) 165 { 166 if (!symbol) 167 return NULL; 168 for (iterator iter = begin(); iter != end(); ++iter) 169 { 170 if (iter->index.getId() == symbol->getId()) 171 return &(iter->index); 172 } 173 return NULL; 174 } 175 176 void TLoopStack::step() 177 { 178 ASSERT(!empty()); 179 rbegin()->index.step(); 180 } 181 182 bool TLoopStack::satisfiesLoopCondition() 183 { 184 ASSERT(!empty()); 185 return rbegin()->index.satisfiesLoopCondition(); 186 } 187 188 bool TLoopStack::needsToReplaceSymbolWithValue(TIntermSymbol *symbol) 189 { 190 TIntermLoop *loop = findLoop(symbol); 191 return loop && loop->getUnrollFlag(); 192 } 193 194 int TLoopStack::getLoopIndexValue(TIntermSymbol *symbol) 195 { 196 TLoopIndexInfo *info = getIndexInfo(symbol); 197 ASSERT(info); 198 return info->getCurrentValue(); 199 } 200 201 void TLoopStack::push(TIntermLoop *loop) 202 { 203 TLoopInfo info(loop); 204 push_back(info); 205 } 206 207 void TLoopStack::pop() 208 { 209 pop_back(); 210 } 211 212