Limit loop init scope to till end of loop.

Bug swiftshader:13

Change-Id: I03cdbb3e5ea28643eb941e162125da68d183d1c6
Reviewed-on: https://swiftshader-review.googlesource.com/7810
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-on: https://swiftshader-review.googlesource.com/8144
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index 8204697..7900063 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -6718,16 +6718,6 @@
 		Nucleus::createUnreachable();
 	}
 
-	BasicBlock *beginLoop()
-	{
-		BasicBlock *loopBB = Nucleus::createBasicBlock();
-
-		Nucleus::createBr(loopBB);
-		Nucleus::setInsertBlock(loopBB);
-
-		return loopBB;
-	}
-
 	bool branch(RValue<Bool> cmp, BasicBlock *bodyBB, BasicBlock *endBB)
 	{
 		Nucleus::createCondBr(cmp.value, bodyBB, endBB);
diff --git a/src/Reactor/Main.cpp b/src/Reactor/Main.cpp
index 092bf9e..e4e884e 100644
--- a/src/Reactor/Main.cpp
+++ b/src/Reactor/Main.cpp
@@ -290,11 +290,18 @@
 					x += 10000;
 			}
 
-			For(Int j = 0, j < 2, j++)
-				If(x == 402222)
-				{
-					If(x != 402222)
+			For(Int i = 0, i < 10, i++)
+				for(int i = 0; i < 10; i++)
+					For(Int i = 0, i < 10, i++)
+					{
 						x += 1000000;
+					}
+
+			For(Int i = 0, i < 2, i++)
+				If(x == 1000402222)
+				{
+					If(x != 1000402222)
+						x += 1000000000;
 				}
 				Else
 					x = -5;
@@ -309,7 +316,7 @@
 			int(*callable)() = (int(*)())routine->getEntry();
 			int result = callable();
 
-			EXPECT_EQ(result, 402222);
+			EXPECT_EQ(result, 1000402222);
 		}
 	}
 
diff --git a/src/Reactor/Reactor.hpp b/src/Reactor/Reactor.hpp
index 7239e47..30bd0f0 100644
--- a/src/Reactor/Reactor.hpp
+++ b/src/Reactor/Reactor.hpp
@@ -2225,7 +2225,60 @@
 //	RValue<Array<T>> operator--(const Array<T> &val, int);   // Post-decrement
 //	const Array<T> &operator--(const Array<T> &val);   // Pre-decrement
 
-	BasicBlock *beginLoop();
+	struct Loop
+	{
+		Loop(bool init) : loopOnce(init)
+		{
+		}
+
+		operator bool()
+		{
+			return loopOnce;
+		}
+
+		bool operator=(bool value)
+		{
+			return loopOnce = value;
+		}
+
+		bool setup()
+		{
+			if(Nucleus::getInsertBlock() != endBB)
+			{
+				testBB = Nucleus::createBasicBlock();
+
+				Nucleus::createBr(testBB);
+				Nucleus::setInsertBlock(testBB);
+
+				return true;
+			}
+
+			return false;
+		}
+
+		bool test(RValue<Bool> cmp)
+		{
+			BasicBlock *bodyBB = Nucleus::createBasicBlock();
+			endBB = Nucleus::createBasicBlock();
+
+			Nucleus::createCondBr(cmp.value, bodyBB, endBB);
+			Nucleus::setInsertBlock(bodyBB);
+
+			return true;
+		}
+
+		void end()
+		{
+			Nucleus::createBr(testBB);
+			Nucleus::setInsertBlock(endBB);
+		}
+
+	private:
+		BasicBlock *testBB = nullptr;
+		BasicBlock *endBB = nullptr;
+		bool loopOnce = true;
+	};
+
 	bool branch(RValue<Bool> cmp, BasicBlock *bodyBB, BasicBlock *endBB);
 	void endIf(BasicBlock *falseBB);
 	bool elseBlock(BasicBlock *falseBB);
@@ -2817,27 +2870,24 @@
 		return ReinterpretCast<T>(val);
 	}
 
-	#define For(init, cond, inc)                     \
-	init;                                            \
-	for(BasicBlock *loopBB__ = beginLoop(),          \
-		*bodyBB__ = Nucleus::createBasicBlock(),     \
-		*endBB__ = Nucleus::createBasicBlock(),      \
-		*onceBB__ = endBB__;                         \
-		onceBB__ && branch(cond, bodyBB__, endBB__); \
-		inc, onceBB__ = 0, Nucleus::createBr(loopBB__), Nucleus::setInsertBlock(endBB__))
+	extern BasicBlock *falseBB__;
 
-	#define While(cond) For(((void*)0), cond, ((void*)0))
+	#define For(init, cond, inc) \
+	for(Loop loop__ = true; loop__; loop__ = false) \
+	for(init; loop__.setup() && loop__.test(cond); inc, loop__.end())
 
-	#define Do                                          \
-	{                                                   \
-		BasicBlock *body = Nucleus::createBasicBlock(); \
-		Nucleus::createBr(body);                        \
-		Nucleus::setInsertBlock(body);
+	#define While(cond) For((void)0, cond, (void)0)
 
-	#define Until(cond)                                 \
-		BasicBlock *end = Nucleus::createBasicBlock();  \
-		Nucleus::createCondBr((cond).value, end, body); \
-		Nucleus::setInsertBlock(end);                   \
+	#define Do                                            \
+	{                                                     \
+		BasicBlock *body__ = Nucleus::createBasicBlock(); \
+		Nucleus::createBr(body__);                        \
+		Nucleus::setInsertBlock(body__);
+
+	#define Until(cond)                                     \
+		BasicBlock *end__ = Nucleus::createBasicBlock();    \
+		Nucleus::createCondBr((cond).value, end__, body__); \
+		Nucleus::setInsertBlock(end__);                     \
 	}
 
 	#define If(cond)                                        \
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index 4ae6dfa..48ee54d 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -6147,16 +6147,6 @@
 		Nucleus::createUnreachable();
 	}
 
-	BasicBlock *beginLoop()
-	{
-		BasicBlock *loopBB = Nucleus::createBasicBlock();
-
-		Nucleus::createBr(loopBB);
-		Nucleus::setInsertBlock(loopBB);
-
-		return loopBB;
-	}
-
 	bool branch(RValue<Bool> cmp, BasicBlock *bodyBB, BasicBlock *endBB)
 	{
 		Nucleus::createCondBr(cmp.value, bodyBB, endBB);