Front-end: Implement 2nd task of issue #400; precision of result and operation.

From the ES spec + Bugzilla 15931 and GL_KHR_vulkan_glsl:
- Update precision qualifiers for all built-in function prototypes.
- Implement the new algorithm used to distinguish built-in function
  operation precisions from result precisions.
Also add tracking of separate result and operation precisions, and
use that in generating SPIR-V.
(SPIR-V cares about precision of operation, while the front-end
cares about precision of result, for propagation.)
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index be266ac..6aec9e6 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -283,10 +283,10 @@
     }
 }
 
-// Translate glslang type to SPIR-V precision decorations.
-spv::Decoration TranslatePrecisionDecoration(const glslang::TType& type)
+// Translate glslang precision to SPIR-V precision decorations.
+spv::Decoration TranslatePrecisionDecoration(glslang::TPrecisionQualifier glslangPrecision)
 {
-    switch (type.getQualifier().precision) {
+    switch (glslangPrecision) {
     case glslang::EpqLow:    return spv::DecorationRelaxedPrecision;
     case glslang::EpqMedium: return spv::DecorationRelaxedPrecision;
     default:
@@ -294,6 +294,12 @@
     }
 }
 
+// Translate glslang type to SPIR-V precision decorations.
+spv::Decoration TranslatePrecisionDecoration(const glslang::TType& type)
+{
+    return TranslatePrecisionDecoration(type.getQualifier().precision);
+}
+
 // Translate glslang type to SPIR-V block decorations.
 spv::Decoration TranslateBlockDecoration(const glslang::TType& type)
 {
@@ -940,7 +946,7 @@
                 spv::Id leftRValue = accessChainLoad(node->getLeft()->getType());
 
                 // do the operation
-                rValue = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()),
+                rValue = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getOperationPrecision()),
                                                TranslateNoContractionDecoration(node->getType().getQualifier()),
                                                convertGlslangToSpvType(node->getType()), leftRValue, rValue,
                                                node->getType().getBasicType());
@@ -1065,7 +1071,7 @@
     spv::Id right = accessChainLoad(node->getRight()->getType());
 
     // get result
-    spv::Id result = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getType()),
+    spv::Id result = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getOperationPrecision()),
                                            TranslateNoContractionDecoration(node->getType().getQualifier()),
                                            convertGlslangToSpvType(node->getType()), left, right,
                                            node->getLeft()->getType().getBasicType());
@@ -1142,7 +1148,7 @@
     else
         operand = accessChainLoad(node->getOperand()->getType());
 
-    spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
+    spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
     spv::Decoration noContraction = TranslateNoContractionDecoration(node->getType().getQualifier());
 
     // it could be a conversion
@@ -1187,7 +1193,7 @@
             else
                 op = glslang::EOpSub;
 
