From 2211835b4d24734c6ba204d501860d4d081de4a0 Mon Sep 17 00:00:00 2001
From: John Kessenich <cepheus@frii.com>
Date: Mon, 21 Dec 2015 20:54:09 -0700
Subject: [PATCH] SPV: Implement composite comparisons (reductions across
 hierchical compare).

---
 SPIRV/GlslangToSpv.cpp                  |   2 +-
 SPIRV/SpvBuilder.cpp                    | 115 ++++---
 SPIRV/SpvBuilder.h                      |  15 +-
 Test/baseResults/spv.aggOps.frag.out    | 405 +++++++++++++++++++++++-
 Test/baseResults/spv.precision.frag.out |   2 +-
 glslang/Include/revision.h              |   2 +-
 6 files changed, 470 insertions(+), 71 deletions(-)

diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index f1d6255f3..c17b2b387 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -2274,7 +2274,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
     if (reduceComparison && (builder.isVector(left) || builder.isMatrix(left) || builder.isAggregate(left))) {
         assert(op == glslang::EOpEqual || op == glslang::EOpNotEqual);
 
-        return builder.createCompare(precision, left, right, op == glslang::EOpEqual);
+        return builder.createCompositeCompare(precision, left, right, op == glslang::EOpEqual);
     }
 
     switch (op) {
diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp
index 7af9595fa..02ee7a0f8 100755
--- a/SPIRV/SpvBuilder.cpp
+++ b/SPIRV/SpvBuilder.cpp
@@ -435,7 +435,7 @@ Op Builder::getMostBasicTypeClass(Id typeId) const
     }
 }
 
-int Builder::getNumTypeComponents(Id typeId) const
+int Builder::getNumTypeConstituents(Id typeId) const
 {
     Instruction* instr = module.getInstruction(typeId);
 
@@ -447,7 +447,10 @@ int Builder::getNumTypeComponents(Id typeId) const
         return 1;
     case OpTypeVector:
     case OpTypeMatrix:
+    case OpTypeArray:
         return instr->getImmediateOperand(1);
+    case OpTypeStruct:
+        return instr->getNumOperands();
     default:
         assert(0);
         return 1;
@@ -1411,88 +1414,78 @@ Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameter
     return query->getResultId();
 }
 
