tint: Show the source of non-uniformity

Show the original source of non-uniformity when producing errors from
the uniformity analysis.

Bug: tint:880
Change-Id: Id386ae8fa5ff1b1443d54c0b5ef12ab76b3b3f13
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/89723
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/resolver/uniformity.cc b/src/tint/resolver/uniformity.cc
index 521fec4..33def3b 100644
--- a/src/tint/resolver/uniformity.cc
+++ b/src/tint/resolver/uniformity.cc
@@ -79,11 +79,23 @@
     std::string tag;
 #endif
 
+    /// Type describes the type of the node, which is used to determine additional diagnostic
+    /// information.
+    enum Type {
+        kRegular,
+        kFunctionCallArgument,
+        kFunctionCallPointerArgumentResult,
+        kFunctionCallReturnValue,
+    };
+
+    /// The type of the node.
+    Type type = kRegular;
+
     /// The corresponding AST node, or nullptr.
     const ast::Node* ast = nullptr;
 
-    /// The function call argument index, or UINT32_MAX.
-    uint32_t arg_index = std::numeric_limits<uint32_t>::max();
+    /// The function call argument index, if applicable.
+    uint32_t arg_index;
 
     /// The set of edges from this node to other nodes in the graph.
     utils::UniqueVector<Node*> edges;
@@ -895,6 +907,7 @@
 
         auto name = builder_->Symbols().NameFor(ident->symbol);
         auto* sem = sem_.Get<sem::VariableUser>(ident)->Variable();
+        auto* node = CreateNode(name + "_ident_expr", ident);
         return Switch(
             sem,
 
@@ -910,38 +923,39 @@
                                 uniform = false;
                             }
                         }
-                        return std::make_pair(cf,
-                                              uniform ? cf : current_function_->may_be_non_uniform);
+                        node->AddEdge(uniform ? cf : current_function_->may_be_non_uniform);
+                        return std::make_pair(cf, node);
                     } else {
                         if (has_nonuniform_entry_point_attribute(param->Declaration())) {
-                            return std::make_pair(cf, current_function_->may_be_non_uniform);
+                            node->AddEdge(current_function_->may_be_non_uniform);
+                        } else {
+                            node->AddEdge(cf);
                         }
-                        return std::make_pair(cf, cf);
+                        return std::make_pair(cf, node);
                     }
                 } else {
-                    auto* result = CreateNode(name + "_result");
                     auto* x = current_function_->variables.Get(param);
-                    result->AddEdge(cf);
-                    result->AddEdge(x);
-                    return std::make_pair(cf, result);
+                    node->AddEdge(cf);
+                    node->AddEdge(x);
+                    return std::make_pair(cf, node);
                 }
             },
 
             [&](const sem::GlobalVariable* global) {
                 if (global->Declaration()->is_const || global->Access() == ast::Access::kRead) {
-                    return std::make_pair(cf, cf);
+                    node->AddEdge(cf);
                 } else {
-                    return std::make_pair(cf, current_function_->may_be_non_uniform);
+                    node->AddEdge(current_function_->may_be_non_uniform);
                 }
+                return std::make_pair(cf, node);
             },
 
             [&](const sem::LocalVariable* local) {
-                auto* result = CreateNode(name + "_result");
-                result->AddEdge(cf);
+                node->AddEdge(cf);
                 if (auto* x = current_function_->variables.Get(local)) {
-                    result->AddEdge(x);
+                    node->AddEdge(x);
                 }
-                return std::make_pair(cf, result);
+                return std::make_pair(cf, node);
             },
 
             [&](Default) {
@@ -1110,6 +1124,7 @@
             // Note: This is an additional node that isn't described in the specification, for the
             // purpose of providing diagnostic information.
             Node* arg_node = CreateNode(name + "_arg_" + std::to_string(i), call);
+            arg_node->type = Node::kFunctionCallArgument;
             arg_node->arg_index = static_cast<uint32_t>(i);
             arg_node->AddEdge(arg_i);
 
@@ -1117,7 +1132,8 @@
             args.push_back(arg_node);
         }
 
-        Node* result = CreateNode("Result_" + name);
+        Node* result = CreateNode(name + "_return_value", call);
+        result->type = Node::kFunctionCallReturnValue;
         Node* cf_after = CreateNode("CF_after_" + name, call);
 
         // Get tags for the callee.
@@ -1200,7 +1216,9 @@
                 auto* sem_arg = sem_.Get(call->args[i]);
                 if (sem_arg->Type()->Is<sem::Pointer>()) {
                     auto* ptr_result =
-                        CreateNode(name + "_ptrarg_" + std::to_string(i) + "_result");
+                        CreateNode(name + "_ptrarg_" + std::to_string(i) + "_result", call);
+                    ptr_result->type = Node::kFunctionCallPointerArgumentResult;
+                    ptr_result->arg_index = static_cast<uint32_t>(i);
                     if (func_info->parameters[i].pointer_may_become_non_uniform) {
                         ptr_result->AddEdge(current_function_->may_be_non_uniform);
                     } else {
@@ -1259,7 +1277,7 @@
             // function and look for one whose node has an edge from the RequiredToBeUniform node.
             auto& target_info = functions_.at(user->Declaration());
             for (auto* call_node : target_info.required_to_be_uniform->edges) {
-                if (call_node->arg_index == std::numeric_limits<uint32_t>::max()) {
+                if (call_node->type == Node::kRegular) {
                     auto* child_call = call_node->ast->As<ast::CallExpression>();
                     return FindBuiltinThatRequiresUniformity(child_call);
                 }
@@ -1315,7 +1333,7 @@
             func_name = builder_->Symbols().NameFor(user->Declaration()->symbol);
         }
 
-        if (cause->arg_index != std::numeric_limits<uint32_t>::max()) {
+        if (cause->type == Node::kFunctionCallArgument) {
             // The requirement was on a function parameter.
             auto param_name = builder_->Symbols().NameFor(
                 target->Parameters()[cause->arg_index]->Declaration()->symbol);
@@ -1353,7 +1371,91 @@
                                       innermost_call->source);
             }
         }
-        // TODO(jrprice): Show the source of non-uniformity.
+
+        // Show the source of non-uniformity.
+        if (!note) {
+            // Traverse the graph to generate a path from RequiredToBeUniform to MayBeNonUniform.
+            function.ResetVisited();
+            Traverse(function.required_to_be_uniform);
+
+            // Get the source of the non-uniform value.
+            auto* non_uniform_source = function.may_be_non_uniform->visited_from;
+            TINT_ASSERT(Resolver, non_uniform_source);
+
+            // TODO(jrprice): Show where the non-uniform value results in non-uniform control flow.
+
+            Switch(
+                non_uniform_source->ast,
+                [&](const ast::IdentifierExpression* ident) {
+                    std::string var_type = "";
+                    auto* var = sem_.Get<sem::VariableUser>(ident)->Variable();
+                    switch (var->StorageClass()) {
+                        case ast::StorageClass::kStorage:
+                            var_type = "read_write storage buffer ";
+                            break;
+                        case ast::StorageClass::kWorkgroup:
+                            var_type = "workgroup storage variable ";
+                            break;
+                        case ast::StorageClass::kPrivate:
+                            var_type = "module-scope private variable ";
+                            break;
+                        default:
+                            if (ast::HasAttribute<ast::BuiltinAttribute>(
+                                    var->Declaration()->attributes)) {
+                                var_type = "builtin ";
+                            } else if (ast::HasAttribute<ast::LocationAttribute>(
+                                           var->Declaration()->attributes)) {
+                                var_type = "user-defined input ";
+                            } else {
+                                // TODO(jrprice): Provide more info for this case.
+                            }
+                            break;
+                    }
+                    diagnostics_.add_note(diag::System::Resolver,
+                                          "reading from " + var_type + "'" +
+                                              builder_->Symbols().NameFor(ident->symbol) +
+                                              "' may result in a non-uniform value",
+                                          ident->source);
+                },
+                [&](const ast::CallExpression* c) {
+                    auto target_name = builder_->Symbols().NameFor(
+                        c->target.name->As<ast::IdentifierExpression>()->symbol);
+                    switch (non_uniform_source->type) {
+                        case Node::kRegular: {
+                            diagnostics_.add_note(
+                                diag::System::Resolver,
+                                "calling '" + target_name +
+                                    "' may cause subsequent control flow to be non-uniform",
+                                c->source);
+                            // TODO(jrprice): Descend into the function and show the reason why.
+                            break;
+                        }
+                        case Node::kFunctionCallReturnValue: {
+                            diagnostics_.add_note(
+                                diag::System::Resolver,
+                                "return value of '" + target_name + "' may be non-uniform",
+                                c->source);
+                            break;
+                        }
+                        case Node::kFunctionCallPointerArgumentResult: {
+                            diagnostics_.add_note(
+                                diag::System::Resolver,
+                                "pointer contents may become non-uniform after calling '" +
+                                    target_name + "'",
+                                c->args[non_uniform_source->arg_index]->source);
+                            break;
+                        }
+                        default: {
+                            TINT_ICE(Resolver, diagnostics_)
+                                << "unhandled source of non-uniformity";
+                            break;
+                        }
+                    }
+                },
+                [&](Default) {
+                    TINT_ICE(Resolver, diagnostics_) << "unhandled source of non-uniformity";
+                });
+        }
     }
 };
 
