From fa668dad99d04389664a38e83bf7b9655ca03865 Mon Sep 17 00:00:00 2001
From: John Kessenich <cepheus@frii.com>
Date: Sun, 13 Sep 2015 14:46:30 -0600
Subject: [PATCH] SPV: Reduce spurious type generation by removing intermediate
 types in the middle of access chains.

This generally simplifies access chain generation, with far fewer  type conversions.
It is particularly important to future SPIR-V changes where there is less aggregate
type uniqueness due to carrying different layout information with the type.
---
 SPIRV/GlslangToSpv.cpp                    |  50 +++++-----
 SPIRV/SpvBuilder.cpp                      |  51 +++++-----
 SPIRV/SpvBuilder.h                        |  18 ++--
 Test/baseResults/spv.310.comp.out         | 108 +++++++++++-----------
 Test/baseResults/spv.Operations.frag.out  |  10 +-
 Test/baseResults/spv.accessChain.frag.out |  24 ++---
 Test/baseResults/spv.double.comp.out      |   8 +-
 Test/baseResults/spv.forLoop.frag.out     |  12 +--
 8 files changed, 144 insertions(+), 137 deletions(-)

diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 4c7c17c1e..0240dea09 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -530,12 +530,12 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
             // evaluate the right
             builder.clearAccessChain();
             node->getRight()->traverse(this);
-            spv::Id rValue = builder.accessChainLoad(TranslatePrecisionDecoration(node->getRight()->getType()));
+            spv::Id rValue = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
 
             if (node->getOp() != glslang::EOpAssign) {
                 // the left is also an r-value
                 builder.setAccessChain(lValue);
-                spv::Id leftRValue = builder.accessChainLoad(TranslatePrecisionDecoration(node->getLeft()->getType()));
+                spv::Id leftRValue = builder.accessChainLoad(convertGlslangToSpvType(node->getLeft()->getType()));
 
                 // do the operation
                 rValue = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()), 
@@ -587,10 +587,10 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
                 // so short circuit the access-chain stuff with a swizzle.
                 std::vector<unsigned> swizzle;
                 swizzle.push_back(node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst());
-                builder.accessChainPushSwizzle(swizzle);
+                builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
             } else {
                 // normal case for indexing array or structure or block
-                builder.accessChainPush(builder.makeIntConstant(index), convertGlslangToSpvType(node->getType()));
+                builder.accessChainPush(builder.makeIntConstant(index));
             }
         }
         return false;
@@ -611,15 +611,15 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
             // compute the next index in the chain
             builder.clearAccessChain();
             node->getRight()->traverse(this);
-            spv::Id index = builder.accessChainLoad(TranslatePrecisionDecoration(node->getRight()->getType()));
+            spv::Id index = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
 
             // restore the saved access chain
             builder.setAccessChain(partial);
 
             if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector())
-                builder.accessChainPushComponent(index);
+                builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()));
             else
-                builder.accessChainPush(index, convertGlslangToSpvType(node->getType()));
+                builder.accessChainPush(index);
         }
         return false;
     case glslang::EOpVectorSwizzle:
@@ -629,7 +629,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
             std::vector<unsigned> swizzle;
             for (int i = 0; i < (int)swizzleSequence.size(); ++i)
                 swizzle.push_back(swizzleSequence[i]->getAsConstantUnion()->getConstArray()[0].getIConst());
-            builder.accessChainPushSwizzle(swizzle);
+            builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
         }
         return false;
     default:
@@ -641,11 +641,11 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
     // Get the operands
     builder.clearAccessChain();
     node->getLeft()->traverse(this);
-    spv::Id left = builder.accessChainLoad(TranslatePrecisionDecoration(node->getLeft()->getType()));
+    spv::Id left = builder.accessChainLoad(convertGlslangToSpvType(node->getLeft()->getType()));
 
     builder.clearAccessChain();
     node->getRight()->traverse(this);
-    spv::Id right = builder.accessChainLoad(TranslatePrecisionDecoration(node->getRight()->getType()));
+    spv::Id right = builder.accessChainLoad(convertGlslangToSpvType(node->getRight()->getType()));
 
     spv::Id result;
     spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
@@ -702,7 +702,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
 
     builder.clearAccessChain();
     node->getOperand()->traverse(this);
-    spv::Id operand = builder.accessChainLoad(TranslatePrecisionDecoration(node->getOperand()->getType()));
+    spv::Id operand = builder.accessChainLoad(convertGlslangToSpvType(node->getOperand()->getType()));
 
     spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
 