-// Comments in header
-Id Builder::createCompare(Decoration precision, Id value1, Id value2, bool equal)
+// External comments in header.
+// Operates recursively to visit the composite's hierarchy.
+Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, bool equal)
 {
     Id boolType = makeBoolType();
     Id valueType = getTypeId(value1);
-
     assert(valueType == getTypeId(value2));
-    assert(! isScalar(value1));
 
-    // Vectors
+    Id resultId;
+
+    int numConstituents = getNumTypeConstituents(valueType);
+
+    // Scalars and Vectors
 
-    if (isVectorType(valueType)) {
-        Id boolVectorType = makeVectorType(boolType, getNumTypeComponents(valueType));
-        Id boolVector;
+    if (isScalarType(valueType) || isVectorType(valueType)) {
+        // These just need a single comparison, just have
+        // to figure out what it is.
         Op op;
-        if (getMostBasicTypeClass(valueType) == OpTypeFloat)
+        switch (getMostBasicTypeClass(valueType)) {
+        case OpTypeFloat:
             op = equal ? OpFOrdEqual : OpFOrdNotEqual;
-        else
+            break;
+        case OpTypeInt:
             op = equal ? OpIEqual : OpINotEqual;
+            break;
+        case OpTypeBool:
+            op = equal ? OpLogicalEqual : OpLogicalNotEqual;
+            precision = NoPrecision;
+            break;
+        }
 
-        boolVector = createBinOp(op, boolVectorType, value1, value2);
-        setPrecision(boolVector, precision);
-
-        // Reduce vector compares with any() and all().
-
-        op = equal ? OpAll : OpAny;
+        if (isScalarType(valueType)) {
+            // scalar
+            resultId = createBinOp(op, boolType, value1, value2);
+            setPrecision(resultId, precision);
+        } else {
+            // vector
+            resultId = createBinOp(op, makeVectorType(boolType, numConstituents), value1, value2);
+            setPrecision(resultId, precision);
+            // reduce vector compares...
+            resultId = createUnaryOp(equal ? OpAll : OpAny, boolType, resultId);
+        }
 
-        return createUnaryOp(op, boolType, boolVector);
+        return resultId;
     }
 
-    spv::MissingFunctionality("Composite comparison of non-vectors");
-
-    return NoResult;
-
-    // Recursively handle aggregates, which include matrices, arrays, and structures
-    // and accumulate the results.
-
-    // Matrices
+    // Only structs, arrays, and matrices should be left.
+    // They share in common the reduction operation across their constituents.
+    assert(isAggregateType(valueType) || isMatrixType(valueType));
 
-    // Arrays
+    // Compare each pair of constituents
+    for (int constituent = 0; constituent < numConstituents; ++constituent) {
+        std::vector<unsigned> indexes(1, constituent);
+        Id constituentType = getContainedTypeId(valueType, constituent);
+        Id constituent1 = createCompositeExtract(value1, constituentType, indexes);
+        Id constituent2 = createCompositeExtract(value2, constituentType, indexes);
 
-    //int numElements;
-    //const llvm::ArrayType* arrayType = llvm::dyn_cast<llvm::ArrayType>(value1->getType());
-    //if (arrayType)
-    //    numElements = (int)arrayType->getNumElements();
-    //else {
-    //    // better be structure
-    //    const llvm::StructType* structType = llvm::dyn_cast<llvm::StructType>(value1->getType());
-    //    assert(structType);
-    //    numElements = structType->getNumElements();
-    //}
+        Id subResultId = createCompositeCompare(precision, constituent1, constituent2, equal);
 
-    //assert(numElements > 0);
-
-    //for (int element = 0; element < numElements; ++element) {
-    //    // Get intermediate comparison values
-    //    llvm::Value* element1 = builder.CreateExtractValue(value1, element, "element1");
-    //    setInstructionPrecision(element1, precision);
-    //    llvm::Value* element2 = builder.CreateExtractValue(value2, element, "element2");
-    //    setInstructionPrecision(element2, precision);
-
-    //    llvm::Value* subResult = createCompare(precision, element1, element2, equal, "comp");
-
-    //    // Accumulate intermediate comparison
-    //    if (element == 0)
-    //        result = subResult;
-    //    else {
-    //        if (equal)
-    //            result = builder.CreateAnd(result, subResult);
-    //        else
-    //            result = builder.CreateOr(result, subResult);
-    //        setInstructionPrecision(result, precision);
-    //    }
-    //}
+        if (constituent == 0)
+            resultId = subResultId;
+        else
+            resultId = createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId);
+    }
 
-    //return result;
+    return resultId;
 }
 
 // OpCompositeConstruct
 Id Builder::createCompositeConstruct(Id typeId, std::vector<Id>& constituents)
 {
-    assert(isAggregateType(typeId) || (getNumTypeComponents(typeId) > 1 && getNumTypeComponents(typeId) == (int)constituents.size()));
+    assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size()));
 
     Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct);
     for (int c = 0; c < (int)constituents.size(); ++c)
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index 2d10ef6ef..71126eb77 100755
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -116,7 +116,8 @@ public:
     Op getTypeClass(Id typeId) const { return getOpCode(typeId); }
     Op getMostBasicTypeClass(Id typeId) const;
     int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); }
-    int getNumTypeComponents(Id typeId) const;
+    int getNumTypeConstituents(Id typeId) const;
+    int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); }
     Id getScalarTypeId(Id typeId) const;
     Id getContainedTypeId(Id typeId) const;
     Id getContainedTypeId(Id typeId, int) const;
@@ -150,7 +151,7 @@ public:
     int getTypeNumColumns(Id typeId) const
     {
         assert(isMatrixType(typeId));
-        return getNumTypeComponents(typeId);
+        return getNumTypeConstituents(typeId);
     }
     int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); }
     int getTypeNumRows(Id typeId) const
@@ -265,11 +266,13 @@ public:
     // (No true lvalue or stores are used.)
     Id createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<unsigned>& channels);
 
-    // If the value passed in is an instruction and the precision is not EMpNone,
+    // If the value passed in is an instruction and the precision is not NoPrecision,
     // it gets tagged with the requested precision.
-    void setPrecision(Id /* value */, Decoration /* precision */)
+    void setPrecision(Id /* value */, Decoration precision)
     {
-        // TODO
+        if (precision != NoPrecision) {
+            ;// TODO
+        }
     }
 
     // Can smear a scalar to a vector for the following forms:
@@ -322,7 +325,7 @@ public:
     Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id);
 
     // Reduction comparision for composites:  For equal and not-equal resulting in a scalar.
-    Id createCompare(Decoration precision, Id, Id, bool /* true if for equal, fales if for not-equal */);
+    Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */);
 
     // OpCompositeConstruct
     Id createCompositeConstruct(Id typeId, std::vector<Id>& constituents);
diff --git a/Test/baseResults/spv.aggOps.frag.out b/Test/baseResults/spv.aggOps.frag.out
index ca118d52d..af643ae7f 100644
--- a/Test/baseResults/spv.aggOps.frag.out
+++ b/Test/baseResults/spv.aggOps.frag.out
@@ -6,4 +6,407 @@ WARNING: 0:6: varying deprecated in version 130; may be removed in future releas
 Linked fragment stage:
 
 
-Missing functionality: Composite comparison of non-vectors
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 346
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 16 41 90 342
+                              ExecutionMode 4 OriginLowerLeft
+                              Source GLSL 130
+                              Name 4  "main"
+                              Name 8  "s1"
+                              MemberName 8(s1) 0  "i"
+                              MemberName 8(s1) 1  "f"
+                              Name 13  "a"
+                              Name 16  "u"
+                              Name 37  "b"
+                              Name 41  "w"
+                              Name 55  "s2"
+                              MemberName 55(s2) 0  "i"
+                              MemberName 55(s2) 1  "f"
+                              MemberName 55(s2) 2  "s1_1"
+                              Name 57  "foo2a"
+                              Name 59  "foo2b"
+                              Name 82  "v"
+                              Name 86  "samp2D"
+                              Name 90  "coord"
+                              Name 342  "gl_FragColor"
+                              Name 345  "foo1"
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 1
+               7:             TypeFloat 32
+           8(s1):             TypeStruct 6(int) 7(float)
+               9:             TypeInt 32 0
+              10:      9(int) Constant 3
+              11:             TypeArray 8(s1) 10
+              12:             TypePointer Function 11
+              14:             TypeVector 7(float) 4
+              15:             TypePointer Input 14(fvec4)
+           16(u):     15(ptr) Variable Input
+              17:      9(int) Constant 0
+              18:             TypePointer Input 7(float)
+              22:      9(int) Constant 1
+              26:      9(int) Constant 2
+              33:      6(int) Constant 14
+              34:    7(float) Constant 1096810496
+              35:       8(s1) ConstantComposite 33 34
+              38:      6(int) Constant 17
+              39:    7(float) Constant 1099431936
+              40:       8(s1) ConstantComposite 38 39
+           41(w):     15(ptr) Variable Input
+          55(s2):             TypeStruct 6(int) 7(float) 8(s1)
+              56:             TypePointer UniformConstant 55(s2)
+       57(foo2a):     56(ptr) Variable UniformConstant
+       59(foo2b):     56(ptr) Variable UniformConstant
+              61:             TypeBool
+              81:             TypePointer Function 14(fvec4)
+              83:             TypeImage 7(float) 2D sampled format:Unknown
+              84:             TypeSampledImage 83
+              85:             TypePointer UniformConstant 84
+      86(samp2D):     85(ptr) Variable UniformConstant
+              88:             TypeVector 7(float) 2
+              89:             TypePointer Input 88(fvec2)
+       90(coord):     89(ptr) Variable Input
+              95:    7(float) Constant 1073741824
+             101:             TypeVector 61(bool) 4
+             106:    7(float) Constant 1077936128
+             115:    7(float) Constant 1082130432
+             121:             TypeVector 61(bool) 2
+             126:    7(float) Constant 1084227584
+             232:    7(float) Constant 1086324736
+             338:    7(float) Constant 1088421888
+             341:             TypePointer Output 14(fvec4)
+342(gl_FragColor):    341(ptr) Variable Output
+             344:             TypePointer UniformConstant 8(s1)
+       345(foo1):    344(ptr) Variable UniformConstant
+         4(main):           2 Function None 3
+               5:             Label
+           13(a):     12(ptr) Variable Function
+           37(b):     12(ptr) Variable Function
+           82(v):     81(ptr) Variable Function
+              19:     18(ptr) AccessChain 16(u) 17
+              20:    7(float) Load 19
+              21:      6(int) ConvertFToS 20
+              23:     18(ptr) AccessChain 16(u) 22
+              24:    7(float) Load 23
+              25:       8(s1) CompositeConstruct 21 24
+              27:     18(ptr) AccessChain 16(u) 26
+              28:    7(float) Load 27
+              29:      6(int) ConvertFToS 28
+              30:     18(ptr) AccessChain 16(u) 10
+              31:    7(float) Load 30
+              32:       8(s1) CompositeConstruct 29 31
+              36:          11 CompositeConstruct 25 32 35
+                              Store 13(a) 36
+              42:     18(ptr) AccessChain 41(w) 17
+              43:    7(float) Load 42
+              44:      6(int) ConvertFToS 43
+              45:     18(ptr) AccessChain 41(w) 22
+              46:    7(float) Load 45
+              47:       8(s1) CompositeConstruct 44 46
+              48:     18(ptr) AccessChain 41(w) 26
+              49:    7(float) Load 48
+              50:      6(int) ConvertFToS 49
+              51:     18(ptr) AccessChain 41(w) 10
+              52:    7(float) Load 51
+              53:       8(s1) CompositeConstruct 50 52
+              54:          11 CompositeConstruct 40 47 53
+                              Store 37(b) 54
+              58:      55(s2) Load 57(foo2a)
+              60:      55(s2) Load 59(foo2b)
+              62:      6(int) CompositeExtract 58 0
+              63:      6(int) CompositeExtract 60 0
+              64:    61(bool) IEqual 62 63
+              65:    7(float) CompositeExtract 58 1
+              66:    7(float) CompositeExtract 60 1
+              67:    61(bool) FOrdEqual 65 66
+              68:    61(bool) LogicalAnd 64 67
+              69:       8(s1) CompositeExtract 58 2
+              70:       8(s1) CompositeExtract 60 2
+              71:      6(int) CompositeExtract 69 0
+              72:      6(int) CompositeExtract 70 0
+              73:    61(bool) IEqual 71 72
+              74:    7(float) CompositeExtract 69 1
+              75:    7(float) CompositeExtract 70 1
+              76:    61(bool) FOrdEqual 74 75
+              77:    61(bool) LogicalAnd 73 76
+              78:    61(bool) LogicalAnd 68 77
+                              SelectionMerge 80 None
+                              BranchConditional 78 79 93
+              79:               Label
+              87:          84   Load 86(samp2D)
+              91:   88(fvec2)   Load 90(coord)
+              92:   14(fvec4)   ImageSampleImplicitLod 87 91
+                                Store 82(v) 92
+                                Branch 80
+              93:               Label
+              94:          84   Load 86(samp2D)
+              96:   88(fvec2)   Load 90(coord)
+              97:   88(fvec2)   VectorTimesScalar 96 95
+              98:   14(fvec4)   ImageSampleImplicitLod 94 97
+                                Store 82(v) 98
+                                Branch 80
+              80:             Label
+              99:   14(fvec4) Load 16(u)
+             100:   14(fvec4) Load 82(v)
+             102:  101(bvec4) FOrdEqual 99 100
+             103:    61(bool) All 102
+                              SelectionMerge 105 None
+                              BranchConditional 103 104 105
+             104:               Label
+             107:   14(fvec4)   Load 82(v)
+             108:   14(fvec4)   VectorTimesScalar 107 106
+                                Store 82(v) 108
+                                Branch 105
+             105:             Label
+             109:   14(fvec4) Load 16(u)
+             110:   14(fvec4) Load 82(v)
+             111:  101(bvec4) FOrdNotEqual 109 110
+             112:    61(bool) Any 111
+                              SelectionMerge 114 None
+                              BranchConditional 112 113 114
+             113:               Label
+             116:   14(fvec4)   Load 82(v)
+             117:   14(fvec4)   VectorTimesScalar 116 115
+                                Store 82(v) 117
+                                Branch 114
+             114:             Label
+             118:   88(fvec2) Load 90(coord)
+             119:   14(fvec4) Load 82(v)
+             120:   88(fvec2) VectorShuffle 119 119 1 3
+             122:  121(bvec2) FOrdEqual 118 120
+             123:    61(bool) All 122
+                              SelectionMerge 125 None
+                              BranchConditional 123 124 125
+             124:               Label
+             127:   14(fvec4)   Load 82(v)
+             128:   14(fvec4)   VectorTimesScalar 127 126
+                                Store 82(v) 128
+                                Branch 125
+             125:             Label
+             129:          11 Load 13(a)
+             130:          11 Load 37(b)
+             131:       8(s1) CompositeExtract 129 0
+             132:       8(s1) CompositeExtract 130 0
+             133:      6(int) CompositeExtract 131 0
+             134:      6(int) CompositeExtract 132 0
+             135:    61(bool) IEqual 133 134
+             136:    7(float) CompositeExtract 131 1
+             137:    7(float) CompositeExtract 132 1
+             138:    61(bool) FOrdEqual 136 137
+             139:    61(bool) LogicalAnd 135 138
+             140:       8(s1) CompositeExtract 129 1
+             141:       8(s1) CompositeExtract 130 1
+             142:      6(int) CompositeExtract 140 0
+             143:      6(int) CompositeExtract 141 0
+             144:    61(bool) IEqual 142 143
+             145:    7(float) CompositeExtract 140 1
+             146:    7(float) CompositeExtract 141 1
+             147:    61(bool) FOrdEqual 145 146
+             148:    61(bool) LogicalAnd 144 147
+             149:    61(bool) LogicalAnd 139 148
+             150:       8(s1) CompositeExtract 129 2
+             151:       8(s1) CompositeExtract 130 2
+             152:      6(int) CompositeExtract 150 0
+             153:      6(int) CompositeExtract 151 0
+             154:    61(bool) IEqual 152 153
+             155:    7(float) CompositeExtract 150 1
+             156:    7(float) CompositeExtract 151 1
+             157:    61(bool) FOrdEqual 155 156
+             158:    61(bool) LogicalAnd 154 157
+             159:    61(bool) LogicalAnd 149 158
+             160:       8(s1) CompositeExtract 129 3
+             161:       8(s1) CompositeExtract 130 3
+             162:      6(int) CompositeExtract 160 0
+             163:      6(int) CompositeExtract 161 0
+             164:    61(bool) IEqual 162 163
+             165:    7(float) CompositeExtract 160 1
+             166:    7(float) CompositeExtract 161 1
+             167:    61(bool) FOrdEqual 165 166
+             168:    61(bool) LogicalAnd 164 167
+             169:    61(bool) LogicalAnd 159 168
+             170:       8(s1) CompositeExtract 129 4
+             171:       8(s1) CompositeExtract 130 4
+             172:      6(int) CompositeExtract 170 0
+             173:      6(int) CompositeExtract 171 0
+             174:    61(bool) IEqual 172 173
+             175:    7(float) CompositeExtract 170 1
+             176:    7(float) CompositeExtract 171 1
+             177:    61(bool) FOrdEqual 175 176
+             178:    61(bool) LogicalAnd 174 177
+             179:    61(bool) LogicalAnd 169 178
+             180:       8(s1) CompositeExtract 129 5
+             181:       8(s1) CompositeExtract 130 5
+             182:      6(int) CompositeExtract 180 0
+             183:      6(int) CompositeExtract 181 0
+             184:    61(bool) IEqual 182 183
+             185:    7(float) CompositeExtract 180 1
+             186:    7(float) CompositeExtract 181 1
+             187:    61(bool) FOrdEqual 185 186
+             188:    61(bool) LogicalAnd 184 187
+             189:    61(bool) LogicalAnd 179 188
+             190:       8(s1) CompositeExtract 129 6
+             191:       8(s1) CompositeExtract 130 6
+             192:      6(int) CompositeExtract 190 0
+             193:      6(int) CompositeExtract 191 0
+             194:    61(bool) IEqual 192 193
+             195:    7(float) CompositeExtract 190 1
+             196:    7(float) CompositeExtract 191 1
+             197:    61(bool) FOrdEqual 195 196
+             198:    61(bool) LogicalAnd 194 197
+             199:    61(bool) LogicalAnd 189 198
+             200:       8(s1) CompositeExtract 129 7
+             201:       8(s1) CompositeExtract 130 7
+             202:      6(int) CompositeExtract 200 0
+             203:      6(int) CompositeExtract 201 0
+             204:    61(bool) IEqual 202 203
+             205:    7(float) CompositeExtract 200 1
+             206:    7(float) CompositeExtract 201 1
+             207:    61(bool) FOrdEqual 205 206
+             208:    61(bool) LogicalAnd 204 207
+             209:    61(bool) LogicalAnd 199 208
+             210:       8(s1) CompositeExtract 129 8
+             211:       8(s1) CompositeExtract 130 8
+             212:      6(int) CompositeExtract 210 0
+             213:      6(int) CompositeExtract 211 0
+             214:    61(bool) IEqual 212 213
+             215:    7(float) CompositeExtract 210 1
+             216:    7(float) CompositeExtract 211 1
+             217:    61(bool) FOrdEqual 215 216
+             218:    61(bool) LogicalAnd 214 217
+             219:    61(bool) LogicalAnd 209 218
+             220:       8(s1) CompositeExtract 129 9
+             221:       8(s1) CompositeExtract 130 9
+             222:      6(int) CompositeExtract 220 0
+             223:      6(int) CompositeExtract 221 0
+             224:    61(bool) IEqual 222 223
+             225:    7(float) CompositeExtract 220 1
+             226:    7(float) CompositeExtract 221 1
+             227:    61(bool) FOrdEqual 225 226
+             228:    61(bool) LogicalAnd 224 227
+             229:    61(bool) LogicalAnd 219 228
+                              SelectionMerge 231 None
+                              BranchConditional 229 230 231
+             230:               Label
+             233:   14(fvec4)   Load 82(v)
+             234:   14(fvec4)   VectorTimesScalar 233 232
+                                Store 82(v) 234
+                                Branch 231
+             231:             Label
+             235:          11 Load 13(a)
+             236:          11 Load 37(b)
+             237:       8(s1) CompositeExtract 235 0
+             238:       8(s1) CompositeExtract 236 0
+             239:      6(int) CompositeExtract 237 0
+             240:      6(int) CompositeExtract 238 0
+             241:    61(bool) INotEqual 239 240
+             242:    7(float) CompositeExtract 237 1
+             243:    7(float) CompositeExtract 238 1
+             244:    61(bool) FOrdNotEqual 242 243
+             245:    61(bool) LogicalOr 241 244
+             246:       8(s1) CompositeExtract 235 1
+             247:       8(s1) CompositeExtract 236 1
+             248:      6(int) CompositeExtract 246 0
+             249:      6(int) CompositeExtract 247 0
+             250:    61(bool) INotEqual 248 249
+             251:    7(float) CompositeExtract 246 1
+             252:    7(float) CompositeExtract 247 1
+             253:    61(bool) FOrdNotEqual 251 252
+             254:    61(bool) LogicalOr 250 253
+             255:    61(bool) LogicalOr 245 254
+             256:       8(s1) CompositeExtract 235 2
+             257:       8(s1) CompositeExtract 236 2
+             258:      6(int) CompositeExtract 256 0
+             259:      6(int) CompositeExtract 257 0
+             260:    61(bool) INotEqual 258 259
+             261:    7(float) CompositeExtract 256 1
+             262:    7(float) CompositeExtract 257 1
+             263:    61(bool) FOrdNotEqual 261 262
+             264:    61(bool) LogicalOr 260 263
+             265:    61(bool) LogicalOr 255 264
+             266:       8(s1) CompositeExtract 235 3
+             267:       8(s1) CompositeExtract 236 3
+             268:      6(int) CompositeExtract 266 0
+             269:      6(int) CompositeExtract 267 0
+             270:    61(bool) INotEqual 268 269
+             271:    7(float) CompositeExtract 266 1
+             272:    7(float) CompositeExtract 267 1
+             273:    61(bool) FOrdNotEqual 271 272
+             274:    61(bool) LogicalOr 270 273
+             275:    61(bool) LogicalOr 265 274
+             276:       8(s1) CompositeExtract 235 4
+             277:       8(s1) CompositeExtract 236 4
+             278:      6(int) CompositeExtract 276 0
+             279:      6(int) CompositeExtract 277 0
+             280:    61(bool) INotEqual 278 279
+             281:    7(float) CompositeExtract 276 1
+             282:    7(float) CompositeExtract 277 1
+             283:    61(bool) FOrdNotEqual 281 282
+             284:    61(bool) LogicalOr 280 283
+             285:    61(bool) LogicalOr 275 284
+             286:       8(s1) CompositeExtract 235 5
+             287:       8(s1) CompositeExtract 236 5
+             288:      6(int) CompositeExtract 286 0
+             289:      6(int) CompositeExtract 287 0
+             290:    61(bool) INotEqual 288 289
+             291:    7(float) CompositeExtract 286 1
+             292:    7(float) CompositeExtract 287 1
+             293:    61(bool) FOrdNotEqual 291 292
+             294:    61(bool) LogicalOr 290 293
+             295:    61(bool) LogicalOr 285 294
+             296:       8(s1) CompositeExtract 235 6
+             297:       8(s1) CompositeExtract 236 6
+             298:      6(int) CompositeExtract 296 0
+             299:      6(int) CompositeExtract 297 0
+             300:    61(bool) INotEqual 298 299
+             301:    7(float) CompositeExtract 296 1
+             302:    7(float) CompositeExtract 297 1
+             303:    61(bool) FOrdNotEqual 301 302
+             304:    61(bool) LogicalOr 300 303
+             305:    61(bool) LogicalOr 295 304
+             306:       8(s1) CompositeExtract 235 7
+             307:       8(s1) CompositeExtract 236 7
+             308:      6(int) CompositeExtract 306 0
+             309:      6(int) CompositeExtract 307 0
+             310:    61(bool) INotEqual 308 309
+             311:    7(float) CompositeExtract 306 1
+             312:    7(float) CompositeExtract 307 1
+             313:    61(bool) FOrdNotEqual 311 312
+             314:    61(bool) LogicalOr 310 313
+             315:    61(bool) LogicalOr 305 314
+             316:       8(s1) CompositeExtract 235 8
+             317:       8(s1) CompositeExtract 236 8
+             318:      6(int) CompositeExtract 316 0
+             319:      6(int) CompositeExtract 317 0
+             320:    61(bool) INotEqual 318 319
+             321:    7(float) CompositeExtract 316 1
+             322:    7(float) CompositeExtract 317 1
+             323:    61(bool) FOrdNotEqual 321 322
+             324:    61(bool) LogicalOr 320 323
+             325:    61(bool) LogicalOr 315 324
+             326:       8(s1) CompositeExtract 235 9
+             327:       8(s1) CompositeExtract 236 9
+             328:      6(int) CompositeExtract 326 0
+             329:      6(int) CompositeExtract 327 0
+             330:    61(bool) INotEqual 328 329
+             331:    7(float) CompositeExtract 326 1
+             332:    7(float) CompositeExtract 327 1
+             333:    61(bool) FOrdNotEqual 331 332
+             334:    61(bool) LogicalOr 330 333
+             335:    61(bool) LogicalOr 325 334
+                              SelectionMerge 337 None
+                              BranchConditional 335 336 337
+             336:               Label
+             339:   14(fvec4)   Load 82(v)
+             340:   14(fvec4)   VectorTimesScalar 339 338
+                                Store 82(v) 340
+                                Branch 337
+             337:             Label
+             343:   14(fvec4) Load 82(v)
+                              Store 342(gl_FragColor) 343
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.precision.frag.out b/Test/baseResults/spv.precision.frag.out
index dc8dc6d8a..8c28fed70 100755
--- a/Test/baseResults/spv.precision.frag.out
+++ b/Test/baseResults/spv.precision.frag.out
@@ -168,7 +168,7 @@ Linked fragment stage:
          18(bv2):     16(ptr) FunctionParameter
               20:             Label
               27:   15(bvec2) Load 18(bv2)
-              31:   15(bvec2) IEqual 27 30
+              31:   15(bvec2) LogicalEqual 27 30
               32:    14(bool) All 31
                               ReturnValue 32
                               FunctionEnd
diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h
index 7c3f0ec1d..4ebfd653f 100644
--- a/glslang/Include/revision.h
+++ b/glslang/Include/revision.h
@@ -2,5 +2,5 @@
 // For the version, it uses the latest git tag followed by the number of commits.
 // For the date, it uses the current date (when then script is run).
 
-#define GLSLANG_REVISION "SPIRV99.862"
+#define GLSLANG_REVISION "SPIRV99.863"
 #define GLSLANG_DATE "21-Dec-2015"
-- 
GitLab