diff --git a/src/tint/resolver/uniformity_test.cc b/src/tint/resolver/uniformity_test.cc
index d81d7d6..d298ec0 100644
--- a/src/tint/resolver/uniformity_test.cc
+++ b/src/tint/resolver/uniformity_test.cc
@@ -394,6 +394,10 @@
               R"(test:17:3 warning: 'workgroupBarrier' must only be called from uniform control flow
   workgroupBarrier();
   ^^^^^^^^^^^^^^^^
+
+test:16:3 note: calling 'foo' may cause subsequent control flow to be non-uniform
+  foo();
+  ^^^
 )");
 }
 
@@ -470,6 +474,10 @@
 test:6:5 note: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:11:7 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  foo(rw);
+      ^^
 )");
 }
 
@@ -515,6 +523,10 @@
               R"(test:10:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:9:11 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  if (foo(rw) == 7) {
+          ^^
 )");
 }
 
@@ -572,6 +584,10 @@
               R"(test:17:3 warning: 'workgroupBarrier' must only be called from uniform control flow
   workgroupBarrier();
   ^^^^^^^^^^^^^^^^
+
+test:16:7 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  foo(rw);
+      ^^
 )");
 }
 
@@ -607,6 +623,10 @@
             R"(test:5:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:4:16 note: reading from builtin 'b' may result in a non-uniform value
+  if (all(vec3(b) == vec3(0u))) {
+               ^
 )");
     }
 }
@@ -634,6 +654,10 @@
             R"(test:9:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:8:16 note: reading from 's' may result in a non-uniform value
+  if (all(vec3(s.b) == vec3(0u))) {
+               ^
 )");
     }
 }
@@ -671,6 +695,10 @@
               R"(test:10:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:9:7 note: reading from 's' may result in a non-uniform value
+  if (s.num_groups.x == 0u) {
+      ^
 )");
 }
 
@@ -694,6 +722,10 @@
                   R"(test:5:5 warning: 'dpdx' must only be called from uniform control flow
     dpdx(0.5);
     ^^^^
+
+test:4:16 note: reading from builtin 'b' may result in a non-uniform value
+  if (u32(vec4(b).x) == 0u) {
+               ^
 )");
     }
 }
@@ -720,6 +752,10 @@
                   R"(test:9:5 warning: 'dpdx' must only be called from uniform control flow
     dpdx(0.5);
     ^^^^
+
+test:8:16 note: reading from 's' may result in a non-uniform value
+  if (u32(vec4(s.b).x) == 0u) {
+               ^
 )");
     }
 }
@@ -749,6 +785,10 @@
               R"(test:5:5 warning: 'dpdx' must only be called from uniform control flow
     dpdx(0.5);
     ^^^^
+
+test:4:7 note: reading from user-defined input 'l' may result in a non-uniform value
+  if (l == 0.0) {
+      ^
 )");
 }
 
@@ -771,6 +811,10 @@
               R"(test:9:5 warning: 'dpdx' must only be called from uniform control flow
     dpdx(0.5);
     ^^^^
+
+test:8:7 note: reading from 's' may result in a non-uniform value
+  if (s.l == 0.0) {
+      ^
 )");
 }
 
@@ -873,12 +917,14 @@
 
     if (condition == kNonUniform) {
         RunTest(src, false);
-        EXPECT_EQ(
+        EXPECT_THAT(
             error_,
-            R"(test:13:5 warning: 'workgroupBarrier' must only be called from uniform control flow
-    workgroupBarrier();
-    ^^^^^^^^^^^^^^^^
-)");
+            ::testing::StartsWith(
+                R"(test:13:5 warning: 'workgroupBarrier' must only be called from uniform control flow
+    workgroupBarrier();)"));
+        EXPECT_THAT(error_,
+                    ::testing::HasSubstr("test:14:9 note: reading from read_write storage buffer "
+                                         "'nonuniform_var' may result in a non-uniform value"));
     } else {
         RunTest(src, true);
     }
@@ -910,12 +956,15 @@
 
     if (condition == kNonUniform) {
         RunTest(src, false);
-        EXPECT_EQ(
+
+        EXPECT_THAT(
             error_,
-            R"(test:14:5 warning: 'workgroupBarrier' must only be called from uniform control flow
-    workgroupBarrier();
-    ^^^^^^^^^^^^^^^^
-)");
+            ::testing::StartsWith(
+                R"(test:14:5 warning: 'workgroupBarrier' must only be called from uniform control flow
+    workgroupBarrier();)"));
+        EXPECT_THAT(error_,
+                    ::testing::HasSubstr("test:13:9 note: reading from read_write storage buffer "
+                                         "'nonuniform_var' may result in a non-uniform value"));
     } else {
         RunTest(src, true);
     }
@@ -949,12 +998,14 @@
 
     if (condition == kNonUniform) {
         RunTest(src, false);
-        EXPECT_EQ(
+        EXPECT_THAT(
             error_,
-            R"(test:15:7 warning: 'workgroupBarrier' must only be called from uniform control flow
-      workgroupBarrier();
-      ^^^^^^^^^^^^^^^^
-)");
+            ::testing::StartsWith(
+                R"(test:15:7 warning: 'workgroupBarrier' must only be called from uniform control flow
+      workgroupBarrier();)"));
+        EXPECT_THAT(error_,
+                    ::testing::HasSubstr("test:13:9 note: reading from read_write storage buffer "
+                                         "'nonuniform_var' may result in a non-uniform value"));
     } else {
         RunTest(src, true);
     }
@@ -1004,6 +1055,10 @@
               R"(test:7:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:10:16 note: reading from read_write storage buffer 'n' may result in a non-uniform value
+      if (i == n) {
+               ^
 )");
 }
 
@@ -1051,6 +1106,10 @@
               R"(test:8:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:10:16 note: reading from read_write storage buffer 'n' may result in a non-uniform value
+      if (i == n) {
+               ^
 )");
 }
 
@@ -1113,6 +1172,10 @@
               R"(test:8:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:12:9 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+    v = non_uniform;
+        ^^^^^^^^^^^
 )");
 }
 