@@ -1038,11 +1038,11 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
 
         builder.clearAccessChain();
         left->traverse(this);
-        spv::Id leftId = builder.accessChainLoad(TranslatePrecisionDecoration(left->getType()));
+        spv::Id leftId = builder.accessChainLoad(convertGlslangToSpvType(left->getType()));
 
         builder.clearAccessChain();
         right->traverse(this);
-        spv::Id rightId = builder.accessChainLoad(TranslatePrecisionDecoration(right->getType()));
+        spv::Id rightId = builder.accessChainLoad(convertGlslangToSpvType(right->getType()));
 
         result = createBinaryOperation(binOp, precision, 
                                        convertGlslangToSpvType(node->getType()), leftId, rightId, 
@@ -1084,7 +1084,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
         if (lvalue)
             operands.push_back(builder.accessChainGetLValue());
         else
-            operands.push_back(builder.accessChainLoad(TranslatePrecisionDecoration(glslangOperands[arg]->getAsTyped()->getType())));
+            operands.push_back(builder.accessChainLoad(convertGlslangToSpvType(glslangOperands[arg]->getAsTyped()->getType())));
     }
 
     if (atomic) {
@@ -1134,13 +1134,13 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
     node->getCondition()->traverse(this);
 
     // make an "if" based on the value created by the condition
-    spv::Builder::If ifBuilder(builder.accessChainLoad(spv::NoPrecision), builder);
+    spv::Builder::If ifBuilder(builder.accessChainLoad(convertGlslangToSpvType(node->getCondition()->getType())), builder);
 
     if (node->getTrueBlock()) {
         // emit the "then" statement
         node->getTrueBlock()->traverse(this);
         if (result)
-            builder.createStore(builder.accessChainLoad(TranslatePrecisionDecoration(node->getTrueBlock()->getAsTyped()->getType())), result);
+            builder.createStore(builder.accessChainLoad(convertGlslangToSpvType(node->getTrueBlock()->getAsTyped()->getType())), result);
     }
 
     if (node->getFalseBlock()) {
@@ -1148,7 +1148,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
         // emit the "else" statement
         node->getFalseBlock()->traverse(this);
         if (result)
-            builder.createStore(builder.accessChainLoad(TranslatePrecisionDecoration(node->getFalseBlock()->getAsTyped()->getType())), result);
+            builder.createStore(builder.accessChainLoad(convertGlslangToSpvType(node->getFalseBlock()->getAsTyped()->getType())), result);
     }
 
     ifBuilder.makeEndIf();
@@ -1169,7 +1169,7 @@ bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::T
 {
     // emit and get the condition before doing anything with switch
     node->getCondition()->traverse(this);
-    spv::Id selector = builder.accessChainLoad(TranslatePrecisionDecoration(node->getCondition()->getAsTyped()->getType()));
+    spv::Id selector = builder.accessChainLoad(convertGlslangToSpvType(node->getCondition()->getAsTyped()->getType()));
 
     // browse the children to sort out code segments
     int defaultSegment = -1;
@@ -1233,7 +1233,7 @@ bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIn
     if (node->getTest()) {
         node->getTest()->traverse(this);
         // the AST only contained the test computation, not the branch, we have to add it
-        spv::Id condition = builder.accessChainLoad(TranslatePrecisionDecoration(node->getTest()->getType()));
+        spv::Id condition = builder.accessChainLoad(convertGlslangToSpvType(node->getTest()->getType()));
         builder.createLoopTestBranch(condition);
     } else {
         builder.createBranchToBody();
@@ -1279,7 +1279,7 @@ bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::T
         if (inMain)
             builder.makeMainReturn();
         else if (node->getExpression())
-            builder.makeReturn(false, builder.accessChainLoad(TranslatePrecisionDecoration(node->getExpression()->getType())));
+            builder.makeReturn(false, builder.accessChainLoad(convertGlslangToSpvType(node->getExpression()->getType())));
         else
             builder.makeReturn();
 
@@ -1664,7 +1664,7 @@ void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermSequence&
     for (int i = 0; i < (int)glslangArguments.size(); ++i) {
         builder.clearAccessChain();
         glslangArguments[i]->traverse(this);
-        arguments.push_back(builder.accessChainLoad(TranslatePrecisionDecoration(glslangArguments[i]->getAsTyped()->getType())));
+        arguments.push_back(builder.accessChainLoad(convertGlslangToSpvType(glslangArguments[i]->getAsTyped()->getType())));
     }
 }
 
@@ -1672,7 +1672,7 @@ void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std
 {
     builder.clearAccessChain();
     node.getOperand()->traverse(this);
-    arguments.push_back(builder.accessChainLoad(TranslatePrecisionDecoration(node.getAsTyped()->getType())));
+    arguments.push_back(builder.accessChainLoad(convertGlslangToSpvType(node.getOperand()->getType())));
 }
 
 spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node)
@@ -1806,17 +1806,19 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
     // 1. Evaluate the arguments
     std::vector<spv::Builder::AccessChain> lValues;
     std::vector<spv::Id> rValues;
+    std::vector<spv::Id> argTypes;
     for (int a = 0; a < (int)glslangArgs.size(); ++a) {
         // build l-value
         builder.clearAccessChain();
         glslangArgs[a]->traverse(this);
+        argTypes.push_back(convertGlslangToSpvType(glslangArgs[a]->getAsTyped()->getType()));
         // keep outputs as l-values, evaluate input-only as r-values
         if (qualifiers[a] != glslang::EvqConstReadOnly) {
             // save l-value
             lValues.push_back(builder.getAccessChain());
         } else {
             // process r-value
-            rValues.push_back(builder.accessChainLoad(TranslatePrecisionDecoration(glslangArgs[a]->getAsTyped()->getType())));
+            rValues.push_back(builder.accessChainLoad(argTypes.back()));
         }
     }
 
@@ -1836,7 +1838,7 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
             if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) {
                 // need to copy the input into output space
                 builder.setAccessChain(lValues[lValueCount]);
-                spv::Id copy = builder.accessChainLoad(spv::NoPrecision);  // TODO: get precision
+                spv::Id copy = builder.accessChainLoad(argTypes[a]);
                 builder.createStore(copy, arg);
             }
             ++lValueCount;
diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp
index 953b60467..9913b0b6e 100755
--- a/SPIRV/SpvBuilder.cpp
+++ b/SPIRV/SpvBuilder.cpp
@@ -1957,18 +1957,23 @@ void Builder::createBranchToLoopHeaderFromInside(const Loop& loop)
 
 void Builder::clearAccessChain()
 {
-    accessChain.base = 0;
+    accessChain.base = NoResult;
     accessChain.indexChain.clear();
-    accessChain.instr = 0;
+    accessChain.instr = NoResult;
     accessChain.swizzle.clear();
-    accessChain.component = 0;
-    accessChain.resultType = NoType;
+    accessChain.component = NoResult;
+    accessChain.preSwizzleBaseType = NoType;
     accessChain.isRValue = false;
 }
 
 // Comments in header
-void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle)
+void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType)
 {
+    // swizzles can be stacked in GLSL, but simplified to a single
+    // one here; the base type doesn't change
+    if (accessChain.preSwizzleBaseType == NoType)
+        accessChain.preSwizzleBaseType = preSwizzleBaseType;
+
     // if needed, propagate the swizzle for the current access chain
     if (accessChain.swizzle.size()) {
         std::vector<unsigned> oldSwizzle = accessChain.swizzle;
@@ -1990,7 +1995,7 @@ void Builder::accessChainStore(Id rvalue)
 
     Id base = collapseAccessChain();
 
-    if (accessChain.swizzle.size() && accessChain.component)
+    if (accessChain.swizzle.size() && accessChain.component != NoResult)
         MissingFunctionality("simultaneous l-value swizzle and dynamic component selection");
 
     // If swizzle exists, it is out-of-order or not full, we must load the target vector,
@@ -2002,7 +2007,7 @@ void Builder::accessChainStore(Id rvalue)
     }
 
     // dynamic component selection
-    if (accessChain.component) {
+    if (accessChain.component != NoResult) {
         Id tempBaseId = (source == NoResult) ? createLoad(base) : source;
         source = createVectorInsertDynamic(tempBaseId, getTypeId(tempBaseId), rvalue, accessChain.component);
     }
@@ -2014,13 +2019,15 @@ void Builder::accessChainStore(Id rvalue)
 }
 
 // Comments in header
-Id Builder::accessChainLoad(Decoration /*precision*/)
+Id Builder::accessChainLoad(Id resultType)
 {
     Id id;
 
     if (accessChain.isRValue) {
         if (accessChain.indexChain.size() > 0) {
             mergeAccessChainSwizzle();  // TODO: optimization: look at applying this optimization more widely
+            Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType;
+        
             // if all the accesses are constants, we can use OpCompositeExtract
             std::vector<unsigned> indexes;
             bool constant = true;
@@ -2034,7 +2041,7 @@ Id Builder::accessChainLoad(Decoration /*precision*/)
             }
 
             if (constant)
-                id = createCompositeExtract(accessChain.base, accessChain.resultType, indexes);
+                id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
             else {
                 // make a new function variable for this r-value
                 Id lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
@@ -2057,24 +2064,22 @@ Id Builder::accessChainLoad(Decoration /*precision*/)
     }
 
     // Done, unless there are swizzles to do
-    if (accessChain.swizzle.size() == 0 && accessChain.component == 0)
+    if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult)
         return id;
 
-    Id componentType = getScalarTypeId(accessChain.resultType);
-
     // Do remaining swizzling
     // First, static swizzling
     if (accessChain.swizzle.size()) {
         // static swizzle
-        Id resultType = componentType;
+        Id swizzledType = getScalarTypeId(getTypeId(id));
         if (accessChain.swizzle.size() > 1)
-            resultType = makeVectorType(componentType, (int)accessChain.swizzle.size());
-        id = createRvalueSwizzle(resultType, id, accessChain.swizzle);
+            swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size());
+        id = createRvalueSwizzle(swizzledType, id, accessChain.swizzle);
     }
 
     // dynamic single-component selection
-    if (accessChain.component)
-        id = createVectorExtractDynamic(id, componentType, accessChain.component);
+    if (accessChain.component != NoResult)
+        id = createVectorExtractDynamic(id, resultType, accessChain.component);
 
     return id;
 }