-            spv::Id result = createBinaryOperation(op, TranslatePrecisionDecoration(node->getType()),
+            spv::Id result = createBinaryOperation(op, precision,
                                                    TranslateNoContractionDecoration(node->getType().getQualifier()),
                                                    convertGlslangToSpvType(node->getType()), operand, one,
                                                    node->getType().getBasicType());
@@ -1249,7 +1255,7 @@
 
     assert(node->getOp());
 
-    spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
+    spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
 
     switch (node->getOp()) {
     case glslang::EOpSequence:
@@ -2573,7 +2579,7 @@
         translateArguments(*node->getAsAggregate(), arguments);
     else
         translateArguments(*node->getAsUnaryNode(), arguments);
-    spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
+    spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
 
     spv::Builder::TextureParameters params = { };
     params.sampler = arguments[0];
diff --git a/Test/baseResults/100.frag.out b/Test/baseResults/100.frag.out
index 70b8934..edd65ab 100644
--- a/Test/baseResults/100.frag.out
+++ b/Test/baseResults/100.frag.out
@@ -241,7 +241,7 @@
 0:122        'sExt' (uniform lowp samplerExternalOES)
 0:122        Construct vec3 (temp lowp 3-component vector of float)
 0:122          'f13' (invariant global mediump float)
-0:123      textureProj (global lowp 4-component vector of float)
+0:123      textureProj (global lowp 4-component vector of float, operation at mediump)
 0:123        'sExt' (uniform lowp samplerExternalOES)
 0:123        direct index (smooth temp mediump 4-component vector of float)
 0:123          'v' (smooth in 3-element array of mediump 4-component vector of float)
@@ -278,7 +278,7 @@
 0:145      'a' (in mediump int)
 0:145      'b' (in mediump float)
 0:147    Sequence
-0:147      textureProjGrad (global lowp 4-component vector of float)
+0:147      textureProjGrad (global lowp 4-component vector of float, operation at mediump)
 0:147        's2Dg' (uniform lowp sampler2D)
 0:147        Construct vec3 (temp mediump 3-component vector of float)
 0:147          'f13' (invariant global mediump float)
@@ -299,17 +299,17 @@
 0:158  Function Definition: foo323433( (global void)
 0:158    Function Parameters: 
 0:160    Sequence
-0:160      textureLod (global lowp 4-component vector of float)
+0:160      textureLod (global lowp 4-component vector of float, operation at mediump)
 0:160        's2Dg' (uniform lowp sampler2D)
 0:160        'uv2' (invariant uniform mediump 2-component vector of float)
 0:160        'f13' (invariant global mediump float)
-0:161      textureProjGrad (global lowp 4-component vector of float)
+0:161      textureProjGrad (global lowp 4-component vector of float, operation at mediump)
 0:161        's2Dg' (uniform lowp sampler2D)
 0:161        Construct vec3 (temp mediump 3-component vector of float)
 0:161          'f13' (invariant global mediump float)
 0:161        'uv2' (invariant uniform mediump 2-component vector of float)
 0:161        'uv2' (invariant uniform mediump 2-component vector of float)
-0:162      textureGrad (global lowp 4-component vector of float)
+0:162      textureGrad (global lowp 4-component vector of float, operation at mediump)
 0:162        's2Dg' (uniform lowp sampler2D)
 0:162        'uv2' (invariant uniform mediump 2-component vector of float)
 0:162        'uv2' (invariant uniform mediump 2-component vector of float)
@@ -579,7 +579,7 @@
 0:122        'sExt' (uniform lowp samplerExternalOES)
 0:122        Construct vec3 (temp lowp 3-component vector of float)
 0:122          'f13' (invariant global mediump float)
-0:123      textureProj (global lowp 4-component vector of float)
+0:123      textureProj (global lowp 4-component vector of float, operation at mediump)
 0:123        'sExt' (uniform lowp samplerExternalOES)
 0:123        direct index (smooth temp mediump 4-component vector of float)
 0:123          'v' (smooth in 3-element array of mediump 4-component vector of float)
@@ -616,7 +616,7 @@
 0:145      'a' (in mediump int)
 0:145      'b' (in mediump float)
 0:147    Sequence
-0:147      textureProjGrad (global lowp 4-component vector of float)
+0:147      textureProjGrad (global lowp 4-component vector of float, operation at mediump)
 0:147        's2Dg' (uniform lowp sampler2D)
 0:147        Construct vec3 (temp mediump 3-component vector of float)
 0:147          'f13' (invariant global mediump float)
@@ -637,17 +637,17 @@
 0:158  Function Definition: foo323433( (global void)
 0:158    Function Parameters: 
 0:160    Sequence
-0:160      textureLod (global lowp 4-component vector of float)
+0:160      textureLod (global lowp 4-component vector of float, operation at mediump)
 0:160        's2Dg' (uniform lowp sampler2D)
 0:160        'uv2' (invariant uniform mediump 2-component vector of float)
 0:160        'f13' (invariant global mediump float)
-0:161      textureProjGrad (global lowp 4-component vector of float)
+0:161      textureProjGrad (global lowp 4-component vector of float, operation at mediump)
 0:161        's2Dg' (uniform lowp sampler2D)
 0:161        Construct vec3 (temp mediump 3-component vector of float)
 0:161          'f13' (invariant global mediump float)
 0:161        'uv2' (invariant uniform mediump 2-component vector of float)
 0:161        'uv2' (invariant uniform mediump 2-component vector of float)
-0:162      textureGrad (global lowp 4-component vector of float)
+0:162      textureGrad (global lowp 4-component vector of float, operation at mediump)
 0:162        's2Dg' (uniform lowp sampler2D)
 0:162        'uv2' (invariant uniform mediump 2-component vector of float)
 0:162        'uv2' (invariant uniform mediump 2-component vector of float)
diff --git a/Test/baseResults/300.frag.out b/Test/baseResults/300.frag.out
index a0c2615..2a3341a 100644
--- a/Test/baseResults/300.frag.out
+++ b/Test/baseResults/300.frag.out
@@ -72,20 +72,20 @@
 0:59            1.200000
 0:60      move second child to first child (temp lowp float)
 0:60        'f' (temp lowp float)
-0:60        textureOffset (global lowp float)
+0:60        textureOffset (global lowp float, operation at mediump)
 0:60          's2DShadow' (uniform lowp sampler2DShadow)
 0:60          'c3D' (smooth in lowp 3-component vector of float)
 0:60          'ic2D' (flat in mediump 2-component vector of int)
 0:60          'c1D' (smooth in lowp float)
 0:61      move second child to first child (temp lowp 4-component vector of float)
 0:61        'v' (temp lowp 4-component vector of float)
-0:61        textureFetch (global lowp 4-component vector of float)
+0:61        textureFetch (global lowp 4-component vector of float, operation at mediump)
 0:61          's3D' (uniform lowp sampler3D)
 0:61          'ic3D' (flat in mediump 3-component vector of int)
 0:61          'ic1D' (flat in mediump int)
 0:62      move second child to first child (temp lowp 4-component vector of float)
 0:62        'v' (temp lowp 4-component vector of float)
-0:62        textureFetchOffset (global lowp 4-component vector of float)
+0:62        textureFetchOffset (global lowp 4-component vector of float, operation at mediump)
 0:62          direct index (temp lowp sampler2D)
 0:62            'arrayedSampler' (uniform 5-element array of lowp sampler2D)
 0:62            Constant:
@@ -96,14 +96,14 @@
 0:62          'ic2D' (flat in mediump 2-component vector of int)
 0:63      move second child to first child (temp lowp float)
 0:63        'f' (temp lowp float)
-0:63        textureLodOffset (global lowp float)
+0:63        textureLodOffset (global lowp float, operation at mediump)
 0:63          's2DShadow' (uniform lowp sampler2DShadow)
 0:63          'c3D' (smooth in lowp 3-component vector of float)
 0:63          'c1D' (smooth in lowp float)
 0:63          'ic2D' (flat in mediump 2-component vector of int)
 0:64      move second child to first child (temp lowp 4-component vector of float)
 0:64        'v' (temp lowp 4-component vector of float)
-0:64        textureProjLodOffset (global lowp 4-component vector of float)
+0:64        textureProjLodOffset (global lowp 4-component vector of float, operation at mediump)
 0:64          's2D' (uniform lowp sampler2D)
 0:64          'c3D' (smooth in lowp 3-component vector of float)
 0:64          'c1D' (smooth in lowp float)
@@ -117,7 +117,7 @@
 0:65          'c3D' (smooth in lowp 3-component vector of float)
 0:66      move second child to first child (temp lowp float)
 0:66        'f' (temp lowp float)
-0:66        textureGradOffset (global lowp float)
+0:66        textureGradOffset (global lowp float, operation at mediump)
 0:66          's2DArrayShadow' (uniform lowp sampler2DArrayShadow)
 0:66          'c4D' (smooth temp lowp 4-component vector of float)
 0:66          'c2D' (smooth in lowp 2-component vector of float)
@@ -132,7 +132,7 @@
 0:67          'c3D' (smooth in lowp 3-component vector of float)
 0:68      move second child to first child (temp lowp 4-component vector of float)
 0:68        'v' (temp lowp 4-component vector of float)
-0:68        textureProjGradOffset (global lowp 4-component vector of float)
+0:68        textureProjGradOffset (global lowp 4-component vector of float, operation at mediump)
 0:68          's2D' (uniform lowp sampler2D)
 0:68          'c3D' (smooth in lowp 3-component vector of float)
 0:68          'c2D' (smooth in lowp 2-component vector of float)
@@ -152,7 +152,7 @@
 0:72          'c2D' (smooth in lowp 2-component vector of float)
 0:73      move second child to first child (temp mediump 4-component vector of int)
 0:73        'iv' (temp mediump 4-component vector of int)
-0:73        textureProjOffset (global lowp 4-component vector of int)
+0:73        textureProjOffset (global lowp 4-component vector of int, operation at mediump)
 0:73          'is2D' (uniform lowp isampler2D)
 0:73          'c4D' (smooth temp lowp 4-component vector of float)
 0:73          'ic2D' (flat in mediump 2-component vector of int)
@@ -184,7 +184,7 @@
 0:77          'c1D' (smooth in lowp float)
 0:78      move second child to first child (temp mediump 4-component vector of int)
 0:78        'iv' (temp mediump 4-component vector of int)
-0:78        textureFetch (global lowp 4-component vector of int)
+0:78        textureFetch (global lowp 4-component vector of int, operation at mediump)
 0:78          'is2DArray' (uniform lowp isampler2DArray)
 0:78          'ic3D' (flat in mediump 3-component vector of int)
 0:78          'ic1D' (flat in mediump int)
@@ -196,7 +196,7 @@
 0:80              0 (const int)
 0:80            Constant:
 0:80              1 (const int)
-0:80        textureSize (global highp 2-component vector of int)
+0:80        textureSize (global highp 2-component vector of int, operation at lowp)
 0:80          'sCubeShadow' (uniform lowp samplerCubeShadow)
 0:80          Constant:
 0:80            2 (const int)
@@ -428,20 +428,20 @@
 0:59            1.200000
 0:60      move second child to first child (temp lowp float)
 0:60        'f' (temp lowp float)
-0:60        textureOffset (global lowp float)
+0:60        textureOffset (global lowp float, operation at mediump)
 0:60          's2DShadow' (uniform lowp sampler2DShadow)
 0:60          'c3D' (smooth in lowp 3-component vector of float)
 0:60          'ic2D' (flat in mediump 2-component vector of int)
 0:60          'c1D' (smooth in lowp float)
 0:61      move second child to first child (temp lowp 4-component vector of float)
 0:61        'v' (temp lowp 4-component vector of float)
-0:61        textureFetch (global lowp 4-component vector of float)
+0:61        textureFetch (global lowp 4-component vector of float, operation at mediump)
 0:61          's3D' (uniform lowp sampler3D)
 0:61          'ic3D' (flat in mediump 3-component vector of int)
 0:61          'ic1D' (flat in mediump int)
 0:62      move second child to first child (temp lowp 4-component vector of float)
 0:62        'v' (temp lowp 4-component vector of float)
-0:62        textureFetchOffset (global lowp 4-component vector of float)
+0:62        textureFetchOffset (global lowp 4-component vector of float, operation at mediump)
 0:62          direct index (temp lowp sampler2D)
 0:62            'arrayedSampler' (uniform 5-element array of lowp sampler2D)
 0:62            Constant:
@@ -452,14 +452,14 @@
 0:62          'ic2D' (flat in mediump 2-component vector of int)
 0:63      move second child to first child (temp lowp float)
 0:63        'f' (temp lowp float)
-0:63        textureLodOffset (global lowp float)
+0:63        textureLodOffset (global lowp float, operation at mediump)
 0:63          's2DShadow' (uniform lowp sampler2DShadow)
 0:63          'c3D' (smooth in lowp 3-component vector of float)
 0:63          'c1D' (smooth in lowp float)
 0:63          'ic2D' (flat in mediump 2-component vector of int)
 0:64      move second child to first child (temp lowp 4-component vector of float)
 0:64        'v' (temp lowp 4-component vector of float)
-0:64        textureProjLodOffset (global lowp 4-component vector of float)
+0:64        textureProjLodOffset (global lowp 4-component vector of float, operation at mediump)
 0:64          's2D' (uniform lowp sampler2D)
 0:64          'c3D' (smooth in lowp 3-component vector of float)
 0:64          'c1D' (smooth in lowp float)
@@ -473,7 +473,7 @@
 0:65          'c3D' (smooth in lowp 3-component vector of float)
 0:66      move second child to first child (temp lowp float)
 0:66        'f' (temp lowp float)
-0:66        textureGradOffset (global lowp float)
+0:66        textureGradOffset (global lowp float, operation at mediump)
 0:66          's2DArrayShadow' (uniform lowp sampler2DArrayShadow)
 0:66          'c4D' (smooth temp lowp 4-component vector of float)
 0:66          'c2D' (smooth in lowp 2-component vector of float)
@@ -488,7 +488,7 @@
 0:67          'c3D' (smooth in lowp 3-component vector of float)
 0:68      move second child to first child (temp lowp 4-component vector of float)
 0:68        'v' (temp lowp 4-component vector of float)
-0:68        textureProjGradOffset (global lowp 4-component vector of float)
+0:68        textureProjGradOffset (global lowp 4-component vector of float, operation at mediump)
 0:68          's2D' (uniform lowp sampler2D)
 0:68          'c3D' (smooth in lowp 3-component vector of float)
 0:68          'c2D' (smooth in lowp 2-component vector of float)
@@ -508,7 +508,7 @@
 0:72          'c2D' (smooth in lowp 2-component vector of float)
 0:73      move second child to first child (temp mediump 4-component vector of int)
 0:73        'iv' (temp mediump 4-component vector of int)
-0:73        textureProjOffset (global lowp 4-component vector of int)
+0:73        textureProjOffset (global lowp 4-component vector of int, operation at mediump)
 0:73          'is2D' (uniform lowp isampler2D)
 0:73          'c4D' (smooth temp lowp 4-component vector of float)
 0:73          'ic2D' (flat in mediump 2-component vector of int)
@@ -540,7 +540,7 @@
 0:77          'c1D' (smooth in lowp float)
 0:78      move second child to first child (temp mediump 4-component vector of int)
 0:78        'iv' (temp mediump 4-component vector of int)
-0:78        textureFetch (global lowp 4-component vector of int)
+0:78        textureFetch (global lowp 4-component vector of int, operation at mediump)
 0:78          'is2DArray' (uniform lowp isampler2DArray)
 0:78          'ic3D' (flat in mediump 3-component vector of int)
 0:78          'ic1D' (flat in mediump int)
@@ -552,7 +552,7 @@
 0:80              0 (const int)
 0:80            Constant:
 0:80              1 (const int)
-0:80        textureSize (global highp 2-component vector of int)
+0:80        textureSize (global highp 2-component vector of int, operation at lowp)
 0:80          'sCubeShadow' (uniform lowp samplerCubeShadow)
 0:80          Constant:
 0:80            2 (const int)
diff --git a/Test/baseResults/300.vert.out b/Test/baseResults/300.vert.out
index 80745ab..66a0651 100644
--- a/Test/baseResults/300.vert.out
+++ b/Test/baseResults/300.vert.out
@@ -175,7 +175,7 @@
 0:120      Sequence
 0:120        move second child to first child (temp highp 2-component vector of int)
 0:120          'x1' (temp highp 2-component vector of int)
-0:120          textureSize (global highp 2-component vector of int)
+0:120          textureSize (global highp 2-component vector of int, operation at lowp)
 0:120            's2D' (uniform lowp sampler2D)
 0:120            Constant:
 0:120              2 (const int)
@@ -184,7 +184,7 @@
 0:122      Sequence
 0:122        move second child to first child (temp highp 3-component vector of int)
 0:122          'x3' (temp highp 3-component vector of int)
-0:122          textureSize (global highp 3-component vector of int)
+0:122          textureSize (global highp 3-component vector of int, operation at lowp)
 0:122            's2DAS' (uniform lowp sampler2DArrayShadow)
 0:122            Constant:
 0:122              -1 (const int)
@@ -193,7 +193,7 @@
 0:124      Sequence
 0:124        move second child to first child (temp highp 4-component vector of float)
 0:124          'x4' (temp highp 4-component vector of float)
-0:124          texture (global lowp 4-component vector of float)
+0:124          texture (global lowp 4-component vector of float, operation at highp)
 0:124            's2D' (uniform lowp sampler2D)
 0:124            'c2D' (in highp 2-component vector of float)
 0:125      Constant:
@@ -217,7 +217,7 @@
 0:128      Sequence
 0:128        move second child to first child (temp highp float)
 0:128          'x6' (temp highp float)
-0:128          textureProjGradOffset (global lowp float)
+0:128          textureProjGradOffset (global lowp float, operation at highp)
 0:128            's2DS' (uniform lowp sampler2DShadow)
 0:128            'invIn' (invariant in highp 4-component vector of float)
 0:128            Constant:
@@ -459,7 +459,7 @@
 0:120      Sequence
 0:120        move second child to first child (temp highp 2-component vector of int)
 0:120          'x1' (temp highp 2-component vector of int)
-0:120          textureSize (global highp 2-component vector of int)
+0:120          textureSize (global highp 2-component vector of int, operation at lowp)
 0:120            's2D' (uniform lowp sampler2D)
 0:120            Constant:
 0:120              2 (const int)
@@ -468,7 +468,7 @@
 0:122      Sequence
 0:122        move second child to first child (temp highp 3-component vector of int)
 0:122          'x3' (temp highp 3-component vector of int)
-0:122          textureSize (global highp 3-component vector of int)
+0:122          textureSize (global highp 3-component vector of int, operation at lowp)
 0:122            's2DAS' (uniform lowp sampler2DArrayShadow)
 0:122            Constant:
 0:122              -1 (const int)
@@ -477,7 +477,7 @@
 0:124      Sequence
 0:124        move second child to first child (temp highp 4-component vector of float)
 0:124          'x4' (temp highp 4-component vector of float)
-0:124          texture (global lowp 4-component vector of float)
+0:124          texture (global lowp 4-component vector of float, operation at highp)
 0:124            's2D' (uniform lowp sampler2D)
 0:124            'c2D' (in highp 2-component vector of float)
 0:125      Constant:
@@ -501,7 +501,7 @@
 0:128      Sequence
 0:128        move second child to first child (temp highp float)
 0:128          'x6' (temp highp float)
-0:128          textureProjGradOffset (global lowp float)
+0:128          textureProjGradOffset (global lowp float, operation at highp)
 0:128            's2DS' (uniform lowp sampler2DShadow)
 0:128            'invIn' (invariant in highp 4-component vector of float)
 0:128            Constant:
diff --git a/Test/baseResults/300BuiltIns.frag.out b/Test/baseResults/300BuiltIns.frag.out
index c2f12c9..a3bab69 100644
--- a/Test/baseResults/300BuiltIns.frag.out
+++ b/Test/baseResults/300BuiltIns.frag.out
@@ -128,12 +128,12 @@
 0:52      Sequence
 0:52        move second child to first child (temp 2-component vector of bool)
 0:52          'b10' (temp 2-component vector of bool)
-0:52          isnan (global 2-component vector of bool)
+0:52          isnan (global 2-component vector of bool, operation at mediump)
 0:52            'v2a' (global mediump 2-component vector of float)
 0:53      Sequence
 0:53        move second child to first child (temp 4-component vector of bool)
 0:53          'b11' (temp 4-component vector of bool)
-0:53          isinf (global 4-component vector of bool)
+0:53          isinf (global 4-component vector of bool, operation at mediump)
 0:53            'v4' (global mediump 4-component vector of float)
 0:56      Sequence
 0:56        move second child to first child (temp highp int)
@@ -158,17 +158,17 @@
 0:62      Sequence
 0:62        move second child to first child (temp highp uint)
 0:62          'u19' (temp mediump uint)
-0:62          packSnorm2x16 (global highp uint)
+0:62          packSnorm2x16 (global highp uint, operation at mediump)
 0:62            'v2a' (global mediump 2-component vector of float)
 0:63      Sequence
-0:63        move second child to first child (temp mediump 2-component vector of float)
+0:63        move second child to first child (temp highp 2-component vector of float)
 0:63          'v20' (temp mediump 2-component vector of float)
-0:63          unpackSnorm2x16 (global mediump 2-component vector of float)
+0:63          unpackSnorm2x16 (global highp 2-component vector of float)
 0:63            'uy' (global mediump uint)
 0:64      Sequence
 0:64        move second child to first child (temp highp uint)
 0:64          'u15' (temp mediump uint)
-0:64          packUnorm2x16 (global highp uint)
+0:64          packUnorm2x16 (global highp uint, operation at mediump)
 0:64            'v2a' (global mediump 2-component vector of float)
 0:65      Sequence
 0:65        move second child to first child (temp highp 2-component vector of float)
@@ -178,12 +178,12 @@
 0:66      Sequence
 0:66        move second child to first child (temp highp uint)
 0:66          'u17' (temp mediump uint)
-0:66          packHalf2x16 (global highp uint)
+0:66          packHalf2x16 (global highp uint, operation at mediump)
 0:66            'v2b' (global mediump 2-component vector of float)
 0:67      Sequence
 0:67        move second child to first child (temp mediump 2-component vector of float)
 0:67          'v18' (temp mediump 2-component vector of float)
-0:67          unpackHalf2x16 (global mediump 2-component vector of float)
+0:67          unpackHalf2x16 (global mediump 2-component vector of float, operation at highp)
 0:67            'uy' (global mediump uint)
 0:70      Constant:
 0:70        0.000000
@@ -335,12 +335,12 @@
 0:52      Sequence
 0:52        move second child to first child (temp 2-component vector of bool)
 0:52          'b10' (temp 2-component vector of bool)
-0:52          isnan (global 2-component vector of bool)
+0:52          isnan (global 2-component vector of bool, operation at mediump)
 0:52            'v2a' (global mediump 2-component vector of float)
 0:53      Sequence
 0:53        move second child to first child (temp 4-component vector of bool)
 0:53          'b11' (temp 4-component vector of bool)
-0:53          isinf (global 4-component vector of bool)
+0:53          isinf (global 4-component vector of bool, operation at mediump)
 0:53            'v4' (global mediump 4-component vector of float)
 0:56      Sequence
 0:56        move second child to first child (temp highp int)
@@ -365,17 +365,17 @@
 0:62      Sequence
 0:62        move second child to first child (temp highp uint)
 0:62          'u19' (temp mediump uint)
-0:62          packSnorm2x16 (global highp uint)
+0:62          packSnorm2x16 (global highp uint, operation at mediump)
 0:62            'v2a' (global mediump 2-component vector of float)
 0:63      Sequence
-0:63        move second child to first child (temp mediump 2-component vector of float)
+0:63        move second child to first child (temp highp 2-component vector of float)
 0:63          'v20' (temp mediump 2-component vector of float)
-0:63          unpackSnorm2x16 (global mediump 2-component vector of float)
+0:63          unpackSnorm2x16 (global highp 2-component vector of float)
 0:63            'uy' (global mediump uint)
 0:64      Sequence
 0:64        move second child to first child (temp highp uint)
 0:64          'u15' (temp mediump uint)
-0:64          packUnorm2x16 (global highp uint)
+0:64          packUnorm2x16 (global highp uint, operation at mediump)
 0:64            'v2a' (global mediump 2-component vector of float)
 0:65      Sequence
 0:65        move second child to first child (temp highp 2-component vector of float)
@@ -385,12 +385,12 @@
 0:66      Sequence
 0:66        move second child to first child (temp highp uint)
 0:66          'u17' (temp mediump uint)
-0:66          packHalf2x16 (global highp uint)
+0:66          packHalf2x16 (global highp uint, operation at mediump)
 0:66            'v2b' (global mediump 2-component vector of float)
 0:67      Sequence
 0:67        move second child to first child (temp mediump 2-component vector of float)
 0:67          'v18' (temp mediump 2-component vector of float)
-0:67          unpackHalf2x16 (global mediump 2-component vector of float)
+0:67          unpackHalf2x16 (global mediump 2-component vector of float, operation at highp)
 0:67            'uy' (global mediump uint)
 0:70      Constant:
 0:70        0.000000
diff --git a/Test/baseResults/310.comp.out b/Test/baseResults/310.comp.out
index b56f070..9a5e4e8 100644
--- a/Test/baseResults/310.comp.out
+++ b/Test/baseResults/310.comp.out
@@ -122,7 +122,7 @@
 0:61            2 (const int)
 0:61        Constant:
 0:61          4.700000
-0:62      array length (temp highp int)
+0:62      array length (temp int)
 0:62        values: direct index for structure (layout(column_major shared ) buffer implicitly-sized array of highp float)
 0:62          'ro' (layout(column_major shared ) readonly buffer block{layout(column_major shared ) buffer highp int value, layout(column_major shared ) buffer implicitly-sized array of highp float values})
 0:62          Constant:
@@ -178,9 +178,9 @@
 0:92          0 (const int)
 0:92          0 (const int)
 0:92          0 (const int)
-0:93      imageLoad (global highp 4-component vector of float)
+0:93      imageLoad (global mediump 4-component vector of float)
 0:93        'img2Drgba' (layout(rgba32f ) readonly uniform mediump image2D)
-0:93        Construct ivec2 (temp highp 2-component vector of int)
+0:93        Construct ivec2 (temp mediump 2-component vector of int)
 0:93          'i' (temp highp int)
 0:93          'i' (temp highp int)
 0:94      imageLoad (global highp 4-component vector of int)
@@ -549,7 +549,7 @@
 0:61            2 (const int)
 0:61        Constant:
 0:61          4.700000
-0:62      array length (temp highp int)
+0:62      array length (temp int)
 0:62        values: direct index for structure (layout(column_major shared ) buffer implicitly-sized array of highp float)
 0:62          'ro' (layout(column_major shared ) readonly buffer block{layout(column_major shared ) buffer highp int value, layout(column_major shared ) buffer implicitly-sized array of highp float values})
 0:62          Constant:
@@ -605,9 +605,9 @@
 0:92          0 (const int)
 0:92          0 (const int)
 0:92          0 (const int)
-0:93      imageLoad (global highp 4-component vector of float)
+0:93      imageLoad (global mediump 4-component vector of float)
 0:93        'img2Drgba' (layout(rgba32f ) readonly uniform mediump image2D)
-0:93        Construct ivec2 (temp highp 2-component vector of int)
+0:93        Construct ivec2 (temp mediump 2-component vector of int)
 0:93          'i' (temp highp int)
 0:93          'i' (temp highp int)
 0:94      imageLoad (global highp 4-component vector of int)
diff --git a/Test/baseResults/310.frag.out b/Test/baseResults/310.frag.out
index 905a9ca..6cfd3f4 100644
--- a/Test/baseResults/310.frag.out
+++ b/Test/baseResults/310.frag.out
@@ -353,7 +353,7 @@
 0:101              3 (const int)
 0:102      move second child to first child (temp highp 2-component vector of int)
 0:102        'v2' (temp highp 2-component vector of int)
-0:102        textureSize (global highp 2-component vector of int)
+0:102        textureSize (global highp 2-component vector of int, operation at mediump)
 0:102          's2dms' (uniform mediump sampler2DMS)
 0:103      move second child to first child (temp highp 2-component vector of int)
 0:103        'v2' (temp highp 2-component vector of int)
@@ -361,19 +361,19 @@
 0:103          'i2D' (layout(binding=2 ) writeonly uniform highp image2D)
 0:104      move second child to first child (temp highp 3-component vector of int)
 0:104        'v3' (temp highp 3-component vector of int)
-0:104        imageQuerySize (global highp 3-component vector of int)
+0:104        imageQuerySize (global highp 3-component vector of int, operation at mediump)
 0:104          'i3D' (layout(binding=4 ) readonly uniform mediump image3D)
 0:105      move second child to first child (temp highp 2-component vector of int)
 0:105        'v2' (temp highp 2-component vector of int)
-0:105        imageQuerySize (global highp 2-component vector of int)
+0:105        imageQuerySize (global highp 2-component vector of int, operation at mediump)
 0:105          'iCube' (layout(binding=5 ) uniform mediump imageCube)
 0:106      move second child to first child (temp highp 3-component vector of int)
 0:106        'v3' (temp highp 3-component vector of int)
-0:106        imageQuerySize (global highp 3-component vector of int)
+0:106        imageQuerySize (global highp 3-component vector of int, operation at mediump)
 0:106          'i2DA' (layout(binding=6 ) uniform mediump image2DArray)
 0:107      move second child to first child (temp highp 2-component vector of int)
 0:107        'v2' (temp highp 2-component vector of int)
-0:107        imageQuerySize (global highp 2-component vector of int)
+0:107        imageQuerySize (global highp 2-component vector of int, operation at mediump)
 0:107          'i2Dqualified' (layout(binding=6 ) coherent volatile restrict uniform mediump image2D)
 0:165  Function Definition: fooIO( (global void)
 0:165    Function Parameters: 
@@ -1234,7 +1234,7 @@
 0:101              3 (const int)
 0:102      move second child to first child (temp highp 2-component vector of int)
 0:102        'v2' (temp highp 2-component vector of int)
-0:102        textureSize (global highp 2-component vector of int)
+0:102        textureSize (global highp 2-component vector of int, operation at mediump)
 0:102          's2dms' (uniform mediump sampler2DMS)
 0:103      move second child to first child (temp highp 2-component vector of int)
 0:103        'v2' (temp highp 2-component vector of int)
@@ -1242,19 +1242,19 @@
 0:103          'i2D' (layout(binding=2 ) writeonly uniform highp image2D)
 0:104      move second child to first child (temp highp 3-component vector of int)
 0:104        'v3' (temp highp 3-component vector of int)
-0:104        imageQuerySize (global highp 3-component vector of int)
+0:104        imageQuerySize (global highp 3-component vector of int, operation at mediump)
 0:104          'i3D' (layout(binding=4 ) readonly uniform mediump image3D)
 0:105      move second child to first child (temp highp 2-component vector of int)
 0:105        'v2' (temp highp 2-component vector of int)
-0:105        imageQuerySize (global highp 2-component vector of int)
+0:105        imageQuerySize (global highp 2-component vector of int, operation at mediump)
 0:105          'iCube' (layout(binding=5 ) uniform mediump imageCube)
 0:106      move second child to first child (temp highp 3-component vector of int)
 0:106        'v3' (temp highp 3-component vector of int)
-0:106        imageQuerySize (global highp 3-component vector of int)
+0:106        imageQuerySize (global highp 3-component vector of int, operation at mediump)
 0:106          'i2DA' (layout(binding=6 ) uniform mediump image2DArray)
 0:107      move second child to first child (temp highp 2-component vector of int)
 0:107        'v2' (temp highp 2-component vector of int)
-0:107        imageQuerySize (global highp 2-component vector of int)
+0:107        imageQuerySize (global highp 2-component vector of int, operation at mediump)
 0:107          'i2Dqualified' (layout(binding=6 ) coherent volatile restrict uniform mediump image2D)
 0:165  Function Definition: fooIO( (global void)
 0:165    Function Parameters: 
diff --git a/Test/baseResults/310.vert.out b/Test/baseResults/310.vert.out
index 678c3e1..84a50e8 100644
--- a/Test/baseResults/310.vert.out
+++ b/Test/baseResults/310.vert.out
@@ -125,12 +125,12 @@
 0:17          'u1' (temp highp uint)
 0:17          'u1' (temp highp uint)
 0:17          'u1' (temp highp uint)
-0:19      uMulExtended (global void)
+0:19      uMulExtended (global highp void)
 0:19        'u4' (temp highp 4-component vector of uint)
 0:19        'u4' (temp highp 4-component vector of uint)
 0:19        'u4' (temp highp 4-component vector of uint)
 0:19        'u4' (temp highp 4-component vector of uint)
-0:21      iMulExtended (global void)
+0:21      iMulExtended (global highp void)
 0:21        'i4' (temp highp 4-component vector of int)
 0:21        'i4' (temp highp 4-component vector of int)
 0:21        'i4' (temp highp 4-component vector of int)
@@ -179,27 +179,27 @@
 0:31          'u4' (temp highp 4-component vector of uint)
 0:32      move second child to first child (temp highp int)
 0:32        'i1' (temp highp int)
-0:32        bitCount (global highp int)
+0:32        bitCount (global lowp int, operation at highp)
 0:32          'i1' (temp highp int)
 0:33      move second child to first child (temp highp 3-component vector of int)
 0:33        'i3' (temp highp 3-component vector of int)
-0:33        bitCount (global highp 3-component vector of int)
+0:33        bitCount (global lowp 3-component vector of int, operation at highp)
 0:33          'u3' (temp highp 3-component vector of uint)
 0:34      move second child to first child (temp highp 2-component vector of int)
 0:34        'i2' (temp highp 2-component vector of int)
-0:34        findLSB (global highp 2-component vector of int)
+0:34        findLSB (global lowp 2-component vector of int, operation at highp)
 0:34          'i2' (temp highp 2-component vector of int)
 0:35      move second child to first child (temp highp 4-component vector of int)
 0:35        'i4' (temp highp 4-component vector of int)
-0:35        findLSB (global highp 4-component vector of int)
+0:35        findLSB (global lowp 4-component vector of int, operation at highp)
 0:35          'u4' (temp highp 4-component vector of uint)
 0:36      move second child to first child (temp highp int)
 0:36        'i1' (temp highp int)
-0:36        findMSB (global highp int)
+0:36        findMSB (global lowp int, operation at highp)
 0:36          'i1' (temp highp int)
 0:37      move second child to first child (temp highp 2-component vector of int)
 0:37        'i2' (temp highp 2-component vector of int)
-0:37        findMSB (global highp 2-component vector of int)
+0:37        findMSB (global lowp 2-component vector of int, operation at highp)
 0:37          'u2' (temp highp 2-component vector of uint)
 0:40      move second child to first child (temp highp 3-component vector of float)
 0:40        'v3' (temp highp 3-component vector of float)
@@ -213,19 +213,19 @@
 0:42          'i2' (temp highp 2-component vector of int)
 0:45      move second child to first child (temp highp uint)
 0:45        'u1' (temp highp uint)
-0:45        PackUnorm4x8 (global highp uint)
+0:45        PackUnorm4x8 (global highp uint, operation at mediump)
 0:45          'v4' (temp mediump 4-component vector of float)
 0:46      move second child to first child (temp highp uint)
 0:46        'u1' (temp highp uint)
-0:46        PackSnorm4x8 (global highp uint)
+0:46        PackSnorm4x8 (global highp uint, operation at mediump)
 0:46          'v4' (temp mediump 4-component vector of float)
-0:47      move second child to first child (temp highp 4-component vector of float)
+0:47      move second child to first child (temp mediump 4-component vector of float)
 0:47        'v4' (temp mediump 4-component vector of float)
-0:47        UnpackUnorm4x8 (global highp 4-component vector of float)
+0:47        UnpackUnorm4x8 (global mediump 4-component vector of float, operation at highp)
 0:47          'u1' (temp highp uint)
-0:48      move second child to first child (temp highp 4-component vector of float)
+0:48      move second child to first child (temp mediump 4-component vector of float)
 0:48        'v4' (temp mediump 4-component vector of float)
-0:48        UnpackSnorm4x8 (global highp 4-component vector of float)
+0:48        UnpackSnorm4x8 (global mediump 4-component vector of float, operation at highp)
 0:48          'u1' (temp highp uint)
 0:60  Function Definition: foo( (global void)
 0:60    Function Parameters: 
@@ -340,7 +340,7 @@
 0:165          0.100000
 0:165        Convert float to int (temp lowp 2-component vector of int)
 0:165          'inf' (in highp 2-component vector of float)
-0:166      textureGatherOffsets (global lowp 4-component vector of float)
+0:166      textureGatherOffsets (global lowp 4-component vector of float, operation at highp)
 0:166        direct index (temp lowp sampler2D)
 0:166          'sArray' (uniform 4-element array of lowp sampler2D)
 0:166          Constant:
@@ -404,7 +404,7 @@
 0:180          0.100000
 0:180        Convert float to int (temp lowp 2-component vector of int)
 0:180          'inf' (in highp 2-component vector of float)
-0:181      textureGatherOffsets (global lowp 4-component vector of float)
+0:181      textureGatherOffsets (global lowp 4-component vector of float, operation at highp)
 0:181        direct index (temp lowp sampler2D)
 0:181          'sArray' (uniform 4-element array of lowp sampler2D)
 0:181          Constant:
@@ -421,7 +421,7 @@
 0:181          0 (const int)
 0:181          0 (const int)
 0:181          0 (const int)
-0:182      textureGatherOffsets (global lowp 4-component vector of float)
+0:182      textureGatherOffsets (global lowp 4-component vector of float, operation at highp)
 0:182        direct index (temp lowp sampler2D)
 0:182          'sArray' (uniform 4-element array of lowp sampler2D)
 0:182          Constant:
@@ -1056,12 +1056,12 @@
 0:17          'u1' (temp highp uint)
 0:17          'u1' (temp highp uint)
 0:17          'u1' (temp highp uint)
-0:19      uMulExtended (global void)
+0:19      uMulExtended (global highp void)
 0:19        'u4' (temp highp 4-component vector of uint)
 0:19        'u4' (temp highp 4-component vector of uint)
 0:19        'u4' (temp highp 4-component vector of uint)
 0:19        'u4' (temp highp 4-component vector of uint)
-0:21      iMulExtended (global void)
+0:21      iMulExtended (global highp void)
 0:21        'i4' (temp highp 4-component vector of int)
 0:21        'i4' (temp highp 4-component vector of int)
 0:21        'i4' (temp highp 4-component vector of int)
@@ -1110,27 +1110,27 @@
 0:31          'u4' (temp highp 4-component vector of uint)
 0:32      move second child to first child (temp highp int)
 0:32        'i1' (temp highp int)
-0:32        bitCount (global highp int)
+0:32        bitCount (global lowp int, operation at highp)
 0:32          'i1' (temp highp int)
 0:33      move second child to first child (temp highp 3-component vector of int)
 0:33        'i3' (temp highp 3-component vector of int)
-0:33        bitCount (global highp 3-component vector of int)
+0:33        bitCount (global lowp 3-component vector of int, operation at highp)
 0:33          'u3' (temp highp 3-component vector of uint)
 0:34      move second child to first child (temp highp 2-component vector of int)
 0:34        'i2' (temp highp 2-component vector of int)
-0:34        findLSB (global highp 2-component vector of int)
+0:34        findLSB (global lowp 2-component vector of int, operation at highp)
 0:34          'i2' (temp highp 2-component vector of int)
 0:35      move second child to first child (temp highp 4-component vector of int)
 0:35        'i4' (temp highp 4-component vector of int)
-0:35        findLSB (global highp 4-component vector of int)
+0:35        findLSB (global lowp 4-component vector of int, operation at highp)
 0:35          'u4' (temp highp 4-component vector of uint)
 0:36      move second child to first child (temp highp int)
 0:36        'i1' (temp highp int)
-0:36        findMSB (global highp int)
+0:36        findMSB (global lowp int, operation at highp)
 0:36          'i1' (temp highp int)
 0:37      move second child to first child (temp highp 2-component vector of int)
 0:37        'i2' (temp highp 2-component vector of int)
-0:37        findMSB (global highp 2-component vector of int)
+0:37        findMSB (global lowp 2-component vector of int, operation at highp)
 0:37          'u2' (temp highp 2-component vector of uint)
 0:40      move second child to first child (temp highp 3-component vector of float)
 0:40        'v3' (temp highp 3-component vector of float)
@@ -1144,19 +1144,19 @@
 0:42          'i2' (temp highp 2-component vector of int)
 0:45      move second child to first child (temp highp uint)
 0:45        'u1' (temp highp uint)
-0:45        PackUnorm4x8 (global highp uint)
+0:45        PackUnorm4x8 (global highp uint, operation at mediump)
 0:45          'v4' (temp mediump 4-component vector of float)
 0:46      move second child to first child (temp highp uint)
 0:46        'u1' (temp highp uint)
-0:46        PackSnorm4x8 (global highp uint)
+0:46        PackSnorm4x8 (global highp uint, operation at mediump)
 0:46          'v4' (temp mediump 4-component vector of float)
-0:47      move second child to first child (temp highp 4-component vector of float)
+0:47      move second child to first child (temp mediump 4-component vector of float)
 0:47        'v4' (temp mediump 4-component vector of float)
-0:47        UnpackUnorm4x8 (global highp 4-component vector of float)
+0:47        UnpackUnorm4x8 (global mediump 4-component vector of float, operation at highp)
 0:47          'u1' (temp highp uint)
-0:48      move second child to first child (temp highp 4-component vector of float)
+0:48      move second child to first child (temp mediump 4-component vector of float)
 0:48        'v4' (temp mediump 4-component vector of float)
-0:48        UnpackSnorm4x8 (global highp 4-component vector of float)
+0:48        UnpackSnorm4x8 (global mediump 4-component vector of float, operation at highp)
 0:48          'u1' (temp highp uint)
 0:60  Function Definition: foo( (global void)
 0:60    Function Parameters: 
@@ -1271,7 +1271,7 @@
 0:165          0.100000
 0:165        Convert float to int (temp lowp 2-component vector of int)
 0:165          'inf' (in highp 2-component vector of float)
-0:166      textureGatherOffsets (global lowp 4-component vector of float)
+0:166      textureGatherOffsets (global lowp 4-component vector of float, operation at highp)
 0:166        direct index (temp lowp sampler2D)
 0:166          'sArray' (uniform 4-element array of lowp sampler2D)
 0:166          Constant:
@@ -1335,7 +1335,7 @@
 0:180          0.100000
 0:180        Convert float to int (temp lowp 2-component vector of int)
 0:180          'inf' (in highp 2-component vector of float)
-0:181      textureGatherOffsets (global lowp 4-component vector of float)
+0:181      textureGatherOffsets (global lowp 4-component vector of float, operation at highp)
 0:181        direct index (temp lowp sampler2D)
 0:181          'sArray' (uniform 4-element array of lowp sampler2D)
 0:181          Constant:
@@ -1352,7 +1352,7 @@
 0:181          0 (const int)
 0:181          0 (const int)
 0:181          0 (const int)
-0:182      textureGatherOffsets (global lowp 4-component vector of float)
+0:182      textureGatherOffsets (global lowp 4-component vector of float, operation at highp)
 0:182        direct index (temp lowp sampler2D)
 0:182          'sArray' (uniform 4-element array of lowp sampler2D)
 0:182          Constant:
diff --git a/Test/baseResults/310AofA.vert.out b/Test/baseResults/310AofA.vert.out
index 40c4321..83f105c 100644
--- a/Test/baseResults/310AofA.vert.out
+++ b/Test/baseResults/310AofA.vert.out
@@ -310,7 +310,7 @@
 0:96          1 (const int)
 0:98      Constant:
 0:98        7 (const int)
-0:99      array length (temp highp int)
+0:99      array length (temp int)
 0:99        v: direct index for structure (layout(column_major shared ) buffer implicitly-sized array of 7-element array of highp 4-component vector of float)
 0:99          direct index (layout(column_major shared ) temp block{layout(column_major shared ) buffer highp float u, layout(column_major shared ) buffer implicitly-sized array of 7-element array of highp 4-component vector of float v})
 0:99            'name3' (layout(column_major shared ) buffer 3-element array of block{layout(column_major shared ) buffer highp float u, layout(column_major shared ) buffer implicitly-sized array of 7-element array of highp 4-component vector of float v})
@@ -622,7 +622,7 @@
 0:96          1 (const int)
 0:98      Constant:
 0:98        7 (const int)
-0:99      array length (temp highp int)
+0:99      array length (temp int)
 0:99        v: direct index for structure (layout(column_major shared ) buffer implicitly-sized array of 7-element array of highp 4-component vector of float)
 0:99          direct index (layout(column_major shared ) temp block{layout(column_major shared ) buffer highp float u, layout(column_major shared ) buffer implicitly-sized array of 7-element array of highp 4-component vector of float v})
 0:99            'name3' (layout(column_major shared ) buffer 3-element array of block{layout(column_major shared ) buffer highp float u, layout(column_major shared ) buffer implicitly-sized array of 7-element array of highp 4-component vector of float v})
diff --git a/Test/baseResults/pointCoord.frag.out b/Test/baseResults/pointCoord.frag.out
index 633d8b9..5d53aea 100644
--- a/Test/baseResults/pointCoord.frag.out
+++ b/Test/baseResults/pointCoord.frag.out
@@ -14,7 +14,7 @@
 0:9        true case
 0:10        move second child to first child (temp highp 4-component vector of float)
 0:10          'color' (temp highp 4-component vector of float)
-0:10          texture (global lowp 4-component vector of float)
+0:10          texture (global lowp 4-component vector of float, operation at mediump)
 0:10            'sampler' (uniform lowp sampler2D)
 0:10            'gl_PointCoord' (gl_PointCoord mediump 2-component vector of float PointCoord)
 0:9        false case
@@ -50,7 +50,7 @@
 0:9        true case
 0:10        move second child to first child (temp highp 4-component vector of float)
 0:10          'color' (temp highp 4-component vector of float)
-0:10          texture (global lowp 4-component vector of float)
+0:10          texture (global lowp 4-component vector of float, operation at mediump)
 0:10            'sampler' (uniform lowp sampler2D)
 0:10            'gl_PointCoord' (gl_PointCoord mediump 2-component vector of float PointCoord)
 0:9        false case
diff --git a/Test/baseResults/uint.frag.out b/Test/baseResults/uint.frag.out
index dbe9578..1ee2825 100644
--- a/Test/baseResults/uint.frag.out
+++ b/Test/baseResults/uint.frag.out
@@ -113,7 +113,7 @@
 0:55        true case
 0:56        move second child to first child (temp mediump 4-component vector of uint)
 0:56          'c' (out mediump 4-component vector of uint)
-0:56          texture (global lowp 4-component vector of uint)
+0:56          texture (global lowp 4-component vector of uint, operation at highp)
 0:56            'usampler' (uniform lowp usampler2D)
 0:56            'tc' (smooth in highp 2-component vector of float)
 0:57      Test condition and select (temp void)
@@ -124,7 +124,7 @@
 0:57        true case
 0:58        move second child to first child (temp mediump 4-component vector of uint)
 0:58          'c' (out mediump 4-component vector of uint)
-0:58          texture (global lowp 4-component vector of uint)
+0:58          texture (global lowp 4-component vector of uint, operation at highp)
 0:58            'usampler' (uniform lowp usampler2D)
 0:58            add (temp highp 2-component vector of float)
 0:58              'tc' (smooth in highp 2-component vector of float)
@@ -139,7 +139,7 @@
 0:59        true case
 0:60        move second child to first child (temp mediump 4-component vector of uint)
 0:60          'c' (out mediump 4-component vector of uint)
-0:60          texture (global lowp 4-component vector of uint)
+0:60          texture (global lowp 4-component vector of uint, operation at highp)
 0:60            'usampler' (uniform lowp usampler2D)
 0:60            subtract (temp highp 2-component vector of float)
 0:60              'tc' (smooth in highp 2-component vector of float)
@@ -412,7 +412,7 @@
 0:55        true case
 0:56        move second child to first child (temp mediump 4-component vector of uint)
 0:56          'c' (out mediump 4-component vector of uint)
-0:56          texture (global lowp 4-component vector of uint)
+0:56          texture (global lowp 4-component vector of uint, operation at highp)
 0:56            'usampler' (uniform lowp usampler2D)
 0:56            'tc' (smooth in highp 2-component vector of float)
 0:57      Test condition and select (temp void)
@@ -423,7 +423,7 @@
 0:57        true case
 0:58        move second child to first child (temp mediump 4-component vector of uint)
 0:58          'c' (out mediump 4-component vector of uint)
-0:58          texture (global lowp 4-component vector of uint)
+0:58          texture (global lowp 4-component vector of uint, operation at highp)
 0:58            'usampler' (uniform lowp usampler2D)
 0:58            add (temp highp 2-component vector of float)
 0:58              'tc' (smooth in highp 2-component vector of float)
@@ -438,7 +438,7 @@
 0:59        true case
 0:60        move second child to first child (temp mediump 4-component vector of uint)
 0:60          'c' (out mediump 4-component vector of uint)
-0:60          texture (global lowp 4-component vector of uint)
+0:60          texture (global lowp 4-component vector of uint, operation at highp)
 0:60            'usampler' (uniform lowp usampler2D)
 0:60            subtract (temp highp 2-component vector of float)
 0:60              'tc' (smooth in highp 2-component vector of float)
diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h
index 4d260f0..bbca934 100644
--- a/glslang/Include/intermediate.h
+++ b/glslang/Include/intermediate.h
@@ -461,6 +461,9 @@
     EOpTextureQueryLod,
     EOpTextureQueryLevels,
     EOpTextureQuerySamples,
+
+    EOpSamplingGuardBegin,
+
     EOpTexture,
     EOpTextureProj,
     EOpTextureLod,
@@ -503,7 +506,7 @@
     EOpSparseTextureGradOffsetClamp,
 
     EOpSparseTextureGuardEnd,
-
+    EOpSamplingGuardEnd,
     EOpTextureGuardEnd,
 
     //
@@ -799,11 +802,27 @@
     virtual bool promote() { return true; }
     bool modifiesState() const;
     bool isConstructor() const;
-    bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; }
-    bool isImage()   const { return op > EOpImageGuardBegin   && op < EOpImageGuardEnd; }
+    bool isTexture()  const { return op > EOpTextureGuardBegin  && op < EOpTextureGuardEnd; }
+    bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; }
+    bool isImage()    const { return op > EOpImageGuardBegin    && op < EOpImageGuardEnd; }
     bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; }
     bool isSparseImage()   const { return op == EOpSparseImageLoad; }
 
+    void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; }
+    TPrecisionQualifier getOperationPrecision() const { return operationPrecision != EpqNone ?
+                                                                                     operationPrecision :
+                                                                                     type.getQualifier().precision; }
+    TString getCompleteString() const
+    {
+        TString cs = type.getCompleteString();
+        if (getOperationPrecision() != type.getQualifier().precision) {
+            cs += ", operation at ";
+            cs += GetPrecisionQualifierString(getOperationPrecision());
+        }
+
+        return cs;
+    }
+
     // Crack the op into the individual dimensions of texturing operation.
     void crackTexture(TSampler sampler, TCrackedTextureOp& cracked) const
     {
@@ -935,9 +954,15 @@
     }
 
 protected:
-    TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o) {}
-    TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
+    TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o), operationPrecision(EpqNone) {}
+    TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o), operationPrecision(EpqNone) {}
     TOperator op;
+    // The result precision is in the inherited TType, and is usually meant to be both
+    // the operation precision and the result precision. However, some more complex things,
+    // like built-in function calls, distinguish between the two, in which case non-EqpNone
+    // 'operationPrecision' overrides the result precision as far as operation precision
+    // is concerned.
+    TPrecisionQualifier operationPrecision;
 };
 
 //
diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h
index faaba8d..3884d07 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.1375"
-#define GLSLANG_DATE "31-Jul-2016"
+#define GLSLANG_REVISION "SPIRV99.1377"
+#define GLSLANG_DATE "02-Aug-2016"
diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp
index 8523398..0323c1b 100644
--- a/glslang/MachineIndependent/Initialize.cpp
+++ b/glslang/MachineIndependent/Initialize.cpp
@@ -934,25 +934,25 @@
     if ((profile == EEsProfile && version >= 300) ||
         (profile != EEsProfile && version >= 330)) {
         commonBuiltins.append(
-            "highp int   floatBitsToInt(highp float value);"
-            "highp ivec2 floatBitsToInt(highp vec2  value);"
-            "highp ivec3 floatBitsToInt(highp vec3  value);"
-            "highp ivec4 floatBitsToInt(highp vec4  value);"
-                     
-            "highp uint  floatBitsToUint(highp float value);"
-            "highp uvec2 floatBitsToUint(highp vec2  value);"
-            "highp uvec3 floatBitsToUint(highp vec3  value);"
-            "highp uvec4 floatBitsToUint(highp vec4  value);"
+            "int   floatBitsToInt(highp float value);"
+            "ivec2 floatBitsToInt(highp vec2  value);"
+            "ivec3 floatBitsToInt(highp vec3  value);"
+            "ivec4 floatBitsToInt(highp vec4  value);"
 
-            "highp float intBitsToFloat(highp int   value);"
-            "highp vec2  intBitsToFloat(highp ivec2 value);"
-            "highp vec3  intBitsToFloat(highp ivec3 value);"
-            "highp vec4  intBitsToFloat(highp ivec4 value);"
+            "uint  floatBitsToUint(highp float value);"
+            "uvec2 floatBitsToUint(highp vec2  value);"
+            "uvec3 floatBitsToUint(highp vec3  value);"
+            "uvec4 floatBitsToUint(highp vec4  value);"
 
-            "highp float uintBitsToFloat(highp uint  value);"
-            "highp vec2  uintBitsToFloat(highp uvec2 value);"
-            "highp vec3  uintBitsToFloat(highp uvec3 value);"
-            "highp vec4  uintBitsToFloat(highp uvec4 value);"
+            "float intBitsToFloat(highp int   value);"
+            "vec2  intBitsToFloat(highp ivec2 value);"
+            "vec3  intBitsToFloat(highp ivec3 value);"
+            "vec4  intBitsToFloat(highp ivec4 value);"
+
+            "float uintBitsToFloat(highp uint  value);"
+            "vec2  uintBitsToFloat(highp uvec2 value);"
+            "vec3  uintBitsToFloat(highp uvec3 value);"
+            "vec4  uintBitsToFloat(highp uvec4 value);"
 
             "\n");
     }