@@ -1189,6 +1252,10 @@
               R"(test:14:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:8:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+      v = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -1219,6 +1286,10 @@
               R"(test:15:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:8:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+      v = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -1254,6 +1325,10 @@
               R"(test:20:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:11:9 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+    v = non_uniform;
+        ^^^^^^^^^^^
 )");
 }
 
@@ -1320,6 +1395,10 @@
               R"(test:20:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:7:9 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+    v = non_uniform;
+        ^^^^^^^^^^^
 )");
 }
 
@@ -1353,6 +1432,10 @@
               R"(test:8:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:12:9 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+    v = non_uniform;
+        ^^^^^^^^^^^
 )");
 }
 
@@ -1391,6 +1474,10 @@
               R"(test:16:9 warning: 'workgroupBarrier' must only be called from uniform control flow
         workgroupBarrier();
         ^^^^^^^^^^^^^^^^
+
+test:7:9 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+    v = non_uniform;
+        ^^^^^^^^^^^
 )");
 }
 
@@ -1424,6 +1511,10 @@
               R"(test:8:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:12:9 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+    v = non_uniform;
+        ^^^^^^^^^^^
 )");
 }
 
@@ -1457,6 +1548,10 @@
               R"(test:8:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:14:13 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+        v = non_uniform;
+            ^^^^^^^^^^^
 )");
 }
 
@@ -1585,6 +1680,10 @@
               R"(test:15:3 warning: 'workgroupBarrier' must only be called from uniform control flow
   workgroupBarrier();
   ^^^^^^^^^^^^^^^^
+
+test:12:5 note: calling 'bar' may cause subsequent control flow to be non-uniform
+    bar();
+    ^^^
 )");
 }
 
@@ -1618,6 +1717,10 @@
               R"(test:6:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:23 note: reading from read_write storage buffer 'n' may result in a non-uniform value
+  for (var i = 0; i < n; i = i + 1) {
+                      ^
 )");
 }
 
@@ -1645,6 +1748,10 @@
               R"(test:14:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:13:16 note: calling 'bar' may cause subsequent control flow to be non-uniform
+  for (var i = bar(); i < 10; i = i + 1) {
+               ^^^
 )");
 }
 
@@ -1672,6 +1779,10 @@
               R"(test:14:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:13:35 note: calling 'bar' may cause subsequent control flow to be non-uniform
+  for (var i = 0; i < 10; i = i + bar()) {
+                                  ^^^
 )");
 }
 
@@ -1697,6 +1808,10 @@
               R"(test:8:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:6:31 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  for (var i = 0; i < 10; v = non_uniform) {
+                              ^^^^^^^^^^^
 )");
 }
 
@@ -1744,6 +1859,10 @@
               R"(test:10:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:31 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  for (var i = 0; i < 10; v = non_uniform) {
+                              ^^^^^^^^^^^
 )");
 }
 
@@ -1791,6 +1910,10 @@
               R"(test:8:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:12:9 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+    v = non_uniform;
+        ^^^^^^^^^^^
 )");
 }
 
@@ -1844,6 +1967,10 @@
               R"(test:15:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:8:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+      v = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -1881,6 +2008,10 @@
               R"(test:21:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:12:9 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+    v = non_uniform;
+        ^^^^^^^^^^^
 )");
 }
 
@@ -1915,6 +2046,10 @@
               R"(test:8:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:12:9 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+    v = non_uniform;
+        ^^^^^^^^^^^
 )");
 }
 
@@ -1948,6 +2083,10 @@
               R"(test:8:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:12:9 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+    v = non_uniform;
+        ^^^^^^^^^^^
 )");
 }
 
@@ -2033,6 +2172,10 @@
               R"(test:6:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:7 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  if (non_uniform == 42) {
+      ^^^^^^^^^^^
 )");
 }
 
@@ -2053,6 +2196,10 @@
               R"(test:7:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:7 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  if (non_uniform == 42) {
+      ^^^^^^^^^^^
 )");
 }
 
@@ -2074,6 +2221,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:7:8 note: reading from read_write storage buffer 'non_uniform_global' may result in a non-uniform value
+  if ((non_uniform_global == 42) && false) {
+       ^^^^^^^^^^^^^^^^^^
 )");
 }
 
@@ -2095,6 +2246,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:7:17 note: reading from read_write storage buffer 'non_uniform_global' may result in a non-uniform value
+  if (false && (non_uniform_global == 42)) {
+                ^^^^^^^^^^^^^^^^^^
 )");
 }
 
@@ -2116,6 +2271,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:7:8 note: reading from read_write storage buffer 'non_uniform_global' may result in a non-uniform value
+  if ((non_uniform_global == 42) || true) {
+       ^^^^^^^^^^^^^^^^^^
 )");
 }
 
@@ -2137,6 +2296,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:7:16 note: reading from read_write storage buffer 'non_uniform_global' may result in a non-uniform value
+  if (true || (non_uniform_global == 42)) {
+               ^^^^^^^^^^^^^^^^^^
 )");
 }
 
@@ -2157,6 +2320,10 @@
               R"(test:7:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:7 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  if (non_uniform == 42) {
+      ^^^^^^^^^^^
 )");
 }
 
@@ -2180,6 +2347,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:7 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  v = rw;
+      ^^
 )");
 }
 
@@ -2249,6 +2420,10 @@
               R"(test:15:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:8:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+      v = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -2324,6 +2499,10 @@
               R"(test:12:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:7 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  v = non_uniform;
+      ^^^^^^^^^^^
 )");
 }
 
@@ -2353,6 +2532,10 @@
               R"(test:13:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:7 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  v = non_uniform;
+      ^^^^^^^^^^^
 )");
 }
 
@@ -2502,6 +2685,10 @@
               R"(test:9:3 warning: 'workgroupBarrier' must only be called from uniform control flow
   workgroupBarrier();
   ^^^^^^^^^^^^^^^^