@@ -2089,7 +2094,7 @@ Id Builder::accessChainGetLValue()
     // extract and insert elements to perform writeMask and/or swizzle.  This does not
     // go with getting a direct l-value pointer.
     assert(accessChain.swizzle.size() == 0);
-    assert(accessChain.component == spv::NoResult);
+    assert(accessChain.component == NoResult);
 
     return lvalue;
 }
@@ -2170,7 +2175,7 @@ void Builder::simplifyAccessChainSwizzle()
 {
     // If the swizzle has fewer components than the vector, it is subsetting, and must stay
     // to preserve that fact.
-    if (getNumTypeComponents(accessChain.resultType) > (int)accessChain.swizzle.size())
+    if (getNumTypeComponents(accessChain.preSwizzleBaseType) > (int)accessChain.swizzle.size())
         return;
 
     // if components are out of order, it is a swizzle
@@ -2181,6 +2186,8 @@ void Builder::simplifyAccessChainSwizzle()
 
     // otherwise, there is no need to track this swizzle
     accessChain.swizzle.clear();
+    if (accessChain.component == NoResult)
+        accessChain.preSwizzleBaseType = NoType;
 }
 
 // clear out swizzle if it can become part of the indexes
@@ -2188,12 +2195,12 @@ void Builder::mergeAccessChainSwizzle()
 {
     // is there even a chance of doing something?  Need a single-component swizzle
     if ((accessChain.swizzle.size() > 1) ||
-        (accessChain.swizzle.size() == 0 && accessChain.component == 0))
+        (accessChain.swizzle.size() == 0 && accessChain.component == NoResult))
         return;
 
     // TODO: optimization: remove this, but for now confine this to non-dynamic accesses
     // (the above test is correct when this is removed.)
-    if (accessChain.component)
+    if (accessChain.component != NoResult)
         return;
 
     // move the swizzle over to the indexes
@@ -2201,10 +2208,10 @@ void Builder::mergeAccessChainSwizzle()
         accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front()));
     else
         accessChain.indexChain.push_back(accessChain.component);
-    accessChain.resultType = getScalarTypeId(accessChain.resultType);
 
     // now there is no need to track this swizzle
     accessChain.component = NoResult;
+    accessChain.preSwizzleBaseType = NoType;
     accessChain.swizzle.clear();
 }
 
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index 1ceb9c69e..f81f9ed2f 100755
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -431,7 +431,7 @@ public:
         Id instr;                    // the instruction that generates this access chain
         std::vector<unsigned> swizzle;
         Id component;                // a dynamic component index, can coexist with a swizzle, done after the swizzle
-        Id resultType;               // dereferenced type, to be exclusive of swizzles
+        Id preSwizzleBaseType;       // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
         bool isRValue;
     };
 