@@ -980,15 +980,15 @@
     if ((profile == EEsProfile && version >= 310) ||
         (profile != EEsProfile && version >= 400)) {
         commonBuiltins.append(
-            "highp float frexp(highp float, out highp int);"
-            "highp vec2  frexp(highp vec2,  out highp ivec2);"
-            "highp vec3  frexp(highp vec3,  out highp ivec3);"
-            "highp vec4  frexp(highp vec4,  out highp ivec4);"
+            "float frexp(highp float, out highp int);"
+            "vec2  frexp(highp vec2,  out highp ivec2);"
+            "vec3  frexp(highp vec3,  out highp ivec3);"
+            "vec4  frexp(highp vec4,  out highp ivec4);"
 
-            "highp float ldexp(highp float, highp int);"
-            "highp vec2  ldexp(highp vec2,  highp ivec2);"
-            "highp vec3  ldexp(highp vec3,  highp ivec3);"
-            "highp vec4  ldexp(highp vec4,  highp ivec4);"
+            "float ldexp(highp float, highp int);"
+            "vec2  ldexp(highp vec2,  highp ivec2);"
+            "vec3  ldexp(highp vec3,  highp ivec3);"
+            "vec4  ldexp(highp vec4,  highp ivec4);"
 
             "\n");
     }
