Implement Else without using basic block predecessor.

Bug swiftshader:13

Change-Id: Idd49e64aa8415ceb5d1cfee7b65a7d67ea0ebd40
Reviewed-on: https://swiftshader-review.googlesource.com/7792
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-on: https://swiftshader-review.googlesource.com/8143
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index 26521d3..8204697 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -69,6 +69,8 @@
 	llvm::Function *function = nullptr;
 
 	sw::BackoffLock codegenMutex;
+
+	sw::BasicBlock *falseBB = nullptr;
 }
 
 namespace sw
@@ -286,11 +288,6 @@
 		return ::builder->SetInsertPoint(basicBlock);
 	}
 
-	BasicBlock *Nucleus::getPredecessor(BasicBlock *basicBlock)
-	{
-		return B(*pred_begin(basicBlock));
-	}
-
 	void Nucleus::createFunction(Type *ReturnType, std::vector<Type*> &Params)
 	{
 		llvm::FunctionType *functionType = llvm::FunctionType::get(ReturnType, T(Params), false);
@@ -6739,14 +6736,28 @@
 		return true;
 	}
 
+	void endIf(BasicBlock *falseBB)
+	{
+		::falseBB = falseBB;
+	}
+
 	bool elseBlock(BasicBlock *falseBB)
 	{
+		assert(falseBB && "Else not preceded by If");
 		falseBB->back().eraseFromParent();
 		Nucleus::setInsertBlock(falseBB);
 
 		return true;
 	}
 
+	BasicBlock *beginElse()
+	{
+		BasicBlock *falseBB = ::falseBB;
+		::falseBB = nullptr;
+
+		return falseBB;
+	}
+
 	RValue<Long> Ticks()
 	{
 		llvm::Function *rdtsc = Intrinsic::getDeclaration(::module, Intrinsic::readcyclecounter);
diff --git a/src/Reactor/Main.cpp b/src/Reactor/Main.cpp
index c0f958c..092bf9e 100644
--- a/src/Reactor/Main.cpp
+++ b/src/Reactor/Main.cpp
@@ -258,6 +258,64 @@
 	delete routine;
 }
 
+TEST(SubzeroReactorTest, Branching)
+{
+	Routine *routine = nullptr;
+
+	{
+		Function<Int(Void)> function;
+		{
+			Int x = 0;
+
+			For(Int i = 0, i < 8, i++)
+			{
+				If(i < 2)
+				{
+					x += 1;
+				}
+				Else If(i < 4)
+				{
+					x += 10;
+				}
+				Else If(i < 6)
+				{
+					x += 100;
+				}
+				Else
+				{
+					x += 1000;
+				}
+
+				For(Int i = 0, i < 5, i++)
+					x += 10000;
+			}
+
+			For(Int j = 0, j < 2, j++)
+				If(x == 402222)
+				{
+					If(x != 402222)
+						x += 1000000;
+				}
+				Else
+					x = -5;
+
+			Return(x);
+		}
+
+		routine = function(L"one");
+
+		if(routine)
+		{
+			int(*callable)() = (int(*)())routine->getEntry();
+			int result = callable();
+
+			EXPECT_EQ(result, 402222);
+		}
+	}
+
+	delete routine;
+}
+
 int main(int argc, char **argv)
 {
 	::testing::InitGoogleTest(&argc, argv);
diff --git a/src/Reactor/Nucleus.hpp b/src/Reactor/Nucleus.hpp
index c91ae17..07cc288 100644
--- a/src/Reactor/Nucleus.hpp
+++ b/src/Reactor/Nucleus.hpp
@@ -57,7 +57,6 @@
 		static BasicBlock *createBasicBlock();
 		static BasicBlock *getInsertBlock();
 		static void setInsertBlock(BasicBlock *basicBlock);
-		static BasicBlock *getPredecessor(BasicBlock *basicBlock);
 
 		static void createFunction(Type *ReturnType, std::vector<Type*> &Params);
 		static Value *getArgument(unsigned int index);
diff --git a/src/Reactor/Reactor.hpp b/src/Reactor/Reactor.hpp
index 86c867c..7239e47 100644
--- a/src/Reactor/Reactor.hpp
+++ b/src/Reactor/Reactor.hpp
@@ -2227,7 +2227,9 @@
 
 	BasicBlock *beginLoop();
 	bool branch(RValue<Bool> cmp, BasicBlock *bodyBB, BasicBlock *endBB);
+	void endIf(BasicBlock *falseBB);
 	bool elseBlock(BasicBlock *falseBB);
+	BasicBlock *beginElse();
 
 	void Return();
 	void Return(bool ret);
@@ -2840,18 +2842,25 @@
 
 	#define If(cond)                                        \
 	for(BasicBlock *trueBB__ = Nucleus::createBasicBlock(), \
-		*falseBB__ = Nucleus::createBasicBlock(),           \
-		*endBB__ = Nucleus::createBasicBlock(),             \
-		*onceBB__ = endBB__;                                \
-		onceBB__ && branch(cond, trueBB__, falseBB__);      \
-		onceBB__ = 0, Nucleus::createBr(endBB__), Nucleus::setInsertBlock(falseBB__), Nucleus::createBr(endBB__), Nucleus::setInsertBlock(endBB__))
+	    *falseBB__ = Nucleus::createBasicBlock(),           \
+	    *endBB__ = Nucleus::createBasicBlock(),             \
+	    *onceBB__ = endBB__;                                \
+	    onceBB__ && branch(cond, trueBB__, falseBB__);      \
+	    onceBB__ = nullptr,                                 \
+	    Nucleus::createBr(endBB__),                         \
+	    Nucleus::setInsertBlock(falseBB__),                 \
+	    Nucleus::createBr(endBB__),                         \
+	    Nucleus::setInsertBlock(endBB__),                   \
+	    endIf(falseBB__))
 
 	#define Else                                         \