@@ -452,7 +452,6 @@ public:
     {
         assert(isPointer(lValue));
         accessChain.base = lValue;
-        accessChain.resultType = getContainedTypeId(getTypeId(lValue));
     }
 
     // set new base value as an r-value
@@ -460,27 +459,30 @@ public:
     {
         accessChain.isRValue = true;
         accessChain.base = rValue;
-        accessChain.resultType = getTypeId(rValue);
     }
 
     // push offset onto the end of the chain
-    void accessChainPush(Id offset, Id newType)
+    void accessChainPush(Id offset)
     {
         accessChain.indexChain.push_back(offset);
-        accessChain.resultType = newType;
     }
 
     // push new swizzle onto the end of any existing swizzle, merging into a single swizzle
-    void accessChainPushSwizzle(std::vector<unsigned>& swizzle);
+    void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType);
 
     // push a variable component selection onto the access chain; supporting only one, so unsided
-    void accessChainPushComponent(Id component) { accessChain.component = component; }
+    void accessChainPushComponent(Id component, Id preSwizzleBaseType)
+    {
+        accessChain.component = component;
+        if (accessChain.preSwizzleBaseType == NoType)
+            accessChain.preSwizzleBaseType = preSwizzleBaseType;
+    }
 
     // use accessChain and swizzle to store value
     void accessChainStore(Id rvalue);
 
     // use accessChain and swizzle to load an r-value
-    Id accessChainLoad(Decoration precision);
+    Id accessChainLoad(Id ResultType);
 
     // get the direct pointer for an l-value
     Id accessChainGetLValue();
diff --git a/Test/baseResults/spv.310.comp.out b/Test/baseResults/spv.310.comp.out
index 9fbb2d58a..b8c7b8845 100644
--- a/Test/baseResults/spv.310.comp.out
+++ b/Test/baseResults/spv.310.comp.out
@@ -7,7 +7,7 @@ Linked compute stage:
 
 // Module Version 99
 // Generated by (magic number): 51a00bb
-// Id's are bound by 72
+// Id's are bound by 68
 
                               Source ESSL 310
                               Capability Shader
@@ -26,21 +26,21 @@ Linked compute stage:
                               MemberName 25(outbna) 0  "k"
                               MemberName 25(outbna) 1  "na"
                               Name 27  "outbnamena"
-                              Name 47  "i"
-                              Name 53  "outs"
-                              MemberName 53(outs) 0  "s"
-                              MemberName 53(outs) 1  "va"
-                              Name 55  "outnames"
-                              Name 59  "gl_LocalInvocationID"
+                              Name 44  "i"
+                              Name 50  "outs"
+                              MemberName 50(outs) 0  "s"
+                              MemberName 50(outs) 1  "va"
+                              Name 52  "outnames"
+                              Name 55  "gl_LocalInvocationID"
                               Decorate 14(outb) GLSLShared
                               Decorate 14(outb) BufferBlock
                               Decorate 25(outbna) GLSLShared
                               Decorate 25(outbna) BufferBlock
-                              Decorate 53(outs) GLSLShared
-                              Decorate 53(outs) BufferBlock
-                              Decorate 59(gl_LocalInvocationID) BuiltIn LocalInvocationId
-                              Decorate 71 BuiltIn WorkgroupSize
-                              Decorate 71 NoStaticUse
+                              Decorate 50(outs) GLSLShared
+                              Decorate 50(outs) BufferBlock
+                              Decorate 55(gl_LocalInvocationID) BuiltIn LocalInvocationId
+                              Decorate 67 BuiltIn WorkgroupSize
+                              Decorate 67 NoStaticUse
                2:             TypeVoid
                3:             TypeFunction 2
                7:             TypeInt 32 0
@@ -64,30 +64,26 @@ Linked compute stage:
   27(outbnamena):     26(ptr) Variable Uniform
               28:     17(int) Constant 1
               31:             TypePointer Uniform 24(fvec4)
