Fix deterministic loops within conditional blocks.

Deterministic loops use the first scalar of the SIMD register used as
the loop index, for addressing arrays. This means that operations on the
index register should not be masked (i.e. it should be treated as a
scalar).

Previously we were still masking it based on conditional statements, and
we didn't disable the masking altogether (using the 'TEST' instruction)
for the loop initialization and initial test.

Also, non-deterministic loops should not have any execution masking
disabled, so don't emit 'TEST' for them.

Bug swiftshader:93
Bug b/118009174

Change-Id: I661de83df931d85f806d2ec5c9e1b2f20a9b5567
Reviewed-on: https://swiftshader-review.googlesource.com/c/21788
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Common/Version.h b/src/Common/Version.h
index 19fcfce..78c74b2 100644
--- a/src/Common/Version.h
+++ b/src/Common/Version.h
@@ -15,7 +15,7 @@
 #define MAJOR_VERSION 4
 #define MINOR_VERSION 1
 #define BUILD_VERSION 0
-#define BUILD_REVISION 4
+#define BUILD_REVISION 5
 
 #define STRINGIFY(x) #x
 #define MACRO_STRINGIFY(x) STRINGIFY(x)
diff --git a/src/OpenGL/compiler/OutputASM.cpp b/src/OpenGL/compiler/OutputASM.cpp
index a2714de..5fa69f1 100644
--- a/src/OpenGL/compiler/OutputASM.cpp
+++ b/src/OpenGL/compiler/OutputASM.cpp
@@ -1848,11 +1848,6 @@
 			return false;
 		}
 
-		if(loop.isDeterministic())
-		{
-			 deterministicVariables.insert(loop.index->getId());
-		}
-
 		bool unroll = (loop.iterations <= 4);
 
 		TIntermNode *init = node->getInit();
@@ -1861,6 +1856,13 @@
 		TIntermNode *body = node->getBody();
 		Constant True(true);
 
+		if(loop.isDeterministic())
+		{
+			 deterministicVariables.insert(loop.index->getId());
+
+			 emit(sw::Shader::OPCODE_TEST);
+		}
+
 		if(node->getType() == ELoopDoWhile)
 		{
 			Temporary iterate(this);
@@ -1924,7 +1926,10 @@
 					body->traverse(this);
 				}
 
-				emit(sw::Shader::OPCODE_TEST);
+				if(loop.isDeterministic())
+				{
+					emit(sw::Shader::OPCODE_TEST);
+				}
 
 				if(expression)
 				{
diff --git a/src/Shader/PixelProgram.cpp b/src/Shader/PixelProgram.cpp
index 473712b..f81596b 100644
--- a/src/Shader/PixelProgram.cpp
+++ b/src/Shader/PixelProgram.cpp
@@ -832,24 +832,26 @@
 
 	Int4 PixelProgram::enableMask(const Shader::Instruction *instruction)
 	{
+		if(whileTest)
+		{
+			return Int4(0xFFFFFFFF);
+		}
+
 		Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
 
-		if(!whileTest)
+		if(shader->containsBreakInstruction() && instruction->analysisBreak)
 		{
-			if(shader->containsBreakInstruction() && instruction->analysisBreak)
-			{
-				enable &= enableBreak;
-			}
+			enable &= enableBreak;
+		}
 
-			if(shader->containsContinueInstruction() && instruction->analysisContinue)
-			{
-				enable &= enableContinue;
-			}
+		if(shader->containsContinueInstruction() && instruction->analysisContinue)
+		{
+			enable &= enableContinue;
+		}
 
-			if(shader->containsLeaveInstruction() && instruction->analysisLeave)
-			{
-				enable &= enableLeave;
-			}
+		if(shader->containsLeaveInstruction() && instruction->analysisLeave)
+		{
+			enable &= enableLeave;
 		}
 
 		return enable;
@@ -1781,6 +1783,7 @@
 		Nucleus::setInsertBlock(loopBlock);
 
 		loopRepDepth++;
+		whileTest = false;
 	}
 
 	void PixelProgram::SWITCH()
diff --git a/src/Shader/VertexProgram.cpp b/src/Shader/VertexProgram.cpp
index ad4e37b..0eb8441 100644
--- a/src/Shader/VertexProgram.cpp
+++ b/src/Shader/VertexProgram.cpp
@@ -978,24 +978,26 @@
 
 	Int4 VertexProgram::enableMask(const Shader::Instruction *instruction)
 	{
+		if(whileTest)
+		{
+			return Int4(0xFFFFFFFF);
+		}
+
 		Int4 enable = instruction->analysisBranch ? Int4(enableStack[enableIndex]) : Int4(0xFFFFFFFF);
 
-		if(!whileTest)
+		if(shader->containsBreakInstruction() && instruction->analysisBreak)
 		{
-			if(shader->containsBreakInstruction() && instruction->analysisBreak)
-			{
-				enable &= enableBreak;
-			}
+			enable &= enableBreak;
+		}
 
-			if(shader->containsContinueInstruction() && instruction->analysisContinue)
-			{
-				enable &= enableContinue;
-			}
+		if(shader->containsContinueInstruction() && instruction->analysisContinue)
+		{
+			enable &= enableContinue;
+		}
 
-			if(shader->containsLeaveInstruction() && instruction->analysisLeave)
-			{
-				enable &= enableLeave;
-			}
+		if(shader->containsLeaveInstruction() && instruction->analysisLeave)
+		{
+			enable &= enableLeave;
 		}
 
 		return enable;
@@ -1495,6 +1497,7 @@
 		Nucleus::setInsertBlock(loopBlock);
 
 		loopRepDepth++;
+		whileTest = false;
 	}
 
 	void VertexProgram::SWITCH()