+
+test:5:7 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  if (non_uniform == 42) {
+      ^^^^^^^^^^^
 )");
 }
 
@@ -2524,6 +2711,10 @@
               R"(test:9:3 warning: 'workgroupBarrier' must only be called from uniform control flow
   workgroupBarrier();
   ^^^^^^^^^^^^^^^^
+
+test:5:7 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  if (non_uniform == 42) {
+      ^^^^^^^^^^^
 )");
 }
 
@@ -2553,6 +2744,10 @@
               R"(test:7:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:5:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  switch (non_uniform) {
+          ^^^^^^^^^^^
 )");
 }
 
@@ -2575,6 +2770,10 @@
               R"(test:7:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:5:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  switch (non_uniform) {
+          ^^^^^^^^^^^
 )");
 }
 
@@ -2602,6 +2801,10 @@
               R"(test:11:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:8:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+      if (non_uniform == 42) {
+          ^^^^^^^^^^^
 )");
 }
 
@@ -2656,6 +2859,10 @@
               R"(test:14:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:8:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+      if (non_uniform == 42) {
+          ^^^^^^^^^^^
 )");
 }
 
@@ -2713,6 +2920,10 @@
               R"(test:14:9 warning: 'workgroupBarrier' must only be called from uniform control flow
         workgroupBarrier();
         ^^^^^^^^^^^^^^^^
+
+test:9:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+      x = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -2744,6 +2955,10 @@
               R"(test:14:9 warning: 'workgroupBarrier' must only be called from uniform control flow
         workgroupBarrier();
         ^^^^^^^^^^^^^^^^
+
+test:6:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var x = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -2802,6 +3017,10 @@
               R"(test:19:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:9:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+      x = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -2860,6 +3079,10 @@
               R"(test:18:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var x = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -2921,6 +3144,10 @@
               R"(test:21:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var x = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -2955,6 +3182,10 @@
               R"(test:9:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:15:13 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+        x = non_uniform;
+            ^^^^^^^^^^^
 )");
 }
 
@@ -3085,6 +3316,10 @@
               R"(test:17:3 warning: 'workgroupBarrier' must only be called from uniform control flow
   workgroupBarrier();
   ^^^^^^^^^^^^^^^^
+
+test:13:7 note: calling 'bar' may cause subsequent control flow to be non-uniform
+      bar();
+      ^^^
 )");
 }
 
@@ -3110,6 +3345,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:9 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  *&v = non_uniform;
+        ^^^^^^^^^^^
 )");
 }
 
@@ -3132,6 +3371,10 @@
               R"(test:9:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:7:9 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  *pv = non_uniform;
+        ^^^^^^^^^^^
 )");
 }
 
@@ -3189,6 +3432,10 @@
               R"(test:11:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:7:7 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  if (non_uniform == 0) {
+      ^^^^^^^^^^^
 )");
 }
 
@@ -3209,6 +3456,10 @@
               R"(test:7:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var v = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -3230,6 +3481,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var v = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -3258,6 +3513,10 @@
 test:6:5 note: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:11:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var v = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -3324,6 +3583,10 @@
               R"(test:9:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:7:7 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  v = non_uniform;
+      ^^^^^^^^^^^
 )");
 }
 
@@ -3364,6 +3627,10 @@
               R"(test:10:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:8:14 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  *&*&*pv2 = non_uniform;
+             ^^^^^^^^^^^
 )");
 }
 
@@ -3386,6 +3653,10 @@
               R"(test:9:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var v = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -3410,6 +3681,10 @@
               R"(test:11:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:9:10 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  *pv2 = non_uniform;
+         ^^^^^^^^^^^
 )");
 }
 
@@ -3453,6 +3728,10 @@
               R"(test:11:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:8:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var v = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -3495,6 +3774,10 @@
               R"(test:12:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:10:7 note: pointer contents may become non-uniform after calling 'bar'
+  bar(&v);
+      ^
 )");
 }
 
@@ -3540,6 +3823,10 @@
               R"(test:12:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:10:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  bar(&v, non_uniform);
+          ^^^^^^^^^^^
 )");
 }
 
@@ -3566,6 +3853,10 @@
               R"(test:13:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:10:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var a = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -3641,6 +3932,10 @@
               R"(test:21:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:18:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var a = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -3727,6 +4022,10 @@
               R"(test:18:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:16:7 note: pointer contents may become non-uniform after calling 'bar'
+  bar(&v);
+      ^
 )");
 }
 
@@ -3756,6 +4055,10 @@
               R"(test:16:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:14:7 note: pointer contents may become non-uniform after calling 'bar'
+  bar(&v);
+      ^
 )");
 }
 
@@ -3785,6 +4088,10 @@
               R"(test:16:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:14:7 note: pointer contents may become non-uniform after calling 'bar'
+  bar(&v);
+      ^
 )");
 }
 
@@ -3822,6 +4129,10 @@
               R"(test:24:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:22:7 note: pointer contents may become non-uniform after calling 'bar'
+  bar(&v);
+      ^
 )");
 }
 
@@ -3853,6 +4164,10 @@
               R"(test:18:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:16:7 note: pointer contents may become non-uniform after calling 'bar'
+  bar(&v);
+      ^
 )");
 }
 
@@ -3881,6 +4196,10 @@
               R"(test:7:7 warning: 'workgroupBarrier' must only be called from uniform control flow
       workgroupBarrier();
       ^^^^^^^^^^^^^^^^
+
+test:12:12 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+      *p = non_uniform;
+           ^^^^^^^^^^^
 )");
 }
 
@@ -3909,6 +4228,10 @@
               R"(test:15:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:12:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var v = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -3936,6 +4259,10 @@
               R"(test:14:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:10:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var a = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -3985,6 +4312,10 @@
               R"(test:14:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:12:11 note: pointer contents may become non-uniform after calling 'bar'
+  bar(&a, &b);
+          ^
 )");
 }
 
@@ -4032,6 +4363,10 @@
               R"(test:12:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:9:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var v = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -4062,6 +4397,10 @@
               R"(test:14:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:12:11 note: pointer contents may become non-uniform after calling 'bar'
+  bar(&a, &b);
+          ^
 )");
 }
 
@@ -4094,6 +4433,10 @@
               R"(test:16:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:11:11 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  var a = non_uniform;
+          ^^^^^^^^^^^
 )");
 }
 
@@ -4155,7 +4498,8 @@
     // TODO(jrprice): Expect false when uniformity issues become errors.
     EXPECT_TRUE(RunTest(std::move(b))) << error_;
     EXPECT_EQ(error_,
-              R"(warning: 'workgroupBarrier' must only be called from uniform control flow)");
+              R"(warning: 'workgroupBarrier' must only be called from uniform control flow
+note: reading from module-scope private variable 'non_uniform_global' may result in a non-uniform value)");
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -4192,6 +4536,10 @@
               R"(test:6:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:7 note: reading from read_write storage buffer 'v' may result in a non-uniform value
+  if (v[2] == 0) {
+      ^
 )");
 }
 