@@ -1015,7 +1015,7 @@
         (profile != EEsProfile && version >= 400)) {
         commonBuiltins.append(
             "highp uint packUnorm2x16(vec2);"
-            "highp vec2 unpackUnorm2x16(highp uint);"
+                  "vec2 unpackUnorm2x16(highp uint);"
             "\n");
     }
 
@@ -1024,18 +1024,37 @@
         commonBuiltins.append(
             "highp uint packSnorm2x16(vec2);"
             "      vec2 unpackSnorm2x16(highp uint);"
-            "highp uint packHalf2x16(mediump vec2);"
-            "      vec2 unpackHalf2x16(highp uint);"
+            "highp uint packHalf2x16(vec2);"
+            "\n");
+    }
+
+    if (profile == EEsProfile && version >= 300) {
+        commonBuiltins.append(
+            "mediump vec2 unpackHalf2x16(highp uint);"
+            "\n");
+    } else if (profile != EEsProfile && version >= 420) {
+        commonBuiltins.append(
+            "        vec2 unpackHalf2x16(highp uint);"
             "\n");
     }
 
     if ((profile == EEsProfile && version >= 310) ||
         (profile != EEsProfile && version >= 400)) {
         commonBuiltins.append(
-            "highp   uint packSnorm4x8  (mediump vec4);"
-            "        vec4 unpackSnorm4x8(highp   uint);"
-            "highp   uint packUnorm4x8  (mediump vec4);"
-            "        vec4 unpackUnorm4x8(highp   uint);"
+            "highp uint packSnorm4x8(vec4);"
+            "highp uint packUnorm4x8(vec4);"
+            "\n");
+    }
+
+    if (profile == EEsProfile && version >= 310) {
+        commonBuiltins.append(
+            "mediump vec4 unpackSnorm4x8(highp uint);"
+            "mediump vec4 unpackUnorm4x8(highp uint);"
+            "\n");
+    } else if (profile != EEsProfile && version >= 400) {
+        commonBuiltins.append(
+                    "vec4 unpackSnorm4x8(highp uint);"
+                    "vec4 unpackUnorm4x8(highp uint);"
             "\n");
     }
 
