diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 4072d6a6ed7b1e8eafdf6d9bdc170e7e7fa5d05f..1cc3e6f89db831067efc50e94079b8e6f9e8d341 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -573,7 +573,7 @@ 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, node->getLeft()->getVectorSize(), convertGlslangToSpvType(node->getType()));
+                builder.accessChainPushSwizzle(swizzle, node->getLeft()->getVectorSize());
             } else {
                 // normal case for indexing array or structure or block
                 builder.accessChainPush(builder.makeIntConstant(index), convertGlslangToSpvType(node->getType()));
@@ -615,7 +615,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, node->getLeft()->getVectorSize(), convertGlslangToSpvType(node->getType()));
+            builder.accessChainPushSwizzle(swizzle, node->getLeft()->getVectorSize());
         }
         return false;
     default:
diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp
index 6699a0c1cb498d25a10b60308f770645b6b65e4b..b94c0ff929b2a9e4de1f76094173670d14672c3d 100644
--- a/SPIRV/SpvBuilder.cpp
+++ b/SPIRV/SpvBuilder.cpp
@@ -907,6 +907,27 @@ Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, std::vecto
     return insert->getResultId();
 }
 
+Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex)
+{
+    Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic);
+    extract->addIdOperand(vector);
+    extract->addIdOperand(componentIndex);
+    buildPoint->addInstruction(extract);
+
+    return extract->getResultId();
+}
+
+Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex)
+{
+    Instruction* insert = new Instruction(getUniqueId(), typeId, OpVectorInsertDynamic);
+    insert->addIdOperand(vector);
+    insert->addIdOperand(component);
+    insert->addIdOperand(componentIndex);
+    buildPoint->addInstruction(insert);
+
+    return insert->getResultId();
+}
+
 // An opcode that has no operands, no result id, and no type
 void Builder::createNoResultOp(Op opCode)
 {
@@ -997,6 +1018,7 @@ Id Builder::createRvalueSwizzle(Id typeId, Id source, std::vector<unsigned>& cha
         return createCompositeExtract(source, typeId, channels.front());
 
     Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
+    assert(isVector(source));
     swizzle->addIdOperand(source);
     swizzle->addIdOperand(source);
     for (int i = 0; i < (int)channels.size(); ++i)
@@ -1014,6 +1036,8 @@ Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<uns
         return createCompositeInsert(source, target, typeId, channels.front());
 
     Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
+    assert(isVector(source));
+    assert(isVector(target));
     swizzle->addIdOperand(target);
     swizzle->addIdOperand(source);
 
@@ -1813,13 +1837,12 @@ void Builder::clearAccessChain()
     accessChain.instr = 0;
     accessChain.swizzle.clear();
     accessChain.component = 0;
-    accessChain.swizzleTargetWidth = 0;
     accessChain.resultType = NoType;
     accessChain.isRValue = false;
 }
 
 // Comments in header
-void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width, Id type)
+void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width)
 {
     // if needed, propagate the swizzle for the current access chain
     if (accessChain.swizzle.size()) {
@@ -1828,15 +1851,8 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width,
         for (unsigned int i = 0; i < swizzle.size(); ++i) {
             accessChain.swizzle.push_back(oldSwizzle[swizzle[i]]);
         }
-    } else {
+    } else
         accessChain.swizzle = swizzle;
-    }
-
-    // track width the swizzle operates on; once known, it does not change
-    if (accessChain.swizzleTargetWidth == 0)
-        accessChain.swizzleTargetWidth = width;
-
-    accessChain.resultType = type;
 
     // determine if we need to track this swizzle anymore
     simplifyAccessChainSwizzle();
@@ -1849,23 +1865,24 @@ void Builder::accessChainStore(Id rvalue)
 
     Id base = collapseAccessChain();
 
+    if (accessChain.swizzle.size() && accessChain.component)
+        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,
     // extract and insert elements to perform writeMask and/or swizzle.
-    Id source;
-
+    Id source = NoResult;
     if (accessChain.swizzle.size()) {
         Id tempBaseId = createLoad(base);
         source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, rvalue, accessChain.swizzle);