@@ -4213,6 +4561,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:10 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  v[2] = rw;
+         ^^
 )");
 }
 
@@ -4250,6 +4602,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:10 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  v[1] = rw;
+         ^^
 )");
 }
 
@@ -4275,6 +4631,10 @@
               R"(test:9:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:10 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  v[1] = rw;
+         ^^
 )");
 }
 
@@ -4300,6 +4660,10 @@
               R"(test:9:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:10 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  v[1] = rw;
+         ^^
 )");
 }
 
@@ -4321,6 +4685,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:10 note: reading from read_write storage buffer 'non_uniform_global' may result in a non-uniform value
+  v[1] = non_uniform_global;
+         ^^^^^^^^^^^^^^^^^^
 )");
 }
 
@@ -4362,6 +4730,10 @@
               R"(test:10:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:9:7 note: reading from read_write storage buffer 's' may result in a non-uniform value
+  if (s.b == 0) {
+      ^
 )");
 }
 
@@ -4387,6 +4759,10 @@
               R"(test:12:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:10:9 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  s.b = rw;
+        ^^
 )");
 }
 
@@ -4432,6 +4808,10 @@
               R"(test:12:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:10:9 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  s.a = rw;
+        ^^
 )");
 }
 
@@ -4461,6 +4841,10 @@
               R"(test:13:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:10:9 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  s.a = rw;
+        ^^
 )");
 }
 
@@ -4490,6 +4874,10 @@
               R"(test:13:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:10:9 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  s.a = rw;
+        ^^
 )");
 }
 
@@ -4523,6 +4911,10 @@
               R"(test:6:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:7 note: reading from read_write storage buffer 'arr' may result in a non-uniform value
+  if (arr[7] == 0) {
+      ^^^
 )");
 }
 
@@ -4544,6 +4936,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:12 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  arr[2] = rw;
+           ^^
 )");
 }
 
@@ -4581,6 +4977,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:12 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  arr[1] = rw;
+           ^^
 )");
 }
 
@@ -4603,6 +5003,10 @@
               R"(test:9:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:7:9 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  *pa = rw;
+        ^^
 )");
 }
 
@@ -4628,6 +5032,10 @@
               R"(test:9:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:12 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  arr[1] = rw;
+           ^^
 )");
 }
 
@@ -4653,6 +5061,10 @@
               R"(test:9:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:12 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  arr[1] = rw;
+           ^^
 )");
 }
 
@@ -4679,6 +5091,10 @@
               R"(test:10:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:7:12 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  arr[1] = rw;
+           ^^
 )");
 }
 
@@ -4702,6 +5118,10 @@
               R"(test:6:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:11 note: reading from read_write storage buffer 'non_uniform_global' may result in a non-uniform value
+  if (i32(non_uniform_global) == 0) {
+          ^^^^^^^^^^^^^^^^^^
 )");
 }
 
@@ -4721,6 +5141,10 @@
               R"(test:6:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:11 note: reading from read_write storage buffer 'non_uniform_global' may result in a non-uniform value
+  if (f32(non_uniform_global) == 0.0) {
+          ^^^^^^^^^^^^^^^^^^
 )");
 }
 
@@ -4740,6 +5164,10 @@
               R"(test:6:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:20 note: reading from read_write storage buffer 'non_uniform_global' may result in a non-uniform value
+  if (bitcast<f32>(non_uniform_global) == 0.0) {
+                   ^^^^^^^^^^^^^^^^^^
 )");
 }
 
@@ -4762,6 +5190,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:6:8 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  v += rw;
+       ^^
 )");
 }
 
@@ -4784,6 +5216,10 @@
               R"(test:8:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:11 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+  var v = rw;
+          ^^
 )");
 }
 
@@ -4810,6 +5246,10 @@
               R"(test:14:3 warning: 'workgroupBarrier' must only be called from uniform control flow
   workgroupBarrier();
   ^^^^^^^^^^^^^^^^
+
+test:13:7 note: calling 'bar' may cause subsequent control flow to be non-uniform
+  _ = bar();
+      ^^^
 )");
 }
 
@@ -4830,6 +5270,10 @@
               R"(test:8:3 warning: 'workgroupBarrier' must only be called from uniform control flow
   workgroupBarrier();
   ^^^^^^^^^^^^^^^^
+
+test:7:12 note: reading from read_write storage buffer 'non_uniform_global' may result in a non-uniform value
+  let b = (non_uniform_global == 42) && false;
+           ^^^^^^^^^^^^^^^^^^
 )");
 }
 
@@ -4895,6 +5339,10 @@
               R"(test:6:5 warning: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:5:18 note: reading from workgroup storage variable 'a' may result in a non-uniform value
+  if (atomicAdd(&a, 1) == 1) {
+                 ^
 )");
 }
 
@@ -4914,6 +5362,10 @@
               R"(test:6:5 warning: 'storageBarrier' must only be called from uniform control flow
     storageBarrier();
     ^^^^^^^^^^^^^^
+
+test:5:18 note: reading from read_write storage buffer 'a' may result in a non-uniform value
+  if (atomicAdd(&a, 1) == 1) {
+                 ^
 )");
 }
 
@@ -4961,6 +5413,10 @@
 test:5:3 note: 'foo' requires uniformity because it calls workgroupBarrier
   workgroupBarrier();
   ^^^^^^^^^^^^^^^^
+
+test:9:7 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  if (non_uniform == 42) {
+      ^^^^^^^^^^^
 )");
 }
 
@@ -4996,6 +5452,10 @@
 test:5:3 note: 'foo' requires uniformity because it indirectly calls workgroupBarrier
   workgroupBarrier();
   ^^^^^^^^^^^^^^^^
+
+test:17:7 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  if (non_uniform == 42) {
+      ^^^^^^^^^^^
 )");
 }
 
@@ -5039,6 +5499,45 @@
 test:6:5 note: 'workgroupBarrier' must only be called from uniform control flow
     workgroupBarrier();
     ^^^^^^^^^^^^^^^^
+
+test:19:7 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value
+  foo(non_uniform);
+      ^^^^^^^^^^^
+)");
+}
+
+TEST_F(UniformityAnalysisTest, Error_ReturnValueMayBeNonUniformChain) {
+    auto src = R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+
+fn zoo() -> i32 {
+  return non_uniform;
+}
+
+fn bar() -> i32 {
+  return zoo();
+}
+
+fn foo() -> i32 {
+  return bar();
+}
+
+fn main() {
+  if (foo() == 42) {
+    workgroupBarrier();
+  }
+}
+)";
+
+    RunTest(src, false);
+    EXPECT_EQ(error_,
+              R"(test:18:5 warning: 'workgroupBarrier' must only be called from uniform control flow
+    workgroupBarrier();
+    ^^^^^^^^^^^^^^^^
+
+test:17:7 note: return value of 'foo' may be non-uniform
+  if (foo() == 42) {
+      ^^^
 )");
 }
 