-	for(BasicBlock *endBB__ = Nucleus::getInsertBlock(), \
-		*falseBB__ = Nucleus::getPredecessor(endBB__),   \
-		*onceBB__ = endBB__;                             \
-		onceBB__ && elseBlock(falseBB__);                \
-		onceBB__ = 0, Nucleus::createBr(endBB__), Nucleus::setInsertBlock(endBB__))
+	for(BasicBlock *elseBB__ = beginElse(),              \
+	    *endBB__ = Nucleus::getInsertBlock(),            \
+	    *onceBB__ = endBB__;                             \
+	    onceBB__ && elseBlock(elseBB__);                 \
+	    onceBB__ = nullptr,                              \
+	    Nucleus::createBr(endBB__),                      \
+	    Nucleus::setInsertBlock(endBB__))
 }
 
 #endif   // sw_Reactor_hpp
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index 98c660e..4ae6dfa 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -47,6 +47,8 @@
 
 	std::mutex codegenMutex;
 
+	sw::BasicBlock *falseBB = nullptr;
+
 	Ice::ELFFileStreamer *elfFile = nullptr;
 	Ice::Fdstream *out = nullptr;
 }
@@ -471,15 +473,10 @@
 
 	void Nucleus::setInsertBlock(BasicBlock *basicBlock)
 	{
-		assert(::basicBlock->getInsts().back().getTerminatorEdges().size() >= 0 && "Previous basic block must have a terminator");
+	//	assert(::basicBlock->getInsts().back().getTerminatorEdges().size() >= 0 && "Previous basic block must have a terminator");
 		::basicBlock = basicBlock;
 	}
 
-	BasicBlock *Nucleus::getPredecessor(BasicBlock *basicBlock)
-	{
-		assert(false && "UNIMPLEMENTED"); return nullptr;
-	}
-
 	void Nucleus::createFunction(Type *ReturnType, std::vector<Type*> &Params)
 	{
 		uint32_t sequenceNumber = 0;
@@ -6168,13 +6165,28 @@
 		return true;
 	}
 
+	void endIf(BasicBlock *falseBB)
+	{
+		::falseBB = falseBB;
+	}
+
 	bool elseBlock(BasicBlock *falseBB)
 	{
+		assert(falseBB && "Else not preceded by If");
+		falseBB->getInsts().back().setDeleted();
 		Nucleus::setInsertBlock(falseBB);
 
 		return true;
 	}
 
+	BasicBlock *beginElse()
+	{
+		BasicBlock *falseBB = ::falseBB;
+		::falseBB = nullptr;
+
+		return falseBB;
+	}
+
 	RValue<Long> Ticks()
 	{
 		assert(false && "UNIMPLEMENTED"); return RValue<Long>(V(nullptr));