-    } else if (accessChain.component) {
-        Id tempBaseId = createLoad(base);
-        Instruction* vectorInsert = new Instruction(getUniqueId(), getTypeId(tempBaseId), OpVectorInsertDynamic);
-        vectorInsert->addIdOperand(tempBaseId);
-        vectorInsert->addIdOperand(rvalue);
-        vectorInsert->addIdOperand(accessChain.component);
-        buildPoint->addInstruction(vectorInsert);
+    }
 
-        source = vectorInsert->getResultId();
-    } else
+    // dynamic component selection
+    if (accessChain.component) {
+        Id tempBaseId = (source == NoResult) ? createLoad(base) : source;
+        source = createVectorInsertDynamic(tempBaseId, getTypeId(tempBaseId), rvalue, accessChain.component);
+    }
+
+    if (source == NoResult)
         source = rvalue;
 
     createStore(source, base);
@@ -1878,6 +1895,7 @@ Id Builder::accessChainLoad(Decoration /*precision*/)
 
     if (accessChain.isRValue) {
         if (accessChain.indexChain.size() > 0) {
+            mergeAccessChainSwizzle();  // TODO: optimization: look at applying this optimization more widely
             // if all the accesses are constants, we can use OpCompositeExtract
             std::vector<unsigned> indexes;
             bool constant = true;
@@ -1913,14 +1931,25 @@ Id Builder::accessChainLoad(Decoration /*precision*/)
         id = createLoad(collapseAccessChain());
     }
 
-    if (accessChain.component) {
-        Instruction* vectorExtract = new Instruction(getUniqueId(), getScalarTypeId(getTypeId(id)), OpVectorExtractDynamic);
-        vectorExtract->addIdOperand(id);
-        vectorExtract->addIdOperand(accessChain.component);
-        buildPoint->addInstruction(vectorExtract);
-        id = vectorExtract->getResultId();
-    } else if (accessChain.swizzle.size())
-        id = createRvalueSwizzle(accessChain.resultType, id, accessChain.swizzle);
+    // Done, unless there are swizzles to do
+    if (accessChain.swizzle.size() == 0 && accessChain.component == 0)
+        return id;
+
+    Id componentType = getScalarTypeId(accessChain.resultType);
+
+    // Do remaining swizzling
+    // First, static swizzling
+    if (accessChain.swizzle.size()) {
+        // static swizzle
+        Id resultType = componentType;
+        if (accessChain.swizzle.size() > 1)
+            resultType = makeVectorType(componentType, accessChain.swizzle.size());
+        id = createRvalueSwizzle(resultType, id, accessChain.swizzle);
+    }
+
+    // dynamic single-component selection
+    if (accessChain.component)
+        id = createVectorExtractDynamic(id, componentType, accessChain.component);
 
     return id;
 }
@@ -2005,8 +2034,9 @@ Id Builder::collapseAccessChain()
 // clear out swizzle if it is redundant
 void Builder::simplifyAccessChainSwizzle()
 {
-    // if swizzle has fewer components than our target, it is a writemask
-    if (accessChain.swizzleTargetWidth > (int)accessChain.swizzle.size())
+    // 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())
         return;
 
     // if components are out of order, it is a swizzle
@@ -2017,7 +2047,31 @@ void Builder::simplifyAccessChainSwizzle()
 
     // otherwise, there is no need to track this swizzle
     accessChain.swizzle.clear();
-    accessChain.swizzleTargetWidth = 0;
+}
+
+// clear out swizzle if it can become part of the indexes
+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)
+        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)
+        return;
+
+    // move the swizzle over to the indexes
+    if (accessChain.swizzle.size() == 1)
+        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.swizzle.clear();
 }
 
 // Utility method for creating a new block and setting the insert point to
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index e4e81788bc31aef80e12d31c2a146c2f66281461..c46c361a960e54b0d975dca0fc91078579c1345b 100644
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -228,6 +228,9 @@ public:
     Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index);
     Id createCompositeInsert(Id object, Id composite, Id typeId, std::vector<unsigned>& indexes);
 
