~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/ThirdParty/ANGLE/src/compiler/ForLoopUnroll.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// Copyright (c) 2002-2011 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/ForLoopUnroll.h"
 
8
 
 
9
namespace {
 
10
 
 
11
class IntegerForLoopUnrollMarker : public TIntermTraverser {
 
12
public:
 
13
 
 
14
    virtual bool visitLoop(Visit, TIntermLoop* node)
 
15
    {
 
16
        // This is called after ValidateLimitations pass, so all the ASSERT
 
17
        // should never fail.
 
18
        // See ValidateLimitations::validateForLoopInit().
 
19
        ASSERT(node);
 
20
        ASSERT(node->getType() == ELoopFor);
 
21
        ASSERT(node->getInit());
 
22
        TIntermAggregate* decl = node->getInit()->getAsAggregate();
 
23
        ASSERT(decl && decl->getOp() == EOpDeclaration);
 
24
        TIntermSequence& declSeq = decl->getSequence();
 
25
        ASSERT(declSeq.size() == 1);
 
26
        TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
 
27
        ASSERT(declInit && declInit->getOp() == EOpInitialize);
 
28
        ASSERT(declInit->getLeft());
 
29
        TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
 
30
        ASSERT(symbol);
 
31
        TBasicType type = symbol->getBasicType();
 
32
        ASSERT(type == EbtInt || type == EbtFloat);
 
33
        if (type == EbtInt)
 
34
            node->setUnrollFlag(true);
 
35
        return true;
 
36
    }
 
37
 
 
38
};
 
39
 
 
40
}  // anonymous namepsace
 
41
 
 
42
void ForLoopUnroll::FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info)
 
43
{
 
44
    ASSERT(node->getType() == ELoopFor);
 
45
    ASSERT(node->getUnrollFlag());
 
46
 
 
47
    TIntermNode* init = node->getInit();
 
48
    ASSERT(init != NULL);
 
49
    TIntermAggregate* decl = init->getAsAggregate();
 
50
    ASSERT((decl != NULL) && (decl->getOp() == EOpDeclaration));
 
51
    TIntermSequence& declSeq = decl->getSequence();
 
52
    ASSERT(declSeq.size() == 1);
 
53
    TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
 
54
    ASSERT((declInit != NULL) && (declInit->getOp() == EOpInitialize));
 
55
    TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
 
56
    ASSERT(symbol != NULL);
 
57
    ASSERT(symbol->getBasicType() == EbtInt);
 
58
 
 
59
    info.id = symbol->getId();
 
60
 
 
61
    ASSERT(declInit->getRight() != NULL);
 
62
    TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion();
 
63
    ASSERT(initNode != NULL);
 
64
 
 
65
    info.initValue = evaluateIntConstant(initNode);
 
66
    info.currentValue = info.initValue;
 
67
 
 
68
    TIntermNode* cond = node->getCondition();
 
69
    ASSERT(cond != NULL);
 
70
    TIntermBinary* binOp = cond->getAsBinaryNode();
 
71
    ASSERT(binOp != NULL);
 
72
    ASSERT(binOp->getRight() != NULL);
 
73
    ASSERT(binOp->getRight()->getAsConstantUnion() != NULL);
 
74
 
 
75
    info.incrementValue = getLoopIncrement(node);
 
76
    info.stopValue = evaluateIntConstant(
 
77
        binOp->getRight()->getAsConstantUnion());
 
78
    info.op = binOp->getOp();
 
79
}
 
80
 
 
81
void ForLoopUnroll::Step()
 
82
{
 
83
    ASSERT(mLoopIndexStack.size() > 0);
 
84
    TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1];
 
85
    info.currentValue += info.incrementValue;
 
86
}
 
87
 
 
88
bool ForLoopUnroll::SatisfiesLoopCondition()
 
89
{
 
90
    ASSERT(mLoopIndexStack.size() > 0);
 
91
    TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1];
 
92
    // Relational operator is one of: > >= < <= == or !=.
 
93
    switch (info.op) {
 
94
      case EOpEqual:
 
95
        return (info.currentValue == info.stopValue);
 
96
      case EOpNotEqual:
 
97
        return (info.currentValue != info.stopValue);
 
98
      case EOpLessThan:
 
99
        return (info.currentValue < info.stopValue);
 
100
      case EOpGreaterThan:
 
101
        return (info.currentValue > info.stopValue);
 
102
      case EOpLessThanEqual:
 
103
        return (info.currentValue <= info.stopValue);
 
104
      case EOpGreaterThanEqual:
 
105
        return (info.currentValue >= info.stopValue);
 
106
      default:
 
107
        UNREACHABLE();
 
108
    }
 