-              33:             TypeRuntimeArray 12(fvec3)
-              34:     17(int) Constant 3
-              35:     17(int) Constant 18
-              36:             TypePointer Uniform 12(fvec3)
-              40:             TypeRuntimeArray 12(fvec3)
-              41:     17(int) Constant 17
-              42:   11(float) Constant 1077936128
-              43:   12(fvec3) ConstantComposite 42 42 42
-              45:             TypeRuntimeArray 12(fvec3)
-              46:             TypePointer WorkgroupLocal 17(int)
-           47(i):     46(ptr) Variable WorkgroupLocal
-              52:             TypeRuntimeArray 24(fvec4)
-        53(outs):             TypeStruct 17(int) 52
-              54:             TypePointer Uniform 53(outs)
-    55(outnames):     54(ptr) Variable Uniform
-              56:             TypeRuntimeArray 24(fvec4)
-              57:             TypeVector 7(int) 3
-              58:             TypePointer Input 57(ivec3)
-59(gl_LocalInvocationID):     58(ptr) Variable Input
-              66:             TypePointer Uniform 17(int)
-              68:      7(int) Constant 16
-              69:      7(int) Constant 32
-              70:      7(int) Constant 4
-              71:   57(ivec3) ConstantComposite 68 69 70
+              33:     17(int) Constant 3
+              34:     17(int) Constant 18
+              35:             TypePointer Uniform 12(fvec3)
+              39:     17(int) Constant 17
+              40:   11(float) Constant 1077936128
+              41:   12(fvec3) ConstantComposite 40 40 40
+              43:             TypePointer WorkgroupLocal 17(int)
+           44(i):     43(ptr) Variable WorkgroupLocal
+              49:             TypeRuntimeArray 24(fvec4)
+        50(outs):             TypeStruct 17(int) 49
+              51:             TypePointer Uniform 50(outs)
+    52(outnames):     51(ptr) Variable Uniform
+              53:             TypeVector 7(int) 3
+              54:             TypePointer Input 53(ivec3)
+55(gl_LocalInvocationID):     54(ptr) Variable Input
+              62:             TypePointer Uniform 17(int)
+              64:      7(int) Constant 16
+              65:      7(int) Constant 32
+              66:      7(int) Constant 4
+              67:   53(ivec3) ConstantComposite 64 65 66
          4(main):           2 Function None 3
                5:             Label
                               MemoryBarrier 8 9
@@ -99,26 +95,26 @@ Linked compute stage:
               30:   24(fvec4) CompositeConstruct 29 29 29 29
               32:     31(ptr) AccessChain 27(outbnamena) 28
                               Store 32 30
-              37:     36(ptr) AccessChain 16(outbname) 34 35
-              38:   12(fvec3) Load 37
-              39:   11(float) CompositeExtract 38 0
-                              Store 20(s) 39
-              44:     36(ptr) AccessChain 16(outbname) 34 41
-                              Store 44 43
-              48:     17(int) Load 47(i)
-              49:   11(float) Load 20(s)
-              50:   12(fvec3) CompositeConstruct 49 49 49
-              51:     36(ptr) AccessChain 16(outbname) 34 48
-                              Store 51 50
-              60:   57(ivec3) Load 59(gl_LocalInvocationID)
-              61:      7(int) CompositeExtract 60 0
-              62:   11(float) Load 20(s)
-              63:   24(fvec4) CompositeConstruct 62 62 62 62
-              64:     31(ptr) AccessChain 55(outnames) 28 61
-                              Store 64 63
-              65:     17(int) ArrayLength 16(outbname)
-              67:     66(ptr) AccessChain 55(outnames) 18
-                              Store 67 65
+              36:     35(ptr) AccessChain 16(outbname) 33 34
+              37:   12(fvec3) Load 36
+              38:   11(float) CompositeExtract 37 0
+                              Store 20(s) 38
+              42:     35(ptr) AccessChain 16(outbname) 33 39
+                              Store 42 41
+              45:     17(int) Load 44(i)
+              46:   11(float) Load 20(s)
+              47:   12(fvec3) CompositeConstruct 46 46 46
+              48:     35(ptr) AccessChain 16(outbname) 33 45
+                              Store 48 47
+              56:   53(ivec3) Load 55(gl_LocalInvocationID)
+              57:      7(int) CompositeExtract 56 0
+              58:   11(float) Load 20(s)
+              59:   24(fvec4) CompositeConstruct 58 58 58 58
+              60:     31(ptr) AccessChain 52(outnames) 28 57
+                              Store 60 59
+              61:     17(int) ArrayLength 16(outbname)
+              63:     62(ptr) AccessChain 52(outnames) 18
+                              Store 63 61
                               Branch 6
                6:             Label
                               Return
diff --git a/Test/baseResults/spv.Operations.frag.out b/Test/baseResults/spv.Operations.frag.out
index 9858f85f8..909bb23d6 100755
--- a/Test/baseResults/spv.Operations.frag.out
+++ b/Test/baseResults/spv.Operations.frag.out
@@ -51,7 +51,7 @@ Linked fragment stage:
              292:     19(int) Constant 2
              299:     19(int) Constant 1
              301:             TypePointer Function 7(float)