@@ -1372,6 +1391,11 @@
             "uvec3 bitfieldInsert(uvec3 base, uvec3, int, int);"
             "uvec4 bitfieldInsert(uvec4 base, uvec4, int, int);"
 
+            "\n");
+    }
+
+    if (profile != EEsProfile && version >= 400) {
+        commonBuiltins.append(
             "  int findLSB(  int);"
             "ivec2 findLSB(ivec2);"
             "ivec3 findLSB(ivec3);"
@@ -1383,95 +1407,23 @@
             "ivec4 findLSB(uvec4);"
 
             "\n");
-    }
-
-    if (profile != EEsProfile && version >= 400) {
+    } else if (profile == EEsProfile && version >= 310) {
         commonBuiltins.append(
-            " uint uaddCarry( uint,  uint, out  uint carry);"
-            "uvec2 uaddCarry(uvec2, uvec2, out uvec2 carry);"
-            "uvec3 uaddCarry(uvec3, uvec3, out uvec3 carry);"
-            "uvec4 uaddCarry(uvec4, uvec4, out uvec4 carry);"
+            "lowp   int findLSB(  int);"
+            "lowp ivec2 findLSB(ivec2);"
+            "lowp ivec3 findLSB(ivec3);"
+            "lowp ivec4 findLSB(ivec4);"
 
-            " uint usubBorrow( uint,  uint, out  uint borrow);"
-            "uvec2 usubBorrow(uvec2, uvec2, out uvec2 borrow);"
-            "uvec3 usubBorrow(uvec3, uvec3, out uvec3 borrow);"
-            "uvec4 usubBorrow(uvec4, uvec4, out uvec4 borrow);"
-
-            "void umulExtended( uint,  uint, out  uint, out  uint lsb);"
-            "void umulExtended(uvec2, uvec2, out uvec2, out uvec2 lsb);"
-            "void umulExtended(uvec3, uvec3, out uvec3, out uvec3 lsb);"
-            "void umulExtended(uvec4, uvec4, out uvec4, out uvec4 lsb);"
-
-            "void imulExtended(  int,   int, out   int, out   int lsb);"
-            "void imulExtended(ivec2, ivec2, out ivec2, out ivec2 lsb);"
-            "void imulExtended(ivec3, ivec3, out ivec3, out ivec3 lsb);"
-            "void imulExtended(ivec4, ivec4, out ivec4, out ivec4 lsb);"
-
-            "  int bitfieldReverse(  int);"
-            "ivec2 bitfieldReverse(ivec2);"
-            "ivec3 bitfieldReverse(ivec3);"
-            "ivec4 bitfieldReverse(ivec4);"
-
-            " uint bitfieldReverse( uint);"
-            "uvec2 bitfieldReverse(uvec2);"
-            "uvec3 bitfieldReverse(uvec3);"
-            "uvec4 bitfieldReverse(uvec4);"
-
-            "  int bitCount(  int);"
-            "ivec2 bitCount(ivec2);"
-            "ivec3 bitCount(ivec3);"
-            "ivec4 bitCount(ivec4);"
-
-            "  int bitCount( uint);"
-            "ivec2 bitCount(uvec2);"
-            "ivec3 bitCount(uvec3);"
-            "ivec4 bitCount(uvec4);"
-
-            "  int findMSB(  int);"
-            "ivec2 findMSB(ivec2);"
-            "ivec3 findMSB(ivec3);"
-            "ivec4 findMSB(ivec4);"
-
-            "  int findMSB( uint);"
-            "ivec2 findMSB(uvec2);"
-            "ivec3 findMSB(uvec3);"
-            "ivec4 findMSB(uvec4);"
+            "lowp   int findLSB( uint);"
+            "lowp ivec2 findLSB(uvec2);"
+            "lowp ivec3 findLSB(uvec3);"
+            "lowp ivec4 findLSB(uvec4);"
 
             "\n");
     }
 