diff --git a/test/tint/bug/dawn/947.wgsl.expected.glsl b/test/tint/bug/dawn/947.wgsl.expected.glsl
index 60c1105..554f41d 100644
--- a/test/tint/bug/dawn/947.wgsl.expected.glsl
+++ b/test/tint/bug/dawn/947.wgsl.expected.glsl
@@ -2,6 +2,10 @@
     var srcColor = textureSample(myTexture, mySampler, texcoord);
                    ^^^^^^^^^^^^^
 
+bug/dawn/947.wgsl:54:15 note: reading from user-defined input 'texcoord' may result in a non-uniform value
+        clamp(texcoord, vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 1.0));
+              ^^^^^^^^
+
 #version 310 es
 
 layout(location = 0) out vec2 texcoords_1;
diff --git a/test/tint/bug/dawn/947.wgsl.expected.hlsl b/test/tint/bug/dawn/947.wgsl.expected.hlsl
index 3b13d95..1ab5cd3 100644
--- a/test/tint/bug/dawn/947.wgsl.expected.hlsl
+++ b/test/tint/bug/dawn/947.wgsl.expected.hlsl
@@ -2,6 +2,10 @@
     var srcColor = textureSample(myTexture, mySampler, texcoord);
                    ^^^^^^^^^^^^^
 
+bug/dawn/947.wgsl:54:15 note: reading from user-defined input 'texcoord' may result in a non-uniform value
+        clamp(texcoord, vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 1.0));
+              ^^^^^^^^
+
 cbuffer cbuffer_uniforms : register(b0, space0) {
   uint4 uniforms[1];
 };
diff --git a/test/tint/bug/dawn/947.wgsl.expected.msl b/test/tint/bug/dawn/947.wgsl.expected.msl
index 07a7f73..48e64b1 100644
--- a/test/tint/bug/dawn/947.wgsl.expected.msl
+++ b/test/tint/bug/dawn/947.wgsl.expected.msl
@@ -2,6 +2,10 @@
     var srcColor = textureSample(myTexture, mySampler, texcoord);
                    ^^^^^^^^^^^^^
 
+bug/dawn/947.wgsl:54:15 note: reading from user-defined input 'texcoord' may result in a non-uniform value
+        clamp(texcoord, vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 1.0));
+              ^^^^^^^^
+
 #include <metal_stdlib>
 
 using namespace metal;
diff --git a/test/tint/bug/dawn/947.wgsl.expected.spvasm b/test/tint/bug/dawn/947.wgsl.expected.spvasm
index a74165c..0982f38 100644
--- a/test/tint/bug/dawn/947.wgsl.expected.spvasm
+++ b/test/tint/bug/dawn/947.wgsl.expected.spvasm
@@ -2,6 +2,10 @@
     var srcColor = textureSample(myTexture, mySampler, texcoord);
                    ^^^^^^^^^^^^^
 
+bug/dawn/947.wgsl:54:15 note: reading from user-defined input 'texcoord' may result in a non-uniform value
+        clamp(texcoord, vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 1.0));
+              ^^^^^^^^
+
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
diff --git a/test/tint/bug/dawn/947.wgsl.expected.wgsl b/test/tint/bug/dawn/947.wgsl.expected.wgsl
index 6f98645..722544b 100644
--- a/test/tint/bug/dawn/947.wgsl.expected.wgsl
+++ b/test/tint/bug/dawn/947.wgsl.expected.wgsl
@@ -2,6 +2,10 @@
     var srcColor = textureSample(myTexture, mySampler, texcoord);
                    ^^^^^^^^^^^^^
 
