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