Home | History | Annotate | Download | only in translator
      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