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));