First cut at new loop codegen.
Change-Id: Id3bdf8b7a5606e7ce5d856ef225d5ddbe59a584b
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 0fff30e..769cf50 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -1342,33 +1342,51 @@
bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIntermLoop* node)
{
- // body emission needs to know what the for-loop terminal is when it sees a "continue"
- loopTerminal.push(node->getTerminal());
+ auto blocks = builder.makeNewLoop();
+ if (node->testFirst() && node->getTest()) {
+ spv::Block& head = builder.makeNewBlock();
+ builder.createBranch(&head);
- builder.makeNewLoop(node->testFirst());
-
- if (node->getTest()) {
+ builder.setBuildPoint(&head);
node->getTest()->traverse(this);
- // the AST only contained the test computation, not the branch, we have to add it
- spv::Id condition = builder.accessChainLoad(convertGlslangToSpvType(node->getTest()->getType()));
- builder.createLoopTestBranch(condition);
+ spv::Id condition =
+ builder.accessChainLoad(convertGlslangToSpvType(node->getTest()->getType()));
+ builder.createLoopMerge(&blocks.merge, &blocks.continue_target, spv::LoopControlMaskNone);
+ builder.createConditionalBranch(condition, &blocks.body, &blocks.merge);
+
+ builder.setBuildPoint(&blocks.body);
+ if (node->getBody())
+ node->getBody()->traverse(this); // continue->cont, break->exit
+ builder.createBranch(&blocks.continue_target);
+
+ builder.setBuildPoint(&blocks.continue_target);
+ if (node->getTerminal())
+ node->getTerminal()->traverse(this);
+ builder.createBranch(&head);
} else {
- builder.createBranchToBody();
+ builder.createBranch(&blocks.body);
+
+ builder.setBuildPoint(&blocks.body);
+ if (node->getBody())
+ node->getBody()->traverse(this); // continue->cont, break->exit
+ builder.createBranch(&blocks.continue_target);
+
+ builder.setBuildPoint(&blocks.continue_target);
+ if (node->getTerminal())
+ node->getTerminal()->traverse(this);
+ if (node->getTest()) {
+ node->getTest()->traverse(this);
+ spv::Id condition =
+ builder.accessChainLoad(convertGlslangToSpvType(node->getTest()->getType()));
+ builder.createLoopMerge(&blocks.merge, &blocks.continue_target,
+ spv::LoopControlMaskNone);
+ builder.createConditionalBranch(condition, &blocks.body, &blocks.merge);
+ } else {
+ builder.createBranch(&blocks.body);
+ }
}
- if (node->getBody()) {
- breakForLoop.push(true);
- node->getBody()->traverse(this);
- breakForLoop.pop();
- }
-
- if (loopTerminal.top())
- loopTerminal.top()->traverse(this);
-
- builder.closeLoop();
-
- loopTerminal.pop();
-
+ builder.setBuildPoint(&blocks.merge);
return false;
}
diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp
index a46c924..57e27e0 100755
--- a/SPIRV/SpvBuilder.cpp
+++ b/SPIRV/SpvBuilder.cpp
@@ -1753,6 +1753,19 @@
switchMerges.pop();
}
+Block& Builder::makeNewBlock()
+{
+ Function& function = buildPoint->getParent();
+ auto block = new Block(getUniqueId(), function);
+ function.addBlock(block);
+ return *block;
+}
+
+Builder::LoopBlocks Builder::makeNewLoop()
+{
+ return {makeNewBlock(), makeNewBlock(), makeNewBlock()};
+}
+
// Comments in header
void Builder::makeNewLoop(bool loopTestFirst)
{
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index 5750b00..d3e7ad9 100755
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -378,6 +378,13 @@
// The loopTestFirst parameter is true when the loop test executes before
// the body. (It is false for do-while loops.)
void makeNewLoop(bool loopTestFirst);
+ struct LoopBlocks {
+ Block &body, &merge, &continue_target;
+ };
+ LoopBlocks makeNewLoop();
+
+ // Create a new block in the function containing the build point.
+ Block& makeNewBlock();
// Add the branch for the loop test, based on the given condition.
// The true branch goes to the first block in the loop body, and
@@ -494,7 +501,11 @@
void dump(std::vector<unsigned int>&) const;
-protected:
+ void createBranch(Block* block);
+ void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
+ void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control);
+
+ protected:
Id makeIntConstant(Id typeId, unsigned value, bool specConstant);
Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const;
Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) const;
@@ -503,10 +514,7 @@
void transferAccessChainSwizzle(bool dynamic);
void simplifyAccessChainSwizzle();
void createAndSetNoPredecessorBlock(const char*);
- void createBranch(Block* block);
void createSelectionMerge(Block* mergeBlock, unsigned int control);
- void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control);
- void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
void dumpInstructions(std::vector<unsigned int>&, const std::vector<Instruction*>&) const;
struct Loop; // Defined below.
diff --git a/Test/baseResults/spv.for-simple.vert.out b/Test/baseResults/spv.for-simple.vert.out
index 95ca758..3dd4fc3 100755
--- a/Test/baseResults/spv.for-simple.vert.out
+++ b/Test/baseResults/spv.for-simple.vert.out
@@ -5,49 +5,51 @@
// Module Version 10000
// Generated by (magic number): 80001
-// Id's are bound by 25
+// Id's are bound by 26
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
- EntryPoint Vertex 4 "main" 23 24
+ EntryPoint Vertex 4 "main" 24 25
Source ESSL 300
Name 4 "main"
Name 8 "i"
- Name 17 "j"
- Name 23 "gl_VertexID"
- Name 24 "gl_InstanceID"
- Decorate 23(gl_VertexID) BuiltIn VertexId
- Decorate 24(gl_InstanceID) BuiltIn InstanceId
+ Name 18 "j"
+ Name 24 "gl_VertexID"
+ Name 25 "gl_InstanceID"
+ Decorate 24(gl_VertexID) BuiltIn VertexId
+ Decorate 25(gl_InstanceID) BuiltIn InstanceId
2: TypeVoid
3: TypeFunction 2
6: TypeInt 32 1
7: TypePointer Function 6(int)
9: 6(int) Constant 0
- 14: 6(int) Constant 10
- 15: TypeBool
- 18: 6(int) Constant 12
- 20: 6(int) Constant 1
- 22: TypePointer Input 6(int)
- 23(gl_VertexID): 22(ptr) Variable Input
-24(gl_InstanceID): 22(ptr) Variable Input
+ 15: 6(int) Constant 10
+ 16: TypeBool
+ 19: 6(int) Constant 12
+ 21: 6(int) Constant 1
+ 23: TypePointer Input 6(int)
+ 24(gl_VertexID): 23(ptr) Variable Input
+25(gl_InstanceID): 23(ptr) Variable Input
4(main): 2 Function None 3
5: Label
8(i): 7(ptr) Variable Function
- 17(j): 7(ptr) Variable Function
+ 18(j): 7(ptr) Variable Function
Store 8(i) 9
- Branch 10
+ Branch 13
10: Label
- 13: 6(int) Load 8(i)
- 16: 15(bool) SLessThan 13 14
- LoopMerge 11 10 None
- BranchConditional 16 12 11
- 12: Label
- Store 17(j) 18
- 19: 6(int) Load 8(i)
- 21: 6(int) IAdd 19 20
- Store 8(i) 21
- Branch 10
+ Store 18(j) 19
+ Branch 12
11: Label
Return
+ 12: Label
+ 20: 6(int) Load 8(i)
+ 22: 6(int) IAdd 20 21
+ Store 8(i) 22
+ Branch 13
+ 13: Label
+ 14: 6(int) Load 8(i)
+ 17: 16(bool) SLessThan 14 15
+ LoopMerge 11 12 None
+ BranchConditional 17 10 11
FunctionEnd