+bug/dawn/947.wgsl:54:15 note: reading from user-defined input 'texcoord' may result in a non-uniform value
+        clamp(texcoord, vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 1.0));
+              ^^^^^^^^
+
 struct Uniforms {
   u_scale : vec2<f32>,
   u_offset : vec2<f32>,
diff --git a/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.glsl b/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.glsl
index 48926b7..7a7cda9 100644
--- a/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.glsl
+++ b/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.glsl
@@ -2,6 +2,10 @@
         let sampleDepth : f32 = textureSample(depthTexture, Sampler, offset.xy).r;
                                 ^^^^^^^^^^^^^
 
+bug/fxc/gradient_in_varying_loop/1112.wgsl:8:29 note: return value of 'textureSample' may be non-uniform
+    let random: vec3<f32> = textureSample(randomTexture, Sampler, vUV).rgb;
+                            ^^^^^^^^^^^^^
+
 #version 310 es
 precision mediump float;
 
diff --git a/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.hlsl b/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.hlsl
index a6c6dd5..91684d2 100644
--- a/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.hlsl
+++ b/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.hlsl
@@ -2,6 +2,10 @@
         let sampleDepth : f32 = textureSample(depthTexture, Sampler, offset.xy).r;
                                 ^^^^^^^^^^^^^
 
+bug/fxc/gradient_in_varying_loop/1112.wgsl:8:29 note: return value of 'textureSample' may be non-uniform
+    let random: vec3<f32> = textureSample(randomTexture, Sampler, vUV).rgb;
+                            ^^^^^^^^^^^^^
+
 SamplerState tint_symbol : register(s0, space0);
 Texture2D<float4> randomTexture : register(t1, space0);
 Texture2D<float4> depthTexture : register(t2, space0);
diff --git a/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.msl b/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.msl
index 62a41ed..9d936ad 100644
--- a/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.msl
+++ b/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.msl
@@ -2,6 +2,10 @@
         let sampleDepth : f32 = textureSample(depthTexture, Sampler, offset.xy).r;
                                 ^^^^^^^^^^^^^
 
+bug/fxc/gradient_in_varying_loop/1112.wgsl:8:29 note: return value of 'textureSample' may be non-uniform
+    let random: vec3<f32> = textureSample(randomTexture, Sampler, vUV).rgb;
+                            ^^^^^^^^^^^^^
+
 #include <metal_stdlib>
 
 using namespace metal;
diff --git a/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.spvasm b/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.spvasm
index 31483ae..8498249 100644
--- a/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.spvasm
+++ b/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.spvasm
@@ -2,6 +2,10 @@
         let sampleDepth : f32 = textureSample(depthTexture, Sampler, offset.xy).r;
                                 ^^^^^^^^^^^^^
 
+bug/fxc/gradient_in_varying_loop/1112.wgsl:8:29 note: return value of 'textureSample' may be non-uniform
+    let random: vec3<f32> = textureSample(randomTexture, Sampler, vUV).rgb;
+                            ^^^^^^^^^^^^^
+
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
diff --git a/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.wgsl b/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.wgsl
index 1761161..751238a 100644
--- a/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.wgsl
+++ b/test/tint/bug/fxc/gradient_in_varying_loop/1112.wgsl.expected.wgsl
@@ -2,6 +2,10 @@
         let sampleDepth : f32 = textureSample(depthTexture, Sampler, offset.xy).r;
                                 ^^^^^^^^^^^^^
 
+bug/fxc/gradient_in_varying_loop/1112.wgsl:8:29 note: return value of 'textureSample' may be non-uniform
+    let random: vec3<f32> = textureSample(randomTexture, Sampler, vUV).rgb;
+                            ^^^^^^^^^^^^^
+
 @group(0) @binding(0) var Sampler : sampler;
 
 @group(0) @binding(1) var randomTexture : texture_2d<f32>;
diff --git a/test/tint/bug/tint/1118.wgsl.expected.glsl b/test/tint/bug/tint/1118.wgsl.expected.glsl
index 39bc459..82784e3 100644
--- a/test/tint/bug/tint/1118.wgsl.expected.glsl
+++ b/test/tint/bug/tint/1118.wgsl.expected.glsl
@@ -2,6 +2,10 @@
   normalW = normalize(-(cross(dpdx(x_62), dpdy(x_64))));
                               ^^^^
 
+bug/tint/1118.wgsl:46:19 note: reading from module-scope private variable 'fClipDistance3' may result in a non-uniform value
+  let x_9 : f32 = fClipDistance3;
+                  ^^^^^^^^^^^^^^
+
 #version 310 es
 precision mediump float;
 
diff --git a/test/tint/bug/tint/1118.wgsl.expected.hlsl b/test/tint/bug/tint/1118.wgsl.expected.hlsl
index 467aea6..e24fb49 100644
--- a/test/tint/bug/tint/1118.wgsl.expected.hlsl
+++ b/test/tint/bug/tint/1118.wgsl.expected.hlsl
@@ -2,6 +2,10 @@
   normalW = normalize(-(cross(dpdx(x_62), dpdy(x_64))));
                               ^^^^
 
+bug/tint/1118.wgsl:46:19 note: reading from module-scope private variable 'fClipDistance3' may result in a non-uniform value
+  let x_9 : f32 = fClipDistance3;
+                  ^^^^^^^^^^^^^^
+
 static float fClipDistance3 = 0.0f;
 static float fClipDistance4 = 0.0f;
 cbuffer cbuffer_x_29 : register(b0, space0) {
diff --git a/test/tint/bug/tint/1118.wgsl.expected.msl b/test/tint/bug/tint/1118.wgsl.expected.msl
index a8d14c5..13b15b3 100644
--- a/test/tint/bug/tint/1118.wgsl.expected.msl
+++ b/test/tint/bug/tint/1118.wgsl.expected.msl
@@ -2,6 +2,10 @@
   normalW = normalize(-(cross(dpdx(x_62), dpdy(x_64))));
                               ^^^^
 
+bug/tint/1118.wgsl:46:19 note: reading from module-scope private variable 'fClipDistance3' may result in a non-uniform value
+  let x_9 : f32 = fClipDistance3;
+                  ^^^^^^^^^^^^^^
+
 #include <metal_stdlib>
 
 using namespace metal;
diff --git a/test/tint/bug/tint/1118.wgsl.expected.spvasm b/test/tint/bug/tint/1118.wgsl.expected.spvasm
index 26653b6..35d97e8 100644
--- a/test/tint/bug/tint/1118.wgsl.expected.spvasm
+++ b/test/tint/bug/tint/1118.wgsl.expected.spvasm
@@ -2,6 +2,10 @@
   normalW = normalize(-(cross(dpdx(x_62), dpdy(x_64))));
                               ^^^^
 
+bug/tint/1118.wgsl:46:19 note: reading from module-scope private variable 'fClipDistance3' may result in a non-uniform value
+  let x_9 : f32 = fClipDistance3;
+                  ^^^^^^^^^^^^^^
+
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
diff --git a/test/tint/bug/tint/1118.wgsl.expected.wgsl b/test/tint/bug/tint/1118.wgsl.expected.wgsl
index d2a3bc3..c2c3289 100644
--- a/test/tint/bug/tint/1118.wgsl.expected.wgsl
+++ b/test/tint/bug/tint/1118.wgsl.expected.wgsl
@@ -2,6 +2,10 @@
   normalW = normalize(-(cross(dpdx(x_62), dpdy(x_64))));
                               ^^^^
 
+bug/tint/1118.wgsl:46:19 note: reading from module-scope private variable 'fClipDistance3' may result in a non-uniform value
+  let x_9 : f32 = fClipDistance3;
+                  ^^^^^^^^^^^^^^
+
 struct Scene {
   vEyePosition : vec4<f32>,
 }
diff --git a/test/tint/bug/tint/943.spvasm.expected.glsl b/test/tint/bug/tint/943.spvasm.expected.glsl
index 7edb269..3f81f5a 100644
--- a/test/tint/bug/tint/943.spvasm.expected.glsl
+++ b/test/tint/bug/tint/943.spvasm.expected.glsl
@@ -1,5 +1,6 @@
 warning: parameter 'dimInner' of 'mm_matMul_i1_i1_i1_' must be uniform
 note: 'workgroupBarrier' must only be called from uniform control flow
+note: reading from module-scope private variable 'dimInner_1' may result in a non-uniform value
 #version 310 es
 
 struct Uniforms {
diff --git a/test/tint/bug/tint/943.spvasm.expected.hlsl b/test/tint/bug/tint/943.spvasm.expected.hlsl
index ece0c20..b3aa90b 100644
--- a/test/tint/bug/tint/943.spvasm.expected.hlsl
+++ b/test/tint/bug/tint/943.spvasm.expected.hlsl
@@ -1,5 +1,6 @@
 warning: parameter 'dimInner' of 'mm_matMul_i1_i1_i1_' must be uniform
 note: 'workgroupBarrier' must only be called from uniform control flow
+note: reading from module-scope private variable 'dimInner_1' may result in a non-uniform value
 static int dimAOuter_1 = 0;
 cbuffer cbuffer_x_48 : register(b3, space0) {
   uint4 x_48[5];
diff --git a/test/tint/bug/tint/943.spvasm.expected.msl b/test/tint/bug/tint/943.spvasm.expected.msl
index 48f3434..63f5ad3 100644
--- a/test/tint/bug/tint/943.spvasm.expected.msl
+++ b/test/tint/bug/tint/943.spvasm.expected.msl
@@ -1,5 +1,6 @@
 warning: parameter 'dimInner' of 'mm_matMul_i1_i1_i1_' must be uniform
 note: 'workgroupBarrier' must only be called from uniform control flow
+note: reading from module-scope private variable 'dimInner_1' may result in a non-uniform value
 #include <metal_stdlib>
 
 using namespace metal;
diff --git a/test/tint/bug/tint/943.spvasm.expected.spvasm b/test/tint/bug/tint/943.spvasm.expected.spvasm
index e9fc8c5..9571912 100644
--- a/test/tint/bug/tint/943.spvasm.expected.spvasm
+++ b/test/tint/bug/tint/943.spvasm.expected.spvasm
@@ -1,5 +1,6 @@
 warning: parameter 'dimInner' of 'mm_matMul_i1_i1_i1_' must be uniform
 note: 'workgroupBarrier' must only be called from uniform control flow
+note: reading from module-scope private variable 'dimInner_1' may result in a non-uniform value
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
diff --git a/test/tint/bug/tint/943.spvasm.expected.wgsl b/test/tint/bug/tint/943.spvasm.expected.wgsl
index 08be16a..f168e2e 100644
--- a/test/tint/bug/tint/943.spvasm.expected.wgsl
+++ b/test/tint/bug/tint/943.spvasm.expected.wgsl
@@ -1,5 +1,6 @@
 warning: parameter 'dimInner' of 'mm_matMul_i1_i1_i1_' must be uniform
 note: 'workgroupBarrier' must only be called from uniform control flow
+note: reading from module-scope private variable 'dimInner_1' may result in a non-uniform value
 struct Uniforms {
   NAN : f32,
   @size(12)
diff --git a/test/tint/bug/tint/948.wgsl.expected.glsl b/test/tint/bug/tint/948.wgsl.expected.glsl
index a675fe9..628473c 100644
--- a/test/tint/bug/tint/948.wgsl.expected.glsl
+++ b/test/tint/bug/tint/948.wgsl.expected.glsl
@@ -2,6 +2,10 @@
         let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
                                 ^^^^^^^^^^^^^^^^^
 
+bug/tint/948.wgsl:146:33 note: return value of 'textureSampleBias' may be non-uniform
+        let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
+                                ^^^^^^^^^^^^^^^^^
+
 #version 310 es
 precision mediump float;
 
diff --git a/test/tint/bug/tint/948.wgsl.expected.hlsl b/test/tint/bug/tint/948.wgsl.expected.hlsl
index 1869503..c866800 100644
--- a/test/tint/bug/tint/948.wgsl.expected.hlsl
+++ b/test/tint/bug/tint/948.wgsl.expected.hlsl
@@ -2,6 +2,10 @@
         let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
                                 ^^^^^^^^^^^^^^^^^
 
+bug/tint/948.wgsl:146:33 note: return value of 'textureSampleBias' may be non-uniform
+        let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
+                                ^^^^^^^^^^^^^^^^^
+
 cbuffer cbuffer_x_20 : register(b9, space2) {
   uint4 x_20[8];
 };
diff --git a/test/tint/bug/tint/948.wgsl.expected.msl b/test/tint/bug/tint/948.wgsl.expected.msl
index f799044..c8cbbb1 100644
--- a/test/tint/bug/tint/948.wgsl.expected.msl
+++ b/test/tint/bug/tint/948.wgsl.expected.msl
@@ -2,6 +2,10 @@
         let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
                                 ^^^^^^^^^^^^^^^^^
 
+bug/tint/948.wgsl:146:33 note: return value of 'textureSampleBias' may be non-uniform
+        let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
+                                ^^^^^^^^^^^^^^^^^
+
 #include <metal_stdlib>
 
 using namespace metal;
diff --git a/test/tint/bug/tint/948.wgsl.expected.spvasm b/test/tint/bug/tint/948.wgsl.expected.spvasm
index 4f5102c..ad59285 100644
--- a/test/tint/bug/tint/948.wgsl.expected.spvasm
+++ b/test/tint/bug/tint/948.wgsl.expected.spvasm
@@ -2,6 +2,10 @@
         let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
                                 ^^^^^^^^^^^^^^^^^
 
+bug/tint/948.wgsl:146:33 note: return value of 'textureSampleBias' may be non-uniform
+        let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
+                                ^^^^^^^^^^^^^^^^^
+
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
diff --git a/test/tint/bug/tint/948.wgsl.expected.wgsl b/test/tint/bug/tint/948.wgsl.expected.wgsl
index 791079b..ee116ab 100644
--- a/test/tint/bug/tint/948.wgsl.expected.wgsl
+++ b/test/tint/bug/tint/948.wgsl.expected.wgsl
@@ -2,6 +2,10 @@
         let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
                                 ^^^^^^^^^^^^^^^^^
 
+bug/tint/948.wgsl:146:33 note: return value of 'textureSampleBias' may be non-uniform
+        let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
+                                ^^^^^^^^^^^^^^^^^
+
 struct LeftOver {
   time : f32,
   @size(12)
diff --git a/test/tint/bug/tint/949.wgsl.expected.glsl b/test/tint/bug/tint/949.wgsl.expected.glsl
index e60090b..3a8e2ec 100644
--- a/test/tint/bug/tint/949.wgsl.expected.glsl
+++ b/test/tint/bug/tint/949.wgsl.expected.glsl
@@ -2,6 +2,10 @@
     let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395));
                             ^^^^^^^^^^^^^
 
+bug/tint/949.wgsl:326:29 note: return value of 'textureSample' may be non-uniform
+    let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395));
+                            ^^^^^^^^^^^^^
+
 #version 310 es
 precision mediump float;
 
diff --git a/test/tint/bug/tint/949.wgsl.expected.hlsl b/test/tint/bug/tint/949.wgsl.expected.hlsl
index 2bdadf0..11c96d9 100644
--- a/test/tint/bug/tint/949.wgsl.expected.hlsl
+++ b/test/tint/bug/tint/949.wgsl.expected.hlsl
@@ -2,6 +2,10 @@
     let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395));
                             ^^^^^^^^^^^^^
 