+    Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex);
+    Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex);
+
     void createNoResultOp(Op);
     void createNoResultOp(Op, Id operand);
     void createControlBarrier(unsigned executionScope);
@@ -244,7 +247,7 @@ public:
 
     // Take a copy of an lvalue (target) and a source of components, and set the
     // source components into the lvalue where the 'channels' say to put them.
-    // An update version of the target is returned.
+    // An updated version of the target is returned.
     // (No true lvalue or stores are used.)
     Id createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<unsigned>& channels);
 
@@ -426,9 +429,8 @@ public:
         std::vector<Id> indexChain;
         Id instr;                    // the instruction that generates this access chain
         std::vector<unsigned> swizzle;
-        Id component;                // a dynamic component index
-        int swizzleTargetWidth;
-        Id resultType;               // dereferenced type, to be inclusive of swizzles, which can't have a pointer
+        Id component;                // a dynamic component index, can coexist with a swizzle, done after the swizzle
+        Id resultType;               // dereferenced type, to be exclusive of swizzles
         bool isRValue;
     };
 
@@ -449,6 +451,7 @@ public:
     {
         assert(isPointer(lValue));
         accessChain.base = lValue;
+        accessChain.resultType = getContainedTypeId(getTypeId(lValue));
     }
 
     // set new base value as an r-value
@@ -467,7 +470,7 @@ public:
     }
 
     // push new swizzle onto the end of any existing swizzle, merging into a single swizzle
-    void accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width, Id type);
+    void accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width);
 
     // push a variable component selection onto the access chain; supporting only one, so unsided
     void accessChainPushComponent(Id component) { accessChain.component = component; }
@@ -489,6 +492,7 @@ protected:
     Id findCompositeConstant(Op typeClass, std::vector<Id>& comps) const;
     Id collapseAccessChain();
     void simplifyAccessChainSwizzle();
+    void mergeAccessChainSwizzle();
     void createAndSetNoPredecessorBlock(const char*);
     void createBranch(Block* block);
     void createMerge(Op, Block*, unsigned int control);
diff --git a/Test/baseResults/spv.Operations.frag.out b/Test/baseResults/spv.Operations.frag.out
index f384924670e08192bd0c363fcdbede936a63c245..8cddbd793f79ffbf44178f8296b98b70898049d8 100644
--- a/Test/baseResults/spv.Operations.frag.out
+++ b/Test/baseResults/spv.Operations.frag.out
@@ -52,7 +52,7 @@ Linked fragment stage:
              292:     19(int) Constant 2
              299:     19(int) Constant 1
              301:             TypePointer Function 7(float)
-             331:             TypeVector 7(float) 3
+             332:             TypeVector 7(float) 3
              347:    7(float) Constant 1073741824
              354:    7(float) Constant 1065353216
              359:     19(int) Constant 66
@@ -435,11 +435,11 @@ Linked fragment stage:
              329:    7(float) Load 302(f) 
              330:    7(float) FAdd 329 328
                               Store 302(f) 330 
-             332:    8(fvec4) Load 10(v) 
-             333:  331(fvec3) VectorShuffle 332 332 0 1 2
+             331:    8(fvec4) Load 10(v) 
+             333:  332(fvec3) VectorShuffle 331 331 0 1 2
              334:    8(fvec4) Load 10(v) 
