Add an compile option to unroll for-loops with integer indices.

ANGLEBUG=193
TEST=with this option, for-loops with integer indices will be unrolled.
Review URL: http://codereview.appspot.com/4899047

git-svn-id: https://angleproject.googlecode.com/svn/trunk@734 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/Compiler.cpp b/src/compiler/Compiler.cpp
index 16b7bd9..eafe70a 100644
--- a/src/compiler/Compiler.cpp
+++ b/src/compiler/Compiler.cpp
@@ -5,6 +5,7 @@
 //
 
 #include "compiler/DetectRecursion.h"
+#include "compiler/ForLoopUnroll.h"
 #include "compiler/Initialize.h"
 #include "compiler/ParseHelper.h"
 #include "compiler/ShHandle.h"
@@ -155,6 +156,10 @@
         if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
             success = validateLimitations(root);
 
+        // Unroll for-loop markup needs to happen after validateLimitations pass.
+        if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
+            ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root);
+
         // Call mapLongVariableNames() before collectAttribsUniforms() so in
         // collectAttribsUniforms() we already have the mapped symbol names and
         // we could composite mapped and original variable names.
diff --git a/src/compiler/ForLoopUnroll.cpp b/src/compiler/ForLoopUnroll.cpp
index d631af4..fdc3f44 100644
--- a/src/compiler/ForLoopUnroll.cpp
+++ b/src/compiler/ForLoopUnroll.cpp
@@ -6,6 +6,39 @@
 
 #include "compiler/ForLoopUnroll.h"
 
+namespace {
+
+class IntegerForLoopUnrollMarker : public TIntermTraverser {
+public:
+
+    virtual bool visitLoop(Visit, TIntermLoop* node)
+    {
+        // This is called after ValidateLimitations pass, so all the ASSERT
+        // should never fail.
+        // See ValidateLimitations::validateForLoopInit().
+        ASSERT(node);
+        ASSERT(node->getType() == ELoopFor);
+        ASSERT(node->getInit());
+        TIntermAggregate* decl = node->getInit()->getAsAggregate();
+        ASSERT(decl && decl->getOp() == EOpDeclaration);
+        TIntermSequence& declSeq = decl->getSequence();
+        ASSERT(declSeq.size() == 1);
+        TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
+        ASSERT(declInit && declInit->getOp() == EOpInitialize);
+        ASSERT(declInit->getLeft());
+        TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
+        ASSERT(symbol);
+        TBasicType type = symbol->getBasicType();
+        ASSERT(type == EbtInt || type == EbtFloat);
+        if (type == EbtInt)
+            node->setUnrollFlag(true);
+        return true;
+    }
+
+};
+
+}  // anonymous namepsace
+
 void ForLoopUnroll::FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info)
 {
     ASSERT(node->getType() == ELoopFor);
@@ -109,6 +142,16 @@
     mLoopIndexStack.pop_back();
 }
 
+// static
+void ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(
+    TIntermNode* root)
+{
+    ASSERT(root);
+
+    IntegerForLoopUnrollMarker marker;
+    root->traverse(&marker);
+}
+
 int ForLoopUnroll::getLoopIncrement(TIntermLoop* node)
 {
     TIntermNode* expr = node->getExpression();
diff --git a/src/compiler/ForLoopUnroll.h b/src/compiler/ForLoopUnroll.h
index b2b2b58..e800e25 100644
--- a/src/compiler/ForLoopUnroll.h
+++ b/src/compiler/ForLoopUnroll.h
@@ -36,6 +36,8 @@
     void Push(TLoopIndexInfo& info);
     void Pop();
 
+    static void MarkForLoopsWithIntegerIndicesForUnrolling(TIntermNode* root);
+
 private:
     int getLoopIncrement(TIntermLoop* node);