+bug/tint/949.wgsl:326:29 note: return value of 'textureSample' may be non-uniform
+    let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395));
+                            ^^^^^^^^^^^^^
+
 struct lightingInfo {
   float3 diffuse;
   float3 specular;
diff --git a/test/tint/bug/tint/949.wgsl.expected.msl b/test/tint/bug/tint/949.wgsl.expected.msl
index 0701a4a..505fa31 100644
--- a/test/tint/bug/tint/949.wgsl.expected.msl
+++ b/test/tint/bug/tint/949.wgsl.expected.msl
@@ -2,6 +2,10 @@
     let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395));
                             ^^^^^^^^^^^^^
 
+bug/tint/949.wgsl:326:29 note: return value of 'textureSample' may be non-uniform
+    let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395));
+                            ^^^^^^^^^^^^^
+
 #include <metal_stdlib>
 
 using namespace metal;
diff --git a/test/tint/bug/tint/949.wgsl.expected.spvasm b/test/tint/bug/tint/949.wgsl.expected.spvasm
index 287968a..0b10e58 100644
--- a/test/tint/bug/tint/949.wgsl.expected.spvasm
+++ b/test/tint/bug/tint/949.wgsl.expected.spvasm
@@ -2,6 +2,10 @@
     let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395));
                             ^^^^^^^^^^^^^
 
+bug/tint/949.wgsl:326:29 note: return value of 'textureSample' may be non-uniform
+    let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395));
+                            ^^^^^^^^^^^^^
+
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 0
diff --git a/test/tint/bug/tint/949.wgsl.expected.wgsl b/test/tint/bug/tint/949.wgsl.expected.wgsl
index 48c21aa..4733075 100644
--- a/test/tint/bug/tint/949.wgsl.expected.wgsl
+++ b/test/tint/bug/tint/949.wgsl.expected.wgsl
@@ -2,6 +2,10 @@
     let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395));
                             ^^^^^^^^^^^^^
 
+bug/tint/949.wgsl:326:29 note: return value of 'textureSample' may be non-uniform
+    let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395));
+                            ^^^^^^^^^^^^^
+
 struct lightingInfo {
   diffuse : vec3<f32>,
   specular : vec3<f32>,