Fix loop unrolling.
Loops were no longer getting unrolled because we analyzed the entire
loop, not just the body, for changes to the index variable. Also, the
logic was inverted. Also, be conservative about loops with return
statements not being unrollable.
Bug chromium:845103
Change-Id: I5957e17f7b985ae90b10053216b6945f3f64338e
Reviewed-on: https://swiftshader-review.googlesource.com/19008
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index d7213cb..8b20758 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -1872,6 +1872,8 @@
if(unroll)
{
+ mContext.info(node->getLine(), "loop unrolled", "for");
+
for(unsigned int i = 0; i < loop.iterations; i++)
{
// condition->traverse(this); // Condition could contain statements, but not in an unrollable loop
@@ -3886,32 +3888,21 @@
}
}
- bool LoopUnrollable::traverse(TIntermNode *node, int indexId)
+ bool LoopUnrollable::traverse(TIntermLoop *loop, int indexId)
{
loopUnrollable = true;
- loopDepth = 0;
loopIndexId = indexId;
+ TIntermNode *body = loop->getBody();
- node->traverse(this);
+ if(body)
+ {
+ body->traverse(this);
+ }
return loopUnrollable;
}
- bool LoopUnrollable::visitLoop(Visit visit, TIntermLoop *loop)
- {
- if(visit == PreVisit)
- {
- loopDepth++;
- }
- else if(visit == PostVisit)
- {
- loopDepth++;
- }
-
- return true;
- }
-
void LoopUnrollable::visitSymbol(TIntermSymbol *node)
{
// Check that the loop index is not used as the argument to a function out or inout parameter.
@@ -3933,7 +3924,7 @@
// Check that the loop index is not statically assigned to.
TIntermSymbol *symbol = node->getLeft()->getAsSymbolNode();
- loopUnrollable = node->modifiesState() && symbol && (symbol->getId() == loopIndexId);
+ loopUnrollable = !(node->modifiesState() && symbol && (symbol->getId() == loopIndexId));
return loopUnrollable;
}
@@ -3947,7 +3938,7 @@
// Check that the loop index is not statically assigned to.
TIntermSymbol *symbol = node->getOperand()->getAsSymbolNode();
- loopUnrollable = node->modifiesState() && symbol && (symbol->getId() == loopIndexId);
+ loopUnrollable = !(node->modifiesState() && symbol && (symbol->getId() == loopIndexId));
return loopUnrollable;
}
@@ -3959,16 +3950,10 @@
return false;
}
- if(!loopDepth)
- {
- return true;
- }
-
switch(node->getFlowOp())
{
case EOpKill:
case EOpReturn:
- break;
case EOpBreak:
case EOpContinue:
loopUnrollable = false;