-             335:  331(fvec3) VectorShuffle 334 334 0 1 2
-             336:  331(fvec3) ExtInst 1(GLSL.std.450) 60(cross) 333 335
+             335:  332(fvec3) VectorShuffle 334 334 0 1 2
+             336:  332(fvec3) ExtInst 1(GLSL.std.450) 60(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
new file mode 100644
index 0000000000000000000000000000000000000000..1c72b8a7cc72a01687d60e53b7bbe6fb37720b67
--- /dev/null
+++ b/Test/baseResults/spv.accessChain.frag.out
@@ -0,0 +1,324 @@
+spv.accessChain.frag
+Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.
+
+
+
+Linked fragment stage:
+
+
+
+// Module Version 99
+// Generated by (magic number): 51a00bb
+// Id's are bound by 198
+
+                              Source GLSL 420
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4
+                              Name 4  "main"
+                              Name 9  "S"
+                              MemberName 9(S) 0  "color"
+                              Name 12  "GetColor1(struct-S-vf31;"
+                              Name 11  "i"
+                              Name 19  "GetColor2(struct-S-vf31;i1;"
+                              Name 17  "i"
+                              Name 18  "comp"
+                              Name 23  "GetColor3(struct-S-vf31;i1;"
+                              Name 21  "i"
+                              Name 22  "comp"
+                              Name 27  "GetColor4(struct-S-vf31;i1;"
+                              Name 25  "i"
+                              Name 26  "comp"
+                              Name 31  "GetColor5(struct-S-vf31;i1;"
+                              Name 29  "i"
+                              Name 30  "comp"
+                              Name 35  "GetColor6(struct-S-vf31;i1;"
+                              Name 33  "i"
+                              Name 34  "comp"
+                              Name 39  "GetColor7(struct-S-vf31;i1;"
+                              Name 37  "i"
+                              Name 38  "comp"
+                              Name 43  "GetColor8(struct-S-vf31;i1;"
+                              Name 41  "i"
+                              Name 42  "comp"
+                              Name 47  "GetColor9(struct-S-vf31;i1;"
+                              Name 45  "i"
+                              Name 46  "comp"
+                              Name 51  "GetColor10(struct-S-vf31;i1;"
+                              Name 49  "i"
+                              Name 50  "comp"
+                              Name 55  "GetColor11(struct-S-vf31;i1;"
+                              Name 53  "i"
+                              Name 54  "comp"
+                              Name 59  "GetColor12(struct-S-vf31;i1;"
+                              Name 57  "i"
+                              Name 58  "comp"
+                              Name 63  "GetColor13(struct-S-vf31;i1;"
+                              Name 61  "i"
+                              Name 62  "comp"
+                              Name 66  "OutColor"
+                              Name 145  "s"
+                              Name 150  "u"
+                              Name 151  "param"
+                              Name 155  "param"
+                              Name 159  "param"
+                              Name 163  "param"
+                              Name 167  "param"
+                              Name 171  "param"
+                              Name 175  "param"
+                              Name 179  "param"
+                              Name 183  "param"
+                              Name 187  "param"
+                              Name 191  "param"
+                              Name 195  "param"
+                              Decorate 66(OutColor) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2 
+               7:             TypeFloat 32
+               8:             TypeVector 7(float) 3
+            9(S):             TypeStruct 8(fvec3)
+              10:             TypeFunction 2 9(S)
+              14:             TypeInt 32 1
+              15:             TypePointer Function 14(int)
+              16:             TypeFunction 2 9(S) 15(ptr)
+              65:             TypePointer Output 8(fvec3)
+    66(OutColor):     65(ptr) Variable Output 
+              67:     14(int) Constant 0
+              68:             TypeInt 32 0
+              69:     68(int) Constant 0
+              97:             TypeVector 7(float) 2
+             110:     68(int) Constant 2
+             142:    7(float) Constant 0
+             143:    8(fvec3) ConstantComposite 142 142 142
+             144:             TypePointer Function 9(S)
+             149:             TypePointer UniformConstant 14(int)
+          150(u):    149(ptr) Variable UniformConstant 
+         4(main):           2 Function None 3
+               5:             Label
+          145(s):    144(ptr) Variable Function 
+      151(param):     15(ptr) Variable Function 
+      155(param):     15(ptr) Variable Function 
+      159(param):     15(ptr) Variable Function 
+      163(param):     15(ptr) Variable Function 
+      167(param):     15(ptr) Variable Function 
+      171(param):     15(ptr) Variable Function 
+      175(param):     15(ptr) Variable Function 
+      179(param):     15(ptr) Variable Function 
+      183(param):     15(ptr) Variable Function 
+      187(param):     15(ptr) Variable Function 
+      191(param):     15(ptr) Variable Function 
+      195(param):     15(ptr) Variable Function 
+                              Store 66(OutColor) 143 
+             146:        9(S) Load 145(s) 
+             147:           2 FunctionCall 12(GetColor1(struct-S-vf31;) 146
+             148:        9(S) Load 145(s) 
+             152:     14(int) Load 150(u) 
+                              Store 151(param) 152 
+             153:           2 FunctionCall 19(GetColor2(struct-S-vf31;i1;) 148 151(param)
+             154:        9(S) Load 145(s) 
+             156:     14(int) Load 150(u) 
+                              Store 155(param) 156 
+             157:           2 FunctionCall 23(GetColor3(struct-S-vf31;i1;) 154 155(param)
+             158:        9(S) Load 145(s) 
+             160:     14(int) Load 150(u) 
+                              Store 159(param) 160 
+             161:           2 FunctionCall 27(GetColor4(struct-S-vf31;i1;) 158 159(param)
+             162:        9(S) Load 145(s) 
+             164:     14(int) Load 150(u) 
+                              Store 163(param) 164 
+             165:           2 FunctionCall 31(GetColor5(struct-S-vf31;i1;) 162 163(param)
+             166:        9(S) Load 145(s) 
+             168:     14(int) Load 150(u) 
+                              Store 167(param) 168 
+             169:           2 FunctionCall 35(GetColor6(struct-S-vf31;i1;) 166 167(param)
+             170:        9(S) Load 145(s) 
+             172:     14(int) Load 150(u) 
+                              Store 171(param) 172 
+             173:           2 FunctionCall 39(GetColor7(struct-S-vf31;i1;) 170 171(param)
+             174:        9(S) Load 145(s) 
+             176:     14(int) Load 150(u) 
+                              Store 175(param) 176 
+             177:           2 FunctionCall 43(GetColor8(struct-S-vf31;i1;) 174 175(param)
+             178:        9(S) Load 145(s) 
+             180:     14(int) Load 150(u) 
+                              Store 179(param) 180 
+             181:           2 FunctionCall 47(GetColor9(struct-S-vf31;i1;) 178 179(param)
+             182:        9(S) Load 145(s) 
+             184:     14(int) Load 150(u) 
+                              Store 183(param) 184 
+             185:           2 FunctionCall 51(GetColor10(struct-S-vf31;i1;) 182 183(param)
+             186:        9(S) Load 145(s) 
+             188:     14(int) Load 150(u) 
+                              Store 187(param) 188 
+             189:           2 FunctionCall 55(GetColor11(struct-S-vf31;i1;) 186 187(param)
+             190:        9(S) Load 145(s) 
+             192:     14(int) Load 150(u) 
+                              Store 191(param) 192 
+             193:           2 FunctionCall 59(GetColor12(struct-S-vf31;i1;) 190 191(param)
+             194:        9(S) Load 145(s) 
+             196:     14(int) Load 150(u) 
+                              Store 195(param) 196 
+             197:           2 FunctionCall 63(GetColor13(struct-S-vf31;i1;) 194 195(param)
+                              Branch 6
+               6:             Label
+                              Return
+                              FunctionEnd
+12(GetColor1(struct-S-vf31;):           2 Function None 10
+           11(i):        9(S) FunctionParameter
+              13:             Label
+              70:    7(float) CompositeExtract 11(i) 0 0
+              71:    8(fvec3) Load 66(OutColor) 
+              72:    8(fvec3) CompositeConstruct 70 70 70
+              73:    8(fvec3) FAdd 71 72
+                              Store 66(OutColor) 73 
+                              Return
+                              FunctionEnd
+19(GetColor2(struct-S-vf31;i1;):           2 Function None 16
+           17(i):        9(S) FunctionParameter
+        18(comp):     15(ptr) FunctionParameter
+              20:             Label
+              74:     14(int) Load 18(comp) 
+              75:    8(fvec3) CompositeExtract 17(i) 0
+              76:    7(float) VectorExtractDynamic 75 74
+              77:    8(fvec3) Load 66(OutColor) 
+              78:    8(fvec3) CompositeConstruct 76 76 76
+              79:    8(fvec3) FAdd 77 78
+                              Store 66(OutColor) 79 
+                              Return
+                              FunctionEnd
+23(GetColor3(struct-S-vf31;i1;):           2 Function None 16
+           21(i):        9(S) FunctionParameter
+        22(comp):     15(ptr) FunctionParameter
+              24:             Label
+              80:     14(int) Load 22(comp) 
+              81:    8(fvec3) CompositeExtract 21(i) 0
+              82:    7(float) VectorExtractDynamic 81 80
+              83:    8(fvec3) Load 66(OutColor) 
+              84:    8(fvec3) CompositeConstruct 82 82 82
+              85:    8(fvec3) FAdd 83 84
+                              Store 66(OutColor) 85 
+                              Return
+                              FunctionEnd
+27(GetColor4(struct-S-vf31;i1;):           2 Function None 16
+           25(i):        9(S) FunctionParameter
+        26(comp):     15(ptr) FunctionParameter
+              28:             Label
+              86:     14(int) Load 26(comp) 
+              87:    8(fvec3) CompositeExtract 25(i) 0
+              88:    7(float) VectorExtractDynamic 87 86
+              89:    8(fvec3) Load 66(OutColor) 
+              90:    8(fvec3) CompositeConstruct 88 88 88
+              91:    8(fvec3) FAdd 89 90
+                              Store 66(OutColor) 91 
+                              Return
+                              FunctionEnd
+31(GetColor5(struct-S-vf31;i1;):           2 Function None 16
+           29(i):        9(S) FunctionParameter
+        30(comp):     15(ptr) FunctionParameter
+              32:             Label
+              92:    8(fvec3) CompositeExtract 29(i) 0
+              93:    8(fvec3) Load 66(OutColor) 
+              94:    8(fvec3) FAdd 93 92
+                              Store 66(OutColor) 94 
+                              Return
+                              FunctionEnd
+35(GetColor6(struct-S-vf31;i1;):           2 Function None 16
+           33(i):        9(S) FunctionParameter
+        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
+              99:    7(float) VectorExtractDynamic 98 95
+             100:    8(fvec3) Load 66(OutColor) 
+             101:    8(fvec3) CompositeConstruct 99 99 99
+             102:    8(fvec3) FAdd 100 101
+                              Store 66(OutColor) 102 
+                              Return
+                              FunctionEnd
+39(GetColor7(struct-S-vf31;i1;):           2 Function None 16
+           37(i):        9(S) FunctionParameter
+        38(comp):     15(ptr) FunctionParameter
+              40:             Label
+             103:    8(fvec3) CompositeExtract 37(i) 0
+             104:   97(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
+             108:    8(fvec3) Load 66(OutColor) 
+             109:    8(fvec3) VectorShuffle 108 107 3 4 2
+                              Store 66(OutColor) 109 
+                              Return
+                              FunctionEnd
+43(GetColor8(struct-S-vf31;i1;):           2 Function None 16
+           41(i):        9(S) FunctionParameter
+        42(comp):     15(ptr) FunctionParameter
+              44:             Label
+             111:    7(float) CompositeExtract 41(i) 0 2
+             112:    8(fvec3) Load 66(OutColor) 
+             113:    8(fvec3) CompositeConstruct 111 111 111
+             114:    8(fvec3) FAdd 112 113
+                              Store 66(OutColor) 114 
+                              Return
+                              FunctionEnd
+47(GetColor9(struct-S-vf31;i1;):           2 Function None 16
+           45(i):        9(S) FunctionParameter
+        46(comp):     15(ptr) FunctionParameter
+              48:             Label
+             115:    8(fvec3) CompositeExtract 45(i) 0
+             116:    8(fvec3) Load 66(OutColor) 
+             117:    8(fvec3) VectorShuffle 116 116 2 0 1
+             118:    8(fvec3) FAdd 117 115
+             119:    8(fvec3) Load 66(OutColor) 
+             120:    8(fvec3) VectorShuffle 119 118 4 5 3
+                              Store 66(OutColor) 120 
+                              Return
+                              FunctionEnd
+51(GetColor10(struct-S-vf31;i1;):           2 Function None 16
+           49(i):        9(S) FunctionParameter
+        50(comp):     15(ptr) FunctionParameter
+              52:             Label
+             121:    8(fvec3) CompositeExtract 49(i) 0
+             122:   97(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
+             126:    8(fvec3) Load 66(OutColor) 
+             127:    8(fvec3) VectorShuffle 126 125 0 4 3
+                              Store 66(OutColor) 127 
+                              Return
+                              FunctionEnd
+55(GetColor11(struct-S-vf31;i1;):           2 Function None 16
+           53(i):        9(S) FunctionParameter
+        54(comp):     15(ptr) FunctionParameter
+              56:             Label
+             128:    8(fvec3) CompositeExtract 53(i) 0
+             129:   97(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
+             133:    8(fvec3) Load 66(OutColor) 
+             134:    8(fvec3) VectorShuffle 133 132 3 1 4
+                              Store 66(OutColor) 134 
+                              Return
+                              FunctionEnd
+59(GetColor12(struct-S-vf31;i1;):           2 Function None 16
+           57(i):        9(S) FunctionParameter
+        58(comp):     15(ptr) FunctionParameter
+              60:             Label
+             135:     14(int) Load 58(comp) 
+             136:    7(float) CompositeExtract 57(i) 0 0
+             137:    8(fvec3) Load 66(OutColor) 
+             138:    7(float) VectorExtractDynamic 137 135
+             139:    7(float) FAdd 138 136
+             140:    8(fvec3) Load 66(OutColor) 
+             141:    8(fvec3) VectorInsertDynamic 140 139 135
+                              Store 66(OutColor) 141 
+                              Return
+                              FunctionEnd
+63(GetColor13(struct-S-vf31;i1;):           2 Function None 16
+           61(i):        9(S) FunctionParameter
+        62(comp):     15(ptr) FunctionParameter
+              64:             Label
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.double.comp.out b/Test/baseResults/spv.double.comp.out
index 5eab420211399e92f6181a9dc3779edaad351478..d8305334bc846d8c04409f22e16bab1cf6bd3b28 100644
--- a/Test/baseResults/spv.double.comp.out
+++ b/Test/baseResults/spv.double.comp.out
@@ -58,7 +58,7 @@ Linked compute stage:
               25:             TypeVector 24(int) 3
               26:             TypePointer Input 25(ivec3)
 27(gl_GlobalInvocationID):     26(ptr) Variable Input 
-              28:             TypeVector 24(int) 2
+              29:             TypeVector 24(int) 2
               32:             TypePointer Function 8(float)
 34(gl_LocalInvocationID):     26(ptr) Variable Input 
               38:     12(int) Constant 8
@@ -87,12 +87,12 @@ Linked compute stage:
                               Store 16 14 
               20:     19(ptr) AccessChain 11(bufInst) 17
                               Store 20 18 
-              29:   25(ivec3) Load 27(gl_GlobalInvocationID) 
-              30:   28(ivec2) VectorShuffle 29 29 0 1
+              28:   25(ivec3) Load 27(gl_GlobalInvocationID) 
+              30:   29(ivec2) VectorShuffle 28 28 0 1
               31:   21(ivec2) Bitcast 30
                               Store 23(storePos) 31 
               35:   25(ivec3) Load 34(gl_LocalInvocationID) 
-              36:   28(ivec2) VectorShuffle 35 35 0 1
+              36:   29(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 0d08293dd302ef97be5f0166be7b9e0be4d70b25..85360ca2451624e6a1b2071a02e41b3eb8d6b21b 100644
--- a/Test/baseResults/spv.forLoop.frag.out
+++ b/Test/baseResults/spv.forLoop.frag.out
@@ -59,7 +59,7 @@ Linked fragment stage:
               50:             TypePointer UniformConstant 49(ivec4)
           51(v4):     50(ptr) Variable UniformConstant 
               71:     48(int) Constant 4
-              85:             TypeVector 7(float) 3
+              86:             TypeVector 7(float) 3
               97:             TypePointer Input 7(float)
            98(f):     97(ptr) Variable Input 
              115:     14(int) Constant 16
@@ -146,8 +146,8 @@ Linked fragment stage:
               82:    8(fvec4) Load 36(gl_FragColor) 
               83:    8(fvec4) FAdd 82 81
                               Store 36(gl_FragColor) 83 
-              86:    8(fvec4) Load 12(BaseColor) 
-              87:   85(fvec3) VectorShuffle 86 86 0 1 2
+              85:    8(fvec4) Load 12(BaseColor) 
+              87:   86(fvec3) VectorShuffle 85 85 0 1 2
               88:    8(fvec4) Load 84(r) 
               89:    8(fvec4) VectorShuffle 88 87 4 5 6 3
                               Store 84(r) 89 
@@ -170,10 +170,10 @@ Linked fragment stage:
                                 Branch 91
               92:             Label
              104:    8(fvec4) Load 84(r) 
-             105:   85(fvec3) VectorShuffle 104 104 0 1 2
+             105:   86(fvec3) VectorShuffle 104 104 0 1 2
              106:    8(fvec4) Load 36(gl_FragColor) 
-             107:   85(fvec3) VectorShuffle 106 106 0 1 2
-             108:   85(fvec3) FAdd 107 105
+             107:   86(fvec3) VectorShuffle 106 106 0 1 2
+             108:   86(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 
diff --git a/Test/spv.accessChain.frag b/Test/spv.accessChain.frag
new file mode 100644
index 0000000000000000000000000000000000000000..0cbf6b3c6f7f798b96aa0b6e96368559e1b0198b
--- /dev/null
+++ b/Test/spv.accessChain.frag
@@ -0,0 +1,94 @@
+#version 420
+
+struct S 
+{
+    vec3 color;
+};
+
+layout(location = 0) out vec3 OutColor;
+
+uniform int u;
+
+void GetColor1(const S i) 
+{ 
+    OutColor += i.color.x;
+}
+
+void GetColor2(const S i, int comp)
+{ 
+    OutColor += i.color[comp];
+}
+
+void GetColor3(const S i, int comp)
+{ 
+    OutColor += i.color[comp].x;
+}
+
+void GetColor4(const S i, int comp)
+{ 
+    OutColor += i.color[comp].x;
+}
+
+void GetColor5(const S i, int comp)
+{ 
+    OutColor += i.color;
+}
+
+void GetColor6(const S i, int comp)
+{ 
+    OutColor += i.color.yx[comp];
+}
+
+void GetColor7(const S i, int comp)
+{ 
+    OutColor.xy += i.color.yxz.yx;
+}
+
+void GetColor8(const S i, int comp)
+{ 
+    OutColor += i.color.yzx.yx.x.x;
+}
+
+void GetColor9(const S i, int comp)
+{ 
+    OutColor.zxy += i.color;
+}
+
+void GetColor10(const S i, int comp)
+{ 
+    OutColor.zy += i.color.xy;
+}
+
+void GetColor11(const S i, int comp)
+{ 
+    OutColor.zxy.yx += i.color.xy;
+}
+
+void GetColor12(const S i, int comp)
+{ 
+    OutColor[comp] += i.color.x;
+}
+
+void GetColor13(const S i, int comp)
+{ 
+    // OutColor.zy[comp] += i.color.x; // not yet supported
+}
+
+void main()
+{
+    S s;
+    OutColor = vec3(0.0);
+    GetColor1(s);
+    GetColor2(s, u);
+    GetColor3(s, u);
+    GetColor4(s, u);
+    GetColor5(s, u);
+    GetColor6(s, u);
+    GetColor7(s, u);
+    GetColor8(s, u);
+    GetColor9(s, u);
+    GetColor10(s, u);
+    GetColor11(s, u);
+    GetColor12(s, u);
+    GetColor13(s, u);
+}
diff --git a/Test/test-spirv-list b/Test/test-spirv-list
index e732a4134f43bc3d850140d3d0b8675105cf5247..62d0f4447267a84b4784deea8e6ee44188497e74 100644
--- a/Test/test-spirv-list
+++ b/Test/test-spirv-list
@@ -28,6 +28,7 @@ spv.400.tesc
 spv.400.tese
 spv.420.geom
 spv.430.vert
+spv.accessChain.frag
 spv.aggOps.frag
 spv.always-discard.frag
 spv.always-discard2.frag