-             332:             TypeVector 7(float) 3
+             331:             TypeVector 7(float) 3
              347:    7(float) Constant 1073741824
              354:    7(float) Constant 1065353216
              359:     19(int) Constant 66
@@ -434,11 +434,11 @@ Linked fragment stage:
              329:    7(float) Load 302(f)
              330:    7(float) FAdd 329 328
                               Store 302(f) 330
-             331:    8(fvec4) Load 10(v)
-             333:  332(fvec3) VectorShuffle 331 331 0 1 2
+             332:    8(fvec4) Load 10(v)
+             333:  331(fvec3) VectorShuffle 332 332 0 1 2
              334:    8(fvec4) Load 10(v)
-             335:  332(fvec3) VectorShuffle 334 334 0 1 2
-             336:  332(fvec3) ExtInst 1(GLSL.std.450) 67(Cross) 333 335
+             335:  331(fvec3) VectorShuffle 334 334 0 1 2
+             336:  331(fvec3) ExtInst 1(GLSL.std.450) 67(Cross) 333 335
              337:    7(float) CompositeExtract 336 0
              338:    7(float) Load 302(f)
              339:    7(float) FAdd 338 337
diff --git a/Test/baseResults/spv.accessChain.frag.out b/Test/baseResults/spv.accessChain.frag.out
index f45cc3435..c280bffd8 100755
--- a/Test/baseResults/spv.accessChain.frag.out
+++ b/Test/baseResults/spv.accessChain.frag.out
@@ -86,7 +86,7 @@ Linked fragment stage:
               67:     14(int) Constant 0
               68:             TypeInt 32 0
               69:     68(int) Constant 0
-              97:             TypeVector 7(float) 2
+              96:             TypeVector 7(float) 2
              110:     68(int) Constant 2
              142:    7(float) Constant 0
              143:    8(fvec3) ConstantComposite 142 142 142
@@ -227,8 +227,8 @@ Linked fragment stage:
         34(comp):     15(ptr) FunctionParameter
               36:             Label
               95:     14(int) Load 34(comp)
-              96:    8(fvec3) CompositeExtract 33(i) 0
-              98:   97(fvec2) VectorShuffle 96 96 1 0
+              97:    8(fvec3) CompositeExtract 33(i) 0
+              98:   96(fvec2) VectorShuffle 97 97 1 0
               99:    7(float) VectorExtractDynamic 98 95
              100:    8(fvec3) Load 66(OutColor)
              101:    8(fvec3) CompositeConstruct 99 99 99
@@ -241,10 +241,10 @@ Linked fragment stage:
         38(comp):     15(ptr) FunctionParameter
               40:             Label
              103:    8(fvec3) CompositeExtract 37(i) 0
-             104:   97(fvec2) VectorShuffle 103 103 0 1
+             104:   96(fvec2) VectorShuffle 103 103 0 1
              105:    8(fvec3) Load 66(OutColor)
-             106:   97(fvec2) VectorShuffle 105 105 0 1
-             107:   97(fvec2) FAdd 106 104
+             106:   96(fvec2) VectorShuffle 105 105 0 1
+             107:   96(fvec2) FAdd 106 104
              108:    8(fvec3) Load 66(OutColor)
              109:    8(fvec3) VectorShuffle 108 107 3 4 2
                               Store 66(OutColor) 109
@@ -279,10 +279,10 @@ Linked fragment stage:
         50(comp):     15(ptr) FunctionParameter
               52:             Label
              121:    8(fvec3) CompositeExtract 49(i) 0
-             122:   97(fvec2) VectorShuffle 121 121 0 1
+             122:   96(fvec2) VectorShuffle 121 121 0 1
              123:    8(fvec3) Load 66(OutColor)
-             124:   97(fvec2) VectorShuffle 123 123 2 1
-             125:   97(fvec2) FAdd 124 122
+             124:   96(fvec2) VectorShuffle 123 123 2 1
+             125:   96(fvec2) FAdd 124 122
              126:    8(fvec3) Load 66(OutColor)
              127:    8(fvec3) VectorShuffle 126 125 0 4 3
                               Store 66(OutColor) 127
@@ -293,10 +293,10 @@ Linked fragment stage:
         54(comp):     15(ptr) FunctionParameter
               56:             Label
              128:    8(fvec3) CompositeExtract 53(i) 0