-    if (profile == EEsProfile && version >= 310) {
+    if (profile != EEsProfile && version >= 400) {
         commonBuiltins.append(
-            "highp  uint uaddCarry(highp  uint, highp  uint, out lowp  uint carry);"
-            "highp uvec2 uaddCarry(highp uvec2, highp uvec2, out lowp uvec2 carry);"
-            "highp uvec3 uaddCarry(highp uvec3, highp uvec3, out lowp uvec3 carry);"
-            "highp uvec4 uaddCarry(highp uvec4, highp uvec4, out lowp uvec4 carry);"
-
-            "highp  uint usubBorrow(highp  uint, highp  uint, out lowp  uint borrow);"
-            "highp uvec2 usubBorrow(highp uvec2, highp uvec2, out lowp uvec2 borrow);"
-            "highp uvec3 usubBorrow(highp uvec3, highp uvec3, out lowp uvec3 borrow);"
-            "highp uvec4 usubBorrow(highp uvec4, highp uvec4, out lowp uvec4 borrow);"
-
-            "void umulExtended(highp  uint, highp  uint, highp out  uint, out highp  uint lsb);"
-            "void umulExtended(highp uvec2, highp uvec2, highp out uvec2, out highp uvec2 lsb);"
-            "void umulExtended(highp uvec3, highp uvec3, highp out uvec3, out highp uvec3 lsb);"
-            "void umulExtended(highp uvec4, highp uvec4, highp out uvec4, out highp uvec4 lsb);"
-
-            "void imulExtended(highp   int, highp   int, highp out   int, out highp   int lsb);"
-            "void imulExtended(highp ivec2, highp ivec2, highp out ivec2, out highp ivec2 lsb);"
-            "void imulExtended(highp ivec3, highp ivec3, highp out ivec3, out highp ivec3 lsb);"
-            "void imulExtended(highp ivec4, highp ivec4, highp out ivec4, out highp ivec4 lsb);"
-
-            "highp   int bitfieldReverse(highp   int);"
-            "highp ivec2 bitfieldReverse(highp ivec2);"
-            "highp ivec3 bitfieldReverse(highp ivec3);"
-            "highp ivec4 bitfieldReverse(highp ivec4);"
-
-            "highp  uint bitfieldReverse(highp  uint);"
-            "highp uvec2 bitfieldReverse(highp uvec2);"
-            "highp uvec3 bitfieldReverse(highp uvec3);"
-            "highp uvec4 bitfieldReverse(highp uvec4);"
-
             "  int bitCount(  int);"
             "ivec2 bitCount(ivec2);"
             "ivec3 bitCount(ivec3);"
@@ -1491,6 +1443,67 @@
             "ivec2 findMSB(highp uvec2);"
             "ivec3 findMSB(highp uvec3);"
             "ivec4 findMSB(highp uvec4);"
+
+            "\n");
+    }
+
+    if ((profile == EEsProfile && version >= 310) ||
+        (profile != EEsProfile && version >= 400)) {
+        commonBuiltins.append(
+            " uint uaddCarry(highp  uint, highp  uint, out lowp  uint carry);"
+            "uvec2 uaddCarry(highp uvec2, highp uvec2, out lowp uvec2 carry);"
+            "uvec3 uaddCarry(highp uvec3, highp uvec3, out lowp uvec3 carry);"
+            "uvec4 uaddCarry(highp uvec4, highp uvec4, out lowp uvec4 carry);"
+
+            " uint usubBorrow(highp  uint, highp  uint, out lowp  uint borrow);"
+            "uvec2 usubBorrow(highp uvec2, highp uvec2, out lowp uvec2 borrow);"
+            "uvec3 usubBorrow(highp uvec3, highp uvec3, out lowp uvec3 borrow);"
+            "uvec4 usubBorrow(highp uvec4, highp uvec4, out lowp uvec4 borrow);"
+
+            "void umulExtended(highp  uint, highp  uint, highp out  uint, out highp  uint lsb);"
+            "void umulExtended(highp uvec2, highp uvec2, highp out uvec2, out highp uvec2 lsb);"
+            "void umulExtended(highp uvec3, highp uvec3, highp out uvec3, out highp uvec3 lsb);"
+            "void umulExtended(highp uvec4, highp uvec4, highp out uvec4, out highp uvec4 lsb);"
+
+            "void imulExtended(highp   int, highp   int, highp out   int, out highp   int lsb);"
+            "void imulExtended(highp ivec2, highp ivec2, highp out ivec2, out highp ivec2 lsb);"
+            "void imulExtended(highp ivec3, highp ivec3, highp out ivec3, out highp ivec3 lsb);"
+            "void imulExtended(highp ivec4, highp ivec4, highp out ivec4, out highp ivec4 lsb);"
+
+            "  int bitfieldReverse(highp   int);"
+            "ivec2 bitfieldReverse(highp ivec2);"
+            "ivec3 bitfieldReverse(highp ivec3);"
+            "ivec4 bitfieldReverse(highp ivec4);"
+
+            " uint bitfieldReverse(highp  uint);"
+            "uvec2 bitfieldReverse(highp uvec2);"
+            "uvec3 bitfieldReverse(highp uvec3);"
+            "uvec4 bitfieldReverse(highp uvec4);"
+
+            "\n");
+    }
+
+    if (profile == EEsProfile && version >= 310) {
+        commonBuiltins.append(
+            "lowp   int bitCount(  int);"
+            "lowp ivec2 bitCount(ivec2);"
+            "lowp ivec3 bitCount(ivec3);"
+            "lowp ivec4 bitCount(ivec4);"
+
+            "lowp   int bitCount( uint);"
+            "lowp ivec2 bitCount(uvec2);"
+            "lowp ivec3 bitCount(uvec3);"
+            "lowp ivec4 bitCount(uvec4);"
+
+            "lowp   int findMSB(highp   int);"
+            "lowp ivec2 findMSB(highp ivec2);"
+            "lowp ivec3 findMSB(highp ivec3);"
+            "lowp ivec4 findMSB(highp ivec4);"
+
+            "lowp   int findMSB(highp  uint);"
+            "lowp ivec2 findMSB(highp uvec2);"
+            "lowp ivec3 findMSB(highp uvec3);"
+            "lowp ivec4 findMSB(highp uvec4);"
             
             "\n");
     }
diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp
index 31d0b16..be828e9 100644
--- a/glslang/MachineIndependent/Intermediate.cpp
+++ b/glslang/MachineIndependent/Intermediate.cpp
@@ -341,35 +341,11 @@
         node->setOperand(child);
         node->setType(returnType);
 
-        // propagate precision up from child
-        if (profile == EEsProfile && returnType.getQualifier().precision == EpqNone && returnType.getBasicType() != EbtBool)
-            node->getQualifier().precision = child->getQualifier().precision;
-
-        // propagate precision down to child
-        if (node->getQualifier().precision != EpqNone)
-            child->propagatePrecision(node->getQualifier().precision);
-
         return node;
     } else {
         // setAggregateOperater() calls fold() for constant folding
         TIntermTyped* node = setAggregateOperator(childNode, op, returnType, loc);
 
-        // if not folded, we'll still have an aggregate node to propagate precision with
-        if (node->getAsAggregate()) {
-            TPrecisionQualifier correctPrecision = returnType.getQualifier().precision;
-            if (correctPrecision == EpqNone && profile == EEsProfile) {
-                // find the maximum precision from the arguments, for the built-in's return precision
-                TIntermSequence& sequence = node->getAsAggregate()->getSequence();
-                for (unsigned int arg = 0; arg < sequence.size(); ++arg)
-                    correctPrecision = std::max(correctPrecision, sequence[arg]->getAsTyped()->getQualifier().precision);
-            }
-
-            // Propagate precision through this node and its children. That algorithm stops
-            // when a precision is found, so start by clearing this subroot precision
-            node->getQualifier().precision = EpqNone;
-            node->propagatePrecision(correctPrecision);
-        }
-
         return node;
     }
 }
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 2ef0286..398de1b 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -1078,17 +1078,16 @@
 {
     TIntermTyped* result = nullptr;
 
-    TOperator op = function->getBuiltInOp();
-    if (op == EOpArrayLength)
+    if (function->getBuiltInOp() == EOpArrayLength)
         result = handleLengthMethod(loc, function, arguments);
-    else if (op != EOpNull) {
+    else if (function->getBuiltInOp() != EOpNull) {
         //
         // Then this should be a constructor.
         // Don't go through the symbol table for constructors.
         // Their parameters will be verified algorithmically.
         //
         TType type(EbtVoid);  // use this to get the type back
-        if (! constructorError(loc, arguments, *function, op, type)) {
+        if (! constructorError(loc, arguments, *function, function->getBuiltInOp(), type)) {
             //
             // It's a constructor, of type 'type'.
             //
@@ -1149,18 +1148,9 @@
                 addInputArgumentConversions(*fnCandidate, arguments);  // arguments may be modified if it's just a single argument node
             }
 
-            op = fnCandidate->getBuiltInOp();
-            if (builtIn && op != EOpNull) {
+            if (builtIn && fnCandidate->getBuiltInOp() != EOpNull) {
                 // A function call mapped to a built-in operation.
-                checkLocation(loc, op);
-                result = intermediate.addBuiltInFunctionCall(loc, op, fnCandidate->getParamCount() == 1, arguments, fnCandidate->getType());
-                if (result == nullptr)  {
-                    error(arguments->getLoc(), " wrong operand type", "Internal Error",
-                                               "built in unary operator function.  Type: %s",
-                                               static_cast<TIntermTyped*>(arguments)->getCompleteString().c_str());
-                } else if (result->getAsOperator()) {
-                    builtInOpCheck(loc, *fnCandidate, *result->getAsOperator());
-                }
+                result = handleBuiltInFunctionCall(loc, *arguments, *fnCandidate);
             } else {
                 // This is a function call not mapped to built-in operator.
                 // It could still be a built-in function, but only if PureOperatorBuiltins == false.
@@ -1207,6 +1197,118 @@
     return result;
 }
 
+TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNode& arguments,
+                                                       const TFunction& function)
+{
+    checkLocation(loc, function.getBuiltInOp());
+    TIntermTyped *result = intermediate.addBuiltInFunctionCall(loc, function.getBuiltInOp(),
+                                                               function.getParamCount() == 1,
+                                                               &arguments, function.getType());
+    computeBuiltinPrecisions(*result, function);
+    if (result == nullptr)  {
+        error(arguments.getLoc(), " wrong operand type", "Internal Error",
+                                  "built in unary operator function.  Type: %s",
+                                  static_cast<TIntermTyped*>(&arguments)->getCompleteString().c_str());
+    } else if (result->getAsOperator())
+        builtInOpCheck(loc, function, *result->getAsOperator());
+
+    return result;
+}
+
+// "The operation of a built-in function can have a different precision
+// qualification than the precision qualification of the resulting value.
+// These two precision qualifications are established as follows.
+//
+// The precision qualification of the operation of a built-in function is
+// based on the precision qualification of its input arguments and formal
+// parameters:  When a formal parameter specifies a precision qualifier,
+// that is used, otherwise, the precision qualification of the calling
+// argument is used.  The highest precision of these will be the precision
+// qualification of the operation of the built-in function. Generally,
+// this is applied across all arguments to a built-in function, with the
+// exceptions being:
+//   - bitfieldExtract and bitfieldInsert ignore the 'offset' and 'bits'
+//     arguments.
+//   - interpolateAt* functions only look at the 'interpolant' argument.
+//
+// The precision qualification of the result of a built-in function is
+// determined in one of the following ways:
+//
+//   - For the texture sampling, image load, and image store functions,
+//     the precision of the return type matches the precision of the
+//     sampler type
+//
+//   Otherwise:
+//
+//   - For prototypes that do not specify a resulting precision qualifier,
+//     the precision will be the same as the precision of the operation.
+//
+//   - For prototypes that do specify a resulting precision qualifier,
+//     the specified precision qualifier is the precision qualification of
+//     the result."
+//
+void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction& function)
+{
+    TPrecisionQualifier operationPrecision = EpqNone;
+    TPrecisionQualifier resultPrecision = EpqNone;
+
+    if (profile != EEsProfile)
+        return;
+
+    TIntermOperator* opNode = node.getAsOperator();
+    if (opNode == nullptr)
+        return;
+
+    if (TIntermUnary* unaryNode = node.getAsUnaryNode()) {
+        operationPrecision = std::max(function[0].type->getQualifier().precision,
+                                      unaryNode->getOperand()->getType().getQualifier().precision);
+        if (function.getType().getBasicType() != EbtBool)
+            resultPrecision = function.getType().getQualifier().precision == EpqNone ? 
+                                        operationPrecision :
+                                        function.getType().getQualifier().precision;
+    } else if (TIntermAggregate* agg = node.getAsAggregate()) {
+        TIntermSequence& sequence = agg->getSequence();
+        int numArgs = (int)sequence.size();
+        switch (agg->getOp()) {
+        case EOpBitfieldExtract:
+            numArgs = 1;
+            break;
+        case EOpBitfieldInsert:
+            numArgs = 2;
+            break;
+        case EOpInterpolateAtCentroid:
+        case EOpInterpolateAtOffset:
+        case EOpInterpolateAtSample:
+            numArgs = 1;
+            break;
+        default:
+            break;
+        }
+        // find the maximum precision from the arguments and parameters
+        for (unsigned int arg = 0; arg < sequence.size(); ++arg) {
+            operationPrecision = std::max(operationPrecision, sequence[arg]->getAsTyped()->getQualifier().precision);
+            operationPrecision = std::max(operationPrecision, function[arg].type->getQualifier().precision);
+        }
+        // compute the result precision
+        if (agg->isSampling() || agg->getOp() == EOpImageLoad || agg->getOp() == EOpImageStore)
+            resultPrecision = sequence[0]->getAsTyped()->getQualifier().precision;
+        else if (function.getType().getBasicType() != EbtBool)
+            resultPrecision = function.getType().getQualifier().precision == EpqNone ? 
+                                        operationPrecision :
+                                        function.getType().getQualifier().precision;
+    }
+
+    // Propagate precision through this node and its children. That algorithm stops
+    // when a precision is found, so start by clearing this subroot precision
+    opNode->getQualifier().precision = EpqNone;
+    if (operationPrecision != EpqNone) {
+        opNode->propagatePrecision(operationPrecision);
+        opNode->setOperationPrecision(operationPrecision);
+    }
+    // Now, set the result precision, which might not match
+    opNode->getQualifier().precision = resultPrecision;
+}
+
 TIntermNode* TParseContext::handleReturnValue(const TSourceLoc& loc, TIntermTyped* value)
 {
     functionReturnsValue = true;
@@ -1433,11 +1535,6 @@
     }
     const TIntermSequence& aggArgs = *argp;  // only valid when unaryArg is nullptr
 
-    // built-in texturing functions get their return value precision from the precision of the sampler
-    if (fnCandidate.getType().getQualifier().precision == EpqNone &&
-        fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler)
-        callNode.getQualifier().precision = arg0->getQualifier().precision;
-
     switch (callNode.getOp()) {
     case EOpTextureGather:
     case EOpTextureGatherOffset:
@@ -1569,11 +1666,6 @@
     case EOpInterpolateAtCentroid:
     case EOpInterpolateAtSample:
     case EOpInterpolateAtOffset:
-        // "For the interpolateAt* functions, the call will return a precision
-        // qualification matching the precision of the 'interpolant' argument to
-        // the function call."
-        callNode.getQualifier().precision = arg0->getQualifier().precision;
-
         // Make sure the first argument is an interpolant, or an array element of an interpolant
         if (arg0->getType().getQualifier().storage != EvqVaryingIn) {
             // It might still be an array element.
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index a5e6f65..544c3d3 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -197,6 +197,8 @@
     TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
     TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
     TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
+    TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode& arguments, const TFunction& function);
+    void computeBuiltinPrecisions(TIntermTyped&, const TFunction&);
     TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
     void checkLocation(const TSourceLoc&, TOperator);
     TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index 1f6c4a9..fcbe12c 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -634,7 +634,7 @@
             if (fields.num == 1) {
                 TIntermTyped* index = intermediate.addConstantUnion(fields.offsets[0], loc);
                 result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
-                result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision));
+                result->setType(TType(base->getBasicType(), EvqTemporary));
             } else {
                 TString vectorString = field;
                 TIntermTyped* index = intermediate.addSwizzle(fields, loc);
@@ -1953,11 +1953,6 @@
     }
     const TIntermSequence& aggArgs = *argp;  // only valid when unaryArg is nullptr
 
-    // built-in texturing functions get their return value precision from the precision of the sampler
-    if (fnCandidate.getType().getQualifier().precision == EpqNone &&
-        fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler)
-        callNode.getQualifier().precision = arg0->getQualifier().precision;
-
     switch (callNode.getOp()) {
     case EOpTextureGather:
     case EOpTextureGatherOffset:
@@ -2060,11 +2055,6 @@
     case EOpInterpolateAtCentroid:
     case EOpInterpolateAtSample:
     case EOpInterpolateAtOffset:
-        // "For the interpolateAt* functions, the call will return a precision
-        // qualification matching the precision of the 'interpolant' argument to
-        // the function call."
-        callNode.getQualifier().precision = arg0->getQualifier().precision;
-
         // Make sure the first argument is an interpolant, or an array element of an interpolant
         if (arg0->getType().getQualifier().storage != EvqVaryingIn) {
             // It might still be an array element.
@@ -2580,10 +2570,6 @@
     else if (src.storage != EvqTemporary && src.storage != EvqGlobal)
         error(loc, "too many storage qualifiers", GetStorageQualifierString(src.storage), "");
 
-    // Precision qualifiers
-    if (dst.precision == EpqNone || (force && src.precision != EpqNone))
-        dst.precision = src.precision;
-
     // Layout qualifiers
     mergeObjectLayoutQualifiers(dst, src, false);