109
    return false;
 
110
}
 
111
 
 
112
bool ForLoopUnroll::NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol)
 
113
{
 
114
    for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin();
 
115
         i != mLoopIndexStack.end();
 
116
         ++i) {
 
117
        if (i->id == symbol->getId())
 
118
            return true;
 
119
    }
 
120
    return false;
 
121
}
 
122
 
 
123
int ForLoopUnroll::GetLoopIndexValue(TIntermSymbol* symbol)
 
124
{
 
125
    for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin();
 
126
         i != mLoopIndexStack.end();
 
127
         ++i) {
 
128
        if (i->id == symbol->getId())
 
129
            return i->currentValue;
 
130
    }
 
131
    UNREACHABLE();
 
132
    return false;
 
133
}
 
134
 
 
135
void ForLoopUnroll::Push(TLoopIndexInfo& info)
 
136
{
 
137
    mLoopIndexStack.push_back(info);
 
138
}
 
139
 
 
140
void ForLoopUnroll::Pop()
 
141
{
 
142
    mLoopIndexStack.pop_back();
 
143
}
 
144
 
 
145
// static
 
146
void ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(
 
147
    TIntermNode* root)
 
148
{
 
149
    ASSERT(root);
 
150
 
 
151
    IntegerForLoopUnrollMarker marker;
 
152
    root->traverse(&marker);
 
153
}
 
154
 
 
155
int ForLoopUnroll::getLoopIncrement(TIntermLoop* node)
 
156
{
 
157
    TIntermNode* expr = node->getExpression();
 
158
    ASSERT(expr != NULL);
 
159
    // for expression has one of the following forms:
 
160
    //     loop_index++
 
161
    //     loop_index--
 
162
    //     loop_index += constant_expression
 
163
    //     loop_index -= constant_expression
 
164
    //     ++loop_index
 
165
    //     --loop_index
 
166
    // The last two forms are not specified in the spec, but I am assuming
 
167
    // its an oversight.
 
168
    TIntermUnary* unOp = expr->getAsUnaryNode();
 
169
    TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode();
 
170
 
 
171
    TOperator op = EOpNull;
 
172
    TIntermConstantUnion* incrementNode = NULL;
 
173
    if (unOp != NULL) {
 
174
        op = unOp->getOp();
 
175
    } else if (binOp != NULL) {
 
176
        op = binOp->getOp();
 
177
        ASSERT(binOp->getRight() != NULL);
 
178
        incrementNode = binOp->getRight()->getAsConstantUnion();
 
179
        ASSERT(incrementNode != NULL);
 
180
    }
 
181
 
 
182
    int increment = 0;
 
183
    // The operator is one of: ++ -- += -=.
 
184
    switch (op) {
 
185
        case EOpPostIncrement:
 
186
        case EOpPreIncrement:
 
187
            ASSERT((unOp != NULL) && (binOp == NULL));
 
188
            increment = 1;
 
189
            break;
 
190
        case EOpPostDecrement:
 
191
        case EOpPreDecrement:
 
192
            ASSERT((unOp != NULL) && (binOp == NULL));
 
193
            increment = -1;
 
194
            break;
 
195
        case EOpAddAssign:
 
196
            ASSERT((unOp == NULL) && (binOp != NULL));
 
197
            increment = evaluateIntConstant(incrementNode);
 
198
            break;
 
199
        case EOpSubAssign:
 
200
            ASSERT((unOp == NULL) && (binOp != NULL));
 
201
            increment = - evaluateIntConstant(incrementNode);
 
202
            break;
 
203
        default:
 
204
            ASSERT(false);
 
205
    }
 
206
 
 
207
    return increment;
 
208
}
 
209
 
 
210
int ForLoopUnroll::evaluateIntConstant(TIntermConstantUnion* node)
 
211
{
 
212
    ASSERT((node != NULL) && (node->getUnionArrayPointer() != NULL));
 
213
    return node->getUnionArrayPointer()->getIConst();
 
214
}
 
215