-             129:   97(fvec2) VectorShuffle 128 128 0 1
+             129:   96(fvec2) VectorShuffle 128 128 0 1
              130:    8(fvec3) Load 66(OutColor)
-             131:   97(fvec2) VectorShuffle 130 130 0 2
-             132:   97(fvec2) FAdd 131 129
+             131:   96(fvec2) VectorShuffle 130 130 0 2
+             132:   96(fvec2) FAdd 131 129
              133:    8(fvec3) Load 66(OutColor)
              134:    8(fvec3) VectorShuffle 133 132 3 1 4
                               Store 66(OutColor) 134
diff --git a/Test/baseResults/spv.double.comp.out b/Test/baseResults/spv.double.comp.out
index 3f2ca156f..d77bc0c06 100755
--- a/Test/baseResults/spv.double.comp.out
+++ b/Test/baseResults/spv.double.comp.out
@@ -57,7 +57,7 @@ Linked compute stage:
               25:             TypeVector 24(int) 3
               26:             TypePointer Input 25(ivec3)
 27(gl_GlobalInvocationID):     26(ptr) Variable Input
-              29:             TypeVector 24(int) 2
+              28:             TypeVector 24(int) 2
               32:             TypePointer Function 8(float)
 34(gl_LocalInvocationID):     26(ptr) Variable Input
               38:     12(int) Constant 8
@@ -86,12 +86,12 @@ Linked compute stage:
                               Store 16 14
               20:     19(ptr) AccessChain 11(bufInst) 17
                               Store 20 18
-              28:   25(ivec3) Load 27(gl_GlobalInvocationID)
-              30:   29(ivec2) VectorShuffle 28 28 0 1
+              29:   25(ivec3) Load 27(gl_GlobalInvocationID)
+              30:   28(ivec2) VectorShuffle 29 29 0 1
               31:   21(ivec2) Bitcast 30
                               Store 23(storePos) 31
               35:   25(ivec3) Load 34(gl_LocalInvocationID)
-              36:   29(ivec2) VectorShuffle 35 35 0 1
+              36:   28(ivec2) VectorShuffle 35 35 0 1
               37:   21(ivec2) Bitcast 36
               39:   21(ivec2) CompositeConstruct 38 38
               40:   21(ivec2) ISub 37 39
diff --git a/Test/baseResults/spv.forLoop.frag.out b/Test/baseResults/spv.forLoop.frag.out
index 972ecead4..75949a041 100755
--- a/Test/baseResults/spv.forLoop.frag.out
+++ b/Test/baseResults/spv.forLoop.frag.out
@@ -58,7 +58,7 @@ Linked fragment stage:
               50:             TypePointer UniformConstant 49(ivec4)
           51(v4):     50(ptr) Variable UniformConstant
               71:     48(int) Constant 4
-              86:             TypeVector 7(float) 3
+              85:             TypeVector 7(float) 3
               97:             TypePointer Input 7(float)
            98(f):     97(ptr) Variable Input
              116:     14(int) Constant 16
@@ -145,8 +145,8 @@ Linked fragment stage:
               82:    8(fvec4) Load 36(gl_FragColor)
               83:    8(fvec4) FAdd 82 81
                               Store 36(gl_FragColor) 83
-              85:    8(fvec4) Load 12(BaseColor)
-              87:   86(fvec3) VectorShuffle 85 85 0 1 2
+              86:    8(fvec4) Load 12(BaseColor)
+              87:   85(fvec3) VectorShuffle 86 86 0 1 2
               88:    8(fvec4) Load 84(r)
               89:    8(fvec4) VectorShuffle 88 87 4 5 6 3
                               Store 84(r) 89
@@ -169,10 +169,10 @@ Linked fragment stage:
                                 Branch 91
               92:             Label
              104:    8(fvec4) Load 84(r)
-             105:   86(fvec3) VectorShuffle 104 104 0 1 2
+             105:   85(fvec3) VectorShuffle 104 104 0 1 2
              106:    8(fvec4) Load 36(gl_FragColor)
-             107:   86(fvec3) VectorShuffle 106 106 0 1 2
-             108:   86(fvec3) FAdd 107 105
+             107:   85(fvec3) VectorShuffle 106 106 0 1 2
+             108:   85(fvec3) FAdd 107 105
              109:    8(fvec4) Load 36(gl_FragColor)
              110:    8(fvec4) VectorShuffle 109 108 4 5 6 3
                               Store 36(gl_FragColor) 110
-- 
GitLab