tint: Add support for atomic ops to spirv reader
The following operations are supported:
OpAtomicLoad
OpAtomicStore
OpAtomicExchange
OpAtomicCompareExchange
OpAtomicCompareExchangeWeak
OpAtomicIIncrement
OpAtomicIDecrement
OpAtomicIAdd
OpAtomicISub
OpAtomicSMin
OpAtomicUMin
OpAtomicSMax
OpAtomicUMax
OpAtomicAnd
OpAtomicOr
OpAtomicXor
These are not, but may be supported in the future:
OpAtomicFlagTestAndSet
OpAtomicFlagClear
OpAtomicFMinEXT
OpAtomicFMaxEXT
OpAtomicFAddEXT
Bug: tint:1441
Change-Id: Ifd53643b38d43664905a0dddfca609add4914670
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/94121
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index d3303bf..8108e54 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -526,6 +526,8 @@
"transform/simplify_pointers.h",
"transform/single_entry_point.cc",
"transform/single_entry_point.h",
+ "transform/spirv_atomic.cc",
+ "transform/spirv_atomic.h",
"transform/transform.cc",
"transform/transform.h",
"transform/unshadow.cc",
@@ -1190,6 +1192,7 @@
"transform/robustness_test.cc",
"transform/simplify_pointers_test.cc",
"transform/single_entry_point_test.cc",
+ "transform/spirv_atomic_test.cc",
"transform/test_helper.h",
"transform/transform_test.cc",
"transform/unshadow_test.cc",
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index 1ea1a6f..3475b1b 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -450,6 +450,8 @@
transform/simplify_pointers.h
transform/single_entry_point.cc
transform/single_entry_point.h
+ transform/spirv_atomic.cc
+ transform/spirv_atomic.h
transform/transform.cc
transform/transform.h
transform/unshadow.cc
@@ -1114,6 +1116,7 @@
transform/robustness_test.cc
transform/simplify_pointers_test.cc
transform/single_entry_point_test.cc
+ transform/spirv_atomic_test.cc
transform/test_helper.h
transform/unshadow_test.cc
transform/unwind_discard_functions_test.cc
diff --git a/src/tint/reader/spirv/function.cc b/src/tint/reader/spirv/function.cc
index 2a5169b..3b333df 100644
--- a/src/tint/reader/spirv/function.cc
+++ b/src/tint/reader/spirv/function.cc
@@ -36,6 +36,7 @@
#include "src/tint/sem/builtin_type.h"
#include "src/tint/sem/depth_texture.h"
#include "src/tint/sem/sampled_texture.h"
+#include "src/tint/transform/spirv_atomic.h"
// Terms:
// CFG: the control flow graph of the function, where basic blocks are the
@@ -501,6 +502,38 @@
}
// @param opcode a SPIR-V opcode
+// @returns true if the given instruction is an atomic operation.
+bool IsAtomicOp(SpvOp opcode) {
+ switch (opcode) {
+ case SpvOpAtomicLoad:
+ case SpvOpAtomicStore:
+ case SpvOpAtomicExchange:
+ case SpvOpAtomicCompareExchange:
+ case SpvOpAtomicCompareExchangeWeak:
+ case SpvOpAtomicIIncrement:
+ case SpvOpAtomicIDecrement:
+ case SpvOpAtomicIAdd:
+ case SpvOpAtomicISub:
+ case SpvOpAtomicSMin:
+ case SpvOpAtomicUMin:
+ case SpvOpAtomicSMax:
+ case SpvOpAtomicUMax:
+ case SpvOpAtomicAnd:
+ case SpvOpAtomicOr:
+ case SpvOpAtomicXor:
+ case SpvOpAtomicFlagTestAndSet:
+ case SpvOpAtomicFlagClear:
+ case SpvOpAtomicFMinEXT:
+ case SpvOpAtomicFMaxEXT:
+ case SpvOpAtomicFAddEXT:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+// @param opcode a SPIR-V opcode
// @returns true if the given instruction is an image sampling, gather,
// or gather-compare operation.
bool IsImageSamplingOrGatherOrDrefGather(SpvOp opcode) {
@@ -3487,6 +3520,10 @@
return EmitImageAccess(inst);
}
+ if (IsAtomicOp(inst.opcode())) {
+ return EmitAtomicOp(inst);
+ }
+
switch (inst.opcode()) {
case SpvOpNop:
return true;
@@ -5417,6 +5454,115 @@
return Fail() << "unhandled image query: " << inst.PrettyPrint();
}
+bool FunctionEmitter::EmitAtomicOp(const spvtools::opt::Instruction& inst) {
+ auto emit_atomic = [&](sem::BuiltinType builtin, std::initializer_list<TypedExpression> args) {
+ // Split args into params and expressions
+ ast::ParameterList params;
+ params.reserve(args.size());
+ ast::ExpressionList exprs;
+ exprs.reserve(args.size());
+ size_t i = 0;
+ for (auto& a : args) {
+ params.emplace_back(builder_.Param("p" + std::to_string(i++), a.type->Build(builder_)));
+ exprs.emplace_back(a.expr);
+ }
+
+ // Function return type
+ const ast::Type* ret_type = nullptr;
+ if (inst.type_id() != 0) {
+ ret_type = parser_impl_.ConvertType(inst.type_id())->Build(builder_);
+ } else {
+ ret_type = builder_.ty.void_();
+ }
+
+ // Emit stub, will be removed by transform::SpirvAtomic
+ auto sym = builder_.Symbols().New(std::string("stub_") + sem::str(builtin));
+ auto* stub_deco =
+ builder_.ASTNodes().Create<transform::SpirvAtomic::Stub>(builder_.ID(), builtin);
+ auto* stub =
+ create<ast::Function>(Source{}, sym, std::move(params), ret_type,
+ /* body */ nullptr,
+ ast::AttributeList{
+ stub_deco,
+ builder_.Disable(ast::DisabledValidation::kFunctionHasNoBody),
+ },
+ ast::AttributeList{});
+ builder_.AST().AddFunction(stub);
+
+ // Emit call to stub, will be replaced with call to atomic builtin by transform::SpirvAtomic
+ auto* call = builder_.Call(Source{}, sym, exprs);
+ if (inst.type_id() != 0) {
+ auto* result_type = parser_impl_.ConvertType(inst.type_id());
+ TypedExpression expr{result_type, call};
+ return EmitConstDefOrWriteToHoistedVar(inst, expr);
+ }
+ AddStatement(create<ast::CallStatement>(call));
+
+ return true;
+ };
+
+ auto oper = [&](uint32_t index) -> TypedExpression { //
+ return MakeOperand(inst, index);
+ };
+
+ auto lit = [&](int v) -> TypedExpression {
+ auto* result_type = parser_impl_.ConvertType(inst.type_id());
+ if (result_type->Is<I32>()) {
+ return TypedExpression(result_type, builder_.Expr(i32(v)));
+ } else if (result_type->Is<U32>()) {
+ return TypedExpression(result_type, builder_.Expr(u32(v)));
+ }
+ return {};
+ };
+
+ switch (inst.opcode()) {
+ case SpvOpAtomicLoad:
+ return emit_atomic(sem::BuiltinType::kAtomicLoad, {oper(/*ptr*/ 0)});
+ case SpvOpAtomicStore:
+ return emit_atomic(sem::BuiltinType::kAtomicStore,
+ {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ case SpvOpAtomicExchange:
+ return emit_atomic(sem::BuiltinType::kAtomicExchange,
+ {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ case SpvOpAtomicCompareExchange:
+ case SpvOpAtomicCompareExchangeWeak:
+ return emit_atomic(sem::BuiltinType::kAtomicCompareExchangeWeak,
+ {oper(/*ptr*/ 0), /*value*/ oper(5), /*comparator*/ oper(4)});
+ case SpvOpAtomicIIncrement:
+ return emit_atomic(sem::BuiltinType::kAtomicAdd, {oper(/*ptr*/ 0), lit(1)});
+ case SpvOpAtomicIDecrement:
+ return emit_atomic(sem::BuiltinType::kAtomicSub, {oper(/*ptr*/ 0), lit(1)});
+ case SpvOpAtomicIAdd:
+ return emit_atomic(sem::BuiltinType::kAtomicAdd, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ case SpvOpAtomicISub:
+ return emit_atomic(sem::BuiltinType::kAtomicSub, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ case SpvOpAtomicSMin:
+ return emit_atomic(sem::BuiltinType::kAtomicMin, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ case SpvOpAtomicUMin:
+ return emit_atomic(sem::BuiltinType::kAtomicMin, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ case SpvOpAtomicSMax:
+ return emit_atomic(sem::BuiltinType::kAtomicMax, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ case SpvOpAtomicUMax:
+ return emit_atomic(sem::BuiltinType::kAtomicMax, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ case SpvOpAtomicAnd:
+ return emit_atomic(sem::BuiltinType::kAtomicAnd, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ case SpvOpAtomicOr:
+ return emit_atomic(sem::BuiltinType::kAtomicOr, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ case SpvOpAtomicXor:
+ return emit_atomic(sem::BuiltinType::kAtomicXor, {oper(/*ptr*/ 0), oper(/*value*/ 3)});
+ case SpvOpAtomicFlagTestAndSet:
+ case SpvOpAtomicFlagClear:
+ case SpvOpAtomicFMinEXT:
+ case SpvOpAtomicFMaxEXT:
+ case SpvOpAtomicFAddEXT:
+ return Fail() << "unsupported atomic op: " << inst.PrettyPrint();
+
+ default:
+ break;
+ }
+ return Fail() << "unhandled atomic op: " << inst.PrettyPrint();
+}
+
ast::ExpressionList FunctionEmitter::MakeCoordinateOperandsForImageAccess(
const spvtools::opt::Instruction& inst) {
if (!parser_impl_.success()) {
diff --git a/src/tint/reader/spirv/function.h b/src/tint/reader/spirv/function.h
index b1c3f57..ae9ef31 100644
--- a/src/tint/reader/spirv/function.h
+++ b/src/tint/reader/spirv/function.h
@@ -1060,7 +1060,7 @@
/// Emits a texture builtin function call for a SPIR-V instruction that
/// accesses an image or sampled image.
/// @param inst the SPIR-V instruction
- /// @returns an expression
+ /// @returns true on success, false on error
bool EmitImageAccess(const spvtools::opt::Instruction& inst);
/// Emits statements to implement a SPIR-V image query.
@@ -1068,6 +1068,11 @@
/// @returns an expression
bool EmitImageQuery(const spvtools::opt::Instruction& inst);
+ /// Emits statements to implement a SPIR-V atomic op.
+ /// @param inst the SPIR-V instruction
+ /// @returns true on success, false on error
+ bool EmitAtomicOp(const spvtools::opt::Instruction& inst);
+
/// Converts the given texel to match the type required for the storage
/// texture with the given type. In WGSL the texel value is always provided
/// as a 4-element vector, but the component type is determined by the
diff --git a/src/tint/reader/spirv/parser.cc b/src/tint/reader/spirv/parser.cc
index f430d94..ac43b9e 100644
--- a/src/tint/reader/spirv/parser.cc
+++ b/src/tint/reader/spirv/parser.cc
@@ -22,6 +22,7 @@
#include "src/tint/transform/manager.h"
#include "src/tint/transform/remove_unreachable_statements.h"
#include "src/tint/transform/simplify_pointers.h"
+#include "src/tint/transform/spirv_atomic.h"
#include "src/tint/transform/unshadow.h"
namespace tint::reader::spirv {
@@ -55,6 +56,7 @@
manager.Add<transform::DecomposeStridedMatrix>();
manager.Add<transform::DecomposeStridedArray>();
manager.Add<transform::RemoveUnreachableStatements>();
+ manager.Add<transform::SpirvAtomic>();
return manager.Run(&program).program;
}
diff --git a/src/tint/tint.natvis b/src/tint/tint.natvis
index c1fd1f3..bce3ce5 100644
--- a/src/tint/tint.natvis
+++ b/src/tint/tint.natvis
@@ -101,11 +101,7 @@
<DisplayString>{*variable};</DisplayString>
</Type>
- <Type Name="tint::ast::UintLiteralExpression">
- <DisplayString>{value}</DisplayString>
- </Type>
-
- <Type Name="tint::ast::SintLiteralExpression">
+ <Type Name="tint::ast::IntLiteralExpression">
<DisplayString>{value}</DisplayString>
</Type>
diff --git a/src/tint/transform/spirv_atomic.cc b/src/tint/transform/spirv_atomic.cc
new file mode 100644
index 0000000..d820a87
--- /dev/null
+++ b/src/tint/transform/spirv_atomic.cc
@@ -0,0 +1,231 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/transform/spirv_atomic.h"
+
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+#include "src/tint/program_builder.h"
+#include "src/tint/sem/block_statement.h"
+#include "src/tint/sem/function.h"
+#include "src/tint/sem/index_accessor_expression.h"
+#include "src/tint/sem/member_accessor_expression.h"
+#include "src/tint/sem/reference.h"
+#include "src/tint/sem/statement.h"
+#include "src/tint/utils/map.h"
+#include "src/tint/utils/unique_vector.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::transform::SpirvAtomic);
+TINT_INSTANTIATE_TYPEINFO(tint::transform::SpirvAtomic::Stub);
+
+namespace tint::transform {
+
+/// Private implementation of transform
+struct SpirvAtomic::State {
+ private:
+ /// A struct that has been forked because a subset of members were made atomic.
+ struct ForkedStruct {
+ Symbol name;
+ std::unordered_set<size_t> atomic_members;
+ };
+
+ CloneContext& ctx;
+ ProgramBuilder& b = *ctx.dst;
+ std::unordered_map<const ast::Struct*, ForkedStruct> forked_structs;
+ std::unordered_set<const sem::Variable*> atomic_variables;
+ utils::UniqueVector<const sem::Expression*> atomic_expressions;
+
+ public:
+ /// Constructor
+ /// @param c the clone context
+ explicit State(CloneContext& c) : ctx(c) {}
+
+ /// Runs the transform
+ void Run() {
+ // Look for stub functions generated by the SPIR-V reader, which are used as placeholders
+ // for atomic builtin calls.
+ for (auto* fn : ctx.src->AST().Functions()) {
+ if (auto* stub = ast::GetAttribute<Stub>(fn->attributes)) {
+ auto* sem = ctx.src->Sem().Get(fn);
+
+ for (auto* call : sem->CallSites()) {
+ // The first argument is always the atomic.
+ // The stub passes this by value, whereas the builtin wants a pointer.
+ // Take the address of the atomic argument.
+ auto& args = call->Declaration()->args;
+ auto out_args = ctx.Clone(args);
+ out_args[0] = b.AddressOf(out_args[0]);
+
+ // Replace all callsites of this stub to a call to the real builtin
+ if (stub->builtin == sem::BuiltinType::kAtomicCompareExchangeWeak) {
+ // atomicCompareExchangeWeak returns a struct, so insert a call to it above
+ // the current statement, and replace the current call with the struct's
+ // `old_value` member.
+ auto* block = call->Stmt()->Block()->Declaration();
+ auto old_value = b.Symbols().New("old_value");
+ auto old_value_decl = b.Decl(b.Let(
+ old_value, nullptr,
+ b.MemberAccessor(b.Call(sem::str(stub->builtin), std::move(out_args)),
+ b.Expr("old_value"))));
+ ctx.InsertBefore(block->statements, call->Stmt()->Declaration(),
+ old_value_decl);
+ ctx.Replace(call->Declaration(), b.Expr(old_value));
+ } else {
+ ctx.Replace(call->Declaration(),
+ b.Call(sem::str(stub->builtin), std::move(out_args)));
+ }
+
+ // Keep track of this expression. We'll need to modify the source variable /
+ // structure to be atomic.
+ atomic_expressions.add(ctx.src->Sem().Get(args[0]));
+ }
+
+ // Remove the stub from the output program
+ ctx.Remove(ctx.src->AST().GlobalDeclarations(), fn);
+ }
+ }
+
+ // Transform all variables and structure members that were used in atomic operations as
+ // atomic types. This propagates up originating expression chains.
+ ProcessAtomicExpressions();
+
+ // If we need to change structure members, then fork them.
+ if (!forked_structs.empty()) {
+ ctx.ReplaceAll([&](const ast::Struct* str) {
+ // Always emit the original structure. This allows unrelated usage of the structure
+ // to continue working.
+ // auto* original = ctx.CloneWithoutTransform(str);
+
+ // Is `str` a structure we need to fork?
+ if (auto it = forked_structs.find(str); it != forked_structs.end()) {
+ const auto& forked = it->second;
+
+ // Re-create the structure swapping in the atomic-flavoured members
+ std::vector<const ast::StructMember*> members(str->members.size());
+ for (size_t i = 0; i < str->members.size(); i++) {
+ auto* member = str->members[i];
+ if (forked.atomic_members.count(i)) {
+ auto* type = AtomicTypeFor(ctx.src->Sem().Get(member)->Type());
+ auto name = ctx.src->Symbols().NameFor(member->symbol);
+ members[i] = b.Member(name, type, ctx.Clone(member->attributes));
+ } else {
+ members[i] = ctx.Clone(member);
+ }
+ }
+ b.Structure(forked.name, std::move(members));
+ }
+
+ // return original;
+ return nullptr;
+ });
+ }
+
+ ctx.Clone();
+ }
+
+ private:
+ ForkedStruct& Fork(const ast::Struct* str) {
+ auto& forked = forked_structs[str];
+ if (!forked.name.IsValid()) {
+ forked.name = b.Symbols().New(ctx.src->Symbols().NameFor(str->name) + "_atomic");
+ }
+ return forked;
+ }
+
+ void ProcessAtomicExpressions() {
+ for (size_t i = 0; i < atomic_expressions.size(); i++) {
+ Switch(
+ atomic_expressions[i], //
+ [&](const sem::VariableUser* user) {
+ auto* v = user->Variable()->Declaration();
+ if (v->type && atomic_variables.emplace(user->Variable()).second) {
+ ctx.Replace(v->type, AtomicTypeFor(user->Variable()->Type()));
+ }
+ if (auto* ctor = user->Variable()->Constructor()) {
+ atomic_expressions.add(ctor);
+ }
+ },
+ [&](const sem::StructMemberAccess* access) {
+ // Fork the struct (the first time) and mark member(s) that need to be made
+ // atomic.
+ auto* member = access->Member();
+ Fork(member->Struct()->Declaration()).atomic_members.emplace(member->Index());
+ atomic_expressions.add(access->Object());
+ },
+ [&](const sem::IndexAccessorExpression* index) {
+ atomic_expressions.add(index->Object());
+ },
+ [&](const sem::Expression* e) {
+ if (auto* unary = e->Declaration()->As<ast::UnaryOpExpression>()) {
+ atomic_expressions.add(ctx.src->Sem().Get(unary->expr));
+ }
+ });
+ }
+ }
+
+ const ast::Type* AtomicTypeFor(const sem::Type* ty) {
+ return Switch(
+ ty, //
+ [&](const sem::I32*) { return b.ty.atomic(CreateASTTypeFor(ctx, ty)); },
+ [&](const sem::U32*) { return b.ty.atomic(CreateASTTypeFor(ctx, ty)); },
+ [&](const sem::Struct* str) { return b.ty.type_name(Fork(str->Declaration()).name); },
+ [&](const sem::Array* arr) {
+ return arr->IsRuntimeSized()
+ ? b.ty.array(AtomicTypeFor(arr->ElemType()))
+ : b.ty.array(AtomicTypeFor(arr->ElemType()), u32(arr->Count()));
+ },
+ [&](const sem::Pointer* ptr) {
+ return b.ty.pointer(AtomicTypeFor(ptr->StoreType()), ptr->StorageClass(),
+ ptr->Access());
+ },
+ [&](const sem::Reference* ref) { return AtomicTypeFor(ref->StoreType()); },
+ [&](Default) {
+ TINT_ICE(Transform, b.Diagnostics())
+ << "unhandled type: " << ty->FriendlyName(ctx.src->Symbols());
+ return nullptr;
+ });
+ }
+};
+
+SpirvAtomic::SpirvAtomic() = default;
+SpirvAtomic::~SpirvAtomic() = default;
+
+SpirvAtomic::Stub::Stub(ProgramID pid, sem::BuiltinType b) : Base(pid), builtin(b) {}
+SpirvAtomic::Stub::~Stub() = default;
+std::string SpirvAtomic::Stub::InternalName() const {
+ return "@internal(spirv-atomic " + std::string(sem::str(builtin)) + ")";
+}
+
+const SpirvAtomic::Stub* SpirvAtomic::Stub::Clone(CloneContext* ctx) const {
+ return ctx->dst->ASTNodes().Create<SpirvAtomic::Stub>(ctx->dst->ID(), builtin);
+}
+
+bool SpirvAtomic::ShouldRun(const Program* program, const DataMap&) const {
+ for (auto* fn : program->AST().Functions()) {
+ if (ast::HasAttribute<Stub>(fn->attributes)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void SpirvAtomic::Run(CloneContext& ctx, const DataMap&, DataMap&) const {
+ State{ctx}.Run();
+}
+
+} // namespace tint::transform
diff --git a/src/tint/transform/spirv_atomic.h b/src/tint/transform/spirv_atomic.h
new file mode 100644
index 0000000..36ac842
--- /dev/null
+++ b/src/tint/transform/spirv_atomic.h
@@ -0,0 +1,84 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_TRANSFORM_SPIRV_ATOMIC_H_
+#define SRC_TINT_TRANSFORM_SPIRV_ATOMIC_H_
+
+#include <string>
+
+#include "src/tint/ast/internal_attribute.h"
+#include "src/tint/sem/builtin_type.h"
+#include "src/tint/transform/transform.h"
+
+// Forward declarations
+namespace tint {
+class CloneContext;
+} // namespace tint
+
+namespace tint::transform {
+
+/// SpirvAtomic is a transform that replaces calls to stub functions created by the SPIR-V reader
+/// with calls to the WGSL atomic builtin. It also makes sure to replace variable declarations that
+/// are the target of the atomic operations with an atomic declaration of the same type. For
+/// structs, it creates a copy of the original struct with atomic members.
+class SpirvAtomic final : public Castable<SpirvAtomic, Transform> {
+ public:
+ /// Constructor
+ SpirvAtomic();
+ /// Destructor
+ ~SpirvAtomic() override;
+
+ /// Stub is an attribute applied to stub SPIR-V reader generated functions that need to be
+ /// translated to an atomic builtin.
+ class Stub final : public Castable<Stub, ast::InternalAttribute> {
+ public:
+ /// @param program_id the identifier of the program that owns this node
+ /// @param builtin the atomic builtin this stub represents
+ Stub(ProgramID program_id, sem::BuiltinType builtin);
+ /// Destructor
+ ~Stub() override;
+
+ /// @return a short description of the internal attribute which will be
+ /// displayed as `@internal(<name>)`
+ std::string InternalName() const override;
+
+ /// Performs a deep clone of this object using the CloneContext `ctx`.
+ /// @param ctx the clone context
+ /// @return the newly cloned object
+ const Stub* Clone(CloneContext* ctx) const override;
+
+ /// The type of the intrinsic
+ const sem::BuiltinType builtin;
+ };
+
+ /// @param program the program to inspect
+ /// @param data optional extra transform-specific input data
+ /// @returns true if this transform should be run for the given program
+ bool ShouldRun(const Program* program, const DataMap& data = {}) const override;
+
+ protected:
+ struct State;
+
+ /// Runs the transform using the CloneContext built for transforming a
+ /// program. Run() is responsible for calling Clone() on the CloneContext.
+ /// @param ctx the CloneContext primed with the input program and
+ /// ProgramBuilder
+ /// @param inputs optional extra transform-specific input data
+ /// @param outputs optional extra transform-specific output data
+ void Run(CloneContext& ctx, const DataMap& inputs, DataMap& outputs) const override;
+};
+
+} // namespace tint::transform
+
+#endif // SRC_TINT_TRANSFORM_SPIRV_ATOMIC_H_
diff --git a/src/tint/transform/spirv_atomic_test.cc b/src/tint/transform/spirv_atomic_test.cc
new file mode 100644
index 0000000..804193e
--- /dev/null
+++ b/src/tint/transform/spirv_atomic_test.cc
@@ -0,0 +1,1022 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/transform/spirv_atomic.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "src/tint/reader/wgsl/parser_impl.h"
+#include "src/tint/transform/test_helper.h"
+
+using namespace tint::number_suffixes; // NOLINT
+
+namespace tint::transform {
+namespace {
+
+class SpirvAtomicTest : public TransformTest {
+ public:
+ Output Run(std::string in) {
+ auto file = std::make_unique<Source::File>("test", std::move(in));
+ auto parser = reader::wgsl::ParserImpl(file.get());
+ parser.Parse();
+
+ auto& b = parser.builder();
+
+ sem::BuiltinType two_params[] = {
+ sem::BuiltinType::kAtomicExchange, sem::BuiltinType::kAtomicAdd,
+ sem::BuiltinType::kAtomicSub, sem::BuiltinType::kAtomicMin,
+ sem::BuiltinType::kAtomicMax, sem::BuiltinType::kAtomicAnd,
+ sem::BuiltinType::kAtomicOr, sem::BuiltinType::kAtomicXor,
+ };
+ for (auto& a : two_params) {
+ b.Func(std::string{"stub_"} + sem::str(a) + "_u32",
+ {
+ b.Param("p0", b.ty.u32()),
+ b.Param("p1", b.ty.u32()),
+ },
+ b.ty.u32(), {b.Return(0_u)},
+ {b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), a)});
+ b.Func(std::string{"stub_"} + sem::str(a) + "_i32",
+ {
+ b.Param("p0", b.ty.i32()),
+ b.Param("p1", b.ty.i32()),
+ },
+ b.ty.i32(), {b.Return(0_i)},
+ {b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), a)});
+ }
+
+ b.Func("stub_atomicLoad_u32",
+ {
+ b.Param("p0", b.ty.u32()),
+ },
+ b.ty.u32(), {b.Return(0_u)},
+ {
+ b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), sem::BuiltinType::kAtomicLoad),
+ });
+ b.Func("stub_atomicLoad_i32",
+ {
+ b.Param("p0", b.ty.i32()),
+ },
+ b.ty.i32(), {b.Return(0_i)},
+ {
+ b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), sem::BuiltinType::kAtomicLoad),
+ });
+
+ b.Func("stub_atomicStore_u32",
+ {
+ b.Param("p0", b.ty.u32()),
+ b.Param("p1", b.ty.u32()),
+ },
+ b.ty.void_(), {},
+ {
+ b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), sem::BuiltinType::kAtomicStore),
+ });
+ b.Func("stub_atomicStore_i32",
+ {
+ b.Param("p0", b.ty.i32()),
+ b.Param("p1", b.ty.i32()),
+ },
+ b.ty.void_(), {},
+ {
+ b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), sem::BuiltinType::kAtomicStore),
+ });
+
+ b.Func("stub_atomic_compare_exchange_weak_u32",
+ {
+ b.Param("p0", b.ty.u32()),
+ b.Param("p1", b.ty.u32()),
+ b.Param("p2", b.ty.u32()),
+ },
+ b.ty.u32(), {b.Return(0_u)},
+ {
+ b.ASTNodes().Create<SpirvAtomic::Stub>(
+ b.ID(), sem::BuiltinType::kAtomicCompareExchangeWeak),
+ });
+ b.Func("stub_atomic_compare_exchange_weak_i32",
+ {b.Param("p0", b.ty.i32()), b.Param("p1", b.ty.i32()), b.Param("p2", b.ty.i32())},
+ b.ty.i32(), {b.Return(0_i)},
+ {
+ b.ASTNodes().Create<SpirvAtomic::Stub>(
+ b.ID(), sem::BuiltinType::kAtomicCompareExchangeWeak),
+ });
+
+ // Keep this pointer alive after Transform() returns
+ files_.emplace_back(std::move(file));
+
+ return TransformTest::Run<SpirvAtomic>(Program(std::move(b)));
+ }
+
+ private:
+ std::vector<std::unique_ptr<Source::File>> files_;
+};
+
+TEST_F(SpirvAtomicTest, ArrayOfU32) {
+ auto* src = R"(
+var<workgroup> wg : array<u32, 4>;
+
+fn f() {
+ stub_atomicStore_u32(wg[1], 1u);
+}
+)";
+
+ auto* expect = R"(
+var<workgroup> wg : array<atomic<u32>, 4u>;
+
+fn f() {
+ atomicStore(&(wg[1]), 1u);
+}
+)";
+
+ auto got = Run(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, ArraysOfU32) {
+ auto* src = R"(
+var<workgroup> wg : array<array<array<u32, 1>, 2>, 3>;
+
+fn f() {
+ stub_atomicStore_u32(wg[2][1][0], 1u);
+}
+)";
+
+ auto* expect = R"(
+var<workgroup> wg : array<array<array<atomic<u32>, 1u>, 2u>, 3u>;
+
+fn f() {
+ atomicStore(&(wg[2][1][0]), 1u);
+}
+)";
+
+ auto got = Run(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, AliasedArraysOfU32) {
+ auto* src = R"(
+type A0 = u32;
+
+type A1 = array<A0, 1>;
+
+type A2 = array<A1, 2>;
+
+type A3 = array<A2, 3>;
+
+var<workgroup> wg : A3;
+
+fn f() {
+ stub_atomicStore_u32(wg[2][1][0], 1u);
+}
+)";
+
+ auto* expect = R"(
+type A0 = u32;
+
+type A1 = array<A0, 1>;
+
+type A2 = array<A1, 2>;
+
+type A3 = array<A2, 3>;
+
+var<workgroup> wg : array<array<array<atomic<u32>, 1u>, 2u>, 3u>;
+
+fn f() {
+ atomicStore(&(wg[2][1][0]), 1u);
+}
+)";
+
+ auto got = Run(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, FlatStructSingleAtomic) {
+ auto* src = R"(
+struct S {
+ a : u32,
+}
+
+var<workgroup> wg : S;
+
+fn f() {
+ stub_atomicStore_u32(wg.a, 1u);
+}
+)";
+
+ auto* expect = R"(
+struct S_atomic {
+ a : atomic<u32>,
+}
+
+struct S {
+ a : u32,
+}
+
+var<workgroup> wg : S_atomic;
+
+fn f() {
+ atomicStore(&(wg.a), 1u);
+}
+)";
+
+ auto got = Run(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, FlatStructMultipleAtomic) {
+ auto* src = R"(
+struct S {
+ a : u32,
+ b : i32,
+}
+
+var<workgroup> wg : S;
+
+fn f1() {
+ stub_atomicStore_u32(wg.a, 1u);
+}
+
+fn f2() {
+ stub_atomicStore_i32(wg.b, 2i);
+}
+)";
+
+ auto* expect = R"(
+struct S_atomic {
+ a : atomic<u32>,
+ b : atomic<i32>,
+}
+
+struct S {
+ a : u32,
+ b : i32,
+}
+
+var<workgroup> wg : S_atomic;
+
+fn f1() {
+ atomicStore(&(wg.a), 1u);
+}
+
+fn f2() {
+ atomicStore(&(wg.b), 2i);
+}
+)";
+
+ auto got = Run(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, NestedStruct) {
+ auto* src = R"(
+struct S0 {
+ a : u32,
+ b : i32,
+ c : u32,
+}
+
+struct S1 {
+ a : i32,
+ b : u32,
+ c : S0,
+}
+
+struct S2 {
+ a : i32,
+ b : S1,
+ c : u32,
+}
+
+var<workgroup> wg : S2;
+
+fn f() {
+ stub_atomicStore_u32(wg.b.c.a, 1u);
+}
+)";
+
+ auto* expect = R"(
+struct S0_atomic {
+ a : atomic<u32>,
+ b : i32,
+ c : u32,
+}
+
+struct S0 {
+ a : u32,
+ b : i32,
+ c : u32,
+}
+
+struct S1_atomic {
+ a : i32,
+ b : u32,
+ c : S0_atomic,
+}
+
+struct S1 {
+ a : i32,
+ b : u32,
+ c : S0,
+}
+
+struct S2_atomic {
+ a : i32,
+ b : S1_atomic,
+ c : u32,
+}
+
+struct S2 {
+ a : i32,
+ b : S1,
+ c : u32,
+}
+
+var<workgroup> wg : S2_atomic;
+
+fn f() {
+ atomicStore(&(wg.b.c.a), 1u);
+}
+)";
+
+ auto got = Run(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, ArrayOfStruct) {
+ auto* src = R"(
+struct S {
+ a : u32,
+ b : i32,
+ c : u32,
+}
+
+@group(0) @binding(1) var<storage, read_write> arr : array<S>;
+
+fn f() {
+ stub_atomicStore_i32(arr[4].b, 1i);
+}
+)";
+
+ auto* expect = R"(
+struct S_atomic {
+ a : u32,
+ b : atomic<i32>,
+ c : u32,
+}
+
+struct S {
+ a : u32,
+ b : i32,
+ c : u32,
+}
+
+@group(0) @binding(1) var<storage, read_write> arr : array<S_atomic>;
+
+fn f() {
+ atomicStore(&(arr[4].b), 1i);
+}
+)";
+
+ auto got = Run(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, StructOfArray) {
+ auto* src = R"(
+struct S {
+ a : array<i32>,
+}
+
+@group(0) @binding(1) var<storage, read_write> s : S;
+
+fn f() {
+ stub_atomicStore_i32(s.a[4], 1i);
+}
+)";
+
+ auto* expect = R"(
+struct S_atomic {
+ a : array<atomic<i32>>,
+}
+
+struct S {
+ a : array<i32>,
+}
+
+@group(0) @binding(1) var<storage, read_write> s : S_atomic;
+
+fn f() {
+ atomicStore(&(s.a[4]), 1i);
+}
+)";
+
+ auto got = Run(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, ViaPtrLet) {
+ auto* src = R"(
+struct S {
+ i : i32,
+}
+
+@group(0) @binding(1) var<storage, read_write> s : S;
+
+fn f() {
+ let p0 = &(s);
+ let p1 : ptr<storage, i32, read_write> = &((*(p0)).i);
+ stub_atomicStore_i32(*p1, 1i);
+}
+)";
+
+ auto* expect =
+ R"(
+struct S_atomic {
+ i : atomic<i32>,
+}
+
+struct S {
+ i : i32,
+}
+
+@group(0) @binding(1) var<storage, read_write> s : S_atomic;
+
+fn f() {
+ let p0 = &(s);
+ let p1 : ptr<storage, atomic<i32>, read_write> = &((*(p0)).i);
+ atomicStore(&(*(p1)), 1i);
+}
+)";
+
+ auto got = Run(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, StructIsolatedMixedUsage) {
+ auto* src = R"(
+struct S {
+ i : i32,
+}
+
+@group(0) @binding(1) var<storage, read_write> s : S;
+
+fn f() {
+ stub_atomicStore_i32(s.i, 1i);
+}
+
+fn another_usage() {
+ var s : S;
+ let x : i32 = s.i;
+ s.i = 3i;
+}
+)";
+
+ auto* expect =
+ R"(
+struct S_atomic {
+ i : atomic<i32>,
+}
+
+struct S {
+ i : i32,
+}
+
+@group(0) @binding(1) var<storage, read_write> s : S_atomic;
+
+fn f() {
+ atomicStore(&(s.i), 1i);
+}
+
+fn another_usage() {
+ var s : S;
+ let x : i32 = s.i;
+ s.i = 3i;
+}
+)";
+
+ auto got = Run(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+// This sort of mixed usage isn't handled yet. Not sure if we need to just yet.
+// If we don't, then the transform should give sensible diagnostics instead of producing invalid
+// WGSL.
+// TODO(crbug.com/tint/1595)
+TEST_F(SpirvAtomicTest, DISABLED_StructComplexMixedUsage) {
+ auto* src = R"(
+struct S {
+ i : i32,
+}
+
+@group(0) @binding(1) var<storage, read_write> s : S;
+
+fn f() {
+ let x : i32 = s.i;
+ stub_atomicStore_i32(s.i, 1i);
+ s.i = 3i;
+}
+)";
+
+ auto* expect =
+ R"(
+struct S_atomic {
+ i : atomic<i32>,
+}
+
+struct S {
+ i : i32,
+}
+
+@group(0) @binding(1) var<storage, read_write> s : S_atomic;
+
+fn f() {
+ let x : i32 = atomicLoad(&s.i);
+ stub_atomicStore_i32(s.i, 1i);
+ atomicStore(&(s.i), 1i);
+}
+)";
+
+ auto got = Run(src);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, AtomicLoad) {
+ auto* src = R"(
+var<workgroup> wg_u32 : u32;
+var<workgroup> wg_i32 : i32;
+@group(0) @binding(0) var<storage, read_write> sg_u32 : u32;
+@group(0) @binding(1) var<storage, read_write> sg_i32 : i32;
+
+fn f() {
+ {let r = stub_atomicLoad_u32(wg_u32);}
+ {let r = stub_atomicLoad_i32(wg_i32);}
+ {let r = stub_atomicLoad_u32(sg_u32);}
+ {let r = stub_atomicLoad_i32(sg_i32);}
+}
+)";
+
+ auto* expect =
+ R"(
+var<workgroup> wg_u32 : atomic<u32>;
+
+var<workgroup> wg_i32 : atomic<i32>;
+
+@group(0) @binding(0) var<storage, read_write> sg_u32 : atomic<u32>;
+
+@group(0) @binding(1) var<storage, read_write> sg_i32 : atomic<i32>;
+
+fn f() {
+ {
+ let r = atomicLoad(&(wg_u32));
+ }
+ {
+ let r = atomicLoad(&(wg_i32));
+ }
+ {
+ let r = atomicLoad(&(sg_u32));
+ }
+ {
+ let r = atomicLoad(&(sg_i32));
+ }
+}
+)";
+
+ auto got = Run(src);
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, AtomicExchange) {
+ auto* src = R"(
+var<workgroup> wg_u32 : u32;
+var<workgroup> wg_i32 : i32;
+@group(0) @binding(0) var<storage, read_write> sg_u32 : u32;
+@group(0) @binding(1) var<storage, read_write> sg_i32 : i32;
+
+fn f() {
+ {let r = stub_atomicExchange_u32(wg_u32, 123u);}
+ {let r = stub_atomicExchange_i32(wg_i32, 123i);}
+ {let r = stub_atomicExchange_u32(sg_u32, 123u);}
+ {let r = stub_atomicExchange_i32(sg_i32, 123i);}
+}
+)";
+
+ auto* expect =
+ R"(
+var<workgroup> wg_u32 : atomic<u32>;
+
+var<workgroup> wg_i32 : atomic<i32>;
+
+@group(0) @binding(0) var<storage, read_write> sg_u32 : atomic<u32>;
+
+@group(0) @binding(1) var<storage, read_write> sg_i32 : atomic<i32>;
+
+fn f() {
+ {
+ let r = atomicExchange(&(wg_u32), 123u);
+ }
+ {
+ let r = atomicExchange(&(wg_i32), 123i);
+ }
+ {
+ let r = atomicExchange(&(sg_u32), 123u);
+ }
+ {
+ let r = atomicExchange(&(sg_i32), 123i);
+ }
+}
+)";
+
+ auto got = Run(src);
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, AtomicAdd) {
+ auto* src = R"(
+var<workgroup> wg_u32 : u32;
+var<workgroup> wg_i32 : i32;
+@group(0) @binding(0) var<storage, read_write> sg_u32 : u32;
+@group(0) @binding(1) var<storage, read_write> sg_i32 : i32;
+
+fn f() {
+ {let r = stub_atomicAdd_u32(wg_u32, 123u);}
+ {let r = stub_atomicAdd_i32(wg_i32, 123i);}
+ {let r = stub_atomicAdd_u32(sg_u32, 123u);}
+ {let r = stub_atomicAdd_i32(sg_i32, 123i);}
+}
+)";
+
+ auto* expect =
+ R"(
+var<workgroup> wg_u32 : atomic<u32>;
+
+var<workgroup> wg_i32 : atomic<i32>;
+
+@group(0) @binding(0) var<storage, read_write> sg_u32 : atomic<u32>;
+
+@group(0) @binding(1) var<storage, read_write> sg_i32 : atomic<i32>;
+
+fn f() {
+ {
+ let r = atomicAdd(&(wg_u32), 123u);
+ }
+ {
+ let r = atomicAdd(&(wg_i32), 123i);
+ }
+ {
+ let r = atomicAdd(&(sg_u32), 123u);
+ }
+ {
+ let r = atomicAdd(&(sg_i32), 123i);
+ }
+}
+)";
+
+ auto got = Run(src);
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, AtomicSub) {
+ auto* src = R"(
+var<workgroup> wg_u32 : u32;
+var<workgroup> wg_i32 : i32;
+@group(0) @binding(0) var<storage, read_write> sg_u32 : u32;
+@group(0) @binding(1) var<storage, read_write> sg_i32 : i32;
+
+fn f() {
+ {let r = stub_atomicSub_u32(wg_u32, 123u);}
+ {let r = stub_atomicSub_i32(wg_i32, 123i);}
+ {let r = stub_atomicSub_u32(sg_u32, 123u);}
+ {let r = stub_atomicSub_i32(sg_i32, 123i);}
+}
+)";
+
+ auto* expect =
+ R"(
+var<workgroup> wg_u32 : atomic<u32>;
+
+var<workgroup> wg_i32 : atomic<i32>;
+
+@group(0) @binding(0) var<storage, read_write> sg_u32 : atomic<u32>;
+
+@group(0) @binding(1) var<storage, read_write> sg_i32 : atomic<i32>;
+
+fn f() {
+ {
+ let r = atomicSub(&(wg_u32), 123u);
+ }
+ {
+ let r = atomicSub(&(wg_i32), 123i);
+ }
+ {
+ let r = atomicSub(&(sg_u32), 123u);
+ }
+ {
+ let r = atomicSub(&(sg_i32), 123i);
+ }
+}
+)";
+
+ auto got = Run(src);
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, AtomicMin) {
+ auto* src = R"(
+var<workgroup> wg_u32 : u32;
+var<workgroup> wg_i32 : i32;
+@group(0) @binding(0) var<storage, read_write> sg_u32 : u32;
+@group(0) @binding(1) var<storage, read_write> sg_i32 : i32;
+
+fn f() {
+ {let r = stub_atomicMin_u32(wg_u32, 123u);}
+ {let r = stub_atomicMin_i32(wg_i32, 123i);}
+ {let r = stub_atomicMin_u32(sg_u32, 123u);}
+ {let r = stub_atomicMin_i32(sg_i32, 123i);}
+}
+)";
+
+ auto* expect =
+ R"(
+var<workgroup> wg_u32 : atomic<u32>;
+
+var<workgroup> wg_i32 : atomic<i32>;
+
+@group(0) @binding(0) var<storage, read_write> sg_u32 : atomic<u32>;
+
+@group(0) @binding(1) var<storage, read_write> sg_i32 : atomic<i32>;
+
+fn f() {
+ {
+ let r = atomicMin(&(wg_u32), 123u);
+ }
+ {
+ let r = atomicMin(&(wg_i32), 123i);
+ }
+ {
+ let r = atomicMin(&(sg_u32), 123u);
+ }
+ {
+ let r = atomicMin(&(sg_i32), 123i);
+ }
+}
+)";
+
+ auto got = Run(src);
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, AtomicMax) {
+ auto* src = R"(
+var<workgroup> wg_u32 : u32;
+var<workgroup> wg_i32 : i32;
+@group(0) @binding(0) var<storage, read_write> sg_u32 : u32;
+@group(0) @binding(1) var<storage, read_write> sg_i32 : i32;
+
+fn f() {
+ {let r = stub_atomicMax_u32(wg_u32, 123u);}
+ {let r = stub_atomicMax_i32(wg_i32, 123i);}
+ {let r = stub_atomicMax_u32(sg_u32, 123u);}
+ {let r = stub_atomicMax_i32(sg_i32, 123i);}
+}
+)";
+
+ auto* expect =
+ R"(
+var<workgroup> wg_u32 : atomic<u32>;
+
+var<workgroup> wg_i32 : atomic<i32>;
+
+@group(0) @binding(0) var<storage, read_write> sg_u32 : atomic<u32>;
+
+@group(0) @binding(1) var<storage, read_write> sg_i32 : atomic<i32>;
+
+fn f() {
+ {
+ let r = atomicMax(&(wg_u32), 123u);
+ }
+ {
+ let r = atomicMax(&(wg_i32), 123i);
+ }
+ {
+ let r = atomicMax(&(sg_u32), 123u);
+ }
+ {
+ let r = atomicMax(&(sg_i32), 123i);
+ }
+}
+)";
+
+ auto got = Run(src);
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, AtomicAnd) {
+ auto* src = R"(
+var<workgroup> wg_u32 : u32;
+var<workgroup> wg_i32 : i32;
+@group(0) @binding(0) var<storage, read_write> sg_u32 : u32;
+@group(0) @binding(1) var<storage, read_write> sg_i32 : i32;
+
+fn f() {
+ {let r = stub_atomicAnd_u32(wg_u32, 123u);}
+ {let r = stub_atomicAnd_i32(wg_i32, 123i);}
+ {let r = stub_atomicAnd_u32(sg_u32, 123u);}
+ {let r = stub_atomicAnd_i32(sg_i32, 123i);}
+}
+)";
+
+ auto* expect =
+ R"(
+var<workgroup> wg_u32 : atomic<u32>;
+
+var<workgroup> wg_i32 : atomic<i32>;
+
+@group(0) @binding(0) var<storage, read_write> sg_u32 : atomic<u32>;
+
+@group(0) @binding(1) var<storage, read_write> sg_i32 : atomic<i32>;
+
+fn f() {
+ {
+ let r = atomicAnd(&(wg_u32), 123u);
+ }
+ {
+ let r = atomicAnd(&(wg_i32), 123i);
+ }
+ {
+ let r = atomicAnd(&(sg_u32), 123u);
+ }
+ {
+ let r = atomicAnd(&(sg_i32), 123i);
+ }
+}
+)";
+
+ auto got = Run(src);
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, AtomicOr) {
+ auto* src = R"(
+var<workgroup> wg_u32 : u32;
+var<workgroup> wg_i32 : i32;
+@group(0) @binding(0) var<storage, read_write> sg_u32 : u32;
+@group(0) @binding(1) var<storage, read_write> sg_i32 : i32;
+
+fn f() {
+ {let r = stub_atomicOr_u32(wg_u32, 123u);}
+ {let r = stub_atomicOr_i32(wg_i32, 123i);}
+ {let r = stub_atomicOr_u32(sg_u32, 123u);}
+ {let r = stub_atomicOr_i32(sg_i32, 123i);}
+}
+)";
+
+ auto* expect =
+ R"(
+var<workgroup> wg_u32 : atomic<u32>;
+
+var<workgroup> wg_i32 : atomic<i32>;
+
+@group(0) @binding(0) var<storage, read_write> sg_u32 : atomic<u32>;
+
+@group(0) @binding(1) var<storage, read_write> sg_i32 : atomic<i32>;
+
+fn f() {
+ {
+ let r = atomicOr(&(wg_u32), 123u);
+ }
+ {
+ let r = atomicOr(&(wg_i32), 123i);
+ }
+ {
+ let r = atomicOr(&(sg_u32), 123u);
+ }
+ {
+ let r = atomicOr(&(sg_i32), 123i);
+ }
+}
+)";
+
+ auto got = Run(src);
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, AtomicXor) {
+ auto* src = R"(
+var<workgroup> wg_u32 : u32;
+var<workgroup> wg_i32 : i32;
+@group(0) @binding(0) var<storage, read_write> sg_u32 : u32;
+@group(0) @binding(1) var<storage, read_write> sg_i32 : i32;
+
+fn f() {
+ {let r = stub_atomicXor_u32(wg_u32, 123u);}
+ {let r = stub_atomicXor_i32(wg_i32, 123i);}
+ {let r = stub_atomicXor_u32(sg_u32, 123u);}
+ {let r = stub_atomicXor_i32(sg_i32, 123i);}
+}
+)";
+
+ auto* expect =
+ R"(
+var<workgroup> wg_u32 : atomic<u32>;
+
+var<workgroup> wg_i32 : atomic<i32>;
+
+@group(0) @binding(0) var<storage, read_write> sg_u32 : atomic<u32>;
+
+@group(0) @binding(1) var<storage, read_write> sg_i32 : atomic<i32>;
+
+fn f() {
+ {
+ let r = atomicXor(&(wg_u32), 123u);
+ }
+ {
+ let r = atomicXor(&(wg_i32), 123i);
+ }
+ {
+ let r = atomicXor(&(sg_u32), 123u);
+ }
+ {
+ let r = atomicXor(&(sg_i32), 123i);
+ }
+}
+)";
+
+ auto got = Run(src);
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(SpirvAtomicTest, AtomicCompareExchangeWeak) {
+ auto* src = R"(
+var<workgroup> wg_u32 : u32;
+var<workgroup> wg_i32 : i32;
+@group(0) @binding(0) var<storage, read_write> sg_u32 : u32;
+@group(0) @binding(1) var<storage, read_write> sg_i32 : i32;
+
+fn f() {
+ {let r = stub_atomic_compare_exchange_weak_u32(wg_u32, 123u, 456u);}
+ {let r = stub_atomic_compare_exchange_weak_i32(wg_i32, 123i, 456i);}
+ {let r = stub_atomic_compare_exchange_weak_u32(sg_u32, 123u, 456u);}
+ {let r = stub_atomic_compare_exchange_weak_i32(sg_i32, 123i, 456i);}
+}
+)";
+
+ auto* expect =
+ R"(
+var<workgroup> wg_u32 : atomic<u32>;
+
+var<workgroup> wg_i32 : atomic<i32>;
+
+@group(0) @binding(0) var<storage, read_write> sg_u32 : atomic<u32>;
+
+@group(0) @binding(1) var<storage, read_write> sg_i32 : atomic<i32>;
+
+fn f() {
+ {
+ let old_value = atomicCompareExchangeWeak(&(wg_u32), 123u, 456u).old_value;
+ let r = old_value;
+ }
+ {
+ let old_value_2 = atomicCompareExchangeWeak(&(wg_i32), 123i, 456i).old_value;
+ let r = old_value_2;
+ }
+ {
+ let old_value_1 = atomicCompareExchangeWeak(&(sg_u32), 123u, 456u).old_value;
+ let r = old_value_1;
+ }
+ {
+ let old_value_3 = atomicCompareExchangeWeak(&(sg_i32), 123i, 456i).old_value;
+ let r = old_value_3;
+ }
+}
+)";
+
+ auto got = Run(src);
+ EXPECT_EQ(expect, str(got));
+}
+
+} // namespace
+} // namespace tint::transform
diff --git a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm
new file mode 100644
index 0000000..0dbd964
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm
@@ -0,0 +1,88 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 58
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %idx "idx"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ OpDecorate %_arr_uint_uint_1 ArrayStride 4
+ OpDecorate %_arr__arr_uint_uint_1_uint_2 ArrayStride 4
+ OpDecorate %_arr__arr__arr_uint_uint_1_uint_2_uint_3 ArrayStride 8
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %uint_1 = OpConstant %uint 1
+%_arr_uint_uint_1 = OpTypeArray %uint %uint_1
+ %uint_2 = OpConstant %uint 2
+%_arr__arr_uint_uint_1_uint_2 = OpTypeArray %_arr_uint_uint_1 %uint_2
+ %uint_3 = OpConstant %uint 3
+%_arr__arr__arr_uint_uint_1_uint_2_uint_3 = OpTypeArray %_arr__arr_uint_uint_1_uint_2 %uint_3
+%_ptr_Workgroup__arr__arr__arr_uint_uint_1_uint_2_uint_3 = OpTypePointer Workgroup %_arr__arr__arr_uint_uint_1_uint_2_uint_3
+ %wg = OpVariable %_ptr_Workgroup__arr__arr__arr_uint_uint_1_uint_2_uint_3 Workgroup
+ %void = OpTypeVoid
+ %12 = OpTypeFunction %void %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %19 = OpConstantNull %uint
+ %uint_6 = OpConstant %uint 6
+ %bool = OpTypeBool
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %int = OpTypeInt 32 1
+ %int_2 = OpConstant %int 2
+ %int_1 = OpConstant %int 1
+ %51 = OpConstantNull %int
+ %53 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %12
+%local_invocation_index = OpFunctionParameter %uint
+ %16 = OpLabel
+ %idx = OpVariable %_ptr_Function_uint Function %19
+ OpStore %idx %local_invocation_index
+ OpBranch %20
+ %20 = OpLabel
+ OpLoopMerge %21 %22 None
+ OpBranch %23
+ %23 = OpLabel
+ %25 = OpLoad %uint %idx
+ %27 = OpULessThan %bool %25 %uint_6
+ %24 = OpLogicalNot %bool %27
+ OpSelectionMerge %29 None
+ OpBranchConditional %24 %30 %29
+ %30 = OpLabel
+ OpBranch %21
+ %29 = OpLabel
+ %31 = OpLoad %uint %idx
+ %32 = OpUDiv %uint %31 %uint_2
+ %33 = OpLoad %uint %idx
+ %34 = OpUMod %uint %33 %uint_2
+ %35 = OpLoad %uint %idx
+ %36 = OpUMod %uint %35 %uint_1
+ %41 = OpAccessChain %_ptr_Workgroup_uint %wg %32 %34 %36
+ OpAtomicStore %41 %uint_2 %uint_0 %19
+ OpBranch %22
+ %22 = OpLabel
+ %42 = OpLoad %uint %idx
+ %43 = OpIAdd %uint %42 %uint_1
+ OpStore %idx %43
+ OpBranch %20
+ %21 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %52 = OpAccessChain %_ptr_Workgroup_uint %wg %int_2 %int_1 %51
+ OpAtomicStore %52 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %53
+ %55 = OpLabel
+ %57 = OpLoad %uint %local_invocation_index_1
+ %56 = OpFunctionCall %void %compute_main_inner %57
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.glsl b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.glsl
new file mode 100644
index 0000000..4cdd505
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.glsl
@@ -0,0 +1,41 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint wg[3][2][1];
+void compute_main_inner(uint local_invocation_index) {
+ uint idx = 0u;
+ idx = local_invocation_index;
+ {
+ for(; !(!((idx < 6u))); idx = (idx + 1u)) {
+ atomicExchange(wg[(idx / 2u)][(idx % 2u)][(idx % 1u)], 0u);
+ }
+ }
+ barrier();
+ atomicExchange(wg[2][1][0], 1u);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 6u); idx_1 = (idx_1 + 1u)) {
+ uint i = (idx_1 / 2u);
+ uint i_1 = (idx_1 % 2u);
+ uint i_2 = (idx_1 % 1u);
+ atomicExchange(wg[i][i_1][i_2], 0u);
+ }
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.hlsl b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.hlsl
new file mode 100644
index 0000000..16f5d2e
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.hlsl
@@ -0,0 +1,47 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint wg[3][2][1];
+
+void compute_main_inner(uint local_invocation_index) {
+ uint idx = 0u;
+ idx = local_invocation_index;
+ {
+ [loop] for(; !(!((idx < 6u))); idx = (idx + 1u)) {
+ uint atomic_result = 0u;
+ InterlockedExchange(wg[(idx / 2u)][(idx % 2u)][(idx % 1u)], 0u, atomic_result);
+ }
+ }
+ GroupMemoryBarrierWithGroupSync();
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(wg[2][1][0], 1u, atomic_result_1);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ [loop] for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 6u); idx_1 = (idx_1 + 1u)) {
+ const uint i = (idx_1 / 2u);
+ const uint i_1 = (idx_1 % 2u);
+ const uint i_2 = (idx_1 % 1u);
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(wg[i][i_1][i_2], 0u, atomic_result_2);
+ }
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.msl b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.msl
new file mode 100644
index 0000000..896696e
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.msl
@@ -0,0 +1,74 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_array_wrapper {
+ uint arr[1];
+};
+
+struct tint_array_wrapper_1 {
+ tint_array_wrapper arr[2];
+};
+
+struct tint_array_wrapper_2 {
+ tint_array_wrapper_1 arr[3];
+};
+
+struct tint_array_wrapper_5 {
+ atomic_uint arr[1];
+};
+
+struct tint_array_wrapper_4 {
+ tint_array_wrapper_5 arr[2];
+};
+
+struct tint_array_wrapper_3 {
+ tint_array_wrapper_4 arr[3];
+};
+
+void compute_main_inner(uint local_invocation_index, threadgroup tint_array_wrapper_3* const tint_symbol) {
+ uint idx = 0u;
+ idx = local_invocation_index;
+ while (true) {
+ uint const x_25 = idx;
+ if (!((x_25 < 6u))) {
+ break;
+ }
+ uint const x_31 = idx;
+ uint const x_33 = idx;
+ uint const x_35 = idx;
+ atomic_store_explicit(&((*(tint_symbol)).arr[(x_31 / 2u)].arr[(x_33 % 2u)].arr[(x_35 % 1u)]), 0u, memory_order_relaxed);
+ {
+ uint const x_42 = idx;
+ idx = (x_42 + 1u);
+ }
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomic_store_explicit(&((*(tint_symbol)).arr[2].arr[1].arr[0]), 1u, memory_order_relaxed);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_1, threadgroup tint_array_wrapper_3* const tint_symbol_2) {
+ uint const x_57 = *(tint_symbol_1);
+ compute_main_inner(x_57, tint_symbol_2);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup tint_array_wrapper_3* const tint_symbol_3, thread uint* const tint_symbol_4) {
+ for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 6u); idx_1 = (idx_1 + 1u)) {
+ uint const i = (idx_1 / 2u);
+ uint const i_1 = (idx_1 % 2u);
+ uint const i_2 = (idx_1 % 1u);
+ atomic_store_explicit(&((*(tint_symbol_3)).arr[i].arr[i_1].arr[i_2]), 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_4) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_4, tint_symbol_3);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup tint_array_wrapper_3 tint_symbol_5;
+ thread uint tint_symbol_6 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_5), &(tint_symbol_6));
+ return;
+}
+
diff --git a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.spvasm
new file mode 100644
index 0000000..8091c97
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.spvasm
@@ -0,0 +1,140 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 90
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %idx "idx"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %idx_1 "idx_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ OpDecorate %_arr_uint_uint_1 ArrayStride 4
+ OpDecorate %_arr__arr_uint_uint_1_uint_2 ArrayStride 4
+ OpDecorate %_arr__arr__arr_uint_uint_1_uint_2_uint_3 ArrayStride 8
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %uint_1 = OpConstant %uint 1
+%_arr_uint_uint_1 = OpTypeArray %uint %uint_1
+ %uint_2 = OpConstant %uint 2
+%_arr__arr_uint_uint_1_uint_2 = OpTypeArray %_arr_uint_uint_1 %uint_2
+ %uint_3 = OpConstant %uint 3
+%_arr__arr__arr_uint_uint_1_uint_2_uint_3 = OpTypeArray %_arr__arr_uint_uint_1_uint_2 %uint_3
+%_ptr_Workgroup__arr__arr__arr_uint_uint_1_uint_2_uint_3 = OpTypePointer Workgroup %_arr__arr__arr_uint_uint_1_uint_2_uint_3
+ %wg = OpVariable %_ptr_Workgroup__arr__arr__arr_uint_uint_1_uint_2_uint_3 Workgroup
+ %void = OpTypeVoid
+ %15 = OpTypeFunction %void %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_6 = OpConstant %uint 6
+ %bool = OpTypeBool
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %int = OpTypeInt 32 1
+ %int_2 = OpConstant %int 2
+ %int_1 = OpConstant %int 1
+ %53 = OpConstantNull %int
+ %55 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %15
+%local_invocation_index = OpFunctionParameter %uint
+ %19 = OpLabel
+ %idx = OpVariable %_ptr_Function_uint Function %6
+ OpStore %idx %6
+ OpStore %idx %local_invocation_index
+ OpBranch %22
+ %22 = OpLabel
+ OpLoopMerge %23 %24 None
+ OpBranch %25
+ %25 = OpLabel
+ %26 = OpLoad %uint %idx
+ %29 = OpULessThan %bool %26 %uint_6
+ %27 = OpLogicalNot %bool %29
+ OpSelectionMerge %31 None
+ OpBranchConditional %27 %32 %31
+ %32 = OpLabel
+ OpBranch %23
+ %31 = OpLabel
+ %33 = OpLoad %uint %idx
+ %34 = OpLoad %uint %idx
+ %35 = OpLoad %uint %idx
+ %39 = OpUDiv %uint %33 %uint_2
+ %40 = OpUMod %uint %34 %uint_2
+ %41 = OpUMod %uint %35 %uint_1
+ %43 = OpAccessChain %_ptr_Workgroup_uint %wg %39 %40 %41
+ OpAtomicStore %43 %uint_2 %uint_0 %6
+ OpBranch %24
+ %24 = OpLabel
+ %44 = OpLoad %uint %idx
+ %45 = OpIAdd %uint %44 %uint_1
+ OpStore %idx %45
+ OpBranch %22
+ %23 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %54 = OpAccessChain %_ptr_Workgroup_uint %wg %int_2 %int_1 %53
+ OpAtomicStore %54 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %55
+ %57 = OpLabel
+ %58 = OpLoad %uint %local_invocation_index_1
+ %59 = OpFunctionCall %void %compute_main_inner %58
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %15
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %62 = OpLabel
+ %idx_1 = OpVariable %_ptr_Function_uint Function %6
+ OpStore %idx_1 %local_invocation_index_1_param
+ OpBranch %64
+ %64 = OpLabel
+ OpLoopMerge %65 %66 None
+ OpBranch %67
+ %67 = OpLabel
+ %69 = OpLoad %uint %idx_1
+ %70 = OpULessThan %bool %69 %uint_6
+ %68 = OpLogicalNot %bool %70
+ OpSelectionMerge %71 None
+ OpBranchConditional %68 %72 %71
+ %72 = OpLabel
+ OpBranch %65
+ %71 = OpLabel
+ %73 = OpLoad %uint %idx_1
+ %74 = OpUDiv %uint %73 %uint_2
+ %75 = OpLoad %uint %idx_1
+ %76 = OpUMod %uint %75 %uint_2
+ %77 = OpLoad %uint %idx_1
+ %78 = OpUMod %uint %77 %uint_1
+ %81 = OpAccessChain %_ptr_Workgroup_uint %wg %74 %76 %78
+ OpAtomicStore %81 %uint_2 %uint_0 %6
+ OpBranch %66
+ %66 = OpLabel
+ %82 = OpLoad %uint %idx_1
+ %83 = OpIAdd %uint %82 %uint_1
+ OpStore %idx_1 %83
+ OpBranch %64
+ %65 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %85 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %55
+ %87 = OpLabel
+ %89 = OpLoad %uint %local_invocation_index_1_param_1
+ %88 = OpFunctionCall %void %compute_main_inner_1 %89
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.wgsl
new file mode 100644
index 0000000..2b2b741
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/aliased_arrays.spvasm.expected.wgsl
@@ -0,0 +1,44 @@
+type Arr = array<u32, 1u>;
+
+type Arr_1 = array<Arr, 2u>;
+
+type Arr_2 = array<Arr_1, 3u>;
+
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> wg : array<array<array<atomic<u32>, 1u>, 2u>, 3u>;
+
+fn compute_main_inner(local_invocation_index : u32) {
+ var idx : u32 = 0u;
+ idx = local_invocation_index;
+ loop {
+ let x_25 : u32 = idx;
+ if (!((x_25 < 6u))) {
+ break;
+ }
+ let x_31 : u32 = idx;
+ let x_33 : u32 = idx;
+ let x_35 : u32 = idx;
+ atomicStore(&(wg[(x_31 / 2u)][(x_33 % 2u)][(x_35 % 1u)]), 0u);
+
+ continuing {
+ let x_42 : u32 = idx;
+ idx = (x_42 + 1u);
+ }
+ }
+ workgroupBarrier();
+ atomicStore(&(wg[2i][1i][0i]), 1u);
+ return;
+}
+
+fn compute_main_1() {
+ let x_57 : u32 = local_invocation_index_1;
+ compute_main_inner(x_57);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomicStore/array/aliased_arrays.wgsl b/test/tint/builtins/atomicStore/array/aliased_arrays.wgsl
new file mode 100644
index 0000000..0f6f01e
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/aliased_arrays.wgsl
@@ -0,0 +1,11 @@
+type A0 = atomic<u32>;
+type A1 = array<A0, 1>;
+type A2 = array<A1, 2>;
+type A3 = array<A2, 3>;
+
+var<workgroup> wg : A3;
+
+@compute @workgroup_size(1)
+fn compute_main() {
+ atomicStore(&wg[2][1][0], 1u);
+}
diff --git a/test/tint/builtins/atomicStore/array/array.spvasm b/test/tint/builtins/atomicStore/array/array.spvasm
new file mode 100644
index 0000000..f41ddf7
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/array.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 48
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %idx "idx"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ OpDecorate %_arr_uint_uint_4 ArrayStride 4
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %uint_4 = OpConstant %uint 4
+%_arr_uint_uint_4 = OpTypeArray %uint %uint_4
+%_ptr_Workgroup__arr_uint_uint_4 = OpTypePointer Workgroup %_arr_uint_uint_4
+ %wg = OpVariable %_ptr_Workgroup__arr_uint_uint_4 Workgroup
+ %void = OpTypeVoid
+ %8 = OpTypeFunction %void %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %15 = OpConstantNull %uint
+ %bool = OpTypeBool
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_264 = OpConstant %uint 264
+ %int = OpTypeInt 32 1
+ %int_1 = OpConstant %int 1
+ %43 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %8
+%local_invocation_index = OpFunctionParameter %uint
+ %12 = OpLabel
+ %idx = OpVariable %_ptr_Function_uint Function %15
+ OpStore %idx %local_invocation_index
+ OpBranch %16
+ %16 = OpLabel
+ OpLoopMerge %17 %18 None
+ OpBranch %19
+ %19 = OpLabel
+ %21 = OpLoad %uint %idx
+ %22 = OpULessThan %bool %21 %uint_4
+ %20 = OpLogicalNot %bool %22
+ OpSelectionMerge %24 None
+ OpBranchConditional %20 %25 %24
+ %25 = OpLabel
+ OpBranch %17
+ %24 = OpLabel
+ %26 = OpLoad %uint %idx
+ %32 = OpAccessChain %_ptr_Workgroup_uint %wg %26
+ OpAtomicStore %32 %uint_2 %uint_0 %15
+ OpBranch %18
+ %18 = OpLabel
+ %33 = OpLoad %uint %idx
+ %35 = OpIAdd %uint %33 %uint_1
+ OpStore %idx %35
+ OpBranch %16
+ %17 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %42 = OpAccessChain %_ptr_Workgroup_uint %wg %int_1
+ OpAtomicStore %42 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %43
+ %45 = OpLabel
+ %47 = OpLoad %uint %local_invocation_index_1
+ %46 = OpFunctionCall %void %compute_main_inner %47
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/array/array.spvasm.expected.glsl b/test/tint/builtins/atomicStore/array/array.spvasm.expected.glsl
new file mode 100644
index 0000000..a8c2193
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/array.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint wg[4];
+void compute_main_inner(uint local_invocation_index) {
+ uint idx = 0u;
+ idx = local_invocation_index;
+ {
+ for(; !(!((idx < 4u))); idx = (idx + 1u)) {
+ atomicExchange(wg[idx], 0u);
+ }
+ }
+ barrier();
+ atomicExchange(wg[1], 1u);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 4u); idx_1 = (idx_1 + 1u)) {
+ uint i = idx_1;
+ atomicExchange(wg[i], 0u);
+ }
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/array/array.spvasm.expected.hlsl b/test/tint/builtins/atomicStore/array/array.spvasm.expected.hlsl
new file mode 100644
index 0000000..76ff725
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/array.spvasm.expected.hlsl
@@ -0,0 +1,45 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint wg[4];
+
+void compute_main_inner(uint local_invocation_index) {
+ uint idx = 0u;
+ idx = local_invocation_index;
+ {
+ [loop] for(; !(!((idx < 4u))); idx = (idx + 1u)) {
+ uint atomic_result = 0u;
+ InterlockedExchange(wg[idx], 0u, atomic_result);
+ }
+ }
+ GroupMemoryBarrierWithGroupSync();
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(wg[1], 1u, atomic_result_1);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ [loop] for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 4u); idx_1 = (idx_1 + 1u)) {
+ const uint i = idx_1;
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(wg[i], 0u, atomic_result_2);
+ }
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/array/array.spvasm.expected.msl b/test/tint/builtins/atomicStore/array/array.spvasm.expected.msl
new file mode 100644
index 0000000..d2ab1ec
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/array.spvasm.expected.msl
@@ -0,0 +1,54 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_array_wrapper {
+ uint arr[4];
+};
+
+struct tint_array_wrapper_1 {
+ atomic_uint arr[4];
+};
+
+void compute_main_inner(uint local_invocation_index, threadgroup tint_array_wrapper_1* const tint_symbol) {
+ uint idx = 0u;
+ idx = local_invocation_index;
+ while (true) {
+ uint const x_21 = idx;
+ if (!((x_21 < 4u))) {
+ break;
+ }
+ uint const x_26 = idx;
+ atomic_store_explicit(&((*(tint_symbol)).arr[x_26]), 0u, memory_order_relaxed);
+ {
+ uint const x_33 = idx;
+ idx = (x_33 + 1u);
+ }
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomic_store_explicit(&((*(tint_symbol)).arr[1]), 1u, memory_order_relaxed);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_1, threadgroup tint_array_wrapper_1* const tint_symbol_2) {
+ uint const x_47 = *(tint_symbol_1);
+ compute_main_inner(x_47, tint_symbol_2);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup tint_array_wrapper_1* const tint_symbol_3, thread uint* const tint_symbol_4) {
+ for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 4u); idx_1 = (idx_1 + 1u)) {
+ uint const i = idx_1;
+ atomic_store_explicit(&((*(tint_symbol_3)).arr[i]), 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_4) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_4, tint_symbol_3);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup tint_array_wrapper_1 tint_symbol_5;
+ thread uint tint_symbol_6 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_5), &(tint_symbol_6));
+ return;
+}
+
diff --git a/test/tint/builtins/atomicStore/array/array.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/array/array.spvasm.expected.spvasm
new file mode 100644
index 0000000..e15c3db
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/array.spvasm.expected.spvasm
@@ -0,0 +1,123 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 75
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %idx "idx"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %idx_1 "idx_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ OpDecorate %_arr_uint_uint_4 ArrayStride 4
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %uint_4 = OpConstant %uint 4
+%_arr_uint_uint_4 = OpTypeArray %uint %uint_4
+%_ptr_Workgroup__arr_uint_uint_4 = OpTypePointer Workgroup %_arr_uint_uint_4
+ %wg = OpVariable %_ptr_Workgroup__arr_uint_uint_4 Workgroup
+ %void = OpTypeVoid
+ %11 = OpTypeFunction %void %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %bool = OpTypeBool
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_264 = OpConstant %uint 264
+ %int = OpTypeInt 32 1
+ %int_1 = OpConstant %int 1
+ %45 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %11
+%local_invocation_index = OpFunctionParameter %uint
+ %15 = OpLabel
+ %idx = OpVariable %_ptr_Function_uint Function %6
+ OpStore %idx %6
+ OpStore %idx %local_invocation_index
+ OpBranch %18
+ %18 = OpLabel
+ OpLoopMerge %19 %20 None
+ OpBranch %21
+ %21 = OpLabel
+ %22 = OpLoad %uint %idx
+ %24 = OpULessThan %bool %22 %uint_4
+ %23 = OpLogicalNot %bool %24
+ OpSelectionMerge %26 None
+ OpBranchConditional %23 %27 %26
+ %27 = OpLabel
+ OpBranch %19
+ %26 = OpLabel
+ %28 = OpLoad %uint %idx
+ %34 = OpAccessChain %_ptr_Workgroup_uint %wg %28
+ OpAtomicStore %34 %uint_2 %uint_0 %6
+ OpBranch %20
+ %20 = OpLabel
+ %35 = OpLoad %uint %idx
+ %37 = OpIAdd %uint %35 %uint_1
+ OpStore %idx %37
+ OpBranch %18
+ %19 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %44 = OpAccessChain %_ptr_Workgroup_uint %wg %int_1
+ OpAtomicStore %44 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %45
+ %47 = OpLabel
+ %48 = OpLoad %uint %local_invocation_index_1
+ %49 = OpFunctionCall %void %compute_main_inner %48
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %11
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %52 = OpLabel
+ %idx_1 = OpVariable %_ptr_Function_uint Function %6
+ OpStore %idx_1 %local_invocation_index_1_param
+ OpBranch %54
+ %54 = OpLabel
+ OpLoopMerge %55 %56 None
+ OpBranch %57
+ %57 = OpLabel
+ %59 = OpLoad %uint %idx_1
+ %60 = OpULessThan %bool %59 %uint_4
+ %58 = OpLogicalNot %bool %60
+ OpSelectionMerge %61 None
+ OpBranchConditional %58 %62 %61
+ %62 = OpLabel
+ OpBranch %55
+ %61 = OpLabel
+ %63 = OpLoad %uint %idx_1
+ %66 = OpAccessChain %_ptr_Workgroup_uint %wg %63
+ OpAtomicStore %66 %uint_2 %uint_0 %6
+ OpBranch %56
+ %56 = OpLabel
+ %67 = OpLoad %uint %idx_1
+ %68 = OpIAdd %uint %67 %uint_1
+ OpStore %idx_1 %68
+ OpBranch %54
+ %55 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %70 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %45
+ %72 = OpLabel
+ %74 = OpLoad %uint %local_invocation_index_1_param_1
+ %73 = OpFunctionCall %void %compute_main_inner_1 %74
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/array/array.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/array/array.spvasm.expected.wgsl
new file mode 100644
index 0000000..c597173
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/array.spvasm.expected.wgsl
@@ -0,0 +1,38 @@
+type Arr = array<u32, 4u>;
+
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> wg : array<atomic<u32>, 4u>;
+
+fn compute_main_inner(local_invocation_index : u32) {
+ var idx : u32 = 0u;
+ idx = local_invocation_index;
+ loop {
+ let x_21 : u32 = idx;
+ if (!((x_21 < 4u))) {
+ break;
+ }
+ let x_26 : u32 = idx;
+ atomicStore(&(wg[x_26]), 0u);
+
+ continuing {
+ let x_33 : u32 = idx;
+ idx = (x_33 + 1u);
+ }
+ }
+ workgroupBarrier();
+ atomicStore(&(wg[1i]), 1u);
+ return;
+}
+
+fn compute_main_1() {
+ let x_47 : u32 = local_invocation_index_1;
+ compute_main_inner(x_47);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomicStore/array/array.wgsl b/test/tint/builtins/atomicStore/array/array.wgsl
new file mode 100644
index 0000000..430207a
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/array.wgsl
@@ -0,0 +1,6 @@
+var<workgroup> wg : array<atomic<u32>, 4>;
+
+@compute @workgroup_size(1)
+fn compute_main() {
+ atomicStore(&wg[1], 1u);
+}
diff --git a/test/tint/builtins/atomicStore/array/arrays.spvasm b/test/tint/builtins/atomicStore/array/arrays.spvasm
new file mode 100644
index 0000000..0dbd964
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/arrays.spvasm
@@ -0,0 +1,88 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 58
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %idx "idx"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ OpDecorate %_arr_uint_uint_1 ArrayStride 4
+ OpDecorate %_arr__arr_uint_uint_1_uint_2 ArrayStride 4
+ OpDecorate %_arr__arr__arr_uint_uint_1_uint_2_uint_3 ArrayStride 8
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %uint_1 = OpConstant %uint 1
+%_arr_uint_uint_1 = OpTypeArray %uint %uint_1
+ %uint_2 = OpConstant %uint 2
+%_arr__arr_uint_uint_1_uint_2 = OpTypeArray %_arr_uint_uint_1 %uint_2
+ %uint_3 = OpConstant %uint 3
+%_arr__arr__arr_uint_uint_1_uint_2_uint_3 = OpTypeArray %_arr__arr_uint_uint_1_uint_2 %uint_3
+%_ptr_Workgroup__arr__arr__arr_uint_uint_1_uint_2_uint_3 = OpTypePointer Workgroup %_arr__arr__arr_uint_uint_1_uint_2_uint_3
+ %wg = OpVariable %_ptr_Workgroup__arr__arr__arr_uint_uint_1_uint_2_uint_3 Workgroup
+ %void = OpTypeVoid
+ %12 = OpTypeFunction %void %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %19 = OpConstantNull %uint
+ %uint_6 = OpConstant %uint 6
+ %bool = OpTypeBool
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %int = OpTypeInt 32 1
+ %int_2 = OpConstant %int 2
+ %int_1 = OpConstant %int 1
+ %51 = OpConstantNull %int
+ %53 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %12
+%local_invocation_index = OpFunctionParameter %uint
+ %16 = OpLabel
+ %idx = OpVariable %_ptr_Function_uint Function %19
+ OpStore %idx %local_invocation_index
+ OpBranch %20
+ %20 = OpLabel
+ OpLoopMerge %21 %22 None
+ OpBranch %23
+ %23 = OpLabel
+ %25 = OpLoad %uint %idx
+ %27 = OpULessThan %bool %25 %uint_6
+ %24 = OpLogicalNot %bool %27
+ OpSelectionMerge %29 None
+ OpBranchConditional %24 %30 %29
+ %30 = OpLabel
+ OpBranch %21
+ %29 = OpLabel
+ %31 = OpLoad %uint %idx
+ %32 = OpUDiv %uint %31 %uint_2
+ %33 = OpLoad %uint %idx
+ %34 = OpUMod %uint %33 %uint_2
+ %35 = OpLoad %uint %idx
+ %36 = OpUMod %uint %35 %uint_1
+ %41 = OpAccessChain %_ptr_Workgroup_uint %wg %32 %34 %36
+ OpAtomicStore %41 %uint_2 %uint_0 %19
+ OpBranch %22
+ %22 = OpLabel
+ %42 = OpLoad %uint %idx
+ %43 = OpIAdd %uint %42 %uint_1
+ OpStore %idx %43
+ OpBranch %20
+ %21 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %52 = OpAccessChain %_ptr_Workgroup_uint %wg %int_2 %int_1 %51
+ OpAtomicStore %52 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %53
+ %55 = OpLabel
+ %57 = OpLoad %uint %local_invocation_index_1
+ %56 = OpFunctionCall %void %compute_main_inner %57
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.glsl b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.glsl
new file mode 100644
index 0000000..4cdd505
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.glsl
@@ -0,0 +1,41 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint wg[3][2][1];
+void compute_main_inner(uint local_invocation_index) {
+ uint idx = 0u;
+ idx = local_invocation_index;
+ {
+ for(; !(!((idx < 6u))); idx = (idx + 1u)) {
+ atomicExchange(wg[(idx / 2u)][(idx % 2u)][(idx % 1u)], 0u);
+ }
+ }
+ barrier();
+ atomicExchange(wg[2][1][0], 1u);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 6u); idx_1 = (idx_1 + 1u)) {
+ uint i = (idx_1 / 2u);
+ uint i_1 = (idx_1 % 2u);
+ uint i_2 = (idx_1 % 1u);
+ atomicExchange(wg[i][i_1][i_2], 0u);
+ }
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.hlsl b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.hlsl
new file mode 100644
index 0000000..16f5d2e
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.hlsl
@@ -0,0 +1,47 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint wg[3][2][1];
+
+void compute_main_inner(uint local_invocation_index) {
+ uint idx = 0u;
+ idx = local_invocation_index;
+ {
+ [loop] for(; !(!((idx < 6u))); idx = (idx + 1u)) {
+ uint atomic_result = 0u;
+ InterlockedExchange(wg[(idx / 2u)][(idx % 2u)][(idx % 1u)], 0u, atomic_result);
+ }
+ }
+ GroupMemoryBarrierWithGroupSync();
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(wg[2][1][0], 1u, atomic_result_1);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ [loop] for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 6u); idx_1 = (idx_1 + 1u)) {
+ const uint i = (idx_1 / 2u);
+ const uint i_1 = (idx_1 % 2u);
+ const uint i_2 = (idx_1 % 1u);
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(wg[i][i_1][i_2], 0u, atomic_result_2);
+ }
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.msl b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.msl
new file mode 100644
index 0000000..896696e
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.msl
@@ -0,0 +1,74 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_array_wrapper {
+ uint arr[1];
+};
+
+struct tint_array_wrapper_1 {
+ tint_array_wrapper arr[2];
+};
+
+struct tint_array_wrapper_2 {
+ tint_array_wrapper_1 arr[3];
+};
+
+struct tint_array_wrapper_5 {
+ atomic_uint arr[1];
+};
+
+struct tint_array_wrapper_4 {
+ tint_array_wrapper_5 arr[2];
+};
+
+struct tint_array_wrapper_3 {
+ tint_array_wrapper_4 arr[3];
+};
+
+void compute_main_inner(uint local_invocation_index, threadgroup tint_array_wrapper_3* const tint_symbol) {
+ uint idx = 0u;
+ idx = local_invocation_index;
+ while (true) {
+ uint const x_25 = idx;
+ if (!((x_25 < 6u))) {
+ break;
+ }
+ uint const x_31 = idx;
+ uint const x_33 = idx;
+ uint const x_35 = idx;
+ atomic_store_explicit(&((*(tint_symbol)).arr[(x_31 / 2u)].arr[(x_33 % 2u)].arr[(x_35 % 1u)]), 0u, memory_order_relaxed);
+ {
+ uint const x_42 = idx;
+ idx = (x_42 + 1u);
+ }
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomic_store_explicit(&((*(tint_symbol)).arr[2].arr[1].arr[0]), 1u, memory_order_relaxed);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_1, threadgroup tint_array_wrapper_3* const tint_symbol_2) {
+ uint const x_57 = *(tint_symbol_1);
+ compute_main_inner(x_57, tint_symbol_2);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup tint_array_wrapper_3* const tint_symbol_3, thread uint* const tint_symbol_4) {
+ for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 6u); idx_1 = (idx_1 + 1u)) {
+ uint const i = (idx_1 / 2u);
+ uint const i_1 = (idx_1 % 2u);
+ uint const i_2 = (idx_1 % 1u);
+ atomic_store_explicit(&((*(tint_symbol_3)).arr[i].arr[i_1].arr[i_2]), 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_4) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_4, tint_symbol_3);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup tint_array_wrapper_3 tint_symbol_5;
+ thread uint tint_symbol_6 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_5), &(tint_symbol_6));
+ return;
+}
+
diff --git a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.spvasm
new file mode 100644
index 0000000..8091c97
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.spvasm
@@ -0,0 +1,140 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 90
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %idx "idx"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %idx_1 "idx_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ OpDecorate %_arr_uint_uint_1 ArrayStride 4
+ OpDecorate %_arr__arr_uint_uint_1_uint_2 ArrayStride 4
+ OpDecorate %_arr__arr__arr_uint_uint_1_uint_2_uint_3 ArrayStride 8
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %uint_1 = OpConstant %uint 1
+%_arr_uint_uint_1 = OpTypeArray %uint %uint_1
+ %uint_2 = OpConstant %uint 2
+%_arr__arr_uint_uint_1_uint_2 = OpTypeArray %_arr_uint_uint_1 %uint_2
+ %uint_3 = OpConstant %uint 3
+%_arr__arr__arr_uint_uint_1_uint_2_uint_3 = OpTypeArray %_arr__arr_uint_uint_1_uint_2 %uint_3
+%_ptr_Workgroup__arr__arr__arr_uint_uint_1_uint_2_uint_3 = OpTypePointer Workgroup %_arr__arr__arr_uint_uint_1_uint_2_uint_3
+ %wg = OpVariable %_ptr_Workgroup__arr__arr__arr_uint_uint_1_uint_2_uint_3 Workgroup
+ %void = OpTypeVoid
+ %15 = OpTypeFunction %void %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_6 = OpConstant %uint 6
+ %bool = OpTypeBool
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %int = OpTypeInt 32 1
+ %int_2 = OpConstant %int 2
+ %int_1 = OpConstant %int 1
+ %53 = OpConstantNull %int
+ %55 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %15
+%local_invocation_index = OpFunctionParameter %uint
+ %19 = OpLabel
+ %idx = OpVariable %_ptr_Function_uint Function %6
+ OpStore %idx %6
+ OpStore %idx %local_invocation_index
+ OpBranch %22
+ %22 = OpLabel
+ OpLoopMerge %23 %24 None
+ OpBranch %25
+ %25 = OpLabel
+ %26 = OpLoad %uint %idx
+ %29 = OpULessThan %bool %26 %uint_6
+ %27 = OpLogicalNot %bool %29
+ OpSelectionMerge %31 None
+ OpBranchConditional %27 %32 %31
+ %32 = OpLabel
+ OpBranch %23
+ %31 = OpLabel
+ %33 = OpLoad %uint %idx
+ %34 = OpLoad %uint %idx
+ %35 = OpLoad %uint %idx
+ %39 = OpUDiv %uint %33 %uint_2
+ %40 = OpUMod %uint %34 %uint_2
+ %41 = OpUMod %uint %35 %uint_1
+ %43 = OpAccessChain %_ptr_Workgroup_uint %wg %39 %40 %41
+ OpAtomicStore %43 %uint_2 %uint_0 %6
+ OpBranch %24
+ %24 = OpLabel
+ %44 = OpLoad %uint %idx
+ %45 = OpIAdd %uint %44 %uint_1
+ OpStore %idx %45
+ OpBranch %22
+ %23 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %54 = OpAccessChain %_ptr_Workgroup_uint %wg %int_2 %int_1 %53
+ OpAtomicStore %54 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %55
+ %57 = OpLabel
+ %58 = OpLoad %uint %local_invocation_index_1
+ %59 = OpFunctionCall %void %compute_main_inner %58
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %15
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %62 = OpLabel
+ %idx_1 = OpVariable %_ptr_Function_uint Function %6
+ OpStore %idx_1 %local_invocation_index_1_param
+ OpBranch %64
+ %64 = OpLabel
+ OpLoopMerge %65 %66 None
+ OpBranch %67
+ %67 = OpLabel
+ %69 = OpLoad %uint %idx_1
+ %70 = OpULessThan %bool %69 %uint_6
+ %68 = OpLogicalNot %bool %70
+ OpSelectionMerge %71 None
+ OpBranchConditional %68 %72 %71
+ %72 = OpLabel
+ OpBranch %65
+ %71 = OpLabel
+ %73 = OpLoad %uint %idx_1
+ %74 = OpUDiv %uint %73 %uint_2
+ %75 = OpLoad %uint %idx_1
+ %76 = OpUMod %uint %75 %uint_2
+ %77 = OpLoad %uint %idx_1
+ %78 = OpUMod %uint %77 %uint_1
+ %81 = OpAccessChain %_ptr_Workgroup_uint %wg %74 %76 %78
+ OpAtomicStore %81 %uint_2 %uint_0 %6
+ OpBranch %66
+ %66 = OpLabel
+ %82 = OpLoad %uint %idx_1
+ %83 = OpIAdd %uint %82 %uint_1
+ OpStore %idx_1 %83
+ OpBranch %64
+ %65 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %85 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %55
+ %87 = OpLabel
+ %89 = OpLoad %uint %local_invocation_index_1_param_1
+ %88 = OpFunctionCall %void %compute_main_inner_1 %89
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.wgsl
new file mode 100644
index 0000000..2b2b741
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/arrays.spvasm.expected.wgsl
@@ -0,0 +1,44 @@
+type Arr = array<u32, 1u>;
+
+type Arr_1 = array<Arr, 2u>;
+
+type Arr_2 = array<Arr_1, 3u>;
+
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> wg : array<array<array<atomic<u32>, 1u>, 2u>, 3u>;
+
+fn compute_main_inner(local_invocation_index : u32) {
+ var idx : u32 = 0u;
+ idx = local_invocation_index;
+ loop {
+ let x_25 : u32 = idx;
+ if (!((x_25 < 6u))) {
+ break;
+ }
+ let x_31 : u32 = idx;
+ let x_33 : u32 = idx;
+ let x_35 : u32 = idx;
+ atomicStore(&(wg[(x_31 / 2u)][(x_33 % 2u)][(x_35 % 1u)]), 0u);
+
+ continuing {
+ let x_42 : u32 = idx;
+ idx = (x_42 + 1u);
+ }
+ }
+ workgroupBarrier();
+ atomicStore(&(wg[2i][1i][0i]), 1u);
+ return;
+}
+
+fn compute_main_1() {
+ let x_57 : u32 = local_invocation_index_1;
+ compute_main_inner(x_57);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomicStore/array/arrays.wgsl b/test/tint/builtins/atomicStore/array/arrays.wgsl
new file mode 100644
index 0000000..3415c58
--- /dev/null
+++ b/test/tint/builtins/atomicStore/array/arrays.wgsl
@@ -0,0 +1,6 @@
+var<workgroup> wg : array<array<array<atomic<u32>, 1>, 2>, 3>;
+
+@compute @workgroup_size(1)
+fn compute_main() {
+ atomicStore(&wg[2][1][0], 1u);
+}
diff --git a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm
new file mode 100644
index 0000000..b9e0fed
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm
@@ -0,0 +1,91 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 54
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %S "S"
+ OpMemberName %S 0 "x"
+ OpMemberName %S 1 "a"
+ OpMemberName %S 2 "y"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %idx "idx"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %S 0 Offset 0
+ OpMemberDecorate %S 1 Offset 4
+ OpMemberDecorate %S 2 Offset 8
+ OpDecorate %_arr_S_uint_10 ArrayStride 12
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+ %S = OpTypeStruct %int %uint %uint
+ %uint_10 = OpConstant %uint 10
+%_arr_S_uint_10 = OpTypeArray %S %uint_10
+%_ptr_Workgroup__arr_S_uint_10 = OpTypePointer Workgroup %_arr_S_uint_10
+ %wg = OpVariable %_ptr_Workgroup__arr_S_uint_10 Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+ %bool = OpTypeBool
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %32 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_1 = OpConstant %uint 1
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+%_ptr_Workgroup_uint_0 = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %int_4 = OpConstant %int 4
+ %49 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %10
+%local_invocation_index = OpFunctionParameter %uint
+ %14 = OpLabel
+ %idx = OpVariable %_ptr_Function_uint Function %17
+ OpStore %idx %local_invocation_index
+ OpBranch %18
+ %18 = OpLabel
+ OpLoopMerge %19 %20 None
+ OpBranch %21
+ %21 = OpLabel
+ %23 = OpLoad %uint %idx
+ %24 = OpULessThan %bool %23 %uint_10
+ %22 = OpLogicalNot %bool %24
+ OpSelectionMerge %26 None
+ OpBranchConditional %22 %27 %26
+ %27 = OpLabel
+ OpBranch %19
+ %26 = OpLabel
+ %28 = OpLoad %uint %idx
+ %31 = OpAccessChain %_ptr_Workgroup_int %wg %28 %uint_0
+ OpStore %31 %32
+ %38 = OpAccessChain %_ptr_Workgroup_uint %wg %28 %uint_1
+ OpAtomicStore %38 %uint_2 %uint_0 %17
+ %40 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %28 %uint_2
+ OpStore %40 %17
+ OpBranch %20
+ %20 = OpLabel
+ %41 = OpLoad %uint %idx
+ %42 = OpIAdd %uint %41 %uint_1
+ OpStore %idx %42
+ OpBranch %18
+ %19 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %48 = OpAccessChain %_ptr_Workgroup_uint %wg %int_4 %uint_1
+ OpAtomicStore %48 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %49
+ %51 = OpLabel
+ %53 = OpLoad %uint %local_invocation_index_1
+ %52 = OpFunctionCall %void %compute_main_inner %53
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.glsl b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.glsl
new file mode 100644
index 0000000..4f23cb9
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.glsl
@@ -0,0 +1,56 @@
+#version 310 es
+
+struct S_atomic {
+ int x;
+ uint a;
+ uint y;
+};
+
+struct S {
+ int x;
+ uint a;
+ uint y;
+};
+
+uint local_invocation_index_1 = 0u;
+shared S_atomic wg[10];
+void compute_main_inner(uint local_invocation_index) {
+ uint idx = 0u;
+ idx = local_invocation_index;
+ {
+ for(; !(!((idx < 10u))); idx = (idx + 1u)) {
+ uint x_28 = idx;
+ wg[x_28].x = 0;
+ atomicExchange(wg[x_28].a, 0u);
+ wg[x_28].y = 0u;
+ }
+ }
+ barrier();
+ atomicExchange(wg[4].a, 1u);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 10u); idx_1 = (idx_1 + 1u)) {
+ uint i = idx_1;
+ wg[i].x = 0;
+ atomicExchange(wg[i].a, 0u);
+ wg[i].y = 0u;
+ }
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.hlsl b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.hlsl
new file mode 100644
index 0000000..9d31dd1
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.hlsl
@@ -0,0 +1,56 @@
+struct S_atomic {
+ int x;
+ uint a;
+ uint y;
+};
+
+static uint local_invocation_index_1 = 0u;
+groupshared S_atomic wg[10];
+
+void compute_main_inner(uint local_invocation_index) {
+ uint idx = 0u;
+ idx = local_invocation_index;
+ {
+ [loop] for(; !(!((idx < 10u))); idx = (idx + 1u)) {
+ const uint x_28 = idx;
+ wg[x_28].x = 0;
+ uint atomic_result = 0u;
+ InterlockedExchange(wg[x_28].a, 0u, atomic_result);
+ wg[x_28].y = 0u;
+ }
+ }
+ GroupMemoryBarrierWithGroupSync();
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(wg[4].a, 1u, atomic_result_1);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ [loop] for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 10u); idx_1 = (idx_1 + 1u)) {
+ const uint i = idx_1;
+ wg[i].x = 0;
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(wg[i].a, 0u, atomic_result_2);
+ wg[i].y = 0u;
+ }
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.msl b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.msl
new file mode 100644
index 0000000..5360fda
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.msl
@@ -0,0 +1,70 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct S_atomic {
+ int x;
+ atomic_uint a;
+ uint y;
+};
+
+struct S {
+ int x;
+ uint a;
+ uint y;
+};
+
+struct tint_array_wrapper {
+ S arr[10];
+};
+
+struct tint_array_wrapper_1 {
+ S_atomic arr[10];
+};
+
+void compute_main_inner(uint local_invocation_index, threadgroup tint_array_wrapper_1* const tint_symbol) {
+ uint idx = 0u;
+ idx = local_invocation_index;
+ while (true) {
+ uint const x_23 = idx;
+ if (!((x_23 < 10u))) {
+ break;
+ }
+ uint const x_28 = idx;
+ (*(tint_symbol)).arr[x_28].x = 0;
+ atomic_store_explicit(&((*(tint_symbol)).arr[x_28].a), 0u, memory_order_relaxed);
+ (*(tint_symbol)).arr[x_28].y = 0u;
+ {
+ uint const x_41 = idx;
+ idx = (x_41 + 1u);
+ }
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomic_store_explicit(&((*(tint_symbol)).arr[4].a), 1u, memory_order_relaxed);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_1, threadgroup tint_array_wrapper_1* const tint_symbol_2) {
+ uint const x_53 = *(tint_symbol_1);
+ compute_main_inner(x_53, tint_symbol_2);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup tint_array_wrapper_1* const tint_symbol_3, thread uint* const tint_symbol_4) {
+ for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 10u); idx_1 = (idx_1 + 1u)) {
+ uint const i = idx_1;
+ (*(tint_symbol_3)).arr[i].x = 0;
+ atomic_store_explicit(&((*(tint_symbol_3)).arr[i].a), 0u, memory_order_relaxed);
+ (*(tint_symbol_3)).arr[i].y = 0u;
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_4) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_4, tint_symbol_3);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup tint_array_wrapper_1 tint_symbol_5;
+ thread uint tint_symbol_6 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_5), &(tint_symbol_6));
+ return;
+}
+
diff --git a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.spvasm
new file mode 100644
index 0000000..b25f900
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.spvasm
@@ -0,0 +1,142 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 83
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %S_atomic "S_atomic"
+ OpMemberName %S_atomic 0 "x"
+ OpMemberName %S_atomic 1 "a"
+ OpMemberName %S_atomic 2 "y"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %idx "idx"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %idx_1 "idx_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %S_atomic 0 Offset 0
+ OpMemberDecorate %S_atomic 1 Offset 4
+ OpMemberDecorate %S_atomic 2 Offset 8
+ OpDecorate %_arr_S_atomic_uint_10 ArrayStride 12
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+ %S_atomic = OpTypeStruct %int %uint %uint
+ %uint_10 = OpConstant %uint 10
+%_arr_S_atomic_uint_10 = OpTypeArray %S_atomic %uint_10
+%_ptr_Workgroup__arr_S_atomic_uint_10 = OpTypePointer Workgroup %_arr_S_atomic_uint_10
+ %wg = OpVariable %_ptr_Workgroup__arr_S_atomic_uint_10 Workgroup
+ %void = OpTypeVoid
+ %13 = OpTypeFunction %void %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %bool = OpTypeBool
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %34 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_1 = OpConstant %uint 1
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+%_ptr_Workgroup_uint_0 = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %int_4 = OpConstant %int 4
+ %51 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %13
+%local_invocation_index = OpFunctionParameter %uint
+ %17 = OpLabel
+ %idx = OpVariable %_ptr_Function_uint Function %6
+ OpStore %idx %6
+ OpStore %idx %local_invocation_index
+ OpBranch %20
+ %20 = OpLabel
+ OpLoopMerge %21 %22 None
+ OpBranch %23
+ %23 = OpLabel
+ %24 = OpLoad %uint %idx
+ %26 = OpULessThan %bool %24 %uint_10
+ %25 = OpLogicalNot %bool %26
+ OpSelectionMerge %28 None
+ OpBranchConditional %25 %29 %28
+ %29 = OpLabel
+ OpBranch %21
+ %28 = OpLabel
+ %30 = OpLoad %uint %idx
+ %33 = OpAccessChain %_ptr_Workgroup_int %wg %30 %uint_0
+ OpStore %33 %34
+ %40 = OpAccessChain %_ptr_Workgroup_uint %wg %30 %uint_1
+ OpAtomicStore %40 %uint_2 %uint_0 %6
+ %42 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %30 %uint_2
+ OpStore %42 %6
+ OpBranch %22
+ %22 = OpLabel
+ %43 = OpLoad %uint %idx
+ %44 = OpIAdd %uint %43 %uint_1
+ OpStore %idx %44
+ OpBranch %20
+ %21 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %50 = OpAccessChain %_ptr_Workgroup_uint %wg %int_4 %uint_1
+ OpAtomicStore %50 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %51
+ %53 = OpLabel
+ %54 = OpLoad %uint %local_invocation_index_1
+ %55 = OpFunctionCall %void %compute_main_inner %54
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %13
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %58 = OpLabel
+ %idx_1 = OpVariable %_ptr_Function_uint Function %6
+ OpStore %idx_1 %local_invocation_index_1_param
+ OpBranch %60
+ %60 = OpLabel
+ OpLoopMerge %61 %62 None
+ OpBranch %63
+ %63 = OpLabel
+ %65 = OpLoad %uint %idx_1
+ %66 = OpULessThan %bool %65 %uint_10
+ %64 = OpLogicalNot %bool %66
+ OpSelectionMerge %67 None
+ OpBranchConditional %64 %68 %67
+ %68 = OpLabel
+ OpBranch %61
+ %67 = OpLabel
+ %69 = OpLoad %uint %idx_1
+ %70 = OpAccessChain %_ptr_Workgroup_int %wg %69 %uint_0
+ OpStore %70 %34
+ %73 = OpAccessChain %_ptr_Workgroup_uint %wg %69 %uint_1
+ OpAtomicStore %73 %uint_2 %uint_0 %6
+ %74 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %69 %uint_2
+ OpStore %74 %6
+ OpBranch %62
+ %62 = OpLabel
+ %75 = OpLoad %uint %idx_1
+ %76 = OpIAdd %uint %75 %uint_1
+ OpStore %idx_1 %76
+ OpBranch %60
+ %61 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %78 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %51
+ %80 = OpLabel
+ %82 = OpLoad %uint %local_invocation_index_1_param_1
+ %81 = OpFunctionCall %void %compute_main_inner_1 %82
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.wgsl
new file mode 100644
index 0000000..de42f48
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/array_of_struct.spvasm.expected.wgsl
@@ -0,0 +1,52 @@
+struct S_atomic {
+ x : i32,
+ a : atomic<u32>,
+ y : u32,
+}
+
+struct S {
+ x : i32,
+ a : u32,
+ y : u32,
+}
+
+type Arr = array<S, 10u>;
+
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> wg : array<S_atomic, 10u>;
+
+fn compute_main_inner(local_invocation_index : u32) {
+ var idx : u32 = 0u;
+ idx = local_invocation_index;
+ loop {
+ let x_23 : u32 = idx;
+ if (!((x_23 < 10u))) {
+ break;
+ }
+ let x_28 : u32 = idx;
+ wg[x_28].x = 0i;
+ atomicStore(&(wg[x_28].a), 0u);
+ wg[x_28].y = 0u;
+
+ continuing {
+ let x_41 : u32 = idx;
+ idx = (x_41 + 1u);
+ }
+ }
+ workgroupBarrier();
+ atomicStore(&(wg[4i].a), 1u);
+ return;
+}
+
+fn compute_main_1() {
+ let x_53 : u32 = local_invocation_index_1;
+ compute_main_inner(x_53);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomicStore/struct/array_of_struct.wgsl b/test/tint/builtins/atomicStore/struct/array_of_struct.wgsl
new file mode 100644
index 0000000..d49a3fd
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/array_of_struct.wgsl
@@ -0,0 +1,12 @@
+struct S {
+ x : i32,
+ a : atomic<u32>,
+ y : u32,
+};
+
+var<workgroup> wg : array<S, 10>;
+
+@compute @workgroup_size(1)
+fn compute_main() {
+ atomicStore(&wg[4].a, 1u);
+}
diff --git a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm
new file mode 100644
index 0000000..f61269c
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm
@@ -0,0 +1,62 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 40
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %S "S"
+ OpMemberName %S 0 "x"
+ OpMemberName %S 1 "a"
+ OpMemberName %S 2 "b"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %S 0 Offset 0
+ OpMemberDecorate %S 1 Offset 4
+ OpMemberDecorate %S 2 Offset 8
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+ %S = OpTypeStruct %int %uint %uint
+%_ptr_Workgroup_S = OpTypePointer Workgroup %S
+ %wg = OpVariable %_ptr_Workgroup_S Workgroup
+ %void = OpTypeVoid
+ %8 = OpTypeFunction %void %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %16 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_1 = OpConstant %uint 1
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %23 = OpConstantNull %uint
+ %uint_264 = OpConstant %uint 264
+ %35 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %8
+%local_invocation_index = OpFunctionParameter %uint
+ %12 = OpLabel
+ %15 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %15 %16
+ %22 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %22 %uint_2 %uint_0 %23
+ %26 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_2
+ OpAtomicStore %26 %uint_2 %uint_0 %23
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %31 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %31 %uint_2 %uint_0 %uint_1
+ %34 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_2
+ OpAtomicStore %34 %uint_2 %uint_0 %uint_2
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %35
+ %37 = OpLabel
+ %39 = OpLoad %uint %local_invocation_index_1
+ %38 = OpFunctionCall %void %compute_main_inner %39
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.glsl b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.glsl
new file mode 100644
index 0000000..4d0836e
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.glsl
@@ -0,0 +1,47 @@
+#version 310 es
+
+struct S_atomic {
+ int x;
+ uint a;
+ uint b;
+};
+
+struct S {
+ int x;
+ uint a;
+ uint b;
+};
+
+uint local_invocation_index_1 = 0u;
+shared S_atomic wg;
+void compute_main_inner(uint local_invocation_index) {
+ wg.x = 0;
+ atomicExchange(wg.a, 0u);
+ atomicExchange(wg.b, 0u);
+ barrier();
+ atomicExchange(wg.a, 1u);
+ atomicExchange(wg.b, 2u);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ wg.x = 0;
+ atomicExchange(wg.a, 0u);
+ atomicExchange(wg.b, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.hlsl b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.hlsl
new file mode 100644
index 0000000..cb340f2
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.hlsl
@@ -0,0 +1,50 @@
+struct S_atomic {
+ int x;
+ uint a;
+ uint b;
+};
+
+static uint local_invocation_index_1 = 0u;
+groupshared S_atomic wg;
+
+void compute_main_inner(uint local_invocation_index) {
+ wg.x = 0;
+ uint atomic_result = 0u;
+ InterlockedExchange(wg.a, 0u, atomic_result);
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(wg.b, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(wg.a, 1u, atomic_result_2);
+ uint atomic_result_3 = 0u;
+ InterlockedExchange(wg.b, 2u, atomic_result_3);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ wg.x = 0;
+ uint atomic_result_4 = 0u;
+ InterlockedExchange(wg.a, 0u, atomic_result_4);
+ uint atomic_result_5 = 0u;
+ InterlockedExchange(wg.b, 0u, atomic_result_5);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.msl b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.msl
new file mode 100644
index 0000000..4e1363d
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.msl
@@ -0,0 +1,49 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct S_atomic {
+ int x;
+ atomic_uint a;
+ atomic_uint b;
+};
+
+struct S {
+ int x;
+ uint a;
+ uint b;
+};
+
+void compute_main_inner(uint local_invocation_index, threadgroup S_atomic* const tint_symbol) {
+ (*(tint_symbol)).x = 0;
+ atomic_store_explicit(&((*(tint_symbol)).a), 0u, memory_order_relaxed);
+ atomic_store_explicit(&((*(tint_symbol)).b), 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomic_store_explicit(&((*(tint_symbol)).a), 1u, memory_order_relaxed);
+ atomic_store_explicit(&((*(tint_symbol)).b), 2u, memory_order_relaxed);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_1, threadgroup S_atomic* const tint_symbol_2) {
+ uint const x_39 = *(tint_symbol_1);
+ compute_main_inner(x_39, tint_symbol_2);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup S_atomic* const tint_symbol_3, thread uint* const tint_symbol_4) {
+ {
+ (*(tint_symbol_3)).x = 0;
+ atomic_store_explicit(&((*(tint_symbol_3)).a), 0u, memory_order_relaxed);
+ atomic_store_explicit(&((*(tint_symbol_3)).b), 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_4) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_4, tint_symbol_3);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup S_atomic tint_symbol_5;
+ thread uint tint_symbol_6 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_5), &(tint_symbol_6));
+ return;
+}
+
diff --git a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.spvasm
new file mode 100644
index 0000000..5ee475d
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.spvasm
@@ -0,0 +1,88 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 58
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %S_atomic "S_atomic"
+ OpMemberName %S_atomic 0 "x"
+ OpMemberName %S_atomic 1 "a"
+ OpMemberName %S_atomic 2 "b"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %S_atomic 0 Offset 0
+ OpMemberDecorate %S_atomic 1 Offset 4
+ OpMemberDecorate %S_atomic 2 Offset 8
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+ %S_atomic = OpTypeStruct %int %uint %uint
+%_ptr_Workgroup_S_atomic = OpTypePointer Workgroup %S_atomic
+ %wg = OpVariable %_ptr_Workgroup_S_atomic Workgroup
+ %void = OpTypeVoid
+ %11 = OpTypeFunction %void %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %19 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_1 = OpConstant %uint 1
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %37 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %11
+%local_invocation_index = OpFunctionParameter %uint
+ %15 = OpLabel
+ %18 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %18 %19
+ %25 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %25 %uint_2 %uint_0 %6
+ %28 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_2
+ OpAtomicStore %28 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %33 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %33 %uint_2 %uint_0 %uint_1
+ %36 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_2
+ OpAtomicStore %36 %uint_2 %uint_0 %uint_2
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %37
+ %39 = OpLabel
+ %40 = OpLoad %uint %local_invocation_index_1
+ %41 = OpFunctionCall %void %compute_main_inner %40
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %11
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %44 = OpLabel
+ %45 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %45 %19
+ %48 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %48 %uint_2 %uint_0 %6
+ %51 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_2
+ OpAtomicStore %51 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %53 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %37
+ %55 = OpLabel
+ %57 = OpLoad %uint %local_invocation_index_1_param_1
+ %56 = OpFunctionCall %void %compute_main_inner_1 %57
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.wgsl
new file mode 100644
index 0000000..20d066a
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.spvasm.expected.wgsl
@@ -0,0 +1,37 @@
+struct S_atomic {
+ x : i32,
+ a : atomic<u32>,
+ b : atomic<u32>,
+}
+
+struct S {
+ x : i32,
+ a : u32,
+ b : u32,
+}
+
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> wg : S_atomic;
+
+fn compute_main_inner(local_invocation_index : u32) {
+ wg.x = 0i;
+ atomicStore(&(wg.a), 0u);
+ atomicStore(&(wg.b), 0u);
+ workgroupBarrier();
+ atomicStore(&(wg.a), 1u);
+ atomicStore(&(wg.b), 2u);
+ return;
+}
+
+fn compute_main_1() {
+ let x_39 : u32 = local_invocation_index_1;
+ compute_main_inner(x_39);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.wgsl b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.wgsl
new file mode 100644
index 0000000..b055a8f
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_multiple_atomics.wgsl
@@ -0,0 +1,13 @@
+struct S {
+ x : i32,
+ a : atomic<u32>,
+ b : atomic<u32>,
+};
+
+var<workgroup> wg: S;
+
+@compute @workgroup_size(1)
+fn compute_main() {
+ atomicStore(&wg.a, 1u);
+ atomicStore(&wg.b, 2u);
+}
diff --git a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm
new file mode 100644
index 0000000..acad988
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm
@@ -0,0 +1,61 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 36
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %S "S"
+ OpMemberName %S 0 "x"
+ OpMemberName %S 1 "a"
+ OpMemberName %S 2 "y"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %S 0 Offset 0
+ OpMemberDecorate %S 1 Offset 4
+ OpMemberDecorate %S 2 Offset 8
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+ %S = OpTypeStruct %int %uint %uint
+%_ptr_Workgroup_S = OpTypePointer Workgroup %S
+ %wg = OpVariable %_ptr_Workgroup_S Workgroup
+ %void = OpTypeVoid
+ %8 = OpTypeFunction %void %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %16 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_1 = OpConstant %uint 1
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %23 = OpConstantNull %uint
+%_ptr_Workgroup_uint_0 = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %31 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %8
+%local_invocation_index = OpFunctionParameter %uint
+ %12 = OpLabel
+ %15 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %15 %16
+ %22 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %22 %uint_2 %uint_0 %23
+ %25 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %uint_2
+ OpStore %25 %23
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %30 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %31
+ %33 = OpLabel
+ %35 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %35
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.glsl b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.glsl
new file mode 100644
index 0000000..2b03ef6
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.glsl
@@ -0,0 +1,46 @@
+#version 310 es
+
+struct S_atomic {
+ int x;
+ uint a;
+ uint y;
+};
+
+struct S {
+ int x;
+ uint a;
+ uint y;
+};
+
+uint local_invocation_index_1 = 0u;
+shared S_atomic wg;
+void compute_main_inner(uint local_invocation_index) {
+ wg.x = 0;
+ atomicExchange(wg.a, 0u);
+ wg.y = 0u;
+ barrier();
+ atomicExchange(wg.a, 1u);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ wg.x = 0;
+ atomicExchange(wg.a, 0u);
+ wg.y = 0u;
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.hlsl b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.hlsl
new file mode 100644
index 0000000..403d1fb
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+struct S_atomic {
+ int x;
+ uint a;
+ uint y;
+};
+
+static uint local_invocation_index_1 = 0u;
+groupshared S_atomic wg;
+
+void compute_main_inner(uint local_invocation_index) {
+ wg.x = 0;
+ uint atomic_result = 0u;
+ InterlockedExchange(wg.a, 0u, atomic_result);
+ wg.y = 0u;
+ GroupMemoryBarrierWithGroupSync();
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(wg.a, 1u, atomic_result_1);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ wg.x = 0;
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(wg.a, 0u, atomic_result_2);
+ wg.y = 0u;
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.msl b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.msl
new file mode 100644
index 0000000..524820a
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.msl
@@ -0,0 +1,48 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct S_atomic {
+ int x;
+ atomic_uint a;
+ uint y;
+};
+
+struct S {
+ int x;
+ uint a;
+ uint y;
+};
+
+void compute_main_inner(uint local_invocation_index, threadgroup S_atomic* const tint_symbol) {
+ (*(tint_symbol)).x = 0;
+ atomic_store_explicit(&((*(tint_symbol)).a), 0u, memory_order_relaxed);
+ (*(tint_symbol)).y = 0u;
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomic_store_explicit(&((*(tint_symbol)).a), 1u, memory_order_relaxed);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_1, threadgroup S_atomic* const tint_symbol_2) {
+ uint const x_35 = *(tint_symbol_1);
+ compute_main_inner(x_35, tint_symbol_2);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup S_atomic* const tint_symbol_3, thread uint* const tint_symbol_4) {
+ {
+ (*(tint_symbol_3)).x = 0;
+ atomic_store_explicit(&((*(tint_symbol_3)).a), 0u, memory_order_relaxed);
+ (*(tint_symbol_3)).y = 0u;
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_4) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_4, tint_symbol_3);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup S_atomic tint_symbol_5;
+ thread uint tint_symbol_6 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_5), &(tint_symbol_6));
+ return;
+}
+
diff --git a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.spvasm
new file mode 100644
index 0000000..35d0d2b
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.spvasm
@@ -0,0 +1,87 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 52
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %S_atomic "S_atomic"
+ OpMemberName %S_atomic 0 "x"
+ OpMemberName %S_atomic 1 "a"
+ OpMemberName %S_atomic 2 "y"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %S_atomic 0 Offset 0
+ OpMemberDecorate %S_atomic 1 Offset 4
+ OpMemberDecorate %S_atomic 2 Offset 8
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+ %S_atomic = OpTypeStruct %int %uint %uint
+%_ptr_Workgroup_S_atomic = OpTypePointer Workgroup %S_atomic
+ %wg = OpVariable %_ptr_Workgroup_S_atomic Workgroup
+ %void = OpTypeVoid
+ %11 = OpTypeFunction %void %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %19 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_1 = OpConstant %uint 1
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+%_ptr_Workgroup_uint_0 = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %33 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %11
+%local_invocation_index = OpFunctionParameter %uint
+ %15 = OpLabel
+ %18 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %18 %19
+ %25 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %25 %uint_2 %uint_0 %6
+ %27 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %uint_2
+ OpStore %27 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %32 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %32 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %33
+ %35 = OpLabel
+ %36 = OpLoad %uint %local_invocation_index_1
+ %37 = OpFunctionCall %void %compute_main_inner %36
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %11
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %40 = OpLabel
+ %41 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %41 %19
+ %44 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %44 %uint_2 %uint_0 %6
+ %45 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %uint_2
+ OpStore %45 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %47 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %33
+ %49 = OpLabel
+ %51 = OpLoad %uint %local_invocation_index_1_param_1
+ %50 = OpFunctionCall %void %compute_main_inner_1 %51
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.wgsl
new file mode 100644
index 0000000..2d90f56
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_single_atomic.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct S_atomic {
+ x : i32,
+ a : atomic<u32>,
+ y : u32,
+}
+
+struct S {
+ x : i32,
+ a : u32,
+ y : u32,
+}
+
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> wg : S_atomic;
+
+fn compute_main_inner(local_invocation_index : u32) {
+ wg.x = 0i;
+ atomicStore(&(wg.a), 0u);
+ wg.y = 0u;
+ workgroupBarrier();
+ atomicStore(&(wg.a), 1u);
+ return;
+}
+
+fn compute_main_1() {
+ let x_35 : u32 = local_invocation_index_1;
+ compute_main_inner(x_35);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomicStore/struct/flat_single_atomic.wgsl b/test/tint/builtins/atomicStore/struct/flat_single_atomic.wgsl
new file mode 100644
index 0000000..e997e87
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/flat_single_atomic.wgsl
@@ -0,0 +1,12 @@
+struct S {
+ x : i32,
+ a : atomic<u32>,
+ y : u32,
+};
+
+var<workgroup> wg: S;
+
+@compute @workgroup_size(1)
+fn compute_main() {
+ atomicStore(&wg.a, 1u);
+}
diff --git a/test/tint/builtins/atomicStore/struct/nested.spvasm b/test/tint/builtins/atomicStore/struct/nested.spvasm
new file mode 100644
index 0000000..a8aaff3
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/nested.spvasm
@@ -0,0 +1,97 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 45
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %S2 "S2"
+ OpMemberName %S2 0 "x"
+ OpMemberName %S2 1 "y"
+ OpMemberName %S2 2 "z"
+ OpMemberName %S2 3 "a"
+ OpName %S1 "S1"
+ OpMemberName %S1 0 "x"
+ OpMemberName %S1 1 "a"
+ OpName %S0 "S0"
+ OpMemberName %S0 0 "x"
+ OpMemberName %S0 1 "a"
+ OpMemberName %S0 2 "y"
+ OpMemberName %S0 3 "z"
+ OpMemberName %S1 2 "y"
+ OpMemberName %S1 3 "z"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %S2 0 Offset 0
+ OpMemberDecorate %S2 1 Offset 4
+ OpMemberDecorate %S2 2 Offset 8
+ OpMemberDecorate %S2 3 Offset 12
+ OpMemberDecorate %S1 0 Offset 0
+ OpMemberDecorate %S1 1 Offset 4
+ OpMemberDecorate %S0 0 Offset 0
+ OpMemberDecorate %S0 1 Offset 4
+ OpMemberDecorate %S0 2 Offset 8
+ OpMemberDecorate %S0 3 Offset 12
+ OpMemberDecorate %S1 2 Offset 20
+ OpMemberDecorate %S1 3 Offset 24
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+ %S0 = OpTypeStruct %int %uint %int %int
+ %S1 = OpTypeStruct %int %S0 %int %int
+ %S2 = OpTypeStruct %int %int %int %S1
+%_ptr_Workgroup_S2 = OpTypePointer Workgroup %S2
+ %wg = OpVariable %_ptr_Workgroup_S2 Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %18 = OpConstantNull %int
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_3 = OpConstant %uint 3
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %30 = OpConstantNull %uint
+ %uint_264 = OpConstant %uint 264
+ %40 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %10
+%local_invocation_index = OpFunctionParameter %uint
+ %14 = OpLabel
+ %17 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %17 %18
+ %20 = OpAccessChain %_ptr_Workgroup_int %wg %uint_1
+ OpStore %20 %18
+ %22 = OpAccessChain %_ptr_Workgroup_int %wg %uint_2
+ OpStore %22 %18
+ %24 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_0
+ OpStore %24 %18
+ %25 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_1 %uint_0
+ OpStore %25 %18
+ %29 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_3 %uint_1 %uint_1
+ OpAtomicStore %29 %uint_2 %uint_0 %30
+ %31 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_1 %uint_2
+ OpStore %31 %18
+ %32 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_1 %uint_3
+ OpStore %32 %18
+ %33 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_2
+ OpStore %33 %18
+ %34 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_3
+ OpStore %34 %18
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %39 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_3 %uint_1 %uint_1
+ OpAtomicStore %39 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %40
+ %42 = OpLabel
+ %44 = OpLoad %uint %local_invocation_index_1
+ %43 = OpFunctionCall %void %compute_main_inner %44
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.glsl b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.glsl
new file mode 100644
index 0000000..1d63b30
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.glsl
@@ -0,0 +1,90 @@
+#version 310 es
+
+struct S0_atomic {
+ int x;
+ uint a;
+ int y;
+ int z;
+};
+
+struct S0 {
+ int x;
+ uint a;
+ int y;
+ int z;
+};
+
+struct S1_atomic {
+ int x;
+ S0_atomic a;
+ int y;
+ int z;
+};
+
+struct S1 {
+ int x;
+ S0 a;
+ int y;
+ int z;
+};
+
+struct S2_atomic {
+ int x;
+ int y;
+ int z;
+ S1_atomic a;
+};
+
+struct S2 {
+ int x;
+ int y;
+ int z;
+ S1 a;
+};
+
+uint local_invocation_index_1 = 0u;
+shared S2_atomic wg;
+void compute_main_inner(uint local_invocation_index) {
+ wg.x = 0;
+ wg.y = 0;
+ wg.z = 0;
+ wg.a.x = 0;
+ wg.a.a.x = 0;
+ atomicExchange(wg.a.a.a, 0u);
+ wg.a.a.y = 0;
+ wg.a.a.z = 0;
+ wg.a.y = 0;
+ wg.a.z = 0;
+ barrier();
+ atomicExchange(wg.a.a.a, 1u);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ wg.x = 0;
+ wg.y = 0;
+ wg.z = 0;
+ wg.a.x = 0;
+ wg.a.a.x = 0;
+ atomicExchange(wg.a.a.a, 0u);
+ wg.a.a.y = 0;
+ wg.a.a.z = 0;
+ wg.a.y = 0;
+ wg.a.z = 0;
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.hlsl b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.hlsl
new file mode 100644
index 0000000..4449c42
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.hlsl
@@ -0,0 +1,73 @@
+struct S0_atomic {
+ int x;
+ uint a;
+ int y;
+ int z;
+};
+struct S1_atomic {
+ int x;
+ S0_atomic a;
+ int y;
+ int z;
+};
+struct S2_atomic {
+ int x;
+ int y;
+ int z;
+ S1_atomic a;
+};
+
+static uint local_invocation_index_1 = 0u;
+groupshared S2_atomic wg;
+
+void compute_main_inner(uint local_invocation_index) {
+ wg.x = 0;
+ wg.y = 0;
+ wg.z = 0;
+ wg.a.x = 0;
+ wg.a.a.x = 0;
+ uint atomic_result = 0u;
+ InterlockedExchange(wg.a.a.a, 0u, atomic_result);
+ wg.a.a.y = 0;
+ wg.a.a.z = 0;
+ wg.a.y = 0;
+ wg.a.z = 0;
+ GroupMemoryBarrierWithGroupSync();
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(wg.a.a.a, 1u, atomic_result_1);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ wg.x = 0;
+ wg.y = 0;
+ wg.z = 0;
+ wg.a.x = 0;
+ wg.a.a.x = 0;
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(wg.a.a.a, 0u, atomic_result_2);
+ wg.a.a.y = 0;
+ wg.a.a.z = 0;
+ wg.a.y = 0;
+ wg.a.z = 0;
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.msl b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.msl
new file mode 100644
index 0000000..1ed439c
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.msl
@@ -0,0 +1,92 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct S0_atomic {
+ int x;
+ atomic_uint a;
+ int y;
+ int z;
+};
+
+struct S0 {
+ int x;
+ uint a;
+ int y;
+ int z;
+};
+
+struct S1_atomic {
+ int x;
+ S0_atomic a;
+ int y;
+ int z;
+};
+
+struct S1 {
+ int x;
+ S0 a;
+ int y;
+ int z;
+};
+
+struct S2_atomic {
+ int x;
+ int y;
+ int z;
+ S1_atomic a;
+};
+
+struct S2 {
+ int x;
+ int y;
+ int z;
+ S1 a;
+};
+
+void compute_main_inner(uint local_invocation_index, threadgroup S2_atomic* const tint_symbol) {
+ (*(tint_symbol)).x = 0;
+ (*(tint_symbol)).y = 0;
+ (*(tint_symbol)).z = 0;
+ (*(tint_symbol)).a.x = 0;
+ (*(tint_symbol)).a.a.x = 0;
+ atomic_store_explicit(&((*(tint_symbol)).a.a.a), 0u, memory_order_relaxed);
+ (*(tint_symbol)).a.a.y = 0;
+ (*(tint_symbol)).a.a.z = 0;
+ (*(tint_symbol)).a.y = 0;
+ (*(tint_symbol)).a.z = 0;
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomic_store_explicit(&((*(tint_symbol)).a.a.a), 1u, memory_order_relaxed);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_1, threadgroup S2_atomic* const tint_symbol_2) {
+ uint const x_44 = *(tint_symbol_1);
+ compute_main_inner(x_44, tint_symbol_2);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup S2_atomic* const tint_symbol_3, thread uint* const tint_symbol_4) {
+ {
+ (*(tint_symbol_3)).x = 0;
+ (*(tint_symbol_3)).y = 0;
+ (*(tint_symbol_3)).z = 0;
+ (*(tint_symbol_3)).a.x = 0;
+ (*(tint_symbol_3)).a.a.x = 0;
+ atomic_store_explicit(&((*(tint_symbol_3)).a.a.a), 0u, memory_order_relaxed);
+ (*(tint_symbol_3)).a.a.y = 0;
+ (*(tint_symbol_3)).a.a.z = 0;
+ (*(tint_symbol_3)).a.y = 0;
+ (*(tint_symbol_3)).a.z = 0;
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_4) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_4, tint_symbol_3);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup S2_atomic tint_symbol_5;
+ thread uint tint_symbol_6 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_5), &(tint_symbol_6));
+ return;
+}
+
diff --git a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.spvasm
new file mode 100644
index 0000000..9f756f3
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.spvasm
@@ -0,0 +1,137 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 68
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %S2_atomic "S2_atomic"
+ OpMemberName %S2_atomic 0 "x"
+ OpMemberName %S2_atomic 1 "y"
+ OpMemberName %S2_atomic 2 "z"
+ OpMemberName %S2_atomic 3 "a"
+ OpName %S1_atomic "S1_atomic"
+ OpMemberName %S1_atomic 0 "x"
+ OpMemberName %S1_atomic 1 "a"
+ OpName %S0_atomic "S0_atomic"
+ OpMemberName %S0_atomic 0 "x"
+ OpMemberName %S0_atomic 1 "a"
+ OpMemberName %S0_atomic 2 "y"
+ OpMemberName %S0_atomic 3 "z"
+ OpMemberName %S1_atomic 2 "y"
+ OpMemberName %S1_atomic 3 "z"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %S2_atomic 0 Offset 0
+ OpMemberDecorate %S2_atomic 1 Offset 4
+ OpMemberDecorate %S2_atomic 2 Offset 8
+ OpMemberDecorate %S2_atomic 3 Offset 12
+ OpMemberDecorate %S1_atomic 0 Offset 0
+ OpMemberDecorate %S1_atomic 1 Offset 4
+ OpMemberDecorate %S0_atomic 0 Offset 0
+ OpMemberDecorate %S0_atomic 1 Offset 4
+ OpMemberDecorate %S0_atomic 2 Offset 8
+ OpMemberDecorate %S0_atomic 3 Offset 12
+ OpMemberDecorate %S1_atomic 2 Offset 20
+ OpMemberDecorate %S1_atomic 3 Offset 24
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+ %S0_atomic = OpTypeStruct %int %uint %int %int
+ %S1_atomic = OpTypeStruct %int %S0_atomic %int %int
+ %S2_atomic = OpTypeStruct %int %int %int %S1_atomic
+%_ptr_Workgroup_S2_atomic = OpTypePointer Workgroup %S2_atomic
+ %wg = OpVariable %_ptr_Workgroup_S2_atomic Workgroup
+ %void = OpTypeVoid
+ %13 = OpTypeFunction %void %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %21 = OpConstantNull %int
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_3 = OpConstant %uint 3
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %42 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %13
+%local_invocation_index = OpFunctionParameter %uint
+ %17 = OpLabel
+ %20 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %20 %21
+ %23 = OpAccessChain %_ptr_Workgroup_int %wg %uint_1
+ OpStore %23 %21
+ %25 = OpAccessChain %_ptr_Workgroup_int %wg %uint_2
+ OpStore %25 %21
+ %27 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_0
+ OpStore %27 %21
+ %28 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_1 %uint_0
+ OpStore %28 %21
+ %32 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_3 %uint_1 %uint_1
+ OpAtomicStore %32 %uint_2 %uint_0 %6
+ %33 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_1 %uint_2
+ OpStore %33 %21
+ %34 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_1 %uint_3
+ OpStore %34 %21
+ %35 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_2
+ OpStore %35 %21
+ %36 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_3
+ OpStore %36 %21
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %41 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_3 %uint_1 %uint_1
+ OpAtomicStore %41 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %42
+ %44 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1
+ %46 = OpFunctionCall %void %compute_main_inner %45
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %13
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %49 = OpLabel
+ %50 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %50 %21
+ %51 = OpAccessChain %_ptr_Workgroup_int %wg %uint_1
+ OpStore %51 %21
+ %52 = OpAccessChain %_ptr_Workgroup_int %wg %uint_2
+ OpStore %52 %21
+ %53 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_0
+ OpStore %53 %21
+ %54 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_1 %uint_0
+ OpStore %54 %21
+ %57 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_3 %uint_1 %uint_1
+ OpAtomicStore %57 %uint_2 %uint_0 %6
+ %58 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_1 %uint_2
+ OpStore %58 %21
+ %59 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_1 %uint_3
+ OpStore %59 %21
+ %60 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_2
+ OpStore %60 %21
+ %61 = OpAccessChain %_ptr_Workgroup_int %wg %uint_3 %uint_3
+ OpStore %61 %21
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %63 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %42
+ %65 = OpLabel
+ %67 = OpLoad %uint %local_invocation_index_1_param_1
+ %66 = OpFunctionCall %void %compute_main_inner_1 %67
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.wgsl
new file mode 100644
index 0000000..7f3c3b3
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/nested.spvasm.expected.wgsl
@@ -0,0 +1,73 @@
+struct S0_atomic {
+ x : i32,
+ a : atomic<u32>,
+ y : i32,
+ z : i32,
+}
+
+struct S0 {
+ x : i32,
+ a : u32,
+ y : i32,
+ z : i32,
+}
+
+struct S1_atomic {
+ x : i32,
+ a : S0_atomic,
+ y : i32,
+ z : i32,
+}
+
+struct S1 {
+ x : i32,
+ a : S0,
+ y : i32,
+ z : i32,
+}
+
+struct S2_atomic {
+ x : i32,
+ y : i32,
+ z : i32,
+ a : S1_atomic,
+}
+
+struct S2 {
+ x : i32,
+ y : i32,
+ z : i32,
+ a : S1,
+}
+
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> wg : S2_atomic;
+
+fn compute_main_inner(local_invocation_index : u32) {
+ wg.x = 0i;
+ wg.y = 0i;
+ wg.z = 0i;
+ wg.a.x = 0i;
+ wg.a.a.x = 0i;
+ atomicStore(&(wg.a.a.a), 0u);
+ wg.a.a.y = 0i;
+ wg.a.a.z = 0i;
+ wg.a.y = 0i;
+ wg.a.z = 0i;
+ workgroupBarrier();
+ atomicStore(&(wg.a.a.a), 1u);
+ return;
+}
+
+fn compute_main_1() {
+ let x_44 : u32 = local_invocation_index_1;
+ compute_main_inner(x_44);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomicStore/struct/nested.wgsl b/test/tint/builtins/atomicStore/struct/nested.wgsl
new file mode 100644
index 0000000..e6b0abe
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/nested.wgsl
@@ -0,0 +1,27 @@
+struct S0 {
+ x : i32,
+ a : atomic<u32>,
+ y : i32,
+ z : i32,
+};
+
+struct S1 {
+ x : i32,
+ a : S0,
+ y : i32,
+ z : i32,
+};
+
+struct S2 {
+ x : i32,
+ y : i32,
+ z : i32,
+ a : S1,
+};
+
+var<workgroup> wg: S2;
+
+@compute @workgroup_size(1)
+fn compute_main() {
+ atomicStore(&wg.a.a.a, 1u);
+}
diff --git a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm
new file mode 100644
index 0000000..9d06d13
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm
@@ -0,0 +1,91 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 54
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %S "S"
+ OpMemberName %S 0 "x"
+ OpMemberName %S 1 "a"
+ OpMemberName %S 2 "y"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %idx "idx"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %S 0 Offset 0
+ OpMemberDecorate %S 1 Offset 4
+ OpDecorate %_arr_uint_uint_10 ArrayStride 4
+ OpMemberDecorate %S 2 Offset 44
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+ %uint_10 = OpConstant %uint 10
+%_arr_uint_uint_10 = OpTypeArray %uint %uint_10
+ %S = OpTypeStruct %int %_arr_uint_uint_10 %uint
+%_ptr_Workgroup_S = OpTypePointer Workgroup %S
+ %wg = OpVariable %_ptr_Workgroup_S Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %18 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %22 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %bool = OpTypeBool
+ %uint_1 = OpConstant %uint 1
+%_ptr_Workgroup_uint_0 = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %int_4 = OpConstant %int 4
+ %49 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %10
+%local_invocation_index = OpFunctionParameter %uint
+ %14 = OpLabel
+ %idx = OpVariable %_ptr_Function_uint Function %22
+ %17 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %17 %18
+ %21 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_2
+ OpStore %21 %22
+ OpStore %idx %local_invocation_index
+ OpBranch %25
+ %25 = OpLabel
+ OpLoopMerge %26 %27 None
+ OpBranch %28
+ %28 = OpLabel
+ %30 = OpLoad %uint %idx
+ %31 = OpULessThan %bool %30 %uint_10
+ %29 = OpLogicalNot %bool %31
+ OpSelectionMerge %33 None
+ OpBranchConditional %29 %34 %33
+ %34 = OpLabel
+ OpBranch %26
+ %33 = OpLabel
+ %35 = OpLoad %uint %idx
+ %40 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %uint_1 %35
+ OpAtomicStore %40 %uint_2 %uint_0 %22
+ OpBranch %27
+ %27 = OpLabel
+ %41 = OpLoad %uint %idx
+ %42 = OpIAdd %uint %41 %uint_1
+ OpStore %idx %42
+ OpBranch %25
+ %26 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %48 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %uint_1 %int_4
+ OpAtomicStore %48 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %49
+ %51 = OpLabel
+ %53 = OpLoad %uint %local_invocation_index_1
+ %52 = OpFunctionCall %void %compute_main_inner %53
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.glsl b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.glsl
new file mode 100644
index 0000000..0a37b13
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.glsl
@@ -0,0 +1,57 @@
+#version 310 es
+
+struct S_atomic {
+ int x;
+ uint a[10];
+ uint y;
+};
+
+struct S {
+ int x;
+ uint a[10];
+ uint y;
+};
+
+uint local_invocation_index_1 = 0u;
+shared S_atomic wg;
+void compute_main_inner(uint local_invocation_index) {
+ uint idx = 0u;
+ wg.x = 0;
+ wg.y = 0u;
+ idx = local_invocation_index;
+ {
+ for(; !(!((idx < 10u))); idx = (idx + 1u)) {
+ atomicExchange(wg.a[idx], 0u);
+ }
+ }
+ barrier();
+ atomicExchange(wg.a[4], 1u);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ wg.x = 0;
+ wg.y = 0u;
+ }
+ {
+ for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 10u); idx_1 = (idx_1 + 1u)) {
+ uint i = idx_1;
+ atomicExchange(wg.a[i], 0u);
+ }
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.hlsl b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.hlsl
new file mode 100644
index 0000000..beb2810
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.hlsl
@@ -0,0 +1,57 @@
+struct S_atomic {
+ int x;
+ uint a[10];
+ uint y;
+};
+
+static uint local_invocation_index_1 = 0u;
+groupshared S_atomic wg;
+
+void compute_main_inner(uint local_invocation_index) {
+ uint idx = 0u;
+ wg.x = 0;
+ wg.y = 0u;
+ idx = local_invocation_index;
+ {
+ [loop] for(; !(!((idx < 10u))); idx = (idx + 1u)) {
+ uint atomic_result = 0u;
+ InterlockedExchange(wg.a[idx], 0u, atomic_result);
+ }
+ }
+ GroupMemoryBarrierWithGroupSync();
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(wg.a[4], 1u, atomic_result_1);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ wg.x = 0;
+ wg.y = 0u;
+ }
+ {
+ [loop] for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 10u); idx_1 = (idx_1 + 1u)) {
+ const uint i = idx_1;
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(wg.a[i], 0u, atomic_result_2);
+ }
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.msl b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.msl
new file mode 100644
index 0000000..089c011
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.msl
@@ -0,0 +1,72 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct tint_array_wrapper {
+ uint arr[10];
+};
+
+struct tint_array_wrapper_1 {
+ atomic_uint arr[10];
+};
+
+struct S_atomic {
+ int x;
+ tint_array_wrapper_1 a;
+ uint y;
+};
+
+struct S {
+ int x;
+ tint_array_wrapper a;
+ uint y;
+};
+
+void compute_main_inner(uint local_invocation_index, threadgroup S_atomic* const tint_symbol) {
+ uint idx = 0u;
+ (*(tint_symbol)).x = 0;
+ (*(tint_symbol)).y = 0u;
+ idx = local_invocation_index;
+ while (true) {
+ uint const x_30 = idx;
+ if (!((x_30 < 10u))) {
+ break;
+ }
+ uint const x_35 = idx;
+ atomic_store_explicit(&((*(tint_symbol)).a.arr[x_35]), 0u, memory_order_relaxed);
+ {
+ uint const x_41 = idx;
+ idx = (x_41 + 1u);
+ }
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomic_store_explicit(&((*(tint_symbol)).a.arr[4]), 1u, memory_order_relaxed);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_1, threadgroup S_atomic* const tint_symbol_2) {
+ uint const x_53 = *(tint_symbol_1);
+ compute_main_inner(x_53, tint_symbol_2);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup S_atomic* const tint_symbol_3, thread uint* const tint_symbol_4) {
+ {
+ (*(tint_symbol_3)).x = 0;
+ (*(tint_symbol_3)).y = 0u;
+ }
+ for(uint idx_1 = local_invocation_index_1_param; (idx_1 < 10u); idx_1 = (idx_1 + 1u)) {
+ uint const i = idx_1;
+ atomic_store_explicit(&((*(tint_symbol_3)).a.arr[i]), 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_4) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_4, tint_symbol_3);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup S_atomic tint_symbol_5;
+ thread uint tint_symbol_6 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_5), &(tint_symbol_6));
+ return;
+}
+
diff --git a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.spvasm
new file mode 100644
index 0000000..d774374
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.spvasm
@@ -0,0 +1,142 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 83
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %S_atomic "S_atomic"
+ OpMemberName %S_atomic 0 "x"
+ OpMemberName %S_atomic 1 "a"
+ OpMemberName %S_atomic 2 "y"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %idx "idx"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %idx_1 "idx_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %S_atomic 0 Offset 0
+ OpMemberDecorate %S_atomic 1 Offset 4
+ OpDecorate %_arr_uint_uint_10 ArrayStride 4
+ OpMemberDecorate %S_atomic 2 Offset 44
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+ %uint_10 = OpConstant %uint 10
+%_arr_uint_uint_10 = OpTypeArray %uint %uint_10
+ %S_atomic = OpTypeStruct %int %_arr_uint_uint_10 %uint
+%_ptr_Workgroup_S_atomic = OpTypePointer Workgroup %S_atomic
+ %wg = OpVariable %_ptr_Workgroup_S_atomic Workgroup
+ %void = OpTypeVoid
+ %13 = OpTypeFunction %void %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %23 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %bool = OpTypeBool
+ %uint_1 = OpConstant %uint 1
+%_ptr_Workgroup_uint_0 = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %int_4 = OpConstant %int 4
+ %51 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %13
+%local_invocation_index = OpFunctionParameter %uint
+ %17 = OpLabel
+ %idx = OpVariable %_ptr_Function_uint Function %6
+ OpStore %idx %6
+ %22 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %22 %23
+ %26 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_2
+ OpStore %26 %6
+ OpStore %idx %local_invocation_index
+ OpBranch %27
+ %27 = OpLabel
+ OpLoopMerge %28 %29 None
+ OpBranch %30
+ %30 = OpLabel
+ %31 = OpLoad %uint %idx
+ %33 = OpULessThan %bool %31 %uint_10
+ %32 = OpLogicalNot %bool %33
+ OpSelectionMerge %35 None
+ OpBranchConditional %32 %36 %35
+ %36 = OpLabel
+ OpBranch %28
+ %35 = OpLabel
+ %37 = OpLoad %uint %idx
+ %42 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %uint_1 %37
+ OpAtomicStore %42 %uint_2 %uint_0 %6
+ OpBranch %29
+ %29 = OpLabel
+ %43 = OpLoad %uint %idx
+ %44 = OpIAdd %uint %43 %uint_1
+ OpStore %idx %44
+ OpBranch %27
+ %28 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %50 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %uint_1 %int_4
+ OpAtomicStore %50 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %51
+ %53 = OpLabel
+ %54 = OpLoad %uint %local_invocation_index_1
+ %55 = OpFunctionCall %void %compute_main_inner %54
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %13
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %58 = OpLabel
+ %idx_1 = OpVariable %_ptr_Function_uint Function %6
+ %59 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %59 %23
+ %60 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_2
+ OpStore %60 %6
+ OpStore %idx_1 %local_invocation_index_1_param
+ OpBranch %62
+ %62 = OpLabel
+ OpLoopMerge %63 %64 None
+ OpBranch %65
+ %65 = OpLabel
+ %67 = OpLoad %uint %idx_1
+ %68 = OpULessThan %bool %67 %uint_10
+ %66 = OpLogicalNot %bool %68
+ OpSelectionMerge %69 None
+ OpBranchConditional %66 %70 %69
+ %70 = OpLabel
+ OpBranch %63
+ %69 = OpLabel
+ %71 = OpLoad %uint %idx_1
+ %74 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %uint_1 %71
+ OpAtomicStore %74 %uint_2 %uint_0 %6
+ OpBranch %64
+ %64 = OpLabel
+ %75 = OpLoad %uint %idx_1
+ %76 = OpIAdd %uint %75 %uint_1
+ OpStore %idx_1 %76
+ OpBranch %62
+ %63 = OpLabel
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %78 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %51
+ %80 = OpLabel
+ %82 = OpLoad %uint %local_invocation_index_1_param_1
+ %81 = OpFunctionCall %void %compute_main_inner_1 %82
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.wgsl
new file mode 100644
index 0000000..f82a9ff
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/struct_of_array.spvasm.expected.wgsl
@@ -0,0 +1,52 @@
+type Arr = array<u32, 10u>;
+
+struct S_atomic {
+ x : i32,
+ a : array<atomic<u32>, 10u>,
+ y : u32,
+}
+
+struct S {
+ x : i32,
+ a : Arr,
+ y : u32,
+}
+
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> wg : S_atomic;
+
+fn compute_main_inner(local_invocation_index : u32) {
+ var idx : u32 = 0u;
+ wg.x = 0i;
+ wg.y = 0u;
+ idx = local_invocation_index;
+ loop {
+ let x_30 : u32 = idx;
+ if (!((x_30 < 10u))) {
+ break;
+ }
+ let x_35 : u32 = idx;
+ atomicStore(&(wg.a[x_35]), 0u);
+
+ continuing {
+ let x_41 : u32 = idx;
+ idx = (x_41 + 1u);
+ }
+ }
+ workgroupBarrier();
+ atomicStore(&(wg.a[4i]), 1u);
+ return;
+}
+
+fn compute_main_1() {
+ let x_53 : u32 = local_invocation_index_1;
+ compute_main_inner(x_53);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomicStore/struct/struct_of_array.wgsl b/test/tint/builtins/atomicStore/struct/struct_of_array.wgsl
new file mode 100644
index 0000000..ada3ef5
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/struct_of_array.wgsl
@@ -0,0 +1,12 @@
+struct S {
+ x : i32,
+ a : array<atomic<u32>, 10>,
+ y : u32,
+};
+
+var<workgroup> wg : S;
+
+@compute @workgroup_size(1)
+fn compute_main() {
+ atomicStore(&wg.a[4], 1u);
+}
diff --git a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm
new file mode 100644
index 0000000..acad988
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm
@@ -0,0 +1,61 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 36
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %S "S"
+ OpMemberName %S 0 "x"
+ OpMemberName %S 1 "a"
+ OpMemberName %S 2 "y"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %S 0 Offset 0
+ OpMemberDecorate %S 1 Offset 4
+ OpMemberDecorate %S 2 Offset 8
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+ %S = OpTypeStruct %int %uint %uint
+%_ptr_Workgroup_S = OpTypePointer Workgroup %S
+ %wg = OpVariable %_ptr_Workgroup_S Workgroup
+ %void = OpTypeVoid
+ %8 = OpTypeFunction %void %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %16 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_1 = OpConstant %uint 1
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %23 = OpConstantNull %uint
+%_ptr_Workgroup_uint_0 = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %31 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %8
+%local_invocation_index = OpFunctionParameter %uint
+ %12 = OpLabel
+ %15 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %15 %16
+ %22 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %22 %uint_2 %uint_0 %23
+ %25 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %uint_2
+ OpStore %25 %23
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %30 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %31
+ %33 = OpLabel
+ %35 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %35
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.glsl b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.glsl
new file mode 100644
index 0000000..2b03ef6
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.glsl
@@ -0,0 +1,46 @@
+#version 310 es
+
+struct S_atomic {
+ int x;
+ uint a;
+ uint y;
+};
+
+struct S {
+ int x;
+ uint a;
+ uint y;
+};
+
+uint local_invocation_index_1 = 0u;
+shared S_atomic wg;
+void compute_main_inner(uint local_invocation_index) {
+ wg.x = 0;
+ atomicExchange(wg.a, 0u);
+ wg.y = 0u;
+ barrier();
+ atomicExchange(wg.a, 1u);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ wg.x = 0;
+ atomicExchange(wg.a, 0u);
+ wg.y = 0u;
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.hlsl b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.hlsl
new file mode 100644
index 0000000..403d1fb
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+struct S_atomic {
+ int x;
+ uint a;
+ uint y;
+};
+
+static uint local_invocation_index_1 = 0u;
+groupshared S_atomic wg;
+
+void compute_main_inner(uint local_invocation_index) {
+ wg.x = 0;
+ uint atomic_result = 0u;
+ InterlockedExchange(wg.a, 0u, atomic_result);
+ wg.y = 0u;
+ GroupMemoryBarrierWithGroupSync();
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(wg.a, 1u, atomic_result_1);
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ wg.x = 0;
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(wg.a, 0u, atomic_result_2);
+ wg.y = 0u;
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.msl b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.msl
new file mode 100644
index 0000000..524820a
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.msl
@@ -0,0 +1,48 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct S_atomic {
+ int x;
+ atomic_uint a;
+ uint y;
+};
+
+struct S {
+ int x;
+ uint a;
+ uint y;
+};
+
+void compute_main_inner(uint local_invocation_index, threadgroup S_atomic* const tint_symbol) {
+ (*(tint_symbol)).x = 0;
+ atomic_store_explicit(&((*(tint_symbol)).a), 0u, memory_order_relaxed);
+ (*(tint_symbol)).y = 0u;
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomic_store_explicit(&((*(tint_symbol)).a), 1u, memory_order_relaxed);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_1, threadgroup S_atomic* const tint_symbol_2) {
+ uint const x_35 = *(tint_symbol_1);
+ compute_main_inner(x_35, tint_symbol_2);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup S_atomic* const tint_symbol_3, thread uint* const tint_symbol_4) {
+ {
+ (*(tint_symbol_3)).x = 0;
+ atomic_store_explicit(&((*(tint_symbol_3)).a), 0u, memory_order_relaxed);
+ (*(tint_symbol_3)).y = 0u;
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_4) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_4, tint_symbol_3);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup S_atomic tint_symbol_5;
+ thread uint tint_symbol_6 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_5), &(tint_symbol_6));
+ return;
+}
+
diff --git a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.spvasm b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.spvasm
new file mode 100644
index 0000000..35d0d2b
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.spvasm
@@ -0,0 +1,87 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 52
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %S_atomic "S_atomic"
+ OpMemberName %S_atomic 0 "x"
+ OpMemberName %S_atomic 1 "a"
+ OpMemberName %S_atomic 2 "y"
+ OpName %wg "wg"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %S_atomic 0 Offset 0
+ OpMemberDecorate %S_atomic 1 Offset 4
+ OpMemberDecorate %S_atomic 2 Offset 8
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+ %S_atomic = OpTypeStruct %int %uint %uint
+%_ptr_Workgroup_S_atomic = OpTypePointer Workgroup %S_atomic
+ %wg = OpVariable %_ptr_Workgroup_S_atomic Workgroup
+ %void = OpTypeVoid
+ %11 = OpTypeFunction %void %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %19 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_1 = OpConstant %uint 1
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+%_ptr_Workgroup_uint_0 = OpTypePointer Workgroup %uint
+ %uint_264 = OpConstant %uint 264
+ %33 = OpTypeFunction %void
+%compute_main_inner = OpFunction %void None %11
+%local_invocation_index = OpFunctionParameter %uint
+ %15 = OpLabel
+ %18 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %18 %19
+ %25 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %25 %uint_2 %uint_0 %6
+ %27 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %uint_2
+ OpStore %27 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %32 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %32 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %33
+ %35 = OpLabel
+ %36 = OpLoad %uint %local_invocation_index_1
+ %37 = OpFunctionCall %void %compute_main_inner %36
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %11
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %40 = OpLabel
+ %41 = OpAccessChain %_ptr_Workgroup_int %wg %uint_0
+ OpStore %41 %19
+ %44 = OpAccessChain %_ptr_Workgroup_uint %wg %uint_1
+ OpAtomicStore %44 %uint_2 %uint_0 %6
+ %45 = OpAccessChain %_ptr_Workgroup_uint_0 %wg %uint_2
+ OpStore %45 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %47 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %33
+ %49 = OpLabel
+ %51 = OpLoad %uint %local_invocation_index_1_param_1
+ %50 = OpFunctionCall %void %compute_main_inner_1 %51
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.wgsl b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.wgsl
new file mode 100644
index 0000000..2d90f56
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/via_ptr_let.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct S_atomic {
+ x : i32,
+ a : atomic<u32>,
+ y : u32,
+}
+
+struct S {
+ x : i32,
+ a : u32,
+ y : u32,
+}
+
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> wg : S_atomic;
+
+fn compute_main_inner(local_invocation_index : u32) {
+ wg.x = 0i;
+ atomicStore(&(wg.a), 0u);
+ wg.y = 0u;
+ workgroupBarrier();
+ atomicStore(&(wg.a), 1u);
+ return;
+}
+
+fn compute_main_1() {
+ let x_35 : u32 = local_invocation_index_1;
+ compute_main_inner(x_35);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomicStore/struct/via_ptr_let.wgsl b/test/tint/builtins/atomicStore/struct/via_ptr_let.wgsl
new file mode 100644
index 0000000..64eeb65
--- /dev/null
+++ b/test/tint/builtins/atomicStore/struct/via_ptr_let.wgsl
@@ -0,0 +1,14 @@
+struct S {
+ x : i32,
+ a : atomic<u32>,
+ y : u32,
+};
+
+var<workgroup> wg : S;
+
+@compute @workgroup_size(1)
+fn compute_main() {
+ let p0 = &wg;
+ let p1 = &((*p0).a);
+ atomicStore(p1, 1u);
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm
new file mode 100644
index 0000000..1167238
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_d32fe4 "atomicAdd_d32fe4"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %19 = OpConstantNull %int
+%atomicAdd_d32fe4 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %19
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %9 = OpAtomicIAdd %int %15 %uint_1 %uint_0 %int_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..875dc08
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAdd_d32fe4() {
+ int res = 0;
+ int x_9 = atomicAdd(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAdd_d32fe4() {
+ int res = 0;
+ int x_9 = atomicAdd(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..358487b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicAdd(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedAdd(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicAdd_d32fe4() {
+ int res = 0;
+ const int x_9 = tint_atomicAdd(sb_rw, 0u, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..64027ff
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicAdd_d32fe4(device SB_RW_atomic* const tint_symbol) {
+ int res = 0;
+ int const x_9 = atomic_fetch_add_explicit(&((*(tint_symbol)).arg_0), 1, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAdd_d32fe4(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAdd_d32fe4(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..13f287a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,66 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_d32fe4 "atomicAdd_d32fe4"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%atomicAdd_d32fe4 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %res %9
+ %18 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %12 = OpAtomicIAdd %int %18 %uint_1 %uint_0 %int_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..cfc64fb
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAdd_d32fe4() {
+ var res : i32 = 0i;
+ let x_9 : i32 = atomicAdd(&(sb_rw.arg_0), 1i);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm
new file mode 100644
index 0000000..3996635
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_8a199a "atomicAdd_8a199a"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+%atomicAdd_8a199a = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %9 = OpAtomicIAdd %uint %14 %uint_1 %uint_0 %uint_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..48a0735
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAdd_8a199a() {
+ uint res = 0u;
+ uint x_9 = atomicAdd(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAdd_8a199a() {
+ uint res = 0u;
+ uint x_9 = atomicAdd(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..bdc43b0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicAdd(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedAdd(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicAdd_8a199a() {
+ uint res = 0u;
+ const uint x_9 = tint_atomicAdd(sb_rw, 0u, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..fa2343b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicAdd_8a199a(device SB_RW_atomic* const tint_symbol) {
+ uint res = 0u;
+ uint const x_9 = atomic_fetch_add_explicit(&((*(tint_symbol)).arg_0), 1u, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAdd_8a199a(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAdd_8a199a(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..e1bf1e9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_8a199a "atomicAdd_8a199a"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicAdd_8a199a = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %res %9
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %12 = OpAtomicIAdd %uint %17 %uint_1 %uint_0 %uint_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..b5d5856
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAdd_8a199a() {
+ var res : u32 = 0u;
+ let x_9 : u32 = atomicAdd(&(sb_rw.arg_0), 1u);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm
new file mode 100644
index 0000000..d8903dc
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_794055 "atomicAdd_794055"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %18 = OpConstantNull %int
+ %19 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_794055 = OpFunction %void None %7
+ %10 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %18
+ %11 = OpAtomicIAdd %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %11
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %18
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %27 = OpFunctionCall %void %atomicAdd_794055
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %29 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %30 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..b745861
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicAdd_794055() {
+ int res = 0;
+ int x_11 = atomicAdd(arg_0, 1);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicAdd_794055();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..ccdf1ad
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicAdd_794055() {
+ int res = 0;
+ int atomic_result = 0;
+ InterlockedAdd(arg_0, 1, atomic_result);
+ const int x_11 = atomic_result;
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAdd_794055();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..62639d7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAdd_794055(threadgroup atomic_int* const tint_symbol) {
+ int res = 0;
+ int const x_11 = atomic_fetch_add_explicit(tint_symbol, 1, memory_order_relaxed);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAdd_794055(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_31 = *(tint_symbol_2);
+ compute_main_inner(x_31, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..3dc0a5d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_794055 "atomicAdd_794055"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_794055 = OpFunction %void None %10
+ %13 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %res %14
+ %17 = OpAtomicIAdd %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicAdd_794055
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..723a113
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicAdd_794055() {
+ var res : i32 = 0i;
+ let x_11 : i32 = atomicAdd(&(arg_0), 1i);
+ res = x_11;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicAdd_794055();
+ return;
+}
+
+fn compute_main_1() {
+ let x_31 : u32 = local_invocation_index_1;
+ compute_main_inner(x_31);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm
new file mode 100644
index 0000000..110fb42
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+ %18 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_d5db1d = OpFunction %void None %6
+ %9 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %10 = OpAtomicIAdd %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %10
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %18
+%local_invocation_index = OpFunctionParameter %uint
+ %21 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %17
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %26 = OpFunctionCall %void %atomicAdd_d5db1d
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %28 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %29 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..97c0c6f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicAdd_d5db1d() {
+ uint res = 0u;
+ uint x_10 = atomicAdd(arg_0, 1u);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicAdd_d5db1d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..c36ae57
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicAdd_d5db1d() {
+ uint res = 0u;
+ uint atomic_result = 0u;
+ InterlockedAdd(arg_0, 1u, atomic_result);
+ const uint x_10 = atomic_result;
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAdd_d5db1d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..04a890a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAdd_d5db1d(threadgroup atomic_uint* const tint_symbol) {
+ uint res = 0u;
+ uint const x_10 = atomic_fetch_add_explicit(tint_symbol, 1u, memory_order_relaxed);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAdd_d5db1d(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_30 = *(tint_symbol_2);
+ compute_main_inner(x_30, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..5daee64
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,74 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_d5db1d = OpFunction %void None %9
+ %12 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %res %6
+ %15 = OpAtomicIAdd %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicAdd_d5db1d
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %30 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %20
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %35 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %39 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %41 = OpLabel
+ %43 = OpLoad %uint %local_invocation_index_1_param_1
+ %42 = OpFunctionCall %void %compute_main_inner_1 %43
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..61d34cc
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAdd/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicAdd_d5db1d() {
+ var res : u32 = 0u;
+ let x_10 : u32 = atomicAdd(&(arg_0), 1u);
+ res = x_10;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicAdd_d5db1d();
+ return;
+}
+
+fn compute_main_1() {
+ let x_30 : u32 = local_invocation_index_1;
+ compute_main_inner(x_30);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm
new file mode 100644
index 0000000..ee4f5dc
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAnd_152966 "atomicAnd_152966"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %19 = OpConstantNull %int
+%atomicAnd_152966 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %19
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %9 = OpAtomicAnd %int %15 %uint_1 %uint_0 %int_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAnd_152966
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicAnd_152966
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..28adfe0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAnd_152966() {
+ int res = 0;
+ int x_9 = atomicAnd(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAnd_152966();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAnd_152966() {
+ int res = 0;
+ int x_9 = atomicAnd(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicAnd_152966();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..0cc23ee
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicAnd(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedAnd(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicAnd_152966() {
+ int res = 0;
+ const int x_9 = tint_atomicAnd(sb_rw, 0u, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAnd_152966();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAnd_152966();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..919a4e1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicAnd_152966(device SB_RW_atomic* const tint_symbol) {
+ int res = 0;
+ int const x_9 = atomic_fetch_and_explicit(&((*(tint_symbol)).arg_0), 1, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAnd_152966(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAnd_152966(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..0c6eb12
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,66 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAnd_152966 "atomicAnd_152966"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%atomicAnd_152966 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %res %9
+ %18 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %12 = OpAtomicAnd %int %18 %uint_1 %uint_0 %int_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAnd_152966
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicAnd_152966
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..c76ec1b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAnd_152966() {
+ var res : i32 = 0i;
+ let x_9 : i32 = atomicAnd(&(sb_rw.arg_0), 1i);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAnd_152966();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAnd_152966();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm
new file mode 100644
index 0000000..e45402c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAnd_85a8d9 "atomicAnd_85a8d9"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+%atomicAnd_85a8d9 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %9 = OpAtomicAnd %uint %14 %uint_1 %uint_0 %uint_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicAnd_85a8d9
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicAnd_85a8d9
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..6d879c1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAnd_85a8d9() {
+ uint res = 0u;
+ uint x_9 = atomicAnd(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAnd_85a8d9();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAnd_85a8d9() {
+ uint res = 0u;
+ uint x_9 = atomicAnd(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicAnd_85a8d9();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..897165d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicAnd(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedAnd(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicAnd_85a8d9() {
+ uint res = 0u;
+ const uint x_9 = tint_atomicAnd(sb_rw, 0u, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAnd_85a8d9();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAnd_85a8d9();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..2589380
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicAnd_85a8d9(device SB_RW_atomic* const tint_symbol) {
+ uint res = 0u;
+ uint const x_9 = atomic_fetch_and_explicit(&((*(tint_symbol)).arg_0), 1u, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAnd_85a8d9(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAnd_85a8d9(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..25da8d5
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAnd_85a8d9 "atomicAnd_85a8d9"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicAnd_85a8d9 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %res %9
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %12 = OpAtomicAnd %uint %17 %uint_1 %uint_0 %uint_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicAnd_85a8d9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicAnd_85a8d9
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..2f8f459
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAnd_85a8d9() {
+ var res : u32 = 0u;
+ let x_9 : u32 = atomicAnd(&(sb_rw.arg_0), 1u);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAnd_85a8d9();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAnd_85a8d9();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm
new file mode 100644
index 0000000..696d2a3
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAnd_45a819 "atomicAnd_45a819"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %18 = OpConstantNull %int
+ %19 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAnd_45a819 = OpFunction %void None %7
+ %10 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %18
+ %11 = OpAtomicAnd %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %11
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %18
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %27 = OpFunctionCall %void %atomicAnd_45a819
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %29 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %30 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..f914b2f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicAnd_45a819() {
+ int res = 0;
+ int x_11 = atomicAnd(arg_0, 1);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicAnd_45a819();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..2e86713
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicAnd_45a819() {
+ int res = 0;
+ int atomic_result = 0;
+ InterlockedAnd(arg_0, 1, atomic_result);
+ const int x_11 = atomic_result;
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAnd_45a819();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..ee4b602
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAnd_45a819(threadgroup atomic_int* const tint_symbol) {
+ int res = 0;
+ int const x_11 = atomic_fetch_and_explicit(tint_symbol, 1, memory_order_relaxed);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAnd_45a819(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_31 = *(tint_symbol_2);
+ compute_main_inner(x_31, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..b7e9939
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAnd_45a819 "atomicAnd_45a819"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAnd_45a819 = OpFunction %void None %10
+ %13 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %res %14
+ %17 = OpAtomicAnd %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicAnd_45a819
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..9369271
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicAnd_45a819() {
+ var res : i32 = 0i;
+ let x_11 : i32 = atomicAnd(&(arg_0), 1i);
+ res = x_11;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicAnd_45a819();
+ return;
+}
+
+fn compute_main_1() {
+ let x_31 : u32 = local_invocation_index_1;
+ compute_main_inner(x_31);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm
new file mode 100644
index 0000000..3d205d2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAnd_34edd3 "atomicAnd_34edd3"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+ %18 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAnd_34edd3 = OpFunction %void None %6
+ %9 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %10 = OpAtomicAnd %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %10
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %18
+%local_invocation_index = OpFunctionParameter %uint
+ %21 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %17
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %26 = OpFunctionCall %void %atomicAnd_34edd3
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %28 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %29 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..92c68d7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicAnd_34edd3() {
+ uint res = 0u;
+ uint x_10 = atomicAnd(arg_0, 1u);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicAnd_34edd3();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..fb9b516
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicAnd_34edd3() {
+ uint res = 0u;
+ uint atomic_result = 0u;
+ InterlockedAnd(arg_0, 1u, atomic_result);
+ const uint x_10 = atomic_result;
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAnd_34edd3();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..ffc5ace
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAnd_34edd3(threadgroup atomic_uint* const tint_symbol) {
+ uint res = 0u;
+ uint const x_10 = atomic_fetch_and_explicit(tint_symbol, 1u, memory_order_relaxed);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAnd_34edd3(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_30 = *(tint_symbol_2);
+ compute_main_inner(x_30, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..02a5b89
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,74 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAnd_34edd3 "atomicAnd_34edd3"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAnd_34edd3 = OpFunction %void None %9
+ %12 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %res %6
+ %15 = OpAtomicAnd %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicAnd_34edd3
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %30 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %20
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %35 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %39 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %41 = OpLabel
+ %43 = OpLoad %uint %local_invocation_index_1_param_1
+ %42 = OpFunctionCall %void %compute_main_inner_1 %43
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..ee27cf6
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicAnd/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicAnd_34edd3() {
+ var res : u32 = 0u;
+ let x_10 : u32 = atomicAnd(&(arg_0), 1u);
+ res = x_10;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicAnd_34edd3();
+ return;
+}
+
+fn compute_main_1() {
+ let x_30 : u32 = local_invocation_index_1;
+ compute_main_inner(x_30);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm
new file mode 100644
index 0000000..454abb1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm
@@ -0,0 +1,62 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicCompareExchangeWeak_1bd40a "atomicCompareExchangeWeak_1bd40a"
+ OpName %__atomic_compare_exchange_resulti32 "__atomic_compare_exchange_resulti32"
+ OpMemberName %__atomic_compare_exchange_resulti32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resulti32 1 "exchanged"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 1 Offset 4
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %bool = OpTypeBool
+%__atomic_compare_exchange_resulti32 = OpTypeStruct %int %bool
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%_ptr_Function___atomic_compare_exchange_resulti32 = OpTypePointer Function %__atomic_compare_exchange_resulti32
+ %23 = OpConstantNull %__atomic_compare_exchange_resulti32
+%atomicCompareExchangeWeak_1bd40a = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function___atomic_compare_exchange_resulti32 Function %23
+ %17 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %19 = OpAtomicCompareExchange %int %17 %uint_1 %uint_0 %uint_0 %int_1 %int_1
+ %20 = OpIEqual %bool %19 %int_1
+ %9 = OpCompositeConstruct %__atomic_compare_exchange_resulti32 %19 %20
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicCompareExchangeWeak_1bd40a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %atomicCompareExchangeWeak_1bd40a
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..b46c227
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,102 @@
+#version 310 es
+precision mediump float;
+
+struct atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicCompareExchangeWeak_1bd40a() {
+ x__atomic_compare_exchange_resulti32 res = x__atomic_compare_exchange_resulti32(0, false);
+ atomic_compare_exchange_resulti32 atomic_compare_result;
+ atomic_compare_result.old_value = atomicCompSwap(sb_rw.arg_0, 1, 1);
+ atomic_compare_result.exchanged = atomic_compare_result.old_value == 1;
+ atomic_compare_exchange_resulti32 tint_symbol = atomic_compare_result;
+ int old_value_1 = tint_symbol.old_value;
+ int x_19 = old_value_1;
+ x__atomic_compare_exchange_resulti32 tint_symbol_1 = x__atomic_compare_exchange_resulti32(x_19, (x_19 == 1));
+ res = tint_symbol_1;
+ return;
+}
+
+void fragment_main_1() {
+ atomicCompareExchangeWeak_1bd40a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicCompareExchangeWeak_1bd40a() {
+ x__atomic_compare_exchange_resulti32 res = x__atomic_compare_exchange_resulti32(0, false);
+ atomic_compare_exchange_resulti32 atomic_compare_result;
+ atomic_compare_result.old_value = atomicCompSwap(sb_rw.arg_0, 1, 1);
+ atomic_compare_result.exchanged = atomic_compare_result.old_value == 1;
+ atomic_compare_exchange_resulti32 tint_symbol = atomic_compare_result;
+ int old_value_1 = tint_symbol.old_value;
+ int x_19 = old_value_1;
+ x__atomic_compare_exchange_resulti32 tint_symbol_1 = x__atomic_compare_exchange_resulti32(x_19, (x_19 == 1));
+ res = tint_symbol_1;
+ return;
+}
+
+void compute_main_1() {
+ atomicCompareExchangeWeak_1bd40a();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..a385d05
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,50 @@
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+struct atomic_compare_exchange_weak_ret_type {
+ int old_value;
+ bool exchanged;
+};
+
+atomic_compare_exchange_weak_ret_type tint_atomicCompareExchangeWeak(RWByteAddressBuffer buffer, uint offset, int compare, int value) {
+ atomic_compare_exchange_weak_ret_type result=(atomic_compare_exchange_weak_ret_type)0;
+ buffer.InterlockedCompareExchange(offset, compare, value, result.old_value);
+ result.exchanged = result.old_value == compare;
+ return result;
+}
+
+
+void atomicCompareExchangeWeak_1bd40a() {
+ x__atomic_compare_exchange_resulti32 res = {0, false};
+ const atomic_compare_exchange_weak_ret_type tint_symbol = tint_atomicCompareExchangeWeak(sb_rw, 0u, 1, 1);
+ const int old_value_1 = tint_symbol.old_value;
+ const int x_19 = old_value_1;
+ const x__atomic_compare_exchange_resulti32 tint_symbol_1 = {x_19, (x_19 == 1)};
+ res = tint_symbol_1;
+ return;
+}
+
+void fragment_main_1() {
+ atomicCompareExchangeWeak_1bd40a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicCompareExchangeWeak_1bd40a();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..3961fdd
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.msl
@@ -0,0 +1,57 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+atomic_compare_exchange_resulti32 atomicCompareExchangeWeak_1(device atomic_int* atomic, int compare, int value) {
+ int old_value = compare;
+ bool exchanged = atomic_compare_exchange_weak_explicit(atomic, &old_value, value, memory_order_relaxed, memory_order_relaxed);
+ return {old_value, exchanged};
+}
+
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+void atomicCompareExchangeWeak_1bd40a(device SB_RW_atomic* const tint_symbol_2) {
+ x__atomic_compare_exchange_resulti32 res = {.old_value=0, .exchanged=false};
+ atomic_compare_exchange_resulti32 const tint_symbol = atomicCompareExchangeWeak_1(&((*(tint_symbol_2)).arg_0), 1, 1);
+ int const old_value_1 = tint_symbol.old_value;
+ int const x_19 = old_value_1;
+ x__atomic_compare_exchange_resulti32 const tint_symbol_1 = {.old_value=x_19, .exchanged=(x_19 == 1)};
+ res = tint_symbol_1;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicCompareExchangeWeak_1bd40a(tint_symbol_3);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_4);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_5) {
+ atomicCompareExchangeWeak_1bd40a(tint_symbol_5);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_6 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_6);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..97cc672
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,87 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 43
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicCompareExchangeWeak_1bd40a "atomicCompareExchangeWeak_1bd40a"
+ OpName %x__atomic_compare_exchange_resulti32 "x__atomic_compare_exchange_resulti32"
+ OpMemberName %x__atomic_compare_exchange_resulti32 0 "old_value"
+ OpMemberName %x__atomic_compare_exchange_resulti32 1 "exchanged"
+ OpName %res "res"
+ OpName %__atomic_compare_exchange_resulti32 "__atomic_compare_exchange_resulti32"
+ OpMemberName %__atomic_compare_exchange_resulti32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resulti32 1 "exchanged"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ OpMemberDecorate %x__atomic_compare_exchange_resulti32 0 Offset 0
+ OpMemberDecorate %x__atomic_compare_exchange_resulti32 1 Offset 4
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 1 Offset 4
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %bool = OpTypeBool
+%x__atomic_compare_exchange_resulti32 = OpTypeStruct %int %bool
+ %11 = OpConstantNull %int
+ %12 = OpConstantNull %bool
+ %13 = OpConstantComposite %x__atomic_compare_exchange_resulti32 %11 %12
+%_ptr_Function_x__atomic_compare_exchange_resulti32 = OpTypePointer Function %x__atomic_compare_exchange_resulti32
+ %16 = OpConstantNull %x__atomic_compare_exchange_resulti32
+%__atomic_compare_exchange_resulti32 = OpTypeStruct %int %bool
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%atomicCompareExchangeWeak_1bd40a = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_x__atomic_compare_exchange_resulti32 Function %16
+ OpStore %res %13
+ %24 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %26 = OpAtomicCompareExchange %int %24 %uint_1 %uint_0 %uint_0 %int_1 %int_1
+ %27 = OpIEqual %bool %26 %int_1
+ %17 = OpCompositeConstruct %__atomic_compare_exchange_resulti32 %26 %27
+ %28 = OpCompositeExtract %int %17 0
+ %29 = OpIEqual %bool %28 %int_1
+ %30 = OpCompositeConstruct %x__atomic_compare_exchange_resulti32 %28 %29
+ OpStore %res %30
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %32 = OpLabel
+ %33 = OpFunctionCall %void %atomicCompareExchangeWeak_1bd40a
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %35 = OpLabel
+ %36 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %38 = OpLabel
+ %39 = OpFunctionCall %void %atomicCompareExchangeWeak_1bd40a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %41 = OpLabel
+ %42 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..cf8754d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,42 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+struct x__atomic_compare_exchange_resulti32 {
+ old_value : i32,
+ exchanged : bool,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicCompareExchangeWeak_1bd40a() {
+ var res : x__atomic_compare_exchange_resulti32 = x__atomic_compare_exchange_resulti32(0i, false);
+ let old_value_1 = atomicCompareExchangeWeak(&(sb_rw.arg_0), 1i, 1i).old_value;
+ let x_19 : i32 = old_value_1;
+ res = x__atomic_compare_exchange_resulti32(x_19, (x_19 == 1i));
+ return;
+}
+
+fn fragment_main_1() {
+ atomicCompareExchangeWeak_1bd40a();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicCompareExchangeWeak_1bd40a();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm
new file mode 100644
index 0000000..09e83a0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm
@@ -0,0 +1,60 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 28
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicCompareExchangeWeak_63d8e6 "atomicCompareExchangeWeak_63d8e6"
+ OpName %__atomic_compare_exchange_resultu32 "__atomic_compare_exchange_resultu32"
+ OpMemberName %__atomic_compare_exchange_resultu32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resultu32 1 "exchanged"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 1 Offset 4
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %bool = OpTypeBool
+%__atomic_compare_exchange_resultu32 = OpTypeStruct %uint %bool
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function___atomic_compare_exchange_resultu32 = OpTypePointer Function %__atomic_compare_exchange_resultu32
+ %21 = OpConstantNull %__atomic_compare_exchange_resultu32
+%atomicCompareExchangeWeak_63d8e6 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function___atomic_compare_exchange_resultu32 Function %21
+ %16 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %17 = OpAtomicCompareExchange %uint %16 %uint_1 %uint_0 %uint_0 %uint_1 %uint_1
+ %18 = OpIEqual %bool %17 %uint_1
+ %9 = OpCompositeConstruct %__atomic_compare_exchange_resultu32 %17 %18
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicCompareExchangeWeak_63d8e6
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicCompareExchangeWeak_63d8e6
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..385735d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,102 @@
+#version 310 es
+precision mediump float;
+
+struct atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicCompareExchangeWeak_63d8e6() {
+ x__atomic_compare_exchange_resultu32 res = x__atomic_compare_exchange_resultu32(0u, false);
+ atomic_compare_exchange_resultu32 atomic_compare_result;
+ atomic_compare_result.old_value = atomicCompSwap(sb_rw.arg_0, 1u, 1u);
+ atomic_compare_result.exchanged = atomic_compare_result.old_value == 1u;
+ atomic_compare_exchange_resultu32 tint_symbol = atomic_compare_result;
+ uint old_value_1 = tint_symbol.old_value;
+ uint x_17 = old_value_1;
+ x__atomic_compare_exchange_resultu32 tint_symbol_1 = x__atomic_compare_exchange_resultu32(x_17, (x_17 == 1u));
+ res = tint_symbol_1;
+ return;
+}
+
+void fragment_main_1() {
+ atomicCompareExchangeWeak_63d8e6();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicCompareExchangeWeak_63d8e6() {
+ x__atomic_compare_exchange_resultu32 res = x__atomic_compare_exchange_resultu32(0u, false);
+ atomic_compare_exchange_resultu32 atomic_compare_result;
+ atomic_compare_result.old_value = atomicCompSwap(sb_rw.arg_0, 1u, 1u);
+ atomic_compare_result.exchanged = atomic_compare_result.old_value == 1u;
+ atomic_compare_exchange_resultu32 tint_symbol = atomic_compare_result;
+ uint old_value_1 = tint_symbol.old_value;
+ uint x_17 = old_value_1;
+ x__atomic_compare_exchange_resultu32 tint_symbol_1 = x__atomic_compare_exchange_resultu32(x_17, (x_17 == 1u));
+ res = tint_symbol_1;
+ return;
+}
+
+void compute_main_1() {
+ atomicCompareExchangeWeak_63d8e6();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..c36984d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,50 @@
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+struct atomic_compare_exchange_weak_ret_type {
+ uint old_value;
+ bool exchanged;
+};
+
+atomic_compare_exchange_weak_ret_type tint_atomicCompareExchangeWeak(RWByteAddressBuffer buffer, uint offset, uint compare, uint value) {
+ atomic_compare_exchange_weak_ret_type result=(atomic_compare_exchange_weak_ret_type)0;
+ buffer.InterlockedCompareExchange(offset, compare, value, result.old_value);
+ result.exchanged = result.old_value == compare;
+ return result;
+}
+
+
+void atomicCompareExchangeWeak_63d8e6() {
+ x__atomic_compare_exchange_resultu32 res = {0u, false};
+ const atomic_compare_exchange_weak_ret_type tint_symbol = tint_atomicCompareExchangeWeak(sb_rw, 0u, 1u, 1u);
+ const uint old_value_1 = tint_symbol.old_value;
+ const uint x_17 = old_value_1;
+ const x__atomic_compare_exchange_resultu32 tint_symbol_1 = {x_17, (x_17 == 1u)};
+ res = tint_symbol_1;
+ return;
+}
+
+void fragment_main_1() {
+ atomicCompareExchangeWeak_63d8e6();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicCompareExchangeWeak_63d8e6();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..b06f2f9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.msl
@@ -0,0 +1,57 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+atomic_compare_exchange_resultu32 atomicCompareExchangeWeak_1(device atomic_uint* atomic, uint compare, uint value) {
+ uint old_value = compare;
+ bool exchanged = atomic_compare_exchange_weak_explicit(atomic, &old_value, value, memory_order_relaxed, memory_order_relaxed);
+ return {old_value, exchanged};
+}
+
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+void atomicCompareExchangeWeak_63d8e6(device SB_RW_atomic* const tint_symbol_2) {
+ x__atomic_compare_exchange_resultu32 res = {.old_value=0u, .exchanged=false};
+ atomic_compare_exchange_resultu32 const tint_symbol = atomicCompareExchangeWeak_1(&((*(tint_symbol_2)).arg_0), 1u, 1u);
+ uint const old_value_1 = tint_symbol.old_value;
+ uint const x_17 = old_value_1;
+ x__atomic_compare_exchange_resultu32 const tint_symbol_1 = {.old_value=x_17, .exchanged=(x_17 == 1u)};
+ res = tint_symbol_1;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicCompareExchangeWeak_63d8e6(tint_symbol_3);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_4);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_5) {
+ atomicCompareExchangeWeak_63d8e6(tint_symbol_5);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_6 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_6);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..bb4e843
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,85 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 41
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicCompareExchangeWeak_63d8e6 "atomicCompareExchangeWeak_63d8e6"
+ OpName %x__atomic_compare_exchange_resultu32 "x__atomic_compare_exchange_resultu32"
+ OpMemberName %x__atomic_compare_exchange_resultu32 0 "old_value"
+ OpMemberName %x__atomic_compare_exchange_resultu32 1 "exchanged"
+ OpName %res "res"
+ OpName %__atomic_compare_exchange_resultu32 "__atomic_compare_exchange_resultu32"
+ OpMemberName %__atomic_compare_exchange_resultu32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resultu32 1 "exchanged"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ OpMemberDecorate %x__atomic_compare_exchange_resultu32 0 Offset 0
+ OpMemberDecorate %x__atomic_compare_exchange_resultu32 1 Offset 4
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 1 Offset 4
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %bool = OpTypeBool
+%x__atomic_compare_exchange_resultu32 = OpTypeStruct %uint %bool
+ %11 = OpConstantNull %uint
+ %12 = OpConstantNull %bool
+ %13 = OpConstantComposite %x__atomic_compare_exchange_resultu32 %11 %12
+%_ptr_Function_x__atomic_compare_exchange_resultu32 = OpTypePointer Function %x__atomic_compare_exchange_resultu32
+ %16 = OpConstantNull %x__atomic_compare_exchange_resultu32
+%__atomic_compare_exchange_resultu32 = OpTypeStruct %uint %bool
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicCompareExchangeWeak_63d8e6 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_x__atomic_compare_exchange_resultu32 Function %16
+ OpStore %res %13
+ %23 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %24 = OpAtomicCompareExchange %uint %23 %uint_1 %uint_0 %uint_0 %uint_1 %uint_1
+ %25 = OpIEqual %bool %24 %uint_1
+ %17 = OpCompositeConstruct %__atomic_compare_exchange_resultu32 %24 %25
+ %26 = OpCompositeExtract %uint %17 0
+ %27 = OpIEqual %bool %26 %uint_1
+ %28 = OpCompositeConstruct %x__atomic_compare_exchange_resultu32 %26 %27
+ OpStore %res %28
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %atomicCompareExchangeWeak_63d8e6
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %33 = OpLabel
+ %34 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %36 = OpLabel
+ %37 = OpFunctionCall %void %atomicCompareExchangeWeak_63d8e6
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %39 = OpLabel
+ %40 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..4382a23
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,42 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+struct x__atomic_compare_exchange_resultu32 {
+ old_value : u32,
+ exchanged : bool,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicCompareExchangeWeak_63d8e6() {
+ var res : x__atomic_compare_exchange_resultu32 = x__atomic_compare_exchange_resultu32(0u, false);
+ let old_value_1 = atomicCompareExchangeWeak(&(sb_rw.arg_0), 1u, 1u).old_value;
+ let x_17 : u32 = old_value_1;
+ res = x__atomic_compare_exchange_resultu32(x_17, (x_17 == 1u));
+ return;
+}
+
+fn fragment_main_1() {
+ atomicCompareExchangeWeak_63d8e6();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicCompareExchangeWeak_63d8e6();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm
new file mode 100644
index 0000000..a0f338c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm
@@ -0,0 +1,63 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 37
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicCompareExchangeWeak_e88938 "atomicCompareExchangeWeak_e88938"
+ OpName %__atomic_compare_exchange_resulti32 "__atomic_compare_exchange_resulti32"
+ OpMemberName %__atomic_compare_exchange_resulti32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resulti32 1 "exchanged"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 1 Offset 4
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %bool = OpTypeBool
+%__atomic_compare_exchange_resulti32 = OpTypeStruct %int %bool
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+%_ptr_Function___atomic_compare_exchange_resulti32 = OpTypePointer Function %__atomic_compare_exchange_resulti32
+ %22 = OpConstantNull %__atomic_compare_exchange_resulti32
+ %23 = OpTypeFunction %void %uint
+ %29 = OpConstantNull %int
+ %uint_264 = OpConstant %uint 264
+%atomicCompareExchangeWeak_e88938 = OpFunction %void None %7
+ %10 = OpLabel
+ %res = OpVariable %_ptr_Function___atomic_compare_exchange_resulti32 Function %22
+ %18 = OpAtomicCompareExchange %int %arg_0 %uint_2 %uint_0 %uint_0 %int_1 %int_1
+ %19 = OpIEqual %bool %18 %int_1
+ %11 = OpCompositeConstruct %__atomic_compare_exchange_resulti32 %18 %19
+ OpStore %res %11
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %23
+%local_invocation_index = OpFunctionParameter %uint
+ %26 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %29
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %32 = OpFunctionCall %void %atomicCompareExchangeWeak_e88938
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %34 = OpLabel
+ %36 = OpLoad %uint %local_invocation_index_1
+ %35 = OpFunctionCall %void %compute_main_inner %36
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..6ccd038
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,54 @@
+#version 310 es
+
+struct atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicCompareExchangeWeak_e88938() {
+ x__atomic_compare_exchange_resulti32 res = x__atomic_compare_exchange_resulti32(0, false);
+ atomic_compare_exchange_resulti32 atomic_compare_result;
+ atomic_compare_result.old_value = atomicCompSwap(arg_0, 1, 1);
+ atomic_compare_result.exchanged = atomic_compare_result.old_value == 1;
+ atomic_compare_exchange_resulti32 tint_symbol = atomic_compare_result;
+ int old_value_1 = tint_symbol.old_value;
+ int x_18 = old_value_1;
+ x__atomic_compare_exchange_resulti32 tint_symbol_1 = x__atomic_compare_exchange_resulti32(x_18, (x_18 == 1));
+ res = tint_symbol_1;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicCompareExchangeWeak_e88938();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..03640dd
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,58 @@
+struct atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicCompareExchangeWeak_e88938() {
+ x__atomic_compare_exchange_resulti32 res = {0, false};
+ atomic_compare_exchange_resulti32 atomic_result = (atomic_compare_exchange_resulti32)0;
+ int atomic_compare_value = 1;
+ InterlockedCompareExchange(arg_0, atomic_compare_value, 1, atomic_result.old_value);
+ atomic_result.exchanged = atomic_result.old_value == atomic_compare_value;
+ const atomic_compare_exchange_resulti32 tint_symbol_2 = atomic_result;
+ const int old_value_1 = tint_symbol_2.old_value;
+ const int x_18 = old_value_1;
+ const x__atomic_compare_exchange_resulti32 tint_symbol_3 = {x_18, (x_18 == 1)};
+ res = tint_symbol_3;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicCompareExchangeWeak_e88938();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..4cfcd1c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,58 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+atomic_compare_exchange_resulti32 atomicCompareExchangeWeak_1(threadgroup atomic_int* atomic, int compare, int value) {
+ int old_value = compare;
+ bool exchanged = atomic_compare_exchange_weak_explicit(atomic, &old_value, value, memory_order_relaxed, memory_order_relaxed);
+ return {old_value, exchanged};
+}
+
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+void atomicCompareExchangeWeak_e88938(threadgroup atomic_int* const tint_symbol_2) {
+ x__atomic_compare_exchange_resulti32 res = {.old_value=0, .exchanged=false};
+ atomic_compare_exchange_resulti32 const tint_symbol = atomicCompareExchangeWeak_1(tint_symbol_2, 1, 1);
+ int const old_value_1 = tint_symbol.old_value;
+ int const x_18 = old_value_1;
+ x__atomic_compare_exchange_resulti32 const tint_symbol_1 = {.old_value=x_18, .exchanged=(x_18 == 1)};
+ res = tint_symbol_1;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_3) {
+ atomic_store_explicit(tint_symbol_3, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicCompareExchangeWeak_e88938(tint_symbol_3);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_4, threadgroup atomic_int* const tint_symbol_5) {
+ uint const x_36 = *(tint_symbol_4);
+ compute_main_inner(x_36, tint_symbol_5);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_6, thread uint* const tint_symbol_7) {
+ {
+ atomic_store_explicit(tint_symbol_6, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_7) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_7, tint_symbol_6);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_8;
+ thread uint tint_symbol_9 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_8), &(tint_symbol_9));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..a9201f5
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,97 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 57
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicCompareExchangeWeak_e88938 "atomicCompareExchangeWeak_e88938"
+ OpName %x__atomic_compare_exchange_resulti32 "x__atomic_compare_exchange_resulti32"
+ OpMemberName %x__atomic_compare_exchange_resulti32 0 "old_value"
+ OpMemberName %x__atomic_compare_exchange_resulti32 1 "exchanged"
+ OpName %res "res"
+ OpName %__atomic_compare_exchange_resulti32 "__atomic_compare_exchange_resulti32"
+ OpMemberName %__atomic_compare_exchange_resulti32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resulti32 1 "exchanged"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %x__atomic_compare_exchange_resulti32 0 Offset 0
+ OpMemberDecorate %x__atomic_compare_exchange_resulti32 1 Offset 4
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 1 Offset 4
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %bool = OpTypeBool
+%x__atomic_compare_exchange_resulti32 = OpTypeStruct %int %bool
+ %16 = OpConstantNull %int
+ %17 = OpConstantNull %bool
+ %18 = OpConstantComposite %x__atomic_compare_exchange_resulti32 %16 %17
+%_ptr_Function_x__atomic_compare_exchange_resulti32 = OpTypePointer Function %x__atomic_compare_exchange_resulti32
+ %21 = OpConstantNull %x__atomic_compare_exchange_resulti32
+%__atomic_compare_exchange_resulti32 = OpTypeStruct %int %bool
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+ %33 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicCompareExchangeWeak_e88938 = OpFunction %void None %10
+ %13 = OpLabel
+ %res = OpVariable %_ptr_Function_x__atomic_compare_exchange_resulti32 Function %21
+ OpStore %res %18
+ %28 = OpAtomicCompareExchange %int %arg_0 %uint_2 %uint_0 %uint_0 %int_1 %int_1
+ %29 = OpIEqual %bool %28 %int_1
+ %22 = OpCompositeConstruct %__atomic_compare_exchange_resulti32 %28 %29
+ %30 = OpCompositeExtract %int %22 0
+ %31 = OpIEqual %bool %30 %int_1
+ %32 = OpCompositeConstruct %x__atomic_compare_exchange_resulti32 %30 %31
+ OpStore %res %32
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %33
+%local_invocation_index = OpFunctionParameter %uint
+ %36 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %16
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %41 = OpFunctionCall %void %atomicCompareExchangeWeak_e88938
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %43 = OpLabel
+ %44 = OpLoad %uint %local_invocation_index_1
+ %45 = OpFunctionCall %void %compute_main_inner %44
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %33
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %48 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %16
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %52 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %54 = OpLabel
+ %56 = OpLoad %uint %local_invocation_index_1_param_1
+ %55 = OpFunctionCall %void %compute_main_inner_1 %56
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..349dccf
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,35 @@
+struct x__atomic_compare_exchange_resulti32 {
+ old_value : i32,
+ exchanged : bool,
+}
+
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicCompareExchangeWeak_e88938() {
+ var res : x__atomic_compare_exchange_resulti32 = x__atomic_compare_exchange_resulti32(0i, false);
+ let old_value_1 = atomicCompareExchangeWeak(&(arg_0), 1i, 1i).old_value;
+ let x_18 : i32 = old_value_1;
+ res = x__atomic_compare_exchange_resulti32(x_18, (x_18 == 1i));
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicCompareExchangeWeak_e88938();
+ return;
+}
+
+fn compute_main_1() {
+ let x_36 : u32 = local_invocation_index_1;
+ compute_main_inner(x_36);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm
new file mode 100644
index 0000000..8264985
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm
@@ -0,0 +1,62 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 36
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicCompareExchangeWeak_83580d "atomicCompareExchangeWeak_83580d"
+ OpName %__atomic_compare_exchange_resultu32 "__atomic_compare_exchange_resultu32"
+ OpMemberName %__atomic_compare_exchange_resultu32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resultu32 1 "exchanged"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 1 Offset 4
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %bool = OpTypeBool
+%__atomic_compare_exchange_resultu32 = OpTypeStruct %uint %bool
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function___atomic_compare_exchange_resultu32 = OpTypePointer Function %__atomic_compare_exchange_resultu32
+ %21 = OpConstantNull %__atomic_compare_exchange_resultu32
+ %22 = OpTypeFunction %void %uint
+ %28 = OpConstantNull %uint
+ %uint_264 = OpConstant %uint 264
+%atomicCompareExchangeWeak_83580d = OpFunction %void None %6
+ %9 = OpLabel
+ %res = OpVariable %_ptr_Function___atomic_compare_exchange_resultu32 Function %21
+ %17 = OpAtomicCompareExchange %uint %arg_0 %uint_2 %uint_0 %uint_0 %uint_1 %uint_1
+ %18 = OpIEqual %bool %17 %uint_1
+ %10 = OpCompositeConstruct %__atomic_compare_exchange_resultu32 %17 %18
+ OpStore %res %10
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %28
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %31 = OpFunctionCall %void %atomicCompareExchangeWeak_83580d
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %33 = OpLabel
+ %35 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %35
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..7bd1617e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,54 @@
+#version 310 es
+
+struct atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicCompareExchangeWeak_83580d() {
+ x__atomic_compare_exchange_resultu32 res = x__atomic_compare_exchange_resultu32(0u, false);
+ atomic_compare_exchange_resultu32 atomic_compare_result;
+ atomic_compare_result.old_value = atomicCompSwap(arg_0, 1u, 1u);
+ atomic_compare_result.exchanged = atomic_compare_result.old_value == 1u;
+ atomic_compare_exchange_resultu32 tint_symbol = atomic_compare_result;
+ uint old_value_1 = tint_symbol.old_value;
+ uint x_17 = old_value_1;
+ x__atomic_compare_exchange_resultu32 tint_symbol_1 = x__atomic_compare_exchange_resultu32(x_17, (x_17 == 1u));
+ res = tint_symbol_1;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicCompareExchangeWeak_83580d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..1c61811
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,58 @@
+struct atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicCompareExchangeWeak_83580d() {
+ x__atomic_compare_exchange_resultu32 res = {0u, false};
+ atomic_compare_exchange_resultu32 atomic_result = (atomic_compare_exchange_resultu32)0;
+ uint atomic_compare_value = 1u;
+ InterlockedCompareExchange(arg_0, atomic_compare_value, 1u, atomic_result.old_value);
+ atomic_result.exchanged = atomic_result.old_value == atomic_compare_value;
+ const atomic_compare_exchange_resultu32 tint_symbol_2 = atomic_result;
+ const uint old_value_1 = tint_symbol_2.old_value;
+ const uint x_17 = old_value_1;
+ const x__atomic_compare_exchange_resultu32 tint_symbol_3 = {x_17, (x_17 == 1u)};
+ res = tint_symbol_3;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicCompareExchangeWeak_83580d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..0f6a268
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,58 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+atomic_compare_exchange_resultu32 atomicCompareExchangeWeak_1(threadgroup atomic_uint* atomic, uint compare, uint value) {
+ uint old_value = compare;
+ bool exchanged = atomic_compare_exchange_weak_explicit(atomic, &old_value, value, memory_order_relaxed, memory_order_relaxed);
+ return {old_value, exchanged};
+}
+
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+void atomicCompareExchangeWeak_83580d(threadgroup atomic_uint* const tint_symbol_2) {
+ x__atomic_compare_exchange_resultu32 res = {.old_value=0u, .exchanged=false};
+ atomic_compare_exchange_resultu32 const tint_symbol = atomicCompareExchangeWeak_1(tint_symbol_2, 1u, 1u);
+ uint const old_value_1 = tint_symbol.old_value;
+ uint const x_17 = old_value_1;
+ x__atomic_compare_exchange_resultu32 const tint_symbol_1 = {.old_value=x_17, .exchanged=(x_17 == 1u)};
+ res = tint_symbol_1;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_3) {
+ atomic_store_explicit(tint_symbol_3, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicCompareExchangeWeak_83580d(tint_symbol_3);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_4, threadgroup atomic_uint* const tint_symbol_5) {
+ uint const x_35 = *(tint_symbol_4);
+ compute_main_inner(x_35, tint_symbol_5);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_6, thread uint* const tint_symbol_7) {
+ {
+ atomic_store_explicit(tint_symbol_6, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_7) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_7, tint_symbol_6);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_8;
+ thread uint tint_symbol_9 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_8), &(tint_symbol_9));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..26382e3
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,95 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 55
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicCompareExchangeWeak_83580d "atomicCompareExchangeWeak_83580d"
+ OpName %x__atomic_compare_exchange_resultu32 "x__atomic_compare_exchange_resultu32"
+ OpMemberName %x__atomic_compare_exchange_resultu32 0 "old_value"
+ OpMemberName %x__atomic_compare_exchange_resultu32 1 "exchanged"
+ OpName %res "res"
+ OpName %__atomic_compare_exchange_resultu32 "__atomic_compare_exchange_resultu32"
+ OpMemberName %__atomic_compare_exchange_resultu32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resultu32 1 "exchanged"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %x__atomic_compare_exchange_resultu32 0 Offset 0
+ OpMemberDecorate %x__atomic_compare_exchange_resultu32 1 Offset 4
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 1 Offset 4
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+ %bool = OpTypeBool
+%x__atomic_compare_exchange_resultu32 = OpTypeStruct %uint %bool
+ %15 = OpConstantNull %bool
+ %16 = OpConstantComposite %x__atomic_compare_exchange_resultu32 %6 %15
+%_ptr_Function_x__atomic_compare_exchange_resultu32 = OpTypePointer Function %x__atomic_compare_exchange_resultu32
+ %19 = OpConstantNull %x__atomic_compare_exchange_resultu32
+%__atomic_compare_exchange_resultu32 = OpTypeStruct %uint %bool
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %31 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicCompareExchangeWeak_83580d = OpFunction %void None %9
+ %12 = OpLabel
+ %res = OpVariable %_ptr_Function_x__atomic_compare_exchange_resultu32 Function %19
+ OpStore %res %16
+ %26 = OpAtomicCompareExchange %uint %arg_0 %uint_2 %uint_0 %uint_0 %uint_1 %uint_1
+ %27 = OpIEqual %bool %26 %uint_1
+ %20 = OpCompositeConstruct %__atomic_compare_exchange_resultu32 %26 %27
+ %28 = OpCompositeExtract %uint %20 0
+ %29 = OpIEqual %bool %28 %uint_1
+ %30 = OpCompositeConstruct %x__atomic_compare_exchange_resultu32 %28 %29
+ OpStore %res %30
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %31
+%local_invocation_index = OpFunctionParameter %uint
+ %34 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %39 = OpFunctionCall %void %atomicCompareExchangeWeak_83580d
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %41 = OpLabel
+ %42 = OpLoad %uint %local_invocation_index_1
+ %43 = OpFunctionCall %void %compute_main_inner %42
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %31
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %46 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %50 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %52 = OpLabel
+ %54 = OpLoad %uint %local_invocation_index_1_param_1
+ %53 = OpFunctionCall %void %compute_main_inner_1 %54
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..9c897f9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,35 @@
+struct x__atomic_compare_exchange_resultu32 {
+ old_value : u32,
+ exchanged : bool,
+}
+
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicCompareExchangeWeak_83580d() {
+ var res : x__atomic_compare_exchange_resultu32 = x__atomic_compare_exchange_resultu32(0u, false);
+ let old_value_1 = atomicCompareExchangeWeak(&(arg_0), 1u, 1u).old_value;
+ let x_17 : u32 = old_value_1;
+ res = x__atomic_compare_exchange_resultu32(x_17, (x_17 == 1u));
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicCompareExchangeWeak_83580d();
+ return;
+}
+
+fn compute_main_1() {
+ let x_35 : u32 = local_invocation_index_1;
+ compute_main_inner(x_35);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm
new file mode 100644
index 0000000..c4f71e9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicExchange_f2e22f "atomicExchange_f2e22f"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %19 = OpConstantNull %int
+%atomicExchange_f2e22f = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %19
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %9 = OpAtomicExchange %int %15 %uint_1 %uint_0 %int_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicExchange_f2e22f
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicExchange_f2e22f
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..4fdae27
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicExchange_f2e22f() {
+ int res = 0;
+ int x_9 = atomicExchange(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicExchange_f2e22f();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicExchange_f2e22f() {
+ int res = 0;
+ int x_9 = atomicExchange(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicExchange_f2e22f();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..deffe11
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicExchange(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedExchange(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicExchange_f2e22f() {
+ int res = 0;
+ const int x_9 = tint_atomicExchange(sb_rw, 0u, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicExchange_f2e22f();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicExchange_f2e22f();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..cbd9391
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicExchange_f2e22f(device SB_RW_atomic* const tint_symbol) {
+ int res = 0;
+ int const x_9 = atomic_exchange_explicit(&((*(tint_symbol)).arg_0), 1, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicExchange_f2e22f(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicExchange_f2e22f(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..10fd286
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,66 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicExchange_f2e22f "atomicExchange_f2e22f"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%atomicExchange_f2e22f = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %res %9
+ %18 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %12 = OpAtomicExchange %int %18 %uint_1 %uint_0 %int_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicExchange_f2e22f
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicExchange_f2e22f
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..625f2c3
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicExchange_f2e22f() {
+ var res : i32 = 0i;
+ let x_9 : i32 = atomicExchange(&(sb_rw.arg_0), 1i);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicExchange_f2e22f();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicExchange_f2e22f();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm
new file mode 100644
index 0000000..bdd9e1d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicExchange_d59712 "atomicExchange_d59712"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+%atomicExchange_d59712 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %9 = OpAtomicExchange %uint %14 %uint_1 %uint_0 %uint_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicExchange_d59712
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicExchange_d59712
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..57f0291
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicExchange_d59712() {
+ uint res = 0u;
+ uint x_9 = atomicExchange(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicExchange_d59712();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicExchange_d59712() {
+ uint res = 0u;
+ uint x_9 = atomicExchange(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicExchange_d59712();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..7b20c96
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicExchange(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedExchange(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicExchange_d59712() {
+ uint res = 0u;
+ const uint x_9 = tint_atomicExchange(sb_rw, 0u, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicExchange_d59712();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicExchange_d59712();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..06d01b5
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicExchange_d59712(device SB_RW_atomic* const tint_symbol) {
+ uint res = 0u;
+ uint const x_9 = atomic_exchange_explicit(&((*(tint_symbol)).arg_0), 1u, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicExchange_d59712(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicExchange_d59712(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..d282cbf
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicExchange_d59712 "atomicExchange_d59712"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicExchange_d59712 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %res %9
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %12 = OpAtomicExchange %uint %17 %uint_1 %uint_0 %uint_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicExchange_d59712
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicExchange_d59712
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..e80aa80
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicExchange_d59712() {
+ var res : u32 = 0u;
+ let x_9 : u32 = atomicExchange(&(sb_rw.arg_0), 1u);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicExchange_d59712();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicExchange_d59712();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm
new file mode 100644
index 0000000..b541d6b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicExchange_e114ba "atomicExchange_e114ba"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %18 = OpConstantNull %int
+ %19 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicExchange_e114ba = OpFunction %void None %7
+ %10 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %18
+ %11 = OpAtomicExchange %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %11
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %18
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %27 = OpFunctionCall %void %atomicExchange_e114ba
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %29 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %30 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..3775b8f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicExchange_e114ba() {
+ int res = 0;
+ int x_11 = atomicExchange(arg_0, 1);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicExchange_e114ba();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..b994cfe
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicExchange_e114ba() {
+ int res = 0;
+ int atomic_result = 0;
+ InterlockedExchange(arg_0, 1, atomic_result);
+ const int x_11 = atomic_result;
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicExchange_e114ba();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..7126a8a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicExchange_e114ba(threadgroup atomic_int* const tint_symbol) {
+ int res = 0;
+ int const x_11 = atomic_exchange_explicit(tint_symbol, 1, memory_order_relaxed);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicExchange_e114ba(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_31 = *(tint_symbol_2);
+ compute_main_inner(x_31, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..bb829c9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicExchange_e114ba "atomicExchange_e114ba"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicExchange_e114ba = OpFunction %void None %10
+ %13 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %res %14
+ %17 = OpAtomicExchange %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicExchange_e114ba
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..4e35c0e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicExchange_e114ba() {
+ var res : i32 = 0i;
+ let x_11 : i32 = atomicExchange(&(arg_0), 1i);
+ res = x_11;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicExchange_e114ba();
+ return;
+}
+
+fn compute_main_1() {
+ let x_31 : u32 = local_invocation_index_1;
+ compute_main_inner(x_31);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm
new file mode 100644
index 0000000..23dbf02
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicExchange_0a5dca "atomicExchange_0a5dca"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+ %18 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicExchange_0a5dca = OpFunction %void None %6
+ %9 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %10 = OpAtomicExchange %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %10
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %18
+%local_invocation_index = OpFunctionParameter %uint
+ %21 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %17
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %26 = OpFunctionCall %void %atomicExchange_0a5dca
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %28 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %29 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..7bfe69f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicExchange_0a5dca() {
+ uint res = 0u;
+ uint x_10 = atomicExchange(arg_0, 1u);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicExchange_0a5dca();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..926f18e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicExchange_0a5dca() {
+ uint res = 0u;
+ uint atomic_result = 0u;
+ InterlockedExchange(arg_0, 1u, atomic_result);
+ const uint x_10 = atomic_result;
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicExchange_0a5dca();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..4027c03
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicExchange_0a5dca(threadgroup atomic_uint* const tint_symbol) {
+ uint res = 0u;
+ uint const x_10 = atomic_exchange_explicit(tint_symbol, 1u, memory_order_relaxed);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicExchange_0a5dca(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_30 = *(tint_symbol_2);
+ compute_main_inner(x_30, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..0aca328
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,74 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicExchange_0a5dca "atomicExchange_0a5dca"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicExchange_0a5dca = OpFunction %void None %9
+ %12 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %res %6
+ %15 = OpAtomicExchange %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicExchange_0a5dca
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %30 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %20
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %35 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %39 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %41 = OpLabel
+ %43 = OpLoad %uint %local_invocation_index_1_param_1
+ %42 = OpFunctionCall %void %compute_main_inner_1 %43
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..fb71c6d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicExchange/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicExchange_0a5dca() {
+ var res : u32 = 0u;
+ let x_10 : u32 = atomicExchange(&(arg_0), 1u);
+ res = x_10;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicExchange_0a5dca();
+ return;
+}
+
+fn compute_main_1() {
+ let x_30 : u32 = local_invocation_index_1;
+ compute_main_inner(x_30);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm
new file mode 100644
index 0000000..d961ea5
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 25
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicLoad_0806ad "atomicLoad_0806ad"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %18 = OpConstantNull %int
+%atomicLoad_0806ad = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %18
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %9 = OpAtomicLoad %int %15 %uint_1 %uint_0
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %20 = OpLabel
+ %21 = OpFunctionCall %void %atomicLoad_0806ad
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicLoad_0806ad
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..d034197
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicLoad_0806ad() {
+ int res = 0;
+ int x_9 = atomicOr(sb_rw.arg_0, 0);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicLoad_0806ad();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicLoad_0806ad() {
+ int res = 0;
+ int x_9 = atomicOr(sb_rw.arg_0, 0);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicLoad_0806ad();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..8ce9cf2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicLoad(RWByteAddressBuffer buffer, uint offset) {
+ int value = 0;
+ buffer.InterlockedOr(offset, 0, value);
+ return value;
+}
+
+
+void atomicLoad_0806ad() {
+ int res = 0;
+ const int x_9 = tint_atomicLoad(sb_rw, 0u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicLoad_0806ad();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicLoad_0806ad();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..1ea07a1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicLoad_0806ad(device SB_RW_atomic* const tint_symbol) {
+ int res = 0;
+ int const x_9 = atomic_load_explicit(&((*(tint_symbol)).arg_0), memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicLoad_0806ad(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicLoad_0806ad(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..40034c7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,65 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicLoad_0806ad "atomicLoad_0806ad"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicLoad_0806ad = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %res %9
+ %18 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %12 = OpAtomicLoad %int %18 %uint_1 %uint_0
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %20 = OpLabel
+ %21 = OpFunctionCall %void %atomicLoad_0806ad
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicLoad_0806ad
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..b13dbfb
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicLoad_0806ad() {
+ var res : i32 = 0i;
+ let x_9 : i32 = atomicLoad(&(sb_rw.arg_0));
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicLoad_0806ad();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicLoad_0806ad();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm
new file mode 100644
index 0000000..776c62c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicLoad_fe6cc3 "atomicLoad_fe6cc3"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+%atomicLoad_fe6cc3 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %9 = OpAtomicLoad %uint %14 %uint_1 %uint_0
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicLoad_fe6cc3
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicLoad_fe6cc3
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..cebe232
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicLoad_fe6cc3() {
+ uint res = 0u;
+ uint x_9 = atomicOr(sb_rw.arg_0, 0u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicLoad_fe6cc3();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicLoad_fe6cc3() {
+ uint res = 0u;
+ uint x_9 = atomicOr(sb_rw.arg_0, 0u);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicLoad_fe6cc3();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..454ed3c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicLoad(RWByteAddressBuffer buffer, uint offset) {
+ uint value = 0;
+ buffer.InterlockedOr(offset, 0, value);
+ return value;
+}
+
+
+void atomicLoad_fe6cc3() {
+ uint res = 0u;
+ const uint x_9 = tint_atomicLoad(sb_rw, 0u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicLoad_fe6cc3();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicLoad_fe6cc3();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..a6cce27
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicLoad_fe6cc3(device SB_RW_atomic* const tint_symbol) {
+ uint res = 0u;
+ uint const x_9 = atomic_load_explicit(&((*(tint_symbol)).arg_0), memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicLoad_fe6cc3(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicLoad_fe6cc3(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..e12b47b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicLoad_fe6cc3 "atomicLoad_fe6cc3"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicLoad_fe6cc3 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %res %9
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %12 = OpAtomicLoad %uint %17 %uint_1 %uint_0
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicLoad_fe6cc3
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicLoad_fe6cc3
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..b03da62e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicLoad_fe6cc3() {
+ var res : u32 = 0u;
+ let x_9 : u32 = atomicLoad(&(sb_rw.arg_0));
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicLoad_fe6cc3();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicLoad_fe6cc3();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm
new file mode 100644
index 0000000..b996359
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicLoad_afcc03 "atomicLoad_afcc03"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+%_ptr_Function_int = OpTypePointer Function %int
+ %17 = OpConstantNull %int
+ %18 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicLoad_afcc03 = OpFunction %void None %7
+ %10 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %17
+ %11 = OpAtomicLoad %int %arg_0 %uint_2 %uint_0
+ OpStore %res %11
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %18
+%local_invocation_index = OpFunctionParameter %uint
+ %21 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %17
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %26 = OpFunctionCall %void %atomicLoad_afcc03
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %28 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %29 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..e0c158b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicLoad_afcc03() {
+ int res = 0;
+ int x_11 = atomicOr(arg_0, 0);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicLoad_afcc03();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..1593c13
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicLoad_afcc03() {
+ int res = 0;
+ int atomic_result = 0;
+ InterlockedOr(arg_0, 0, atomic_result);
+ const int x_11 = atomic_result;
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicLoad_afcc03();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..8f6ee40
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicLoad_afcc03(threadgroup atomic_int* const tint_symbol) {
+ int res = 0;
+ int const x_11 = atomic_load_explicit(tint_symbol, memory_order_relaxed);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicLoad_afcc03(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_30 = *(tint_symbol_2);
+ compute_main_inner(x_30, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..829b848
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,75 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 45
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicLoad_afcc03 "atomicLoad_afcc03"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicLoad_afcc03 = OpFunction %void None %10
+ %13 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %res %14
+ %17 = OpAtomicLoad %int %arg_0 %uint_2 %uint_0
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicLoad_afcc03
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %31 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %33 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %21
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %36 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %40 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %42 = OpLabel
+ %44 = OpLoad %uint %local_invocation_index_1_param_1
+ %43 = OpFunctionCall %void %compute_main_inner_1 %44
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..af0c057
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicLoad_afcc03() {
+ var res : i32 = 0i;
+ let x_11 : i32 = atomicLoad(&(arg_0));
+ res = x_11;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicLoad_afcc03();
+ return;
+}
+
+fn compute_main_1() {
+ let x_30 : u32 = local_invocation_index_1;
+ compute_main_inner(x_30);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm
new file mode 100644
index 0000000..20eeca7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicLoad_361bf1 "atomicLoad_361bf1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %16 = OpConstantNull %uint
+ %17 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicLoad_361bf1 = OpFunction %void None %6
+ %9 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %16
+ %10 = OpAtomicLoad %uint %arg_0 %uint_2 %uint_0
+ OpStore %res %10
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %17
+%local_invocation_index = OpFunctionParameter %uint
+ %20 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %16
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %25 = OpFunctionCall %void %atomicLoad_361bf1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %27 = OpLabel
+ %29 = OpLoad %uint %local_invocation_index_1
+ %28 = OpFunctionCall %void %compute_main_inner %29
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..8bd40a6
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicLoad_361bf1() {
+ uint res = 0u;
+ uint x_10 = atomicOr(arg_0, 0u);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicLoad_361bf1();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..803eadd
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicLoad_361bf1() {
+ uint res = 0u;
+ uint atomic_result = 0u;
+ InterlockedOr(arg_0, 0, atomic_result);
+ const uint x_10 = atomic_result;
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicLoad_361bf1();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..d7fcb6e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicLoad_361bf1(threadgroup atomic_uint* const tint_symbol) {
+ uint res = 0u;
+ uint const x_10 = atomic_load_explicit(tint_symbol, memory_order_relaxed);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicLoad_361bf1(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_29 = *(tint_symbol_2);
+ compute_main_inner(x_29, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..7a075ba
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,73 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 43
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicLoad_361bf1 "atomicLoad_361bf1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %19 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicLoad_361bf1 = OpFunction %void None %9
+ %12 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %res %6
+ %15 = OpAtomicLoad %uint %arg_0 %uint_2 %uint_0
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %27 = OpFunctionCall %void %atomicLoad_361bf1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %29 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %31 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %19
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %34 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %38 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %40 = OpLabel
+ %42 = OpLoad %uint %local_invocation_index_1_param_1
+ %41 = OpFunctionCall %void %compute_main_inner_1 %42
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..f132c6f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicLoad/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicLoad_361bf1() {
+ var res : u32 = 0u;
+ let x_10 : u32 = atomicLoad(&(arg_0));
+ res = x_10;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicLoad_361bf1();
+ return;
+}
+
+fn compute_main_1() {
+ let x_29 : u32 = local_invocation_index_1;
+ compute_main_inner(x_29);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm
new file mode 100644
index 0000000..82be997
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMax_92aa72 "atomicMax_92aa72"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %19 = OpConstantNull %int
+%atomicMax_92aa72 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %19
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %9 = OpAtomicSMax %int %15 %uint_1 %uint_0 %int_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicMax_92aa72
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicMax_92aa72
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..6341848
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicMax_92aa72() {
+ int res = 0;
+ int x_9 = atomicMax(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMax_92aa72();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicMax_92aa72() {
+ int res = 0;
+ int x_9 = atomicMax(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicMax_92aa72();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..4fd3948
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicMax(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedMax(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicMax_92aa72() {
+ int res = 0;
+ const int x_9 = tint_atomicMax(sb_rw, 0u, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMax_92aa72();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicMax_92aa72();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..39a434c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicMax_92aa72(device SB_RW_atomic* const tint_symbol) {
+ int res = 0;
+ int const x_9 = atomic_fetch_max_explicit(&((*(tint_symbol)).arg_0), 1, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicMax_92aa72(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicMax_92aa72(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..34dd4c3
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,66 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMax_92aa72 "atomicMax_92aa72"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%atomicMax_92aa72 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %res %9
+ %18 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %12 = OpAtomicSMax %int %18 %uint_1 %uint_0 %int_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicMax_92aa72
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicMax_92aa72
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..ae52315
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicMax_92aa72() {
+ var res : i32 = 0i;
+ let x_9 : i32 = atomicMax(&(sb_rw.arg_0), 1i);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicMax_92aa72();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicMax_92aa72();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm
new file mode 100644
index 0000000..7fb135e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMax_51b9be "atomicMax_51b9be"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+%atomicMax_51b9be = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %9 = OpAtomicUMax %uint %14 %uint_1 %uint_0 %uint_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicMax_51b9be
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicMax_51b9be
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..08dd962
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicMax_51b9be() {
+ uint res = 0u;
+ uint x_9 = atomicMax(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMax_51b9be();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicMax_51b9be() {
+ uint res = 0u;
+ uint x_9 = atomicMax(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicMax_51b9be();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..9934904
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicMax(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedMax(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicMax_51b9be() {
+ uint res = 0u;
+ const uint x_9 = tint_atomicMax(sb_rw, 0u, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMax_51b9be();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicMax_51b9be();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..bc40d81
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicMax_51b9be(device SB_RW_atomic* const tint_symbol) {
+ uint res = 0u;
+ uint const x_9 = atomic_fetch_max_explicit(&((*(tint_symbol)).arg_0), 1u, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicMax_51b9be(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicMax_51b9be(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..be00498
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMax_51b9be "atomicMax_51b9be"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicMax_51b9be = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %res %9
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %12 = OpAtomicUMax %uint %17 %uint_1 %uint_0 %uint_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicMax_51b9be
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicMax_51b9be
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..9b20062
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicMax_51b9be() {
+ var res : u32 = 0u;
+ let x_9 : u32 = atomicMax(&(sb_rw.arg_0), 1u);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicMax_51b9be();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicMax_51b9be();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm
new file mode 100644
index 0000000..62355e0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMax_a89cc3 "atomicMax_a89cc3"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %18 = OpConstantNull %int
+ %19 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMax_a89cc3 = OpFunction %void None %7
+ %10 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %18
+ %11 = OpAtomicSMax %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %11
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %18
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %27 = OpFunctionCall %void %atomicMax_a89cc3
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %29 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %30 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..44e03cf
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicMax_a89cc3() {
+ int res = 0;
+ int x_11 = atomicMax(arg_0, 1);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicMax_a89cc3();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..bdcfb2a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicMax_a89cc3() {
+ int res = 0;
+ int atomic_result = 0;
+ InterlockedMax(arg_0, 1, atomic_result);
+ const int x_11 = atomic_result;
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicMax_a89cc3();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..9421382
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicMax_a89cc3(threadgroup atomic_int* const tint_symbol) {
+ int res = 0;
+ int const x_11 = atomic_fetch_max_explicit(tint_symbol, 1, memory_order_relaxed);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicMax_a89cc3(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_31 = *(tint_symbol_2);
+ compute_main_inner(x_31, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..0360ae6
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMax_a89cc3 "atomicMax_a89cc3"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMax_a89cc3 = OpFunction %void None %10
+ %13 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %res %14
+ %17 = OpAtomicSMax %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicMax_a89cc3
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..0c3e2a8
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicMax_a89cc3() {
+ var res : i32 = 0i;
+ let x_11 : i32 = atomicMax(&(arg_0), 1i);
+ res = x_11;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicMax_a89cc3();
+ return;
+}
+
+fn compute_main_1() {
+ let x_31 : u32 = local_invocation_index_1;
+ compute_main_inner(x_31);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm
new file mode 100644
index 0000000..2636c66
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMax_beccfc "atomicMax_beccfc"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+ %18 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMax_beccfc = OpFunction %void None %6
+ %9 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %10 = OpAtomicUMax %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %10
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %18
+%local_invocation_index = OpFunctionParameter %uint
+ %21 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %17
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %26 = OpFunctionCall %void %atomicMax_beccfc
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %28 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %29 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..dc7354c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicMax_beccfc() {
+ uint res = 0u;
+ uint x_10 = atomicMax(arg_0, 1u);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicMax_beccfc();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..9c405cb
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicMax_beccfc() {
+ uint res = 0u;
+ uint atomic_result = 0u;
+ InterlockedMax(arg_0, 1u, atomic_result);
+ const uint x_10 = atomic_result;
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicMax_beccfc();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..200a901
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicMax_beccfc(threadgroup atomic_uint* const tint_symbol) {
+ uint res = 0u;
+ uint const x_10 = atomic_fetch_max_explicit(tint_symbol, 1u, memory_order_relaxed);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicMax_beccfc(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_30 = *(tint_symbol_2);
+ compute_main_inner(x_30, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..7f01c87
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,74 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMax_beccfc "atomicMax_beccfc"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMax_beccfc = OpFunction %void None %9
+ %12 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %res %6
+ %15 = OpAtomicUMax %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicMax_beccfc
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %30 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %20
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %35 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %39 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %41 = OpLabel
+ %43 = OpLoad %uint %local_invocation_index_1_param_1
+ %42 = OpFunctionCall %void %compute_main_inner_1 %43
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..39ee5df
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMax/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicMax_beccfc() {
+ var res : u32 = 0u;
+ let x_10 : u32 = atomicMax(&(arg_0), 1u);
+ res = x_10;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicMax_beccfc();
+ return;
+}
+
+fn compute_main_1() {
+ let x_30 : u32 = local_invocation_index_1;
+ compute_main_inner(x_30);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm
new file mode 100644
index 0000000..660547b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMin_8e38dc "atomicMin_8e38dc"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %19 = OpConstantNull %int
+%atomicMin_8e38dc = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %19
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %9 = OpAtomicSMin %int %15 %uint_1 %uint_0 %int_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicMin_8e38dc
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicMin_8e38dc
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..021d201
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicMin_8e38dc() {
+ int res = 0;
+ int x_9 = atomicMin(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMin_8e38dc();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicMin_8e38dc() {
+ int res = 0;
+ int x_9 = atomicMin(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicMin_8e38dc();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..efe6471
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicMin(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedMin(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicMin_8e38dc() {
+ int res = 0;
+ const int x_9 = tint_atomicMin(sb_rw, 0u, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMin_8e38dc();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicMin_8e38dc();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..efe7671
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicMin_8e38dc(device SB_RW_atomic* const tint_symbol) {
+ int res = 0;
+ int const x_9 = atomic_fetch_min_explicit(&((*(tint_symbol)).arg_0), 1, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicMin_8e38dc(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicMin_8e38dc(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..42e5312
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,66 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMin_8e38dc "atomicMin_8e38dc"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%atomicMin_8e38dc = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %res %9
+ %18 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %12 = OpAtomicSMin %int %18 %uint_1 %uint_0 %int_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicMin_8e38dc
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicMin_8e38dc
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..667b13a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicMin_8e38dc() {
+ var res : i32 = 0i;
+ let x_9 : i32 = atomicMin(&(sb_rw.arg_0), 1i);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicMin_8e38dc();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicMin_8e38dc();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm
new file mode 100644
index 0000000..0ed9315
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMin_c67a74 "atomicMin_c67a74"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+%atomicMin_c67a74 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %9 = OpAtomicUMin %uint %14 %uint_1 %uint_0 %uint_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicMin_c67a74
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicMin_c67a74
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..66cb351
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicMin_c67a74() {
+ uint res = 0u;
+ uint x_9 = atomicMin(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMin_c67a74();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicMin_c67a74() {
+ uint res = 0u;
+ uint x_9 = atomicMin(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicMin_c67a74();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..1bb4ca0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicMin(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedMin(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicMin_c67a74() {
+ uint res = 0u;
+ const uint x_9 = tint_atomicMin(sb_rw, 0u, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMin_c67a74();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicMin_c67a74();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..e03cf33
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicMin_c67a74(device SB_RW_atomic* const tint_symbol) {
+ uint res = 0u;
+ uint const x_9 = atomic_fetch_min_explicit(&((*(tint_symbol)).arg_0), 1u, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicMin_c67a74(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicMin_c67a74(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..c1fc0dc
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMin_c67a74 "atomicMin_c67a74"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicMin_c67a74 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %res %9
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %12 = OpAtomicUMin %uint %17 %uint_1 %uint_0 %uint_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicMin_c67a74
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicMin_c67a74
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..62f9e6a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicMin_c67a74() {
+ var res : u32 = 0u;
+ let x_9 : u32 = atomicMin(&(sb_rw.arg_0), 1u);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicMin_c67a74();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicMin_c67a74();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm
new file mode 100644
index 0000000..dfe5a35
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMin_278235 "atomicMin_278235"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %18 = OpConstantNull %int
+ %19 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMin_278235 = OpFunction %void None %7
+ %10 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %18
+ %11 = OpAtomicSMin %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %11
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %18
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %27 = OpFunctionCall %void %atomicMin_278235
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %29 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %30 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..f8151e3
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicMin_278235() {
+ int res = 0;
+ int x_11 = atomicMin(arg_0, 1);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicMin_278235();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..72197d7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicMin_278235() {
+ int res = 0;
+ int atomic_result = 0;
+ InterlockedMin(arg_0, 1, atomic_result);
+ const int x_11 = atomic_result;
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicMin_278235();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..3c4bd98
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicMin_278235(threadgroup atomic_int* const tint_symbol) {
+ int res = 0;
+ int const x_11 = atomic_fetch_min_explicit(tint_symbol, 1, memory_order_relaxed);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicMin_278235(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_31 = *(tint_symbol_2);
+ compute_main_inner(x_31, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..cea2249
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMin_278235 "atomicMin_278235"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMin_278235 = OpFunction %void None %10
+ %13 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %res %14
+ %17 = OpAtomicSMin %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicMin_278235
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..5ddda3e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicMin_278235() {
+ var res : i32 = 0i;
+ let x_11 : i32 = atomicMin(&(arg_0), 1i);
+ res = x_11;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicMin_278235();
+ return;
+}
+
+fn compute_main_1() {
+ let x_31 : u32 = local_invocation_index_1;
+ compute_main_inner(x_31);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm
new file mode 100644
index 0000000..de92bee
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMin_69d383 "atomicMin_69d383"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+ %18 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMin_69d383 = OpFunction %void None %6
+ %9 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %10 = OpAtomicUMin %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %10
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %18
+%local_invocation_index = OpFunctionParameter %uint
+ %21 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %17
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %26 = OpFunctionCall %void %atomicMin_69d383
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %28 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %29 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..466b141
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicMin_69d383() {
+ uint res = 0u;
+ uint x_10 = atomicMin(arg_0, 1u);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicMin_69d383();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..f91f02a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicMin_69d383() {
+ uint res = 0u;
+ uint atomic_result = 0u;
+ InterlockedMin(arg_0, 1u, atomic_result);
+ const uint x_10 = atomic_result;
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicMin_69d383();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..226629f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicMin_69d383(threadgroup atomic_uint* const tint_symbol) {
+ uint res = 0u;
+ uint const x_10 = atomic_fetch_min_explicit(tint_symbol, 1u, memory_order_relaxed);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicMin_69d383(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_30 = *(tint_symbol_2);
+ compute_main_inner(x_30, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..475d1ce
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,74 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMin_69d383 "atomicMin_69d383"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMin_69d383 = OpFunction %void None %9
+ %12 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %res %6
+ %15 = OpAtomicUMin %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicMin_69d383
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %30 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %20
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %35 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %39 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %41 = OpLabel
+ %43 = OpLoad %uint %local_invocation_index_1_param_1
+ %42 = OpFunctionCall %void %compute_main_inner_1 %43
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..8f37c6b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicMin/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicMin_69d383() {
+ var res : u32 = 0u;
+ let x_10 : u32 = atomicMin(&(arg_0), 1u);
+ res = x_10;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicMin_69d383();
+ return;
+}
+
+fn compute_main_1() {
+ let x_30 : u32 = local_invocation_index_1;
+ compute_main_inner(x_30);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm
new file mode 100644
index 0000000..1bf00f2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicOr_8d96a0 "atomicOr_8d96a0"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %19 = OpConstantNull %int
+%atomicOr_8d96a0 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %19
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %9 = OpAtomicOr %int %15 %uint_1 %uint_0 %int_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicOr_8d96a0
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicOr_8d96a0
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..b9557e3
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicOr_8d96a0() {
+ int res = 0;
+ int x_9 = atomicOr(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicOr_8d96a0();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicOr_8d96a0() {
+ int res = 0;
+ int x_9 = atomicOr(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicOr_8d96a0();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..f9e84d9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicOr(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedOr(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicOr_8d96a0() {
+ int res = 0;
+ const int x_9 = tint_atomicOr(sb_rw, 0u, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicOr_8d96a0();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicOr_8d96a0();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..2a66f9f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicOr_8d96a0(device SB_RW_atomic* const tint_symbol) {
+ int res = 0;
+ int const x_9 = atomic_fetch_or_explicit(&((*(tint_symbol)).arg_0), 1, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicOr_8d96a0(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicOr_8d96a0(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..a971056
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,66 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicOr_8d96a0 "atomicOr_8d96a0"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%atomicOr_8d96a0 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %res %9
+ %18 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %12 = OpAtomicOr %int %18 %uint_1 %uint_0 %int_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicOr_8d96a0
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicOr_8d96a0
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..bd4a06b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicOr_8d96a0() {
+ var res : i32 = 0i;
+ let x_9 : i32 = atomicOr(&(sb_rw.arg_0), 1i);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicOr_8d96a0();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicOr_8d96a0();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm
new file mode 100644
index 0000000..4778bc8
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicOr_5e95d4 "atomicOr_5e95d4"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+%atomicOr_5e95d4 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %9 = OpAtomicOr %uint %14 %uint_1 %uint_0 %uint_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicOr_5e95d4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicOr_5e95d4
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..5ad5f61
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicOr_5e95d4() {
+ uint res = 0u;
+ uint x_9 = atomicOr(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicOr_5e95d4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicOr_5e95d4() {
+ uint res = 0u;
+ uint x_9 = atomicOr(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicOr_5e95d4();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..b0ac7e6
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicOr(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedOr(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicOr_5e95d4() {
+ uint res = 0u;
+ const uint x_9 = tint_atomicOr(sb_rw, 0u, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicOr_5e95d4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicOr_5e95d4();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..e47c2db
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicOr_5e95d4(device SB_RW_atomic* const tint_symbol) {
+ uint res = 0u;
+ uint const x_9 = atomic_fetch_or_explicit(&((*(tint_symbol)).arg_0), 1u, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicOr_5e95d4(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicOr_5e95d4(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..a46ca1d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicOr_5e95d4 "atomicOr_5e95d4"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicOr_5e95d4 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %res %9
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %12 = OpAtomicOr %uint %17 %uint_1 %uint_0 %uint_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicOr_5e95d4
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicOr_5e95d4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..4f5bf4c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicOr_5e95d4() {
+ var res : u32 = 0u;
+ let x_9 : u32 = atomicOr(&(sb_rw.arg_0), 1u);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicOr_5e95d4();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicOr_5e95d4();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm
new file mode 100644
index 0000000..cd14aa9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicOr_d09248 "atomicOr_d09248"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %18 = OpConstantNull %int
+ %19 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicOr_d09248 = OpFunction %void None %7
+ %10 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %18
+ %11 = OpAtomicOr %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %11
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %18
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %27 = OpFunctionCall %void %atomicOr_d09248
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %29 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %30 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..4fdf338
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicOr_d09248() {
+ int res = 0;
+ int x_11 = atomicOr(arg_0, 1);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicOr_d09248();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..9f15c6c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicOr_d09248() {
+ int res = 0;
+ int atomic_result = 0;
+ InterlockedOr(arg_0, 1, atomic_result);
+ const int x_11 = atomic_result;
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicOr_d09248();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..74c1a58
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicOr_d09248(threadgroup atomic_int* const tint_symbol) {
+ int res = 0;
+ int const x_11 = atomic_fetch_or_explicit(tint_symbol, 1, memory_order_relaxed);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicOr_d09248(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_31 = *(tint_symbol_2);
+ compute_main_inner(x_31, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..9ef5893
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicOr_d09248 "atomicOr_d09248"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicOr_d09248 = OpFunction %void None %10
+ %13 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %res %14
+ %17 = OpAtomicOr %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicOr_d09248
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..5563b2b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicOr_d09248() {
+ var res : i32 = 0i;
+ let x_11 : i32 = atomicOr(&(arg_0), 1i);
+ res = x_11;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicOr_d09248();
+ return;
+}
+
+fn compute_main_1() {
+ let x_31 : u32 = local_invocation_index_1;
+ compute_main_inner(x_31);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm
new file mode 100644
index 0000000..1b9dc27
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicOr_5e3d61 "atomicOr_5e3d61"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+ %18 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicOr_5e3d61 = OpFunction %void None %6
+ %9 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %10 = OpAtomicOr %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %10
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %18
+%local_invocation_index = OpFunctionParameter %uint
+ %21 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %17
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %26 = OpFunctionCall %void %atomicOr_5e3d61
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %28 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %29 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..e9191a7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicOr_5e3d61() {
+ uint res = 0u;
+ uint x_10 = atomicOr(arg_0, 1u);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicOr_5e3d61();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..22393c1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicOr_5e3d61() {
+ uint res = 0u;
+ uint atomic_result = 0u;
+ InterlockedOr(arg_0, 1u, atomic_result);
+ const uint x_10 = atomic_result;
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicOr_5e3d61();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..2513fa7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicOr_5e3d61(threadgroup atomic_uint* const tint_symbol) {
+ uint res = 0u;
+ uint const x_10 = atomic_fetch_or_explicit(tint_symbol, 1u, memory_order_relaxed);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicOr_5e3d61(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_30 = *(tint_symbol_2);
+ compute_main_inner(x_30, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..ad9af50
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,74 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicOr_5e3d61 "atomicOr_5e3d61"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicOr_5e3d61 = OpFunction %void None %9
+ %12 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %res %6
+ %15 = OpAtomicOr %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicOr_5e3d61
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %30 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %20
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %35 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %39 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %41 = OpLabel
+ %43 = OpLoad %uint %local_invocation_index_1_param_1
+ %42 = OpFunctionCall %void %compute_main_inner_1 %43
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..2e9093e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicOr/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicOr_5e3d61() {
+ var res : u32 = 0u;
+ let x_10 : u32 = atomicOr(&(arg_0), 1u);
+ res = x_10;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicOr_5e3d61();
+ return;
+}
+
+fn compute_main_1() {
+ let x_30 : u32 = local_invocation_index_1;
+ compute_main_inner(x_30);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm
new file mode 100644
index 0000000..a471433
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm
@@ -0,0 +1,48 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 23
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicStore_d1e9a6 "atomicStore_d1e9a6"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%atomicStore_d1e9a6 = OpFunction %void None %5
+ %8 = OpLabel
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ OpAtomicStore %15 %uint_1 %uint_0 %int_1
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %18 = OpLabel
+ %19 = OpFunctionCall %void %atomicStore_d1e9a6
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicStore_d1e9a6
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..24fc51e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,64 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicStore_d1e9a6() {
+ atomicExchange(sb_rw.arg_0, 1);
+ return;
+}
+
+void fragment_main_1() {
+ atomicStore_d1e9a6();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicStore_d1e9a6() {
+ atomicExchange(sb_rw.arg_0, 1);
+ return;
+}
+
+void compute_main_1() {
+ atomicStore_d1e9a6();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..5ef62c9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,33 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+void tint_atomicStore(RWByteAddressBuffer buffer, uint offset, int value) {
+ int ignored;
+ buffer.InterlockedExchange(offset, value, ignored);
+}
+
+
+void atomicStore_d1e9a6() {
+ tint_atomicStore(sb_rw, 0u, 1);
+ return;
+}
+
+void fragment_main_1() {
+ atomicStore_d1e9a6();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicStore_d1e9a6();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..03e234a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.msl
@@ -0,0 +1,36 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicStore_d1e9a6(device SB_RW_atomic* const tint_symbol) {
+ atomic_store_explicit(&((*(tint_symbol)).arg_0), 1, memory_order_relaxed);
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicStore_d1e9a6(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicStore_d1e9a6(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..cabaea3
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,60 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 29
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicStore_d1e9a6 "atomicStore_d1e9a6"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%atomicStore_d1e9a6 = OpFunction %void None %5
+ %8 = OpLabel
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ OpAtomicStore %15 %uint_1 %uint_0 %int_1
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %18 = OpLabel
+ %19 = OpFunctionCall %void %atomicStore_d1e9a6
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicStore_d1e9a6
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..eaf478b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,34 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicStore_d1e9a6() {
+ atomicStore(&(sb_rw.arg_0), 1i);
+ return;
+}
+
+fn fragment_main_1() {
+ atomicStore_d1e9a6();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicStore_d1e9a6();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm
new file mode 100644
index 0000000..97adea0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm
@@ -0,0 +1,46 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 21
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicStore_cdc29e "atomicStore_cdc29e"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicStore_cdc29e = OpFunction %void None %5
+ %8 = OpLabel
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ OpAtomicStore %14 %uint_1 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %16 = OpLabel
+ %17 = OpFunctionCall %void %atomicStore_cdc29e
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicStore_cdc29e
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..e9c81a2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,64 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicStore_cdc29e() {
+ atomicExchange(sb_rw.arg_0, 1u);
+ return;
+}
+
+void fragment_main_1() {
+ atomicStore_cdc29e();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicStore_cdc29e() {
+ atomicExchange(sb_rw.arg_0, 1u);
+ return;
+}
+
+void compute_main_1() {
+ atomicStore_cdc29e();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..259c472
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,33 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+void tint_atomicStore(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint ignored;
+ buffer.InterlockedExchange(offset, value, ignored);
+}
+
+
+void atomicStore_cdc29e() {
+ tint_atomicStore(sb_rw, 0u, 1u);
+ return;
+}
+
+void fragment_main_1() {
+ atomicStore_cdc29e();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicStore_cdc29e();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..cc29ffd
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.msl
@@ -0,0 +1,36 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicStore_cdc29e(device SB_RW_atomic* const tint_symbol) {
+ atomic_store_explicit(&((*(tint_symbol)).arg_0), 1u, memory_order_relaxed);
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicStore_cdc29e(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicStore_cdc29e(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..bcda0e7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,58 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 27
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicStore_cdc29e "atomicStore_cdc29e"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicStore_cdc29e = OpFunction %void None %5
+ %8 = OpLabel
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ OpAtomicStore %14 %uint_1 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %16 = OpLabel
+ %17 = OpFunctionCall %void %atomicStore_cdc29e
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicStore_cdc29e
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..93b7fff
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,34 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicStore_cdc29e() {
+ atomicStore(&(sb_rw.arg_0), 1u);
+ return;
+}
+
+fn fragment_main_1() {
+ atomicStore_cdc29e();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicStore_cdc29e();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm
new file mode 100644
index 0000000..a08c2e8
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm
@@ -0,0 +1,49 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicStore_8bea94 "atomicStore_8bea94"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+ %16 = OpTypeFunction %void %uint
+ %22 = OpConstantNull %int
+ %uint_264 = OpConstant %uint 264
+%atomicStore_8bea94 = OpFunction %void None %7
+ %10 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %int_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %16
+%local_invocation_index = OpFunctionParameter %uint
+ %19 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %22
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %25 = OpFunctionCall %void %atomicStore_8bea94
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %27 = OpLabel
+ %29 = OpLoad %uint %local_invocation_index_1
+ %28 = OpFunctionCall %void %compute_main_inner %29
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..cc9e431
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,35 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicStore_8bea94() {
+ atomicExchange(arg_0, 1);
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicStore_8bea94();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..c2dbd19
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,41 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicStore_8bea94() {
+ int atomic_result = 0;
+ InterlockedExchange(arg_0, 1, atomic_result);
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicStore_8bea94();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..78e73c5
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,37 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicStore_8bea94(threadgroup atomic_int* const tint_symbol) {
+ atomic_store_explicit(tint_symbol, 1, memory_order_relaxed);
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicStore_8bea94(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_29 = *(tint_symbol_2);
+ compute_main_inner(x_29, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..319461d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicStore_8bea94 "atomicStore_8bea94"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+ %19 = OpTypeFunction %void %uint
+ %25 = OpConstantNull %int
+ %uint_264 = OpConstant %uint 264
+%atomicStore_8bea94 = OpFunction %void None %10
+ %13 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %int_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %25
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicStore_8bea94
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %30 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %19
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %35 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %25
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %39 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %41 = OpLabel
+ %43 = OpLoad %uint %local_invocation_index_1_param_1
+ %42 = OpFunctionCall %void %compute_main_inner_1 %43
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..800c8fd
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,27 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicStore_8bea94() {
+ atomicStore(&(arg_0), 1i);
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicStore_8bea94();
+ return;
+}
+
+fn compute_main_1() {
+ let x_29 : u32 = local_invocation_index_1;
+ compute_main_inner(x_29);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm
new file mode 100644
index 0000000..59738ef
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm
@@ -0,0 +1,48 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 29
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicStore_726882 "atomicStore_726882"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %15 = OpTypeFunction %void %uint
+ %21 = OpConstantNull %uint
+ %uint_264 = OpConstant %uint 264
+%atomicStore_726882 = OpFunction %void None %6
+ %9 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %15
+%local_invocation_index = OpFunctionParameter %uint
+ %18 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %21
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %24 = OpFunctionCall %void %atomicStore_726882
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %26 = OpLabel
+ %28 = OpLoad %uint %local_invocation_index_1
+ %27 = OpFunctionCall %void %compute_main_inner %28
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..678f189
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,35 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicStore_726882() {
+ atomicExchange(arg_0, 1u);
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicStore_726882();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..309c7df
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,41 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicStore_726882() {
+ uint atomic_result = 0u;
+ InterlockedExchange(arg_0, 1u, atomic_result);
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicStore_726882();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..1a458eb
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,37 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicStore_726882(threadgroup atomic_uint* const tint_symbol) {
+ atomic_store_explicit(tint_symbol, 1u, memory_order_relaxed);
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicStore_726882(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_28 = *(tint_symbol_2);
+ compute_main_inner(x_28, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..6f8e362
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,69 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 42
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicStore_726882 "atomicStore_726882"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %18 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicStore_726882 = OpFunction %void None %9
+ %12 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %uint_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %18
+%local_invocation_index = OpFunctionParameter %uint
+ %21 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %26 = OpFunctionCall %void %atomicStore_726882
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %28 = OpLabel
+ %29 = OpLoad %uint %local_invocation_index_1
+ %30 = OpFunctionCall %void %compute_main_inner %29
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %18
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %33 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %37 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %39 = OpLabel
+ %41 = OpLoad %uint %local_invocation_index_1_param_1
+ %40 = OpFunctionCall %void %compute_main_inner_1 %41
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..b90d965
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicStore/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,27 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicStore_726882() {
+ atomicStore(&(arg_0), 1u);
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicStore_726882();
+ return;
+}
+
+fn compute_main_1() {
+ let x_28 : u32 = local_invocation_index_1;
+ compute_main_inner(x_28);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm
new file mode 100644
index 0000000..f4b9264
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicSub_051100 "atomicSub_051100"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %19 = OpConstantNull %int
+%atomicSub_051100 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %19
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %9 = OpAtomicISub %int %15 %uint_1 %uint_0 %int_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicSub_051100
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicSub_051100
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..8f573df
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicSub_051100() {
+ int res = 0;
+ int x_9 = atomicAdd(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicSub_051100();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicSub_051100() {
+ int res = 0;
+ int x_9 = atomicAdd(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicSub_051100();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..3624845
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicSub(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedAdd(offset, -value, original_value);
+ return original_value;
+}
+
+
+void atomicSub_051100() {
+ int res = 0;
+ const int x_9 = tint_atomicSub(sb_rw, 0u, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicSub_051100();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicSub_051100();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..4696114
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicSub_051100(device SB_RW_atomic* const tint_symbol) {
+ int res = 0;
+ int const x_9 = atomic_fetch_sub_explicit(&((*(tint_symbol)).arg_0), 1, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicSub_051100(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicSub_051100(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..9ada74b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,66 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicSub_051100 "atomicSub_051100"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%atomicSub_051100 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %res %9
+ %18 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %12 = OpAtomicISub %int %18 %uint_1 %uint_0 %int_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicSub_051100
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicSub_051100
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..3fde6a5
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicSub_051100() {
+ var res : i32 = 0i;
+ let x_9 : i32 = atomicSub(&(sb_rw.arg_0), 1i);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicSub_051100();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicSub_051100();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm
new file mode 100644
index 0000000..b7cd92d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicSub_15bfc9 "atomicSub_15bfc9"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+%atomicSub_15bfc9 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %9 = OpAtomicISub %uint %14 %uint_1 %uint_0 %uint_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicSub_15bfc9
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicSub_15bfc9
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..e462c21
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicSub_15bfc9() {
+ uint res = 0u;
+ uint x_9 = atomicAdd(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicSub_15bfc9();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicSub_15bfc9() {
+ uint res = 0u;
+ uint x_9 = atomicAdd(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicSub_15bfc9();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..1bcbe09
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicSub(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedAdd(offset, -value, original_value);
+ return original_value;
+}
+
+
+void atomicSub_15bfc9() {
+ uint res = 0u;
+ const uint x_9 = tint_atomicSub(sb_rw, 0u, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicSub_15bfc9();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicSub_15bfc9();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..4cd9ce2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicSub_15bfc9(device SB_RW_atomic* const tint_symbol) {
+ uint res = 0u;
+ uint const x_9 = atomic_fetch_sub_explicit(&((*(tint_symbol)).arg_0), 1u, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicSub_15bfc9(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicSub_15bfc9(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..885f703
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicSub_15bfc9 "atomicSub_15bfc9"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicSub_15bfc9 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %res %9
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %12 = OpAtomicISub %uint %17 %uint_1 %uint_0 %uint_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicSub_15bfc9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicSub_15bfc9
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..23ba9fe
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicSub_15bfc9() {
+ var res : u32 = 0u;
+ let x_9 : u32 = atomicSub(&(sb_rw.arg_0), 1u);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicSub_15bfc9();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicSub_15bfc9();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm
new file mode 100644
index 0000000..f0471be
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicSub_77883a "atomicSub_77883a"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %18 = OpConstantNull %int
+ %19 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicSub_77883a = OpFunction %void None %7
+ %10 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %18
+ %11 = OpAtomicISub %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %11
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %18
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %27 = OpFunctionCall %void %atomicSub_77883a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %29 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %30 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..0583afc
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicSub_77883a() {
+ int res = 0;
+ int x_11 = atomicAdd(arg_0, 1);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicSub_77883a();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..75a1b4a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicSub_77883a() {
+ int res = 0;
+ int atomic_result = 0;
+ InterlockedAdd(arg_0, -1, atomic_result);
+ const int x_11 = atomic_result;
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicSub_77883a();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..86f5de2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicSub_77883a(threadgroup atomic_int* const tint_symbol) {
+ int res = 0;
+ int const x_11 = atomic_fetch_sub_explicit(tint_symbol, 1, memory_order_relaxed);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicSub_77883a(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_31 = *(tint_symbol_2);
+ compute_main_inner(x_31, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..820d0ae
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicSub_77883a "atomicSub_77883a"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicSub_77883a = OpFunction %void None %10
+ %13 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %res %14
+ %17 = OpAtomicISub %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicSub_77883a
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..56079fe
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicSub_77883a() {
+ var res : i32 = 0i;
+ let x_11 : i32 = atomicSub(&(arg_0), 1i);
+ res = x_11;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicSub_77883a();
+ return;
+}
+
+fn compute_main_1() {
+ let x_31 : u32 = local_invocation_index_1;
+ compute_main_inner(x_31);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm
new file mode 100644
index 0000000..0412631
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicSub_0d26c2 "atomicSub_0d26c2"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+ %18 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicSub_0d26c2 = OpFunction %void None %6
+ %9 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %10 = OpAtomicISub %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %10
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %18
+%local_invocation_index = OpFunctionParameter %uint
+ %21 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %17
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %26 = OpFunctionCall %void %atomicSub_0d26c2
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %28 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %29 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..49553d0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicSub_0d26c2() {
+ uint res = 0u;
+ uint x_10 = atomicAdd(arg_0, 1u);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicSub_0d26c2();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..e6f8372
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicSub_0d26c2() {
+ uint res = 0u;
+ uint atomic_result = 0u;
+ InterlockedAdd(arg_0, -1u, atomic_result);
+ const uint x_10 = atomic_result;
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicSub_0d26c2();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..91e3b4b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicSub_0d26c2(threadgroup atomic_uint* const tint_symbol) {
+ uint res = 0u;
+ uint const x_10 = atomic_fetch_sub_explicit(tint_symbol, 1u, memory_order_relaxed);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicSub_0d26c2(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_30 = *(tint_symbol_2);
+ compute_main_inner(x_30, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..c42f0b9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,74 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicSub_0d26c2 "atomicSub_0d26c2"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicSub_0d26c2 = OpFunction %void None %9
+ %12 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %res %6
+ %15 = OpAtomicISub %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicSub_0d26c2
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %30 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %20
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %35 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %39 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %41 = OpLabel
+ %43 = OpLoad %uint %local_invocation_index_1_param_1
+ %42 = OpFunctionCall %void %compute_main_inner_1 %43
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..2b69af6
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicSub/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicSub_0d26c2() {
+ var res : u32 = 0u;
+ let x_10 : u32 = atomicSub(&(arg_0), 1u);
+ res = x_10;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicSub_0d26c2();
+ return;
+}
+
+fn compute_main_1() {
+ let x_30 : u32 = local_invocation_index_1;
+ compute_main_inner(x_30);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm
new file mode 100644
index 0000000..98ac9c2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicXor_c1b78c "atomicXor_c1b78c"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %19 = OpConstantNull %int
+%atomicXor_c1b78c = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %19
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %9 = OpAtomicXor %int %15 %uint_1 %uint_0 %int_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicXor_c1b78c
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicXor_c1b78c
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..cc05c28
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicXor_c1b78c() {
+ int res = 0;
+ int x_9 = atomicXor(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicXor_c1b78c();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicXor_c1b78c() {
+ int res = 0;
+ int x_9 = atomicXor(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicXor_c1b78c();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..605a4d7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicXor(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedXor(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicXor_c1b78c() {
+ int res = 0;
+ const int x_9 = tint_atomicXor(sb_rw, 0u, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicXor_c1b78c();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicXor_c1b78c();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..fbde760
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicXor_c1b78c(device SB_RW_atomic* const tint_symbol) {
+ int res = 0;
+ int const x_9 = atomic_fetch_xor_explicit(&((*(tint_symbol)).arg_0), 1, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicXor_c1b78c(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicXor_c1b78c(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..1302c1a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,66 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicXor_c1b78c "atomicXor_c1b78c"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%atomicXor_c1b78c = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %res %9
+ %18 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %12 = OpAtomicXor %int %18 %uint_1 %uint_0 %int_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicXor_c1b78c
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicXor_c1b78c
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..7992f58
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicXor_c1b78c() {
+ var res : i32 = 0i;
+ let x_9 : i32 = atomicXor(&(sb_rw.arg_0), 1i);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicXor_c1b78c();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicXor_c1b78c();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm
new file mode 100644
index 0000000..8b4ef21
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicXor_54510e "atomicXor_54510e"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+%atomicXor_54510e = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %9 = OpAtomicXor %uint %14 %uint_1 %uint_0 %uint_1
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicXor_54510e
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicXor_54510e
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..2893791
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicXor_54510e() {
+ uint res = 0u;
+ uint x_9 = atomicXor(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicXor_54510e();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicXor_54510e() {
+ uint res = 0u;
+ uint x_9 = atomicXor(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicXor_54510e();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..3c2aad7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicXor(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedXor(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicXor_54510e() {
+ uint res = 0u;
+ const uint x_9 = tint_atomicXor(sb_rw, 0u, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicXor_54510e();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicXor_54510e();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..dd37adc
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicXor_54510e(device SB_RW_atomic* const tint_symbol) {
+ uint res = 0u;
+ uint const x_9 = atomic_fetch_xor_explicit(&((*(tint_symbol)).arg_0), 1u, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicXor_54510e(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicXor_54510e(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..1fb9bcc
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicXor_54510e "atomicXor_54510e"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicXor_54510e = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %res %9
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %12 = OpAtomicXor %uint %17 %uint_1 %uint_0 %uint_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicXor_54510e
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicXor_54510e
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..7fbc313
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicXor_54510e() {
+ var res : u32 = 0u;
+ let x_9 : u32 = atomicXor(&(sb_rw.arg_0), 1u);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicXor_54510e();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicXor_54510e();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm
new file mode 100644
index 0000000..4e729e2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicXor_75dc95 "atomicXor_75dc95"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %18 = OpConstantNull %int
+ %19 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicXor_75dc95 = OpFunction %void None %7
+ %10 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %18
+ %11 = OpAtomicXor %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %11
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %18
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %27 = OpFunctionCall %void %atomicXor_75dc95
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %29 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %30 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..b260d4d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicXor_75dc95() {
+ int res = 0;
+ int x_11 = atomicXor(arg_0, 1);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicXor_75dc95();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..5ffbd31
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicXor_75dc95() {
+ int res = 0;
+ int atomic_result = 0;
+ InterlockedXor(arg_0, 1, atomic_result);
+ const int x_11 = atomic_result;
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicXor_75dc95();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..b5c2e2c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicXor_75dc95(threadgroup atomic_int* const tint_symbol) {
+ int res = 0;
+ int const x_11 = atomic_fetch_xor_explicit(tint_symbol, 1, memory_order_relaxed);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicXor_75dc95(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_31 = *(tint_symbol_2);
+ compute_main_inner(x_31, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..542376d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicXor_75dc95 "atomicXor_75dc95"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicXor_75dc95 = OpFunction %void None %10
+ %13 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %res %14
+ %17 = OpAtomicXor %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicXor_75dc95
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..f14ac31
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicXor_75dc95() {
+ var res : i32 = 0i;
+ let x_11 : i32 = atomicXor(&(arg_0), 1i);
+ res = x_11;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicXor_75dc95();
+ return;
+}
+
+fn compute_main_1() {
+ let x_31 : u32 = local_invocation_index_1;
+ compute_main_inner(x_31);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm
new file mode 100644
index 0000000..a683557
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicXor_c8e6be "atomicXor_c8e6be"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+ %18 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicXor_c8e6be = OpFunction %void None %6
+ %9 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %10 = OpAtomicXor %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %10
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %18
+%local_invocation_index = OpFunctionParameter %uint
+ %21 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %17
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %26 = OpFunctionCall %void %atomicXor_c8e6be
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %28 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %29 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..a15719a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicXor_c8e6be() {
+ uint res = 0u;
+ uint x_10 = atomicXor(arg_0, 1u);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicXor_c8e6be();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..8296d86
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicXor_c8e6be() {
+ uint res = 0u;
+ uint atomic_result = 0u;
+ InterlockedXor(arg_0, 1u, atomic_result);
+ const uint x_10 = atomic_result;
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicXor_c8e6be();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..6993e95
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicXor_c8e6be(threadgroup atomic_uint* const tint_symbol) {
+ uint res = 0u;
+ uint const x_10 = atomic_fetch_xor_explicit(tint_symbol, 1u, memory_order_relaxed);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicXor_c8e6be(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_30 = *(tint_symbol_2);
+ compute_main_inner(x_30, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..4f19634
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,74 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicXor_c8e6be "atomicXor_c8e6be"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicXor_c8e6be = OpFunction %void None %9
+ %12 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %res %6
+ %15 = OpAtomicXor %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicXor_c8e6be
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %30 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %20
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %35 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %39 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %41 = OpLabel
+ %43 = OpLoad %uint %local_invocation_index_1_param_1
+ %42 = OpFunctionCall %void %compute_main_inner_1 %43
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..53f7436
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/atomicXor/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicXor_c8e6be() {
+ var res : u32 = 0u;
+ let x_10 : u32 = atomicXor(&(arg_0), 1u);
+ res = x_10;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicXor_c8e6be();
+ return;
+}
+
+fn compute_main_1() {
+ let x_30 : u32 = local_invocation_index_1;
+ compute_main_inner(x_30);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm
new file mode 100644
index 0000000..fe8b450
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_d32fe4 "atomicAdd_d32fe4"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %19 = OpConstantNull %int
+%atomicAdd_d32fe4 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %19
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %9 = OpAtomicIDecrement %int %15 %uint_1 %uint_0
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..875dc08
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAdd_d32fe4() {
+ int res = 0;
+ int x_9 = atomicAdd(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAdd_d32fe4() {
+ int res = 0;
+ int x_9 = atomicAdd(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..ab2b1ee
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicSub(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedAdd(offset, -value, original_value);
+ return original_value;
+}
+
+
+void atomicAdd_d32fe4() {
+ int res = 0;
+ const int x_9 = tint_atomicSub(sb_rw, 0u, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..8a042c1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicAdd_d32fe4(device SB_RW_atomic* const tint_symbol) {
+ int res = 0;
+ int const x_9 = atomic_fetch_sub_explicit(&((*(tint_symbol)).arg_0), 1, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAdd_d32fe4(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAdd_d32fe4(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..97fa9d7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,66 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_d32fe4 "atomicAdd_d32fe4"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%atomicAdd_d32fe4 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %res %9
+ %18 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %12 = OpAtomicISub %int %18 %uint_1 %uint_0 %int_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..e048762
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAdd_d32fe4() {
+ var res : i32 = 0i;
+ let x_9 : i32 = atomicSub(&(sb_rw.arg_0), 1i);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm
new file mode 100644
index 0000000..5197526
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_8a199a "atomicAdd_8a199a"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+%atomicAdd_8a199a = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %9 = OpAtomicIDecrement %uint %14 %uint_1 %uint_0
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..48a0735
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAdd_8a199a() {
+ uint res = 0u;
+ uint x_9 = atomicAdd(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAdd_8a199a() {
+ uint res = 0u;
+ uint x_9 = atomicAdd(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..6f0bb19
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicSub(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedAdd(offset, -value, original_value);
+ return original_value;
+}
+
+
+void atomicAdd_8a199a() {
+ uint res = 0u;
+ const uint x_9 = tint_atomicSub(sb_rw, 0u, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..adfd3c7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicAdd_8a199a(device SB_RW_atomic* const tint_symbol) {
+ uint res = 0u;
+ uint const x_9 = atomic_fetch_sub_explicit(&((*(tint_symbol)).arg_0), 1u, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAdd_8a199a(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAdd_8a199a(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..4ea9dce
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_8a199a "atomicAdd_8a199a"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicAdd_8a199a = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %res %9
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %12 = OpAtomicISub %uint %17 %uint_1 %uint_0 %uint_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..d22b2aaa
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAdd_8a199a() {
+ var res : u32 = 0u;
+ let x_9 : u32 = atomicSub(&(sb_rw.arg_0), 1u);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm
new file mode 100644
index 0000000..eb2f859
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_794055 "atomicAdd_794055"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %18 = OpConstantNull %int
+ %19 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_794055 = OpFunction %void None %7
+ %10 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %18
+ %11 = OpAtomicIDecrement %int %arg_0 %uint_2 %uint_0
+ OpStore %res %11
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %18
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %27 = OpFunctionCall %void %atomicAdd_794055
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %29 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %30 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..b745861
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicAdd_794055() {
+ int res = 0;
+ int x_11 = atomicAdd(arg_0, 1);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicAdd_794055();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..09f225c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicAdd_794055() {
+ int res = 0;
+ int atomic_result = 0;
+ InterlockedAdd(arg_0, -1, atomic_result);
+ const int x_11 = atomic_result;
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAdd_794055();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..e7d19e9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAdd_794055(threadgroup atomic_int* const tint_symbol) {
+ int res = 0;
+ int const x_11 = atomic_fetch_sub_explicit(tint_symbol, 1, memory_order_relaxed);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAdd_794055(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_31 = *(tint_symbol_2);
+ compute_main_inner(x_31, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..32bc60e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_794055 "atomicAdd_794055"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_794055 = OpFunction %void None %10
+ %13 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %res %14
+ %17 = OpAtomicISub %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicAdd_794055
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..6050ff2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicAdd_794055() {
+ var res : i32 = 0i;
+ let x_11 : i32 = atomicSub(&(arg_0), 1i);
+ res = x_11;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicAdd_794055();
+ return;
+}
+
+fn compute_main_1() {
+ let x_31 : u32 = local_invocation_index_1;
+ compute_main_inner(x_31);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm
new file mode 100644
index 0000000..8c3ebfc
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+ %18 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_d5db1d = OpFunction %void None %6
+ %9 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %10 = OpAtomicIDecrement %uint %arg_0 %uint_2 %uint_0
+ OpStore %res %10
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %18
+%local_invocation_index = OpFunctionParameter %uint
+ %21 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %17
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %26 = OpFunctionCall %void %atomicAdd_d5db1d
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %28 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %29 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..97c0c6f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicAdd_d5db1d() {
+ uint res = 0u;
+ uint x_10 = atomicAdd(arg_0, 1u);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicAdd_d5db1d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..33bfa08
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicAdd_d5db1d() {
+ uint res = 0u;
+ uint atomic_result = 0u;
+ InterlockedAdd(arg_0, -1u, atomic_result);
+ const uint x_10 = atomic_result;
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAdd_d5db1d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..bd63c56
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAdd_d5db1d(threadgroup atomic_uint* const tint_symbol) {
+ uint res = 0u;
+ uint const x_10 = atomic_fetch_sub_explicit(tint_symbol, 1u, memory_order_relaxed);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAdd_d5db1d(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_30 = *(tint_symbol_2);
+ compute_main_inner(x_30, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..c50dbae
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,74 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_d5db1d = OpFunction %void None %9
+ %12 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %res %6
+ %15 = OpAtomicISub %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicAdd_d5db1d
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %30 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %20
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %35 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %39 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %41 = OpLabel
+ %43 = OpLoad %uint %local_invocation_index_1_param_1
+ %42 = OpFunctionCall %void %compute_main_inner_1 %43
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..f7f54474
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicAdd_d5db1d() {
+ var res : u32 = 0u;
+ let x_10 : u32 = atomicSub(&(arg_0), 1u);
+ res = x_10;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicAdd_d5db1d();
+ return;
+}
+
+fn compute_main_1() {
+ let x_30 : u32 = local_invocation_index_1;
+ compute_main_inner(x_30);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm
new file mode 100644
index 0000000..efd1d3a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_d32fe4 "atomicAdd_d32fe4"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %19 = OpConstantNull %int
+%atomicAdd_d32fe4 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %19
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %9 = OpAtomicIIncrement %int %15 %uint_1 %uint_0
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..875dc08
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAdd_d32fe4() {
+ int res = 0;
+ int x_9 = atomicAdd(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAdd_d32fe4() {
+ int res = 0;
+ int x_9 = atomicAdd(sb_rw.arg_0, 1);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..358487b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicAdd(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedAdd(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicAdd_d32fe4() {
+ int res = 0;
+ const int x_9 = tint_atomicAdd(sb_rw, 0u, 1);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..64027ff
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicAdd_d32fe4(device SB_RW_atomic* const tint_symbol) {
+ int res = 0;
+ int const x_9 = atomic_fetch_add_explicit(&((*(tint_symbol)).arg_0), 1, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAdd_d32fe4(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAdd_d32fe4(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..13f287a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,66 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_d32fe4 "atomicAdd_d32fe4"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+ %int_1 = OpConstant %int 1
+%atomicAdd_d32fe4 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %res %9
+ %18 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %12 = OpAtomicIAdd %int %18 %uint_1 %uint_0 %int_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..cfc64fb
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAdd_d32fe4() {
+ var res : i32 = 0i;
+ let x_9 : i32 = atomicAdd(&(sb_rw.arg_0), 1i);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm
new file mode 100644
index 0000000..a805c50
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_8a199a "atomicAdd_8a199a"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+%atomicAdd_8a199a = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %9 = OpAtomicIIncrement %uint %14 %uint_1 %uint_0
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..48a0735
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAdd_8a199a() {
+ uint res = 0u;
+ uint x_9 = atomicAdd(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAdd_8a199a() {
+ uint res = 0u;
+ uint x_9 = atomicAdd(sb_rw.arg_0, 1u);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..bdc43b0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicAdd(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedAdd(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicAdd_8a199a() {
+ uint res = 0u;
+ const uint x_9 = tint_atomicAdd(sb_rw, 0u, 1u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..fa2343b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicAdd_8a199a(device SB_RW_atomic* const tint_symbol) {
+ uint res = 0u;
+ uint const x_9 = atomic_fetch_add_explicit(&((*(tint_symbol)).arg_0), 1u, memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAdd_8a199a(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAdd_8a199a(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..e1bf1e9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_8a199a "atomicAdd_8a199a"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicAdd_8a199a = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %res %9
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %12 = OpAtomicIAdd %uint %17 %uint_1 %uint_0 %uint_1
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..b5d5856
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAdd_8a199a() {
+ var res : u32 = 0u;
+ let x_9 : u32 = atomicAdd(&(sb_rw.arg_0), 1u);
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm
new file mode 100644
index 0000000..255bfe1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_794055 "atomicAdd_794055"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %18 = OpConstantNull %int
+ %19 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_794055 = OpFunction %void None %7
+ %10 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %18
+ %11 = OpAtomicIIncrement %int %arg_0 %uint_2 %uint_0
+ OpStore %res %11
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %18
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %27 = OpFunctionCall %void %atomicAdd_794055
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %29 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %30 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..b745861
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicAdd_794055() {
+ int res = 0;
+ int x_11 = atomicAdd(arg_0, 1);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicAdd_794055();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..ccdf1ad
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicAdd_794055() {
+ int res = 0;
+ int atomic_result = 0;
+ InterlockedAdd(arg_0, 1, atomic_result);
+ const int x_11 = atomic_result;
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAdd_794055();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..62639d7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAdd_794055(threadgroup atomic_int* const tint_symbol) {
+ int res = 0;
+ int const x_11 = atomic_fetch_add_explicit(tint_symbol, 1, memory_order_relaxed);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAdd_794055(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_31 = *(tint_symbol_2);
+ compute_main_inner(x_31, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..3dc0a5d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,76 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_794055 "atomicAdd_794055"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %int_1 = OpConstant %int 1
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_794055 = OpFunction %void None %10
+ %13 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %res %14
+ %17 = OpAtomicIAdd %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicAdd_794055
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..723a113
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicAdd_794055() {
+ var res : i32 = 0i;
+ let x_11 : i32 = atomicAdd(&(arg_0), 1i);
+ res = x_11;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicAdd_794055();
+ return;
+}
+
+fn compute_main_1() {
+ let x_31 : u32 = local_invocation_index_1;
+ compute_main_inner(x_31);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm
new file mode 100644
index 0000000..c26936d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+ %18 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_d5db1d = OpFunction %void None %6
+ %9 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %10 = OpAtomicIIncrement %uint %arg_0 %uint_2 %uint_0
+ OpStore %res %10
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %18
+%local_invocation_index = OpFunctionParameter %uint
+ %21 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %17
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %26 = OpFunctionCall %void %atomicAdd_d5db1d
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %28 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %29 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..97c0c6f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicAdd_d5db1d() {
+ uint res = 0u;
+ uint x_10 = atomicAdd(arg_0, 1u);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicAdd_d5db1d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..c36ae57
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicAdd_d5db1d() {
+ uint res = 0u;
+ uint atomic_result = 0u;
+ InterlockedAdd(arg_0, 1u, atomic_result);
+ const uint x_10 = atomic_result;
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAdd_d5db1d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..04a890a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAdd_d5db1d(threadgroup atomic_uint* const tint_symbol) {
+ uint res = 0u;
+ uint const x_10 = atomic_fetch_add_explicit(tint_symbol, 1u, memory_order_relaxed);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAdd_d5db1d(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_30 = *(tint_symbol_2);
+ compute_main_inner(x_30, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..5daee64
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,74 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 44
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %uint_1 = OpConstant %uint 1
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_d5db1d = OpFunction %void None %9
+ %12 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %res %6
+ %15 = OpAtomicIAdd %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicAdd_d5db1d
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %30 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %20
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %35 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %39 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %41 = OpLabel
+ %43 = OpLoad %uint %local_invocation_index_1_param_1
+ %42 = OpFunctionCall %void %compute_main_inner_1 %43
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..61d34cc
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/literal/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicAdd_d5db1d() {
+ var res : u32 = 0u;
+ let x_10 : u32 = atomicAdd(&(arg_0), 1u);
+ res = x_10;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicAdd_d5db1d();
+ return;
+}
+
+fn compute_main_1() {
+ let x_30 : u32 = local_invocation_index_1;
+ compute_main_inner(x_30);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm
new file mode 100644
index 0000000..2fd0e19
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 28
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_d32fe4 "atomicAdd_d32fe4"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %12 = OpConstantNull %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicAdd_d32fe4 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %12
+ %res = OpVariable %_ptr_Function_int Function %12
+ OpStore %arg_1 %int_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %20 = OpLoad %int %arg_1
+ %13 = OpAtomicIAdd %int %19 %uint_1 %uint_0 %20
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..bd9f7f8
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAdd_d32fe4() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicAdd(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAdd_d32fe4() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicAdd(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..1b338c9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicAdd(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedAdd(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicAdd_d32fe4() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ const int x_13 = tint_atomicAdd(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..3106aff
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicAdd_d32fe4(device SB_RW_atomic* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_20 = arg_1;
+ int const x_13 = atomic_fetch_add_explicit(&((*(tint_symbol)).arg_0), x_20, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAdd_d32fe4(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAdd_d32fe4(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..c38ab55
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_d32fe4 "atomicAdd_d32fe4"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicAdd_d32fe4 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %9
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %int_1
+ %14 = OpLoad %int %arg_1
+ %21 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %15 = OpAtomicIAdd %int %21 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %32 = OpLabel
+ %33 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..ea83a05
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAdd_d32fe4() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_20 : i32 = arg_1;
+ let x_13 : i32 = atomicAdd(&(sb_rw.arg_0), x_20);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm
new file mode 100644
index 0000000..98d9690
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm
@@ -0,0 +1,55 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_8a199a "atomicAdd_8a199a"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %12 = OpConstantNull %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicAdd_8a199a = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %12
+ %res = OpVariable %_ptr_Function_uint Function %12
+ OpStore %arg_1 %uint_1
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %18 = OpLoad %uint %arg_1
+ %13 = OpAtomicIAdd %uint %17 %uint_1 %uint_0 %18
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..5c1a1b0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAdd_8a199a() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicAdd(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAdd_8a199a() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicAdd(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..845d1f7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicAdd(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedAdd(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicAdd_8a199a() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ const uint x_13 = tint_atomicAdd(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..da05cfb
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicAdd_8a199a(device SB_RW_atomic* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_13 = atomic_fetch_add_explicit(&((*(tint_symbol)).arg_0), x_18, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAdd_8a199a(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAdd_8a199a(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..d015d49
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,69 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_8a199a "atomicAdd_8a199a"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicAdd_8a199a = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %9
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %uint_1
+ %14 = OpLoad %uint %arg_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %15 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..887a798
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAdd_8a199a() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_13 : u32 = atomicAdd(&(sb_rw.arg_0), x_18);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm
new file mode 100644
index 0000000..9a311f1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_794055 "atomicAdd_794055"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %14 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_794055 = OpFunction %void None %7
+ %10 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %15 = OpAtomicIAdd %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicAdd_794055
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %31 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..89a4577
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicAdd_794055() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_15 = atomicAdd(arg_0, arg_1);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicAdd_794055();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..0cfd696
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicAdd_794055() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int atomic_result = 0;
+ InterlockedAdd(arg_0, arg_1, atomic_result);
+ const int x_15 = atomic_result;
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAdd_794055();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..b30df09
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAdd_794055(threadgroup atomic_int* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_19 = arg_1;
+ int const x_15 = atomic_fetch_add_explicit(tint_symbol, x_19, memory_order_relaxed);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAdd_794055(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_33 = *(tint_symbol_2);
+ compute_main_inner(x_33, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..3d67dcf
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,81 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 48
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_794055 "atomicAdd_794055"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %24 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_794055 = OpFunction %void None %10
+ %13 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %14
+ OpStore %res %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %20 = OpAtomicIAdd %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %20
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %24
+%local_invocation_index = OpFunctionParameter %uint
+ %27 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %32 = OpFunctionCall %void %atomicAdd_794055
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %34 = OpLabel
+ %35 = OpLoad %uint %local_invocation_index_1
+ %36 = OpFunctionCall %void %compute_main_inner %35
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %24
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %39 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %43 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %45 = OpLabel
+ %47 = OpLoad %uint %local_invocation_index_1_param_1
+ %46 = OpFunctionCall %void %compute_main_inner_1 %47
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..27e5276
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicAdd_794055() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_19 : i32 = arg_1;
+ let x_15 : i32 = atomicAdd(&(arg_0), x_19);
+ res = x_15;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicAdd_794055();
+ return;
+}
+
+fn compute_main_1() {
+ let x_33 : u32 = local_invocation_index_1;
+ compute_main_inner(x_33);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm
new file mode 100644
index 0000000..7ab1e8d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm
@@ -0,0 +1,56 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %13 = OpConstantNull %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_d5db1d = OpFunction %void None %6
+ %9 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %13
+ %res = OpVariable %_ptr_Function_uint Function %13
+ OpStore %arg_1 %uint_1
+ %18 = OpLoad %uint %arg_1
+ %14 = OpAtomicIAdd %uint %arg_0 %uint_2 %uint_0 %18
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %13
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicAdd_d5db1d
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %30 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %31 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..07177c9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicAdd_d5db1d() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_14 = atomicAdd(arg_0, arg_1);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicAdd_d5db1d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..380a1a5
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicAdd_d5db1d() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint atomic_result = 0u;
+ InterlockedAdd(arg_0, arg_1, atomic_result);
+ const uint x_14 = atomic_result;
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAdd_d5db1d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..29c6f4b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAdd_d5db1d(threadgroup atomic_uint* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_14 = atomic_fetch_add_explicit(tint_symbol, x_18, memory_order_relaxed);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAdd_d5db1d(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_32 = *(tint_symbol_2);
+ compute_main_inner(x_32, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..1cab36f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,79 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_d5db1d = OpFunction %void None %9
+ %12 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %6
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %arg_1 %6
+ OpStore %res %6
+ OpStore %arg_1 %uint_1
+ %17 = OpLoad %uint %arg_1
+ %18 = OpAtomicIAdd %uint %arg_0 %uint_2 %uint_0 %17
+ OpStore %res %18
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicAdd_d5db1d
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..1ef7a33
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAdd/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicAdd_d5db1d() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_14 : u32 = atomicAdd(&(arg_0), x_18);
+ res = x_14;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicAdd_d5db1d();
+ return;
+}
+
+fn compute_main_1() {
+ let x_32 : u32 = local_invocation_index_1;
+ compute_main_inner(x_32);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm
new file mode 100644
index 0000000..18408ba
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 28
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAnd_152966 "atomicAnd_152966"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %12 = OpConstantNull %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicAnd_152966 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %12
+ %res = OpVariable %_ptr_Function_int Function %12
+ OpStore %arg_1 %int_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %20 = OpLoad %int %arg_1
+ %13 = OpAtomicAnd %int %19 %uint_1 %uint_0 %20
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicAnd_152966
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicAnd_152966
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..ea9ff84
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAnd_152966() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicAnd(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAnd_152966();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAnd_152966() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicAnd(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicAnd_152966();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..ea4a0f8
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicAnd(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedAnd(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicAnd_152966() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ const int x_13 = tint_atomicAnd(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAnd_152966();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAnd_152966();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..a9960d67
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicAnd_152966(device SB_RW_atomic* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_20 = arg_1;
+ int const x_13 = atomic_fetch_and_explicit(&((*(tint_symbol)).arg_0), x_20, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAnd_152966(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAnd_152966(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..3257d23
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAnd_152966 "atomicAnd_152966"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicAnd_152966 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %9
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %int_1
+ %14 = OpLoad %int %arg_1
+ %21 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %15 = OpAtomicAnd %int %21 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicAnd_152966
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %atomicAnd_152966
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %32 = OpLabel
+ %33 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..bdc601d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAnd_152966() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_20 : i32 = arg_1;
+ let x_13 : i32 = atomicAnd(&(sb_rw.arg_0), x_20);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAnd_152966();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAnd_152966();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm
new file mode 100644
index 0000000..d8c4b78
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm
@@ -0,0 +1,55 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAnd_85a8d9 "atomicAnd_85a8d9"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %12 = OpConstantNull %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicAnd_85a8d9 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %12
+ %res = OpVariable %_ptr_Function_uint Function %12
+ OpStore %arg_1 %uint_1
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %18 = OpLoad %uint %arg_1
+ %13 = OpAtomicAnd %uint %17 %uint_1 %uint_0 %18
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAnd_85a8d9
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicAnd_85a8d9
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..e3abb2a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAnd_85a8d9() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicAnd(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAnd_85a8d9();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAnd_85a8d9() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicAnd(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicAnd_85a8d9();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..44c8b7d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicAnd(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedAnd(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicAnd_85a8d9() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ const uint x_13 = tint_atomicAnd(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAnd_85a8d9();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAnd_85a8d9();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..798abe6
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicAnd_85a8d9(device SB_RW_atomic* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_13 = atomic_fetch_and_explicit(&((*(tint_symbol)).arg_0), x_18, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAnd_85a8d9(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAnd_85a8d9(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..668f193
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,69 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAnd_85a8d9 "atomicAnd_85a8d9"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicAnd_85a8d9 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %9
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %uint_1
+ %14 = OpLoad %uint %arg_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %15 = OpAtomicAnd %uint %19 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAnd_85a8d9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicAnd_85a8d9
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..4bf4b48
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAnd_85a8d9() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_13 : u32 = atomicAnd(&(sb_rw.arg_0), x_18);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAnd_85a8d9();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAnd_85a8d9();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm
new file mode 100644
index 0000000..e0c9a7e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAnd_45a819 "atomicAnd_45a819"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %14 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAnd_45a819 = OpFunction %void None %7
+ %10 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %15 = OpAtomicAnd %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicAnd_45a819
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %31 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..cc74ce6
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicAnd_45a819() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_15 = atomicAnd(arg_0, arg_1);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicAnd_45a819();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..cd9a7b7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicAnd_45a819() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int atomic_result = 0;
+ InterlockedAnd(arg_0, arg_1, atomic_result);
+ const int x_15 = atomic_result;
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAnd_45a819();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..962a96c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAnd_45a819(threadgroup atomic_int* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_19 = arg_1;
+ int const x_15 = atomic_fetch_and_explicit(tint_symbol, x_19, memory_order_relaxed);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAnd_45a819(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_33 = *(tint_symbol_2);
+ compute_main_inner(x_33, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..598acf2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,81 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 48
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAnd_45a819 "atomicAnd_45a819"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %24 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAnd_45a819 = OpFunction %void None %10
+ %13 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %14
+ OpStore %res %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %20 = OpAtomicAnd %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %20
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %24
+%local_invocation_index = OpFunctionParameter %uint
+ %27 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %32 = OpFunctionCall %void %atomicAnd_45a819
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %34 = OpLabel
+ %35 = OpLoad %uint %local_invocation_index_1
+ %36 = OpFunctionCall %void %compute_main_inner %35
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %24
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %39 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %43 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %45 = OpLabel
+ %47 = OpLoad %uint %local_invocation_index_1_param_1
+ %46 = OpFunctionCall %void %compute_main_inner_1 %47
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..d757c09
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicAnd_45a819() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_19 : i32 = arg_1;
+ let x_15 : i32 = atomicAnd(&(arg_0), x_19);
+ res = x_15;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicAnd_45a819();
+ return;
+}
+
+fn compute_main_1() {
+ let x_33 : u32 = local_invocation_index_1;
+ compute_main_inner(x_33);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm
new file mode 100644
index 0000000..e6e94c1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm
@@ -0,0 +1,56 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAnd_34edd3 "atomicAnd_34edd3"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %13 = OpConstantNull %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAnd_34edd3 = OpFunction %void None %6
+ %9 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %13
+ %res = OpVariable %_ptr_Function_uint Function %13
+ OpStore %arg_1 %uint_1
+ %18 = OpLoad %uint %arg_1
+ %14 = OpAtomicAnd %uint %arg_0 %uint_2 %uint_0 %18
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %13
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicAnd_34edd3
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %30 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %31 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..39b8c3e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicAnd_34edd3() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_14 = atomicAnd(arg_0, arg_1);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicAnd_34edd3();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..37f4fee
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicAnd_34edd3() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint atomic_result = 0u;
+ InterlockedAnd(arg_0, arg_1, atomic_result);
+ const uint x_14 = atomic_result;
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAnd_34edd3();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..d162405
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAnd_34edd3(threadgroup atomic_uint* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_14 = atomic_fetch_and_explicit(tint_symbol, x_18, memory_order_relaxed);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAnd_34edd3(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_32 = *(tint_symbol_2);
+ compute_main_inner(x_32, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..0eeed44
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,79 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAnd_34edd3 "atomicAnd_34edd3"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAnd_34edd3 = OpFunction %void None %9
+ %12 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %6
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %arg_1 %6
+ OpStore %res %6
+ OpStore %arg_1 %uint_1
+ %17 = OpLoad %uint %arg_1
+ %18 = OpAtomicAnd %uint %arg_0 %uint_2 %uint_0 %17
+ OpStore %res %18
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicAnd_34edd3
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..dba5360
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicAnd/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicAnd_34edd3() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_14 : u32 = atomicAnd(&(arg_0), x_18);
+ res = x_14;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicAnd_34edd3();
+ return;
+}
+
+fn compute_main_1() {
+ let x_32 : u32 = local_invocation_index_1;
+ compute_main_inner(x_32);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm
new file mode 100644
index 0000000..0999969
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm
@@ -0,0 +1,72 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 36
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicCompareExchangeWeak_1bd40a "atomicCompareExchangeWeak_1bd40a"
+ OpName %arg_1 "arg_1"
+ OpName %arg_2 "arg_2"
+ OpName %__atomic_compare_exchange_resulti32 "__atomic_compare_exchange_resulti32"
+ OpMemberName %__atomic_compare_exchange_resulti32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resulti32 1 "exchanged"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 1 Offset 4
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %12 = OpConstantNull %int
+ %bool = OpTypeBool
+%__atomic_compare_exchange_resulti32 = OpTypeStruct %int %bool
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%_ptr_Function___atomic_compare_exchange_resulti32 = OpTypePointer Function %__atomic_compare_exchange_resulti32
+ %29 = OpConstantNull %__atomic_compare_exchange_resulti32
+%atomicCompareExchangeWeak_1bd40a = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %12
+ %arg_2 = OpVariable %_ptr_Function_int Function %12
+ %res = OpVariable %_ptr_Function___atomic_compare_exchange_resulti32 Function %29
+ OpStore %arg_1 %int_1
+ OpStore %arg_2 %int_1
+ %22 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %23 = OpLoad %int %arg_2
+ %24 = OpLoad %int %arg_1
+ %25 = OpAtomicCompareExchange %int %22 %uint_1 %uint_0 %uint_0 %23 %24
+ %26 = OpIEqual %bool %25 %23
+ %14 = OpCompositeConstruct %__atomic_compare_exchange_resulti32 %25 %26
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %31 = OpLabel
+ %32 = OpFunctionCall %void %atomicCompareExchangeWeak_1bd40a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %34 = OpLabel
+ %35 = OpFunctionCall %void %atomicCompareExchangeWeak_1bd40a
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..286017b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,112 @@
+#version 310 es
+precision mediump float;
+
+struct atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicCompareExchangeWeak_1bd40a() {
+ int arg_1 = 0;
+ int arg_2 = 0;
+ x__atomic_compare_exchange_resulti32 res = x__atomic_compare_exchange_resulti32(0, false);
+ arg_1 = 1;
+ arg_2 = 1;
+ int x_23 = arg_2;
+ atomic_compare_exchange_resulti32 atomic_compare_result;
+ atomic_compare_result.old_value = atomicCompSwap(sb_rw.arg_0, arg_1, x_23);
+ atomic_compare_result.exchanged = atomic_compare_result.old_value == arg_1;
+ atomic_compare_exchange_resulti32 tint_symbol = atomic_compare_result;
+ int old_value_1 = tint_symbol.old_value;
+ int x_25 = old_value_1;
+ x__atomic_compare_exchange_resulti32 tint_symbol_1 = x__atomic_compare_exchange_resulti32(x_25, (x_25 == x_23));
+ res = tint_symbol_1;
+ return;
+}
+
+void fragment_main_1() {
+ atomicCompareExchangeWeak_1bd40a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicCompareExchangeWeak_1bd40a() {
+ int arg_1 = 0;
+ int arg_2 = 0;
+ x__atomic_compare_exchange_resulti32 res = x__atomic_compare_exchange_resulti32(0, false);
+ arg_1 = 1;
+ arg_2 = 1;
+ int x_23 = arg_2;
+ atomic_compare_exchange_resulti32 atomic_compare_result;
+ atomic_compare_result.old_value = atomicCompSwap(sb_rw.arg_0, arg_1, x_23);
+ atomic_compare_result.exchanged = atomic_compare_result.old_value == arg_1;
+ atomic_compare_exchange_resulti32 tint_symbol = atomic_compare_result;
+ int old_value_1 = tint_symbol.old_value;
+ int x_25 = old_value_1;
+ x__atomic_compare_exchange_resulti32 tint_symbol_1 = x__atomic_compare_exchange_resulti32(x_25, (x_25 == x_23));
+ res = tint_symbol_1;
+ return;
+}
+
+void compute_main_1() {
+ atomicCompareExchangeWeak_1bd40a();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..b121c66
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,55 @@
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+struct atomic_compare_exchange_weak_ret_type {
+ int old_value;
+ bool exchanged;
+};
+
+atomic_compare_exchange_weak_ret_type tint_atomicCompareExchangeWeak(RWByteAddressBuffer buffer, uint offset, int compare, int value) {
+ atomic_compare_exchange_weak_ret_type result=(atomic_compare_exchange_weak_ret_type)0;
+ buffer.InterlockedCompareExchange(offset, compare, value, result.old_value);
+ result.exchanged = result.old_value == compare;
+ return result;
+}
+
+
+void atomicCompareExchangeWeak_1bd40a() {
+ int arg_1 = 0;
+ int arg_2 = 0;
+ x__atomic_compare_exchange_resulti32 res = {0, false};
+ arg_1 = 1;
+ arg_2 = 1;
+ const int x_23 = arg_2;
+ const atomic_compare_exchange_weak_ret_type tint_symbol = tint_atomicCompareExchangeWeak(sb_rw, 0u, arg_1, x_23);
+ const int old_value_1 = tint_symbol.old_value;
+ const int x_25 = old_value_1;
+ const x__atomic_compare_exchange_resulti32 tint_symbol_1 = {x_25, (x_25 == x_23)};
+ res = tint_symbol_1;
+ return;
+}
+
+void fragment_main_1() {
+ atomicCompareExchangeWeak_1bd40a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicCompareExchangeWeak_1bd40a();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..fa2d372
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.msl
@@ -0,0 +1,63 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+atomic_compare_exchange_resulti32 atomicCompareExchangeWeak_1(device atomic_int* atomic, int compare, int value) {
+ int old_value = compare;
+ bool exchanged = atomic_compare_exchange_weak_explicit(atomic, &old_value, value, memory_order_relaxed, memory_order_relaxed);
+ return {old_value, exchanged};
+}
+
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+void atomicCompareExchangeWeak_1bd40a(device SB_RW_atomic* const tint_symbol_2) {
+ int arg_1 = 0;
+ int arg_2 = 0;
+ x__atomic_compare_exchange_resulti32 res = {.old_value=0, .exchanged=false};
+ arg_1 = 1;
+ arg_2 = 1;
+ int const x_23 = arg_2;
+ int const x_24 = arg_1;
+ atomic_compare_exchange_resulti32 const tint_symbol = atomicCompareExchangeWeak_1(&((*(tint_symbol_2)).arg_0), x_24, x_23);
+ int const old_value_1 = tint_symbol.old_value;
+ int const x_25 = old_value_1;
+ x__atomic_compare_exchange_resulti32 const tint_symbol_1 = {.old_value=x_25, .exchanged=(x_25 == x_23)};
+ res = tint_symbol_1;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicCompareExchangeWeak_1bd40a(tint_symbol_3);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_4);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_5) {
+ atomicCompareExchangeWeak_1bd40a(tint_symbol_5);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_6 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_6);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..dde3fc2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,98 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 48
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicCompareExchangeWeak_1bd40a "atomicCompareExchangeWeak_1bd40a"
+ OpName %arg_1 "arg_1"
+ OpName %arg_2 "arg_2"
+ OpName %x__atomic_compare_exchange_resulti32 "x__atomic_compare_exchange_resulti32"
+ OpMemberName %x__atomic_compare_exchange_resulti32 0 "old_value"
+ OpMemberName %x__atomic_compare_exchange_resulti32 1 "exchanged"
+ OpName %res "res"
+ OpName %__atomic_compare_exchange_resulti32 "__atomic_compare_exchange_resulti32"
+ OpMemberName %__atomic_compare_exchange_resulti32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resulti32 1 "exchanged"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ OpMemberDecorate %x__atomic_compare_exchange_resulti32 0 Offset 0
+ OpMemberDecorate %x__atomic_compare_exchange_resulti32 1 Offset 4
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 1 Offset 4
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %bool = OpTypeBool
+%x__atomic_compare_exchange_resulti32 = OpTypeStruct %int %bool
+ %15 = OpConstantNull %bool
+ %16 = OpConstantComposite %x__atomic_compare_exchange_resulti32 %9 %15
+%_ptr_Function_x__atomic_compare_exchange_resulti32 = OpTypePointer Function %x__atomic_compare_exchange_resulti32
+ %19 = OpConstantNull %x__atomic_compare_exchange_resulti32
+ %int_1 = OpConstant %int 1
+%__atomic_compare_exchange_resulti32 = OpTypeStruct %int %bool
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicCompareExchangeWeak_1bd40a = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %9
+ %arg_2 = OpVariable %_ptr_Function_int Function %9
+ %res = OpVariable %_ptr_Function_x__atomic_compare_exchange_resulti32 Function %19
+ OpStore %arg_1 %9
+ OpStore %arg_2 %9
+ OpStore %res %16
+ OpStore %arg_1 %int_1
+ OpStore %arg_2 %int_1
+ %21 = OpLoad %int %arg_2
+ %22 = OpLoad %int %arg_1
+ %30 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %31 = OpAtomicCompareExchange %int %30 %uint_1 %uint_0 %uint_0 %21 %22
+ %32 = OpIEqual %bool %31 %21
+ %23 = OpCompositeConstruct %__atomic_compare_exchange_resulti32 %31 %32
+ %33 = OpCompositeExtract %int %23 0
+ %34 = OpIEqual %bool %33 %21
+ %35 = OpCompositeConstruct %x__atomic_compare_exchange_resulti32 %33 %34
+ OpStore %res %35
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %37 = OpLabel
+ %38 = OpFunctionCall %void %atomicCompareExchangeWeak_1bd40a
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %40 = OpLabel
+ %41 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %43 = OpLabel
+ %44 = OpFunctionCall %void %atomicCompareExchangeWeak_1bd40a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %46 = OpLabel
+ %47 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..84a3a29
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,48 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+struct x__atomic_compare_exchange_resulti32 {
+ old_value : i32,
+ exchanged : bool,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicCompareExchangeWeak_1bd40a() {
+ var arg_1 : i32 = 0i;
+ var arg_2 : i32 = 0i;
+ var res : x__atomic_compare_exchange_resulti32 = x__atomic_compare_exchange_resulti32(0i, false);
+ arg_1 = 1i;
+ arg_2 = 1i;
+ let x_23 : i32 = arg_2;
+ let x_24 : i32 = arg_1;
+ let old_value_1 = atomicCompareExchangeWeak(&(sb_rw.arg_0), x_24, x_23).old_value;
+ let x_25 : i32 = old_value_1;
+ res = x__atomic_compare_exchange_resulti32(x_25, (x_25 == x_23));
+ return;
+}
+
+fn fragment_main_1() {
+ atomicCompareExchangeWeak_1bd40a();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicCompareExchangeWeak_1bd40a();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm
new file mode 100644
index 0000000..3723643
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm
@@ -0,0 +1,70 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicCompareExchangeWeak_63d8e6 "atomicCompareExchangeWeak_63d8e6"
+ OpName %arg_1 "arg_1"
+ OpName %arg_2 "arg_2"
+ OpName %__atomic_compare_exchange_resultu32 "__atomic_compare_exchange_resultu32"
+ OpMemberName %__atomic_compare_exchange_resultu32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resultu32 1 "exchanged"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 1 Offset 4
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %12 = OpConstantNull %uint
+ %bool = OpTypeBool
+%__atomic_compare_exchange_resultu32 = OpTypeStruct %uint %bool
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function___atomic_compare_exchange_resultu32 = OpTypePointer Function %__atomic_compare_exchange_resultu32
+ %27 = OpConstantNull %__atomic_compare_exchange_resultu32
+%atomicCompareExchangeWeak_63d8e6 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %12
+ %arg_2 = OpVariable %_ptr_Function_uint Function %12
+ %res = OpVariable %_ptr_Function___atomic_compare_exchange_resultu32 Function %27
+ OpStore %arg_1 %uint_1
+ OpStore %arg_2 %uint_1
+ %20 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %21 = OpLoad %uint %arg_2
+ %22 = OpLoad %uint %arg_1
+ %23 = OpAtomicCompareExchange %uint %20 %uint_1 %uint_0 %uint_0 %21 %22
+ %24 = OpIEqual %bool %23 %21
+ %14 = OpCompositeConstruct %__atomic_compare_exchange_resultu32 %23 %24
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %atomicCompareExchangeWeak_63d8e6
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %32 = OpLabel
+ %33 = OpFunctionCall %void %atomicCompareExchangeWeak_63d8e6
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..ec3e6e1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,112 @@
+#version 310 es
+precision mediump float;
+
+struct atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicCompareExchangeWeak_63d8e6() {
+ uint arg_1 = 0u;
+ uint arg_2 = 0u;
+ x__atomic_compare_exchange_resultu32 res = x__atomic_compare_exchange_resultu32(0u, false);
+ arg_1 = 1u;
+ arg_2 = 1u;
+ uint x_21 = arg_2;
+ atomic_compare_exchange_resultu32 atomic_compare_result;
+ atomic_compare_result.old_value = atomicCompSwap(sb_rw.arg_0, arg_1, x_21);
+ atomic_compare_result.exchanged = atomic_compare_result.old_value == arg_1;
+ atomic_compare_exchange_resultu32 tint_symbol = atomic_compare_result;
+ uint old_value_1 = tint_symbol.old_value;
+ uint x_23 = old_value_1;
+ x__atomic_compare_exchange_resultu32 tint_symbol_1 = x__atomic_compare_exchange_resultu32(x_23, (x_23 == x_21));
+ res = tint_symbol_1;
+ return;
+}
+
+void fragment_main_1() {
+ atomicCompareExchangeWeak_63d8e6();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicCompareExchangeWeak_63d8e6() {
+ uint arg_1 = 0u;
+ uint arg_2 = 0u;
+ x__atomic_compare_exchange_resultu32 res = x__atomic_compare_exchange_resultu32(0u, false);
+ arg_1 = 1u;
+ arg_2 = 1u;
+ uint x_21 = arg_2;
+ atomic_compare_exchange_resultu32 atomic_compare_result;
+ atomic_compare_result.old_value = atomicCompSwap(sb_rw.arg_0, arg_1, x_21);
+ atomic_compare_result.exchanged = atomic_compare_result.old_value == arg_1;
+ atomic_compare_exchange_resultu32 tint_symbol = atomic_compare_result;
+ uint old_value_1 = tint_symbol.old_value;
+ uint x_23 = old_value_1;
+ x__atomic_compare_exchange_resultu32 tint_symbol_1 = x__atomic_compare_exchange_resultu32(x_23, (x_23 == x_21));
+ res = tint_symbol_1;
+ return;
+}
+
+void compute_main_1() {
+ atomicCompareExchangeWeak_63d8e6();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..7a9c971
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,55 @@
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+struct atomic_compare_exchange_weak_ret_type {
+ uint old_value;
+ bool exchanged;
+};
+
+atomic_compare_exchange_weak_ret_type tint_atomicCompareExchangeWeak(RWByteAddressBuffer buffer, uint offset, uint compare, uint value) {
+ atomic_compare_exchange_weak_ret_type result=(atomic_compare_exchange_weak_ret_type)0;
+ buffer.InterlockedCompareExchange(offset, compare, value, result.old_value);
+ result.exchanged = result.old_value == compare;
+ return result;
+}
+
+
+void atomicCompareExchangeWeak_63d8e6() {
+ uint arg_1 = 0u;
+ uint arg_2 = 0u;
+ x__atomic_compare_exchange_resultu32 res = {0u, false};
+ arg_1 = 1u;
+ arg_2 = 1u;
+ const uint x_21 = arg_2;
+ const atomic_compare_exchange_weak_ret_type tint_symbol = tint_atomicCompareExchangeWeak(sb_rw, 0u, arg_1, x_21);
+ const uint old_value_1 = tint_symbol.old_value;
+ const uint x_23 = old_value_1;
+ const x__atomic_compare_exchange_resultu32 tint_symbol_1 = {x_23, (x_23 == x_21)};
+ res = tint_symbol_1;
+ return;
+}
+
+void fragment_main_1() {
+ atomicCompareExchangeWeak_63d8e6();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicCompareExchangeWeak_63d8e6();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..39de0ea
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.msl
@@ -0,0 +1,63 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+atomic_compare_exchange_resultu32 atomicCompareExchangeWeak_1(device atomic_uint* atomic, uint compare, uint value) {
+ uint old_value = compare;
+ bool exchanged = atomic_compare_exchange_weak_explicit(atomic, &old_value, value, memory_order_relaxed, memory_order_relaxed);
+ return {old_value, exchanged};
+}
+
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+void atomicCompareExchangeWeak_63d8e6(device SB_RW_atomic* const tint_symbol_2) {
+ uint arg_1 = 0u;
+ uint arg_2 = 0u;
+ x__atomic_compare_exchange_resultu32 res = {.old_value=0u, .exchanged=false};
+ arg_1 = 1u;
+ arg_2 = 1u;
+ uint const x_21 = arg_2;
+ uint const x_22 = arg_1;
+ atomic_compare_exchange_resultu32 const tint_symbol = atomicCompareExchangeWeak_1(&((*(tint_symbol_2)).arg_0), x_22, x_21);
+ uint const old_value_1 = tint_symbol.old_value;
+ uint const x_23 = old_value_1;
+ x__atomic_compare_exchange_resultu32 const tint_symbol_1 = {.old_value=x_23, .exchanged=(x_23 == x_21)};
+ res = tint_symbol_1;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicCompareExchangeWeak_63d8e6(tint_symbol_3);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_4);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_5) {
+ atomicCompareExchangeWeak_63d8e6(tint_symbol_5);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_6 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_6);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..9cce848
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,96 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicCompareExchangeWeak_63d8e6 "atomicCompareExchangeWeak_63d8e6"
+ OpName %arg_1 "arg_1"
+ OpName %arg_2 "arg_2"
+ OpName %x__atomic_compare_exchange_resultu32 "x__atomic_compare_exchange_resultu32"
+ OpMemberName %x__atomic_compare_exchange_resultu32 0 "old_value"
+ OpMemberName %x__atomic_compare_exchange_resultu32 1 "exchanged"
+ OpName %res "res"
+ OpName %__atomic_compare_exchange_resultu32 "__atomic_compare_exchange_resultu32"
+ OpMemberName %__atomic_compare_exchange_resultu32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resultu32 1 "exchanged"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ OpMemberDecorate %x__atomic_compare_exchange_resultu32 0 Offset 0
+ OpMemberDecorate %x__atomic_compare_exchange_resultu32 1 Offset 4
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 1 Offset 4
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %bool = OpTypeBool
+%x__atomic_compare_exchange_resultu32 = OpTypeStruct %uint %bool
+ %15 = OpConstantNull %bool
+ %16 = OpConstantComposite %x__atomic_compare_exchange_resultu32 %9 %15
+%_ptr_Function_x__atomic_compare_exchange_resultu32 = OpTypePointer Function %x__atomic_compare_exchange_resultu32
+ %19 = OpConstantNull %x__atomic_compare_exchange_resultu32
+ %uint_1 = OpConstant %uint 1
+%__atomic_compare_exchange_resultu32 = OpTypeStruct %uint %bool
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicCompareExchangeWeak_63d8e6 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %9
+ %arg_2 = OpVariable %_ptr_Function_uint Function %9
+ %res = OpVariable %_ptr_Function_x__atomic_compare_exchange_resultu32 Function %19
+ OpStore %arg_1 %9
+ OpStore %arg_2 %9
+ OpStore %res %16
+ OpStore %arg_1 %uint_1
+ OpStore %arg_2 %uint_1
+ %21 = OpLoad %uint %arg_2
+ %22 = OpLoad %uint %arg_1
+ %28 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %29 = OpAtomicCompareExchange %uint %28 %uint_1 %uint_0 %uint_0 %21 %22
+ %30 = OpIEqual %bool %29 %21
+ %23 = OpCompositeConstruct %__atomic_compare_exchange_resultu32 %29 %30
+ %31 = OpCompositeExtract %uint %23 0
+ %32 = OpIEqual %bool %31 %21
+ %33 = OpCompositeConstruct %x__atomic_compare_exchange_resultu32 %31 %32
+ OpStore %res %33
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %35 = OpLabel
+ %36 = OpFunctionCall %void %atomicCompareExchangeWeak_63d8e6
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %38 = OpLabel
+ %39 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %41 = OpLabel
+ %42 = OpFunctionCall %void %atomicCompareExchangeWeak_63d8e6
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %44 = OpLabel
+ %45 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..c3b661b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,48 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+struct x__atomic_compare_exchange_resultu32 {
+ old_value : u32,
+ exchanged : bool,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicCompareExchangeWeak_63d8e6() {
+ var arg_1 : u32 = 0u;
+ var arg_2 : u32 = 0u;
+ var res : x__atomic_compare_exchange_resultu32 = x__atomic_compare_exchange_resultu32(0u, false);
+ arg_1 = 1u;
+ arg_2 = 1u;
+ let x_21 : u32 = arg_2;
+ let x_22 : u32 = arg_1;
+ let old_value_1 = atomicCompareExchangeWeak(&(sb_rw.arg_0), x_22, x_21).old_value;
+ let x_23 : u32 = old_value_1;
+ res = x__atomic_compare_exchange_resultu32(x_23, (x_23 == x_21));
+ return;
+}
+
+fn fragment_main_1() {
+ atomicCompareExchangeWeak_63d8e6();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicCompareExchangeWeak_63d8e6();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm
new file mode 100644
index 0000000..b4e3102
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm
@@ -0,0 +1,72 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 42
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicCompareExchangeWeak_e88938 "atomicCompareExchangeWeak_e88938"
+ OpName %arg_1 "arg_1"
+ OpName %arg_2 "arg_2"
+ OpName %__atomic_compare_exchange_resulti32 "__atomic_compare_exchange_resulti32"
+ OpMemberName %__atomic_compare_exchange_resulti32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resulti32 1 "exchanged"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 1 Offset 4
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %14 = OpConstantNull %int
+ %bool = OpTypeBool
+%__atomic_compare_exchange_resulti32 = OpTypeStruct %int %bool
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+%_ptr_Function___atomic_compare_exchange_resulti32 = OpTypePointer Function %__atomic_compare_exchange_resulti32
+ %28 = OpConstantNull %__atomic_compare_exchange_resulti32
+ %29 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicCompareExchangeWeak_e88938 = OpFunction %void None %7
+ %10 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %arg_2 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function___atomic_compare_exchange_resulti32 Function %28
+ OpStore %arg_1 %int_1
+ OpStore %arg_2 %int_1
+ %22 = OpLoad %int %arg_2
+ %23 = OpLoad %int %arg_1
+ %24 = OpAtomicCompareExchange %int %arg_0 %uint_2 %uint_0 %uint_0 %22 %23
+ %25 = OpIEqual %bool %24 %22
+ %16 = OpCompositeConstruct %__atomic_compare_exchange_resulti32 %24 %25
+ OpStore %res %16
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %29
+%local_invocation_index = OpFunctionParameter %uint
+ %32 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %37 = OpFunctionCall %void %atomicCompareExchangeWeak_e88938
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %39 = OpLabel
+ %41 = OpLoad %uint %local_invocation_index_1
+ %40 = OpFunctionCall %void %compute_main_inner %41
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..c370e71
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,59 @@
+#version 310 es
+
+struct atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicCompareExchangeWeak_e88938() {
+ int arg_1 = 0;
+ int arg_2 = 0;
+ x__atomic_compare_exchange_resulti32 res = x__atomic_compare_exchange_resulti32(0, false);
+ arg_1 = 1;
+ arg_2 = 1;
+ int x_22 = arg_2;
+ atomic_compare_exchange_resulti32 atomic_compare_result;
+ atomic_compare_result.old_value = atomicCompSwap(arg_0, arg_1, x_22);
+ atomic_compare_result.exchanged = atomic_compare_result.old_value == arg_1;
+ atomic_compare_exchange_resulti32 tint_symbol = atomic_compare_result;
+ int old_value_1 = tint_symbol.old_value;
+ int x_24 = old_value_1;
+ x__atomic_compare_exchange_resulti32 tint_symbol_1 = x__atomic_compare_exchange_resulti32(x_24, (x_24 == x_22));
+ res = tint_symbol_1;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicCompareExchangeWeak_e88938();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..55ac417
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,63 @@
+struct atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicCompareExchangeWeak_e88938() {
+ int arg_1 = 0;
+ int arg_2 = 0;
+ x__atomic_compare_exchange_resulti32 res = {0, false};
+ arg_1 = 1;
+ arg_2 = 1;
+ const int x_22 = arg_2;
+ atomic_compare_exchange_resulti32 atomic_result = (atomic_compare_exchange_resulti32)0;
+ int atomic_compare_value = arg_1;
+ InterlockedCompareExchange(arg_0, atomic_compare_value, x_22, atomic_result.old_value);
+ atomic_result.exchanged = atomic_result.old_value == atomic_compare_value;
+ const atomic_compare_exchange_resulti32 tint_symbol_2 = atomic_result;
+ const int old_value_1 = tint_symbol_2.old_value;
+ const int x_24 = old_value_1;
+ const x__atomic_compare_exchange_resulti32 tint_symbol_3 = {x_24, (x_24 == x_22)};
+ res = tint_symbol_3;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicCompareExchangeWeak_e88938();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..52cfd0f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,64 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+atomic_compare_exchange_resulti32 atomicCompareExchangeWeak_1(threadgroup atomic_int* atomic, int compare, int value) {
+ int old_value = compare;
+ bool exchanged = atomic_compare_exchange_weak_explicit(atomic, &old_value, value, memory_order_relaxed, memory_order_relaxed);
+ return {old_value, exchanged};
+}
+
+struct x__atomic_compare_exchange_resulti32 {
+ int old_value;
+ bool exchanged;
+};
+
+void atomicCompareExchangeWeak_e88938(threadgroup atomic_int* const tint_symbol_2) {
+ int arg_1 = 0;
+ int arg_2 = 0;
+ x__atomic_compare_exchange_resulti32 res = {.old_value=0, .exchanged=false};
+ arg_1 = 1;
+ arg_2 = 1;
+ int const x_22 = arg_2;
+ int const x_23 = arg_1;
+ atomic_compare_exchange_resulti32 const tint_symbol = atomicCompareExchangeWeak_1(tint_symbol_2, x_23, x_22);
+ int const old_value_1 = tint_symbol.old_value;
+ int const x_24 = old_value_1;
+ x__atomic_compare_exchange_resulti32 const tint_symbol_1 = {.old_value=x_24, .exchanged=(x_24 == x_22)};
+ res = tint_symbol_1;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_3) {
+ atomic_store_explicit(tint_symbol_3, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicCompareExchangeWeak_e88938(tint_symbol_3);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_4, threadgroup atomic_int* const tint_symbol_5) {
+ uint const x_41 = *(tint_symbol_4);
+ compute_main_inner(x_41, tint_symbol_5);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_6, thread uint* const tint_symbol_7) {
+ {
+ atomic_store_explicit(tint_symbol_6, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_7) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_7, tint_symbol_6);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_8;
+ thread uint tint_symbol_9 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_8), &(tint_symbol_9));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..ceae3b5
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,108 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 62
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicCompareExchangeWeak_e88938 "atomicCompareExchangeWeak_e88938"
+ OpName %arg_1 "arg_1"
+ OpName %arg_2 "arg_2"
+ OpName %x__atomic_compare_exchange_resulti32 "x__atomic_compare_exchange_resulti32"
+ OpMemberName %x__atomic_compare_exchange_resulti32 0 "old_value"
+ OpMemberName %x__atomic_compare_exchange_resulti32 1 "exchanged"
+ OpName %res "res"
+ OpName %__atomic_compare_exchange_resulti32 "__atomic_compare_exchange_resulti32"
+ OpMemberName %__atomic_compare_exchange_resulti32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resulti32 1 "exchanged"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %x__atomic_compare_exchange_resulti32 0 Offset 0
+ OpMemberDecorate %x__atomic_compare_exchange_resulti32 1 Offset 4
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resulti32 1 Offset 4
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %bool = OpTypeBool
+%x__atomic_compare_exchange_resulti32 = OpTypeStruct %int %bool
+ %20 = OpConstantNull %bool
+ %21 = OpConstantComposite %x__atomic_compare_exchange_resulti32 %14 %20
+%_ptr_Function_x__atomic_compare_exchange_resulti32 = OpTypePointer Function %x__atomic_compare_exchange_resulti32
+ %24 = OpConstantNull %x__atomic_compare_exchange_resulti32
+ %int_1 = OpConstant %int 1
+%__atomic_compare_exchange_resulti32 = OpTypeStruct %int %bool
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %38 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicCompareExchangeWeak_e88938 = OpFunction %void None %10
+ %13 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %arg_2 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_x__atomic_compare_exchange_resulti32 Function %24
+ OpStore %arg_1 %14
+ OpStore %arg_2 %14
+ OpStore %res %21
+ OpStore %arg_1 %int_1
+ OpStore %arg_2 %int_1
+ %26 = OpLoad %int %arg_2
+ %27 = OpLoad %int %arg_1
+ %33 = OpAtomicCompareExchange %int %arg_0 %uint_2 %uint_0 %uint_0 %26 %27
+ %34 = OpIEqual %bool %33 %26
+ %28 = OpCompositeConstruct %__atomic_compare_exchange_resulti32 %33 %34
+ %35 = OpCompositeExtract %int %28 0
+ %36 = OpIEqual %bool %35 %26
+ %37 = OpCompositeConstruct %x__atomic_compare_exchange_resulti32 %35 %36
+ OpStore %res %37
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %38
+%local_invocation_index = OpFunctionParameter %uint
+ %41 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %46 = OpFunctionCall %void %atomicCompareExchangeWeak_e88938
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %48 = OpLabel
+ %49 = OpLoad %uint %local_invocation_index_1
+ %50 = OpFunctionCall %void %compute_main_inner %49
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %38
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %53 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %57 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %59 = OpLabel
+ %61 = OpLoad %uint %local_invocation_index_1_param_1
+ %60 = OpFunctionCall %void %compute_main_inner_1 %61
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..aaa949e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,41 @@
+struct x__atomic_compare_exchange_resulti32 {
+ old_value : i32,
+ exchanged : bool,
+}
+
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicCompareExchangeWeak_e88938() {
+ var arg_1 : i32 = 0i;
+ var arg_2 : i32 = 0i;
+ var res : x__atomic_compare_exchange_resulti32 = x__atomic_compare_exchange_resulti32(0i, false);
+ arg_1 = 1i;
+ arg_2 = 1i;
+ let x_22 : i32 = arg_2;
+ let x_23 : i32 = arg_1;
+ let old_value_1 = atomicCompareExchangeWeak(&(arg_0), x_23, x_22).old_value;
+ let x_24 : i32 = old_value_1;
+ res = x__atomic_compare_exchange_resulti32(x_24, (x_24 == x_22));
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicCompareExchangeWeak_e88938();
+ return;
+}
+
+fn compute_main_1() {
+ let x_41 : u32 = local_invocation_index_1;
+ compute_main_inner(x_41);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm
new file mode 100644
index 0000000..b163b6f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 41
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicCompareExchangeWeak_83580d "atomicCompareExchangeWeak_83580d"
+ OpName %arg_1 "arg_1"
+ OpName %arg_2 "arg_2"
+ OpName %__atomic_compare_exchange_resultu32 "__atomic_compare_exchange_resultu32"
+ OpMemberName %__atomic_compare_exchange_resultu32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resultu32 1 "exchanged"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 1 Offset 4
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %13 = OpConstantNull %uint
+ %bool = OpTypeBool
+%__atomic_compare_exchange_resultu32 = OpTypeStruct %uint %bool
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+%_ptr_Function___atomic_compare_exchange_resultu32 = OpTypePointer Function %__atomic_compare_exchange_resultu32
+ %27 = OpConstantNull %__atomic_compare_exchange_resultu32
+ %28 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicCompareExchangeWeak_83580d = OpFunction %void None %6
+ %9 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %13
+ %arg_2 = OpVariable %_ptr_Function_uint Function %13
+ %res = OpVariable %_ptr_Function___atomic_compare_exchange_resultu32 Function %27
+ OpStore %arg_1 %uint_1
+ OpStore %arg_2 %uint_1
+ %21 = OpLoad %uint %arg_2
+ %22 = OpLoad %uint %arg_1
+ %23 = OpAtomicCompareExchange %uint %arg_0 %uint_2 %uint_0 %uint_0 %21 %22
+ %24 = OpIEqual %bool %23 %21
+ %15 = OpCompositeConstruct %__atomic_compare_exchange_resultu32 %23 %24
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %28
+%local_invocation_index = OpFunctionParameter %uint
+ %31 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %13
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %36 = OpFunctionCall %void %atomicCompareExchangeWeak_83580d
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %38 = OpLabel
+ %40 = OpLoad %uint %local_invocation_index_1
+ %39 = OpFunctionCall %void %compute_main_inner %40
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..645a53e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,59 @@
+#version 310 es
+
+struct atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicCompareExchangeWeak_83580d() {
+ uint arg_1 = 0u;
+ uint arg_2 = 0u;
+ x__atomic_compare_exchange_resultu32 res = x__atomic_compare_exchange_resultu32(0u, false);
+ arg_1 = 1u;
+ arg_2 = 1u;
+ uint x_21 = arg_2;
+ atomic_compare_exchange_resultu32 atomic_compare_result;
+ atomic_compare_result.old_value = atomicCompSwap(arg_0, arg_1, x_21);
+ atomic_compare_result.exchanged = atomic_compare_result.old_value == arg_1;
+ atomic_compare_exchange_resultu32 tint_symbol = atomic_compare_result;
+ uint old_value_1 = tint_symbol.old_value;
+ uint x_23 = old_value_1;
+ x__atomic_compare_exchange_resultu32 tint_symbol_1 = x__atomic_compare_exchange_resultu32(x_23, (x_23 == x_21));
+ res = tint_symbol_1;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicCompareExchangeWeak_83580d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..6a120b1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,63 @@
+struct atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicCompareExchangeWeak_83580d() {
+ uint arg_1 = 0u;
+ uint arg_2 = 0u;
+ x__atomic_compare_exchange_resultu32 res = {0u, false};
+ arg_1 = 1u;
+ arg_2 = 1u;
+ const uint x_21 = arg_2;
+ atomic_compare_exchange_resultu32 atomic_result = (atomic_compare_exchange_resultu32)0;
+ uint atomic_compare_value = arg_1;
+ InterlockedCompareExchange(arg_0, atomic_compare_value, x_21, atomic_result.old_value);
+ atomic_result.exchanged = atomic_result.old_value == atomic_compare_value;
+ const atomic_compare_exchange_resultu32 tint_symbol_2 = atomic_result;
+ const uint old_value_1 = tint_symbol_2.old_value;
+ const uint x_23 = old_value_1;
+ const x__atomic_compare_exchange_resultu32 tint_symbol_3 = {x_23, (x_23 == x_21)};
+ res = tint_symbol_3;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicCompareExchangeWeak_83580d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..b788874
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,64 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+struct atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+atomic_compare_exchange_resultu32 atomicCompareExchangeWeak_1(threadgroup atomic_uint* atomic, uint compare, uint value) {
+ uint old_value = compare;
+ bool exchanged = atomic_compare_exchange_weak_explicit(atomic, &old_value, value, memory_order_relaxed, memory_order_relaxed);
+ return {old_value, exchanged};
+}
+
+struct x__atomic_compare_exchange_resultu32 {
+ uint old_value;
+ bool exchanged;
+};
+
+void atomicCompareExchangeWeak_83580d(threadgroup atomic_uint* const tint_symbol_2) {
+ uint arg_1 = 0u;
+ uint arg_2 = 0u;
+ x__atomic_compare_exchange_resultu32 res = {.old_value=0u, .exchanged=false};
+ arg_1 = 1u;
+ arg_2 = 1u;
+ uint const x_21 = arg_2;
+ uint const x_22 = arg_1;
+ atomic_compare_exchange_resultu32 const tint_symbol = atomicCompareExchangeWeak_1(tint_symbol_2, x_22, x_21);
+ uint const old_value_1 = tint_symbol.old_value;
+ uint const x_23 = old_value_1;
+ x__atomic_compare_exchange_resultu32 const tint_symbol_1 = {.old_value=x_23, .exchanged=(x_23 == x_21)};
+ res = tint_symbol_1;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_3) {
+ atomic_store_explicit(tint_symbol_3, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicCompareExchangeWeak_83580d(tint_symbol_3);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_4, threadgroup atomic_uint* const tint_symbol_5) {
+ uint const x_40 = *(tint_symbol_4);
+ compute_main_inner(x_40, tint_symbol_5);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_6, thread uint* const tint_symbol_7) {
+ {
+ atomic_store_explicit(tint_symbol_6, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_7) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_7, tint_symbol_6);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_8;
+ thread uint tint_symbol_9 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_8), &(tint_symbol_9));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..a2d0294
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,106 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 60
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicCompareExchangeWeak_83580d "atomicCompareExchangeWeak_83580d"
+ OpName %arg_1 "arg_1"
+ OpName %arg_2 "arg_2"
+ OpName %x__atomic_compare_exchange_resultu32 "x__atomic_compare_exchange_resultu32"
+ OpMemberName %x__atomic_compare_exchange_resultu32 0 "old_value"
+ OpMemberName %x__atomic_compare_exchange_resultu32 1 "exchanged"
+ OpName %res "res"
+ OpName %__atomic_compare_exchange_resultu32 "__atomic_compare_exchange_resultu32"
+ OpMemberName %__atomic_compare_exchange_resultu32 0 "old_value"
+ OpMemberName %__atomic_compare_exchange_resultu32 1 "exchanged"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ OpMemberDecorate %x__atomic_compare_exchange_resultu32 0 Offset 0
+ OpMemberDecorate %x__atomic_compare_exchange_resultu32 1 Offset 4
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 0 Offset 0
+ OpMemberDecorate %__atomic_compare_exchange_resultu32 1 Offset 4
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %bool = OpTypeBool
+%x__atomic_compare_exchange_resultu32 = OpTypeStruct %uint %bool
+ %18 = OpConstantNull %bool
+ %19 = OpConstantComposite %x__atomic_compare_exchange_resultu32 %6 %18
+%_ptr_Function_x__atomic_compare_exchange_resultu32 = OpTypePointer Function %x__atomic_compare_exchange_resultu32
+ %22 = OpConstantNull %x__atomic_compare_exchange_resultu32
+ %uint_1 = OpConstant %uint 1
+%__atomic_compare_exchange_resultu32 = OpTypeStruct %uint %bool
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %36 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicCompareExchangeWeak_83580d = OpFunction %void None %9
+ %12 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %6
+ %arg_2 = OpVariable %_ptr_Function_uint Function %6
+ %res = OpVariable %_ptr_Function_x__atomic_compare_exchange_resultu32 Function %22
+ OpStore %arg_1 %6
+ OpStore %arg_2 %6
+ OpStore %res %19
+ OpStore %arg_1 %uint_1
+ OpStore %arg_2 %uint_1
+ %24 = OpLoad %uint %arg_2
+ %25 = OpLoad %uint %arg_1
+ %31 = OpAtomicCompareExchange %uint %arg_0 %uint_2 %uint_0 %uint_0 %24 %25
+ %32 = OpIEqual %bool %31 %24
+ %26 = OpCompositeConstruct %__atomic_compare_exchange_resultu32 %31 %32
+ %33 = OpCompositeExtract %uint %26 0
+ %34 = OpIEqual %bool %33 %24
+ %35 = OpCompositeConstruct %x__atomic_compare_exchange_resultu32 %33 %34
+ OpStore %res %35
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %36
+%local_invocation_index = OpFunctionParameter %uint
+ %39 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %44 = OpFunctionCall %void %atomicCompareExchangeWeak_83580d
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %46 = OpLabel
+ %47 = OpLoad %uint %local_invocation_index_1
+ %48 = OpFunctionCall %void %compute_main_inner %47
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %36
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %51 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %55 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %57 = OpLabel
+ %59 = OpLoad %uint %local_invocation_index_1_param_1
+ %58 = OpFunctionCall %void %compute_main_inner_1 %59
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..4a5fdf8
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicCompareExchangeWeak/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,41 @@
+struct x__atomic_compare_exchange_resultu32 {
+ old_value : u32,
+ exchanged : bool,
+}
+
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicCompareExchangeWeak_83580d() {
+ var arg_1 : u32 = 0u;
+ var arg_2 : u32 = 0u;
+ var res : x__atomic_compare_exchange_resultu32 = x__atomic_compare_exchange_resultu32(0u, false);
+ arg_1 = 1u;
+ arg_2 = 1u;
+ let x_21 : u32 = arg_2;
+ let x_22 : u32 = arg_1;
+ let old_value_1 = atomicCompareExchangeWeak(&(arg_0), x_22, x_21).old_value;
+ let x_23 : u32 = old_value_1;
+ res = x__atomic_compare_exchange_resultu32(x_23, (x_23 == x_21));
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicCompareExchangeWeak_83580d();
+ return;
+}
+
+fn compute_main_1() {
+ let x_40 : u32 = local_invocation_index_1;
+ compute_main_inner(x_40);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm
new file mode 100644
index 0000000..755a537
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 28
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicExchange_f2e22f "atomicExchange_f2e22f"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %12 = OpConstantNull %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicExchange_f2e22f = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %12
+ %res = OpVariable %_ptr_Function_int Function %12
+ OpStore %arg_1 %int_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %20 = OpLoad %int %arg_1
+ %13 = OpAtomicExchange %int %19 %uint_1 %uint_0 %20
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicExchange_f2e22f
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicExchange_f2e22f
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..284be71
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicExchange_f2e22f() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicExchange(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicExchange_f2e22f();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicExchange_f2e22f() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicExchange(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicExchange_f2e22f();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..32a2a70
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicExchange(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedExchange(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicExchange_f2e22f() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ const int x_13 = tint_atomicExchange(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicExchange_f2e22f();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicExchange_f2e22f();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..1f5986b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicExchange_f2e22f(device SB_RW_atomic* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_20 = arg_1;
+ int const x_13 = atomic_exchange_explicit(&((*(tint_symbol)).arg_0), x_20, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicExchange_f2e22f(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicExchange_f2e22f(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..2b2b678
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicExchange_f2e22f "atomicExchange_f2e22f"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicExchange_f2e22f = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %9
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %int_1
+ %14 = OpLoad %int %arg_1
+ %21 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %15 = OpAtomicExchange %int %21 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicExchange_f2e22f
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %atomicExchange_f2e22f
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %32 = OpLabel
+ %33 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..e4dad2d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicExchange_f2e22f() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_20 : i32 = arg_1;
+ let x_13 : i32 = atomicExchange(&(sb_rw.arg_0), x_20);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicExchange_f2e22f();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicExchange_f2e22f();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm
new file mode 100644
index 0000000..2ec90f3
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm
@@ -0,0 +1,55 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicExchange_d59712 "atomicExchange_d59712"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %12 = OpConstantNull %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicExchange_d59712 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %12
+ %res = OpVariable %_ptr_Function_uint Function %12
+ OpStore %arg_1 %uint_1
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %18 = OpLoad %uint %arg_1
+ %13 = OpAtomicExchange %uint %17 %uint_1 %uint_0 %18
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicExchange_d59712
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicExchange_d59712
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..edc360d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicExchange_d59712() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicExchange(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicExchange_d59712();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicExchange_d59712() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicExchange(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicExchange_d59712();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..84b133b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicExchange(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedExchange(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicExchange_d59712() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ const uint x_13 = tint_atomicExchange(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicExchange_d59712();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicExchange_d59712();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..e27ba22
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicExchange_d59712(device SB_RW_atomic* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_13 = atomic_exchange_explicit(&((*(tint_symbol)).arg_0), x_18, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicExchange_d59712(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicExchange_d59712(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..7e620f0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,69 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicExchange_d59712 "atomicExchange_d59712"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicExchange_d59712 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %9
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %uint_1
+ %14 = OpLoad %uint %arg_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %15 = OpAtomicExchange %uint %19 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicExchange_d59712
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicExchange_d59712
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..d7b8cb6
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicExchange_d59712() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_13 : u32 = atomicExchange(&(sb_rw.arg_0), x_18);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicExchange_d59712();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicExchange_d59712();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm
new file mode 100644
index 0000000..0e6f0a8
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicExchange_e114ba "atomicExchange_e114ba"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %14 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicExchange_e114ba = OpFunction %void None %7
+ %10 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %15 = OpAtomicExchange %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicExchange_e114ba
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %31 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..03a22c2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicExchange_e114ba() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_15 = atomicExchange(arg_0, arg_1);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicExchange_e114ba();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..d0e30a4
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicExchange_e114ba() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int atomic_result = 0;
+ InterlockedExchange(arg_0, arg_1, atomic_result);
+ const int x_15 = atomic_result;
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicExchange_e114ba();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..1886d0a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicExchange_e114ba(threadgroup atomic_int* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_19 = arg_1;
+ int const x_15 = atomic_exchange_explicit(tint_symbol, x_19, memory_order_relaxed);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicExchange_e114ba(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_33 = *(tint_symbol_2);
+ compute_main_inner(x_33, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..e72725b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,81 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 48
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicExchange_e114ba "atomicExchange_e114ba"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %24 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicExchange_e114ba = OpFunction %void None %10
+ %13 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %14
+ OpStore %res %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %20 = OpAtomicExchange %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %20
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %24
+%local_invocation_index = OpFunctionParameter %uint
+ %27 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %32 = OpFunctionCall %void %atomicExchange_e114ba
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %34 = OpLabel
+ %35 = OpLoad %uint %local_invocation_index_1
+ %36 = OpFunctionCall %void %compute_main_inner %35
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %24
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %39 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %43 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %45 = OpLabel
+ %47 = OpLoad %uint %local_invocation_index_1_param_1
+ %46 = OpFunctionCall %void %compute_main_inner_1 %47
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..555469e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicExchange_e114ba() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_19 : i32 = arg_1;
+ let x_15 : i32 = atomicExchange(&(arg_0), x_19);
+ res = x_15;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicExchange_e114ba();
+ return;
+}
+
+fn compute_main_1() {
+ let x_33 : u32 = local_invocation_index_1;
+ compute_main_inner(x_33);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm
new file mode 100644
index 0000000..3bbfe18
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm
@@ -0,0 +1,56 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicExchange_0a5dca "atomicExchange_0a5dca"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %13 = OpConstantNull %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicExchange_0a5dca = OpFunction %void None %6
+ %9 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %13
+ %res = OpVariable %_ptr_Function_uint Function %13
+ OpStore %arg_1 %uint_1
+ %18 = OpLoad %uint %arg_1
+ %14 = OpAtomicExchange %uint %arg_0 %uint_2 %uint_0 %18
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %13
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicExchange_0a5dca
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %30 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %31 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..32711c9
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicExchange_0a5dca() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_14 = atomicExchange(arg_0, arg_1);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicExchange_0a5dca();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..f5ff3f7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicExchange_0a5dca() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint atomic_result = 0u;
+ InterlockedExchange(arg_0, arg_1, atomic_result);
+ const uint x_14 = atomic_result;
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicExchange_0a5dca();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..c42c47d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicExchange_0a5dca(threadgroup atomic_uint* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_14 = atomic_exchange_explicit(tint_symbol, x_18, memory_order_relaxed);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicExchange_0a5dca(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_32 = *(tint_symbol_2);
+ compute_main_inner(x_32, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..6970053
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,79 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicExchange_0a5dca "atomicExchange_0a5dca"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicExchange_0a5dca = OpFunction %void None %9
+ %12 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %6
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %arg_1 %6
+ OpStore %res %6
+ OpStore %arg_1 %uint_1
+ %17 = OpLoad %uint %arg_1
+ %18 = OpAtomicExchange %uint %arg_0 %uint_2 %uint_0 %17
+ OpStore %res %18
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicExchange_0a5dca
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..89fff60
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicExchange/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicExchange_0a5dca() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_14 : u32 = atomicExchange(&(arg_0), x_18);
+ res = x_14;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicExchange_0a5dca();
+ return;
+}
+
+fn compute_main_1() {
+ let x_32 : u32 = local_invocation_index_1;
+ compute_main_inner(x_32);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm
new file mode 100644
index 0000000..d961ea5
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 25
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicLoad_0806ad "atomicLoad_0806ad"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %18 = OpConstantNull %int
+%atomicLoad_0806ad = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %18
+ %15 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %9 = OpAtomicLoad %int %15 %uint_1 %uint_0
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %20 = OpLabel
+ %21 = OpFunctionCall %void %atomicLoad_0806ad
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicLoad_0806ad
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..d034197
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicLoad_0806ad() {
+ int res = 0;
+ int x_9 = atomicOr(sb_rw.arg_0, 0);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicLoad_0806ad();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicLoad_0806ad() {
+ int res = 0;
+ int x_9 = atomicOr(sb_rw.arg_0, 0);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicLoad_0806ad();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..8ce9cf2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicLoad(RWByteAddressBuffer buffer, uint offset) {
+ int value = 0;
+ buffer.InterlockedOr(offset, 0, value);
+ return value;
+}
+
+
+void atomicLoad_0806ad() {
+ int res = 0;
+ const int x_9 = tint_atomicLoad(sb_rw, 0u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicLoad_0806ad();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicLoad_0806ad();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..1ea07a1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicLoad_0806ad(device SB_RW_atomic* const tint_symbol) {
+ int res = 0;
+ int const x_9 = atomic_load_explicit(&((*(tint_symbol)).arg_0), memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicLoad_0806ad(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicLoad_0806ad(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..40034c7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,65 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicLoad_0806ad "atomicLoad_0806ad"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicLoad_0806ad = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %res %9
+ %18 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %12 = OpAtomicLoad %int %18 %uint_1 %uint_0
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %20 = OpLabel
+ %21 = OpFunctionCall %void %atomicLoad_0806ad
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicLoad_0806ad
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..b13dbfb
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicLoad_0806ad() {
+ var res : i32 = 0i;
+ let x_9 : i32 = atomicLoad(&(sb_rw.arg_0));
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicLoad_0806ad();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicLoad_0806ad();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm
new file mode 100644
index 0000000..776c62c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 24
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicLoad_fe6cc3 "atomicLoad_fe6cc3"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %17 = OpConstantNull %uint
+%atomicLoad_fe6cc3 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %17
+ %14 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %9 = OpAtomicLoad %uint %14 %uint_1 %uint_0
+ OpStore %res %9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicLoad_fe6cc3
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicLoad_fe6cc3
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..cebe232
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicLoad_fe6cc3() {
+ uint res = 0u;
+ uint x_9 = atomicOr(sb_rw.arg_0, 0u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicLoad_fe6cc3();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicLoad_fe6cc3() {
+ uint res = 0u;
+ uint x_9 = atomicOr(sb_rw.arg_0, 0u);
+ res = x_9;
+ return;
+}
+
+void compute_main_1() {
+ atomicLoad_fe6cc3();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..454ed3c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,36 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicLoad(RWByteAddressBuffer buffer, uint offset) {
+ uint value = 0;
+ buffer.InterlockedOr(offset, 0, value);
+ return value;
+}
+
+
+void atomicLoad_fe6cc3() {
+ uint res = 0u;
+ const uint x_9 = tint_atomicLoad(sb_rw, 0u);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1() {
+ atomicLoad_fe6cc3();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicLoad_fe6cc3();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..a6cce27
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicLoad_fe6cc3(device SB_RW_atomic* const tint_symbol) {
+ uint res = 0u;
+ uint const x_9 = atomic_load_explicit(&((*(tint_symbol)).arg_0), memory_order_relaxed);
+ res = x_9;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicLoad_fe6cc3(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicLoad_fe6cc3(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..e12b47b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,64 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicLoad_fe6cc3 "atomicLoad_fe6cc3"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicLoad_fe6cc3 = OpFunction %void None %5
+ %8 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %res %9
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %12 = OpAtomicLoad %uint %17 %uint_1 %uint_0
+ OpStore %res %12
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %19 = OpLabel
+ %20 = OpFunctionCall %void %atomicLoad_fe6cc3
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicLoad_fe6cc3
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..b03da62e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,36 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicLoad_fe6cc3() {
+ var res : u32 = 0u;
+ let x_9 : u32 = atomicLoad(&(sb_rw.arg_0));
+ res = x_9;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicLoad_fe6cc3();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicLoad_fe6cc3();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm
new file mode 100644
index 0000000..b996359
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicLoad_afcc03 "atomicLoad_afcc03"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+%_ptr_Function_int = OpTypePointer Function %int
+ %17 = OpConstantNull %int
+ %18 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicLoad_afcc03 = OpFunction %void None %7
+ %10 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %17
+ %11 = OpAtomicLoad %int %arg_0 %uint_2 %uint_0
+ OpStore %res %11
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %18
+%local_invocation_index = OpFunctionParameter %uint
+ %21 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %17
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %26 = OpFunctionCall %void %atomicLoad_afcc03
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %28 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %29 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..e0c158b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicLoad_afcc03() {
+ int res = 0;
+ int x_11 = atomicOr(arg_0, 0);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicLoad_afcc03();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..1593c13
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicLoad_afcc03() {
+ int res = 0;
+ int atomic_result = 0;
+ InterlockedOr(arg_0, 0, atomic_result);
+ const int x_11 = atomic_result;
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicLoad_afcc03();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..8f6ee40
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicLoad_afcc03(threadgroup atomic_int* const tint_symbol) {
+ int res = 0;
+ int const x_11 = atomic_load_explicit(tint_symbol, memory_order_relaxed);
+ res = x_11;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicLoad_afcc03(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_30 = *(tint_symbol_2);
+ compute_main_inner(x_30, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..829b848
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,75 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 45
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicLoad_afcc03 "atomicLoad_afcc03"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicLoad_afcc03 = OpFunction %void None %10
+ %13 = OpLabel
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %res %14
+ %17 = OpAtomicLoad %int %arg_0 %uint_2 %uint_0
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicLoad_afcc03
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %31 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %33 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %21
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %36 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %40 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %42 = OpLabel
+ %44 = OpLoad %uint %local_invocation_index_1_param_1
+ %43 = OpFunctionCall %void %compute_main_inner_1 %44
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..af0c057
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicLoad_afcc03() {
+ var res : i32 = 0i;
+ let x_11 : i32 = atomicLoad(&(arg_0));
+ res = x_11;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicLoad_afcc03();
+ return;
+}
+
+fn compute_main_1() {
+ let x_30 : u32 = local_invocation_index_1;
+ compute_main_inner(x_30);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm
new file mode 100644
index 0000000..20eeca7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm
@@ -0,0 +1,51 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 30
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicLoad_361bf1 "atomicLoad_361bf1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %16 = OpConstantNull %uint
+ %17 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicLoad_361bf1 = OpFunction %void None %6
+ %9 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %16
+ %10 = OpAtomicLoad %uint %arg_0 %uint_2 %uint_0
+ OpStore %res %10
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %17
+%local_invocation_index = OpFunctionParameter %uint
+ %20 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %16
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %25 = OpFunctionCall %void %atomicLoad_361bf1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %27 = OpLabel
+ %29 = OpLoad %uint %local_invocation_index_1
+ %28 = OpFunctionCall %void %compute_main_inner %29
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..8bd40a6
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicLoad_361bf1() {
+ uint res = 0u;
+ uint x_10 = atomicOr(arg_0, 0u);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicLoad_361bf1();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..803eadd
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,44 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicLoad_361bf1() {
+ uint res = 0u;
+ uint atomic_result = 0u;
+ InterlockedOr(arg_0, 0, atomic_result);
+ const uint x_10 = atomic_result;
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicLoad_361bf1();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..d7fcb6e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicLoad_361bf1(threadgroup atomic_uint* const tint_symbol) {
+ uint res = 0u;
+ uint const x_10 = atomic_load_explicit(tint_symbol, memory_order_relaxed);
+ res = x_10;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicLoad_361bf1(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_29 = *(tint_symbol_2);
+ compute_main_inner(x_29, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..7a075ba
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,73 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 43
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicLoad_361bf1 "atomicLoad_361bf1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %19 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicLoad_361bf1 = OpFunction %void None %9
+ %12 = OpLabel
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %res %6
+ %15 = OpAtomicLoad %uint %arg_0 %uint_2 %uint_0
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %27 = OpFunctionCall %void %atomicLoad_361bf1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %29 = OpLabel
+ %30 = OpLoad %uint %local_invocation_index_1
+ %31 = OpFunctionCall %void %compute_main_inner %30
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %19
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %34 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %38 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %40 = OpLabel
+ %42 = OpLoad %uint %local_invocation_index_1_param_1
+ %41 = OpFunctionCall %void %compute_main_inner_1 %42
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..f132c6f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicLoad/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,29 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicLoad_361bf1() {
+ var res : u32 = 0u;
+ let x_10 : u32 = atomicLoad(&(arg_0));
+ res = x_10;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicLoad_361bf1();
+ return;
+}
+
+fn compute_main_1() {
+ let x_29 : u32 = local_invocation_index_1;
+ compute_main_inner(x_29);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm
new file mode 100644
index 0000000..e6ff30e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 28
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMax_92aa72 "atomicMax_92aa72"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %12 = OpConstantNull %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicMax_92aa72 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %12
+ %res = OpVariable %_ptr_Function_int Function %12
+ OpStore %arg_1 %int_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %20 = OpLoad %int %arg_1
+ %13 = OpAtomicSMax %int %19 %uint_1 %uint_0 %20
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicMax_92aa72
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicMax_92aa72
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..d458f05
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicMax_92aa72() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicMax(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMax_92aa72();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicMax_92aa72() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicMax(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicMax_92aa72();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..9b64baf
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicMax(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedMax(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicMax_92aa72() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ const int x_13 = tint_atomicMax(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMax_92aa72();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicMax_92aa72();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..61bf2eb
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicMax_92aa72(device SB_RW_atomic* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_20 = arg_1;
+ int const x_13 = atomic_fetch_max_explicit(&((*(tint_symbol)).arg_0), x_20, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicMax_92aa72(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicMax_92aa72(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..c0a4470
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMax_92aa72 "atomicMax_92aa72"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicMax_92aa72 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %9
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %int_1
+ %14 = OpLoad %int %arg_1
+ %21 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %15 = OpAtomicSMax %int %21 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicMax_92aa72
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %atomicMax_92aa72
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %32 = OpLabel
+ %33 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..eea496e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicMax_92aa72() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_20 : i32 = arg_1;
+ let x_13 : i32 = atomicMax(&(sb_rw.arg_0), x_20);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicMax_92aa72();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicMax_92aa72();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm
new file mode 100644
index 0000000..97bae6a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm
@@ -0,0 +1,55 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMax_51b9be "atomicMax_51b9be"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %12 = OpConstantNull %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicMax_51b9be = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %12
+ %res = OpVariable %_ptr_Function_uint Function %12
+ OpStore %arg_1 %uint_1
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %18 = OpLoad %uint %arg_1
+ %13 = OpAtomicUMax %uint %17 %uint_1 %uint_0 %18
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicMax_51b9be
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicMax_51b9be
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..e5f7f89
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicMax_51b9be() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicMax(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMax_51b9be();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicMax_51b9be() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicMax(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicMax_51b9be();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..e9a8f84
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicMax(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedMax(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicMax_51b9be() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ const uint x_13 = tint_atomicMax(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMax_51b9be();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicMax_51b9be();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..a77e9cf
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicMax_51b9be(device SB_RW_atomic* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_13 = atomic_fetch_max_explicit(&((*(tint_symbol)).arg_0), x_18, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicMax_51b9be(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicMax_51b9be(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..4ed13b0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,69 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMax_51b9be "atomicMax_51b9be"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicMax_51b9be = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %9
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %uint_1
+ %14 = OpLoad %uint %arg_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %15 = OpAtomicUMax %uint %19 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicMax_51b9be
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicMax_51b9be
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..ea27f1d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicMax_51b9be() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_13 : u32 = atomicMax(&(sb_rw.arg_0), x_18);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicMax_51b9be();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicMax_51b9be();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm
new file mode 100644
index 0000000..2864a14
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMax_a89cc3 "atomicMax_a89cc3"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %14 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMax_a89cc3 = OpFunction %void None %7
+ %10 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %15 = OpAtomicSMax %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicMax_a89cc3
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %31 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..ce19147
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicMax_a89cc3() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_15 = atomicMax(arg_0, arg_1);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicMax_a89cc3();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..3020cf2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicMax_a89cc3() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int atomic_result = 0;
+ InterlockedMax(arg_0, arg_1, atomic_result);
+ const int x_15 = atomic_result;
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicMax_a89cc3();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..7a3987d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicMax_a89cc3(threadgroup atomic_int* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_19 = arg_1;
+ int const x_15 = atomic_fetch_max_explicit(tint_symbol, x_19, memory_order_relaxed);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicMax_a89cc3(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_33 = *(tint_symbol_2);
+ compute_main_inner(x_33, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..696868b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,81 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 48
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMax_a89cc3 "atomicMax_a89cc3"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %24 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMax_a89cc3 = OpFunction %void None %10
+ %13 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %14
+ OpStore %res %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %20 = OpAtomicSMax %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %20
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %24
+%local_invocation_index = OpFunctionParameter %uint
+ %27 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %32 = OpFunctionCall %void %atomicMax_a89cc3
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %34 = OpLabel
+ %35 = OpLoad %uint %local_invocation_index_1
+ %36 = OpFunctionCall %void %compute_main_inner %35
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %24
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %39 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %43 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %45 = OpLabel
+ %47 = OpLoad %uint %local_invocation_index_1_param_1
+ %46 = OpFunctionCall %void %compute_main_inner_1 %47
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..9086b74
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicMax_a89cc3() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_19 : i32 = arg_1;
+ let x_15 : i32 = atomicMax(&(arg_0), x_19);
+ res = x_15;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicMax_a89cc3();
+ return;
+}
+
+fn compute_main_1() {
+ let x_33 : u32 = local_invocation_index_1;
+ compute_main_inner(x_33);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm
new file mode 100644
index 0000000..03577ee
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm
@@ -0,0 +1,56 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMax_beccfc "atomicMax_beccfc"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %13 = OpConstantNull %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMax_beccfc = OpFunction %void None %6
+ %9 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %13
+ %res = OpVariable %_ptr_Function_uint Function %13
+ OpStore %arg_1 %uint_1
+ %18 = OpLoad %uint %arg_1
+ %14 = OpAtomicUMax %uint %arg_0 %uint_2 %uint_0 %18
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %13
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicMax_beccfc
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %30 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %31 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..f209644
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicMax_beccfc() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_14 = atomicMax(arg_0, arg_1);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicMax_beccfc();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..b87186d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicMax_beccfc() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint atomic_result = 0u;
+ InterlockedMax(arg_0, arg_1, atomic_result);
+ const uint x_14 = atomic_result;
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicMax_beccfc();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..edd3102
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicMax_beccfc(threadgroup atomic_uint* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_14 = atomic_fetch_max_explicit(tint_symbol, x_18, memory_order_relaxed);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicMax_beccfc(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_32 = *(tint_symbol_2);
+ compute_main_inner(x_32, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..ad735e1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,79 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMax_beccfc "atomicMax_beccfc"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMax_beccfc = OpFunction %void None %9
+ %12 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %6
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %arg_1 %6
+ OpStore %res %6
+ OpStore %arg_1 %uint_1
+ %17 = OpLoad %uint %arg_1
+ %18 = OpAtomicUMax %uint %arg_0 %uint_2 %uint_0 %17
+ OpStore %res %18
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicMax_beccfc
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..e740599
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMax/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicMax_beccfc() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_14 : u32 = atomicMax(&(arg_0), x_18);
+ res = x_14;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicMax_beccfc();
+ return;
+}
+
+fn compute_main_1() {
+ let x_32 : u32 = local_invocation_index_1;
+ compute_main_inner(x_32);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm
new file mode 100644
index 0000000..f2ca9b8
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 28
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMin_8e38dc "atomicMin_8e38dc"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %12 = OpConstantNull %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicMin_8e38dc = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %12
+ %res = OpVariable %_ptr_Function_int Function %12
+ OpStore %arg_1 %int_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %20 = OpLoad %int %arg_1
+ %13 = OpAtomicSMin %int %19 %uint_1 %uint_0 %20
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicMin_8e38dc
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicMin_8e38dc
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..e233a68
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicMin_8e38dc() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicMin(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMin_8e38dc();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicMin_8e38dc() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicMin(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicMin_8e38dc();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..e169190
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicMin(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedMin(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicMin_8e38dc() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ const int x_13 = tint_atomicMin(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMin_8e38dc();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicMin_8e38dc();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..dfe6ecb
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicMin_8e38dc(device SB_RW_atomic* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_20 = arg_1;
+ int const x_13 = atomic_fetch_min_explicit(&((*(tint_symbol)).arg_0), x_20, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicMin_8e38dc(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicMin_8e38dc(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..7e5e670
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMin_8e38dc "atomicMin_8e38dc"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicMin_8e38dc = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %9
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %int_1
+ %14 = OpLoad %int %arg_1
+ %21 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %15 = OpAtomicSMin %int %21 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicMin_8e38dc
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %atomicMin_8e38dc
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %32 = OpLabel
+ %33 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..0ef4541
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicMin_8e38dc() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_20 : i32 = arg_1;
+ let x_13 : i32 = atomicMin(&(sb_rw.arg_0), x_20);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicMin_8e38dc();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicMin_8e38dc();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm
new file mode 100644
index 0000000..f3cc67b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm
@@ -0,0 +1,55 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMin_c67a74 "atomicMin_c67a74"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %12 = OpConstantNull %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicMin_c67a74 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %12
+ %res = OpVariable %_ptr_Function_uint Function %12
+ OpStore %arg_1 %uint_1
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %18 = OpLoad %uint %arg_1
+ %13 = OpAtomicUMin %uint %17 %uint_1 %uint_0 %18
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicMin_c67a74
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicMin_c67a74
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..06e8d89
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicMin_c67a74() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicMin(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMin_c67a74();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicMin_c67a74() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicMin(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicMin_c67a74();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..76447ef
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicMin(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedMin(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicMin_c67a74() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ const uint x_13 = tint_atomicMin(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicMin_c67a74();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicMin_c67a74();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..147d01e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicMin_c67a74(device SB_RW_atomic* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_13 = atomic_fetch_min_explicit(&((*(tint_symbol)).arg_0), x_18, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicMin_c67a74(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicMin_c67a74(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..309f258
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,69 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicMin_c67a74 "atomicMin_c67a74"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicMin_c67a74 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %9
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %uint_1
+ %14 = OpLoad %uint %arg_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %15 = OpAtomicUMin %uint %19 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicMin_c67a74
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicMin_c67a74
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..3586e32
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicMin_c67a74() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_13 : u32 = atomicMin(&(sb_rw.arg_0), x_18);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicMin_c67a74();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicMin_c67a74();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm
new file mode 100644
index 0000000..ddfa25a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMin_278235 "atomicMin_278235"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %14 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMin_278235 = OpFunction %void None %7
+ %10 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %15 = OpAtomicSMin %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicMin_278235
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %31 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..abb7ad0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicMin_278235() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_15 = atomicMin(arg_0, arg_1);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicMin_278235();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..cfc09f2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicMin_278235() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int atomic_result = 0;
+ InterlockedMin(arg_0, arg_1, atomic_result);
+ const int x_15 = atomic_result;
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicMin_278235();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..8b6eeeb
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicMin_278235(threadgroup atomic_int* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_19 = arg_1;
+ int const x_15 = atomic_fetch_min_explicit(tint_symbol, x_19, memory_order_relaxed);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicMin_278235(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_33 = *(tint_symbol_2);
+ compute_main_inner(x_33, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..564e8b7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,81 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 48
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMin_278235 "atomicMin_278235"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %24 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMin_278235 = OpFunction %void None %10
+ %13 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %14
+ OpStore %res %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %20 = OpAtomicSMin %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %20
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %24
+%local_invocation_index = OpFunctionParameter %uint
+ %27 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %32 = OpFunctionCall %void %atomicMin_278235
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %34 = OpLabel
+ %35 = OpLoad %uint %local_invocation_index_1
+ %36 = OpFunctionCall %void %compute_main_inner %35
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %24
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %39 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %43 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %45 = OpLabel
+ %47 = OpLoad %uint %local_invocation_index_1_param_1
+ %46 = OpFunctionCall %void %compute_main_inner_1 %47
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..e55849b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicMin_278235() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_19 : i32 = arg_1;
+ let x_15 : i32 = atomicMin(&(arg_0), x_19);
+ res = x_15;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicMin_278235();
+ return;
+}
+
+fn compute_main_1() {
+ let x_33 : u32 = local_invocation_index_1;
+ compute_main_inner(x_33);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm
new file mode 100644
index 0000000..784a014
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm
@@ -0,0 +1,56 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMin_69d383 "atomicMin_69d383"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %13 = OpConstantNull %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMin_69d383 = OpFunction %void None %6
+ %9 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %13
+ %res = OpVariable %_ptr_Function_uint Function %13
+ OpStore %arg_1 %uint_1
+ %18 = OpLoad %uint %arg_1
+ %14 = OpAtomicUMin %uint %arg_0 %uint_2 %uint_0 %18
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %13
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicMin_69d383
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %30 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %31 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..b5b3a4a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicMin_69d383() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_14 = atomicMin(arg_0, arg_1);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicMin_69d383();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..64c8150
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicMin_69d383() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint atomic_result = 0u;
+ InterlockedMin(arg_0, arg_1, atomic_result);
+ const uint x_14 = atomic_result;
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicMin_69d383();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..6336751
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicMin_69d383(threadgroup atomic_uint* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_14 = atomic_fetch_min_explicit(tint_symbol, x_18, memory_order_relaxed);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicMin_69d383(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_32 = *(tint_symbol_2);
+ compute_main_inner(x_32, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..8c0bfde
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,79 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicMin_69d383 "atomicMin_69d383"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicMin_69d383 = OpFunction %void None %9
+ %12 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %6
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %arg_1 %6
+ OpStore %res %6
+ OpStore %arg_1 %uint_1
+ %17 = OpLoad %uint %arg_1
+ %18 = OpAtomicUMin %uint %arg_0 %uint_2 %uint_0 %17
+ OpStore %res %18
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicMin_69d383
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..9a15df0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicMin/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicMin_69d383() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_14 : u32 = atomicMin(&(arg_0), x_18);
+ res = x_14;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicMin_69d383();
+ return;
+}
+
+fn compute_main_1() {
+ let x_32 : u32 = local_invocation_index_1;
+ compute_main_inner(x_32);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm
new file mode 100644
index 0000000..978e4ad
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 28
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicOr_8d96a0 "atomicOr_8d96a0"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %12 = OpConstantNull %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicOr_8d96a0 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %12
+ %res = OpVariable %_ptr_Function_int Function %12
+ OpStore %arg_1 %int_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %20 = OpLoad %int %arg_1
+ %13 = OpAtomicOr %int %19 %uint_1 %uint_0 %20
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicOr_8d96a0
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicOr_8d96a0
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..dd17274
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicOr_8d96a0() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicOr(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicOr_8d96a0();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicOr_8d96a0() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicOr(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicOr_8d96a0();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..1daeac4
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicOr(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedOr(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicOr_8d96a0() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ const int x_13 = tint_atomicOr(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicOr_8d96a0();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicOr_8d96a0();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..a0bf71f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicOr_8d96a0(device SB_RW_atomic* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_20 = arg_1;
+ int const x_13 = atomic_fetch_or_explicit(&((*(tint_symbol)).arg_0), x_20, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicOr_8d96a0(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicOr_8d96a0(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..a5753a7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicOr_8d96a0 "atomicOr_8d96a0"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicOr_8d96a0 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %9
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %int_1
+ %14 = OpLoad %int %arg_1
+ %21 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %15 = OpAtomicOr %int %21 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicOr_8d96a0
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %atomicOr_8d96a0
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %32 = OpLabel
+ %33 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..5c96c73
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicOr_8d96a0() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_20 : i32 = arg_1;
+ let x_13 : i32 = atomicOr(&(sb_rw.arg_0), x_20);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicOr_8d96a0();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicOr_8d96a0();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm
new file mode 100644
index 0000000..c38fc52
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm
@@ -0,0 +1,55 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicOr_5e95d4 "atomicOr_5e95d4"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %12 = OpConstantNull %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicOr_5e95d4 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %12
+ %res = OpVariable %_ptr_Function_uint Function %12
+ OpStore %arg_1 %uint_1
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %18 = OpLoad %uint %arg_1
+ %13 = OpAtomicOr %uint %17 %uint_1 %uint_0 %18
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicOr_5e95d4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicOr_5e95d4
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..ba78059
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicOr_5e95d4() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicOr(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicOr_5e95d4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicOr_5e95d4() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicOr(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicOr_5e95d4();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..2268f30
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicOr(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedOr(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicOr_5e95d4() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ const uint x_13 = tint_atomicOr(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicOr_5e95d4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicOr_5e95d4();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..fa54565
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicOr_5e95d4(device SB_RW_atomic* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_13 = atomic_fetch_or_explicit(&((*(tint_symbol)).arg_0), x_18, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicOr_5e95d4(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicOr_5e95d4(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..2d2a230
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,69 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicOr_5e95d4 "atomicOr_5e95d4"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicOr_5e95d4 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %9
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %uint_1
+ %14 = OpLoad %uint %arg_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %15 = OpAtomicOr %uint %19 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicOr_5e95d4
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicOr_5e95d4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..8dae20d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicOr_5e95d4() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_13 : u32 = atomicOr(&(sb_rw.arg_0), x_18);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicOr_5e95d4();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicOr_5e95d4();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm
new file mode 100644
index 0000000..6a5541c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicOr_d09248 "atomicOr_d09248"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %14 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicOr_d09248 = OpFunction %void None %7
+ %10 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %15 = OpAtomicOr %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicOr_d09248
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %31 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..b045e75
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicOr_d09248() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_15 = atomicOr(arg_0, arg_1);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicOr_d09248();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..a4a9b58
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicOr_d09248() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int atomic_result = 0;
+ InterlockedOr(arg_0, arg_1, atomic_result);
+ const int x_15 = atomic_result;
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicOr_d09248();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..e262929
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicOr_d09248(threadgroup atomic_int* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_19 = arg_1;
+ int const x_15 = atomic_fetch_or_explicit(tint_symbol, x_19, memory_order_relaxed);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicOr_d09248(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_33 = *(tint_symbol_2);
+ compute_main_inner(x_33, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..f2cdcca
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,81 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 48
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicOr_d09248 "atomicOr_d09248"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %24 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicOr_d09248 = OpFunction %void None %10
+ %13 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %14
+ OpStore %res %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %20 = OpAtomicOr %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %20
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %24
+%local_invocation_index = OpFunctionParameter %uint
+ %27 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %32 = OpFunctionCall %void %atomicOr_d09248
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %34 = OpLabel
+ %35 = OpLoad %uint %local_invocation_index_1
+ %36 = OpFunctionCall %void %compute_main_inner %35
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %24
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %39 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %43 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %45 = OpLabel
+ %47 = OpLoad %uint %local_invocation_index_1_param_1
+ %46 = OpFunctionCall %void %compute_main_inner_1 %47
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..f0329eb
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicOr_d09248() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_19 : i32 = arg_1;
+ let x_15 : i32 = atomicOr(&(arg_0), x_19);
+ res = x_15;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicOr_d09248();
+ return;
+}
+
+fn compute_main_1() {
+ let x_33 : u32 = local_invocation_index_1;
+ compute_main_inner(x_33);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm
new file mode 100644
index 0000000..9db7191
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm
@@ -0,0 +1,56 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicOr_5e3d61 "atomicOr_5e3d61"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %13 = OpConstantNull %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicOr_5e3d61 = OpFunction %void None %6
+ %9 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %13
+ %res = OpVariable %_ptr_Function_uint Function %13
+ OpStore %arg_1 %uint_1
+ %18 = OpLoad %uint %arg_1
+ %14 = OpAtomicOr %uint %arg_0 %uint_2 %uint_0 %18
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %13
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicOr_5e3d61
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %30 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %31 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..2894885
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicOr_5e3d61() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_14 = atomicOr(arg_0, arg_1);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicOr_5e3d61();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..7a4ad50
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicOr_5e3d61() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint atomic_result = 0u;
+ InterlockedOr(arg_0, arg_1, atomic_result);
+ const uint x_14 = atomic_result;
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicOr_5e3d61();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..4078be6
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicOr_5e3d61(threadgroup atomic_uint* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_14 = atomic_fetch_or_explicit(tint_symbol, x_18, memory_order_relaxed);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicOr_5e3d61(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_32 = *(tint_symbol_2);
+ compute_main_inner(x_32, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..437d7bf
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,79 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicOr_5e3d61 "atomicOr_5e3d61"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicOr_5e3d61 = OpFunction %void None %9
+ %12 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %6
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %arg_1 %6
+ OpStore %res %6
+ OpStore %arg_1 %uint_1
+ %17 = OpLoad %uint %arg_1
+ %18 = OpAtomicOr %uint %arg_0 %uint_2 %uint_0 %17
+ OpStore %res %18
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicOr_5e3d61
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..781ca2e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicOr/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicOr_5e3d61() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_14 : u32 = atomicOr(&(arg_0), x_18);
+ res = x_14;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicOr_5e3d61();
+ return;
+}
+
+fn compute_main_1() {
+ let x_32 : u32 = local_invocation_index_1;
+ compute_main_inner(x_32);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm
new file mode 100644
index 0000000..5d03e4e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm
@@ -0,0 +1,54 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 27
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicStore_d1e9a6 "atomicStore_d1e9a6"
+ OpName %arg_1 "arg_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %12 = OpConstantNull %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicStore_d1e9a6 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %12
+ OpStore %arg_1 %int_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %20 = OpLoad %int %arg_1
+ OpAtomicStore %19 %uint_1 %uint_0 %20
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicStore_d1e9a6
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %atomicStore_d1e9a6
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..cf63c29
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicStore_d1e9a6() {
+ int arg_1 = 0;
+ arg_1 = 1;
+ atomicExchange(sb_rw.arg_0, arg_1);
+ return;
+}
+
+void fragment_main_1() {
+ atomicStore_d1e9a6();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicStore_d1e9a6() {
+ int arg_1 = 0;
+ arg_1 = 1;
+ atomicExchange(sb_rw.arg_0, arg_1);
+ return;
+}
+
+void compute_main_1() {
+ atomicStore_d1e9a6();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..4151049
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,35 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+void tint_atomicStore(RWByteAddressBuffer buffer, uint offset, int value) {
+ int ignored;
+ buffer.InterlockedExchange(offset, value, ignored);
+}
+
+
+void atomicStore_d1e9a6() {
+ int arg_1 = 0;
+ arg_1 = 1;
+ tint_atomicStore(sb_rw, 0u, arg_1);
+ return;
+}
+
+void fragment_main_1() {
+ atomicStore_d1e9a6();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicStore_d1e9a6();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..4aa0544
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicStore_d1e9a6(device SB_RW_atomic* const tint_symbol) {
+ int arg_1 = 0;
+ arg_1 = 1;
+ int const x_20 = arg_1;
+ atomic_store_explicit(&((*(tint_symbol)).arg_0), x_20, memory_order_relaxed);
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicStore_d1e9a6(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicStore_d1e9a6(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..77ab9b0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,67 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicStore_d1e9a6 "atomicStore_d1e9a6"
+ OpName %arg_1 "arg_1"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicStore_d1e9a6 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %9
+ OpStore %arg_1 %9
+ OpStore %arg_1 %int_1
+ %13 = OpLoad %int %arg_1
+ %20 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ OpAtomicStore %20 %uint_1 %uint_0 %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicStore_d1e9a6
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %atomicStore_d1e9a6
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %31 = OpLabel
+ %32 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..9db31ae
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,37 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicStore_d1e9a6() {
+ var arg_1 : i32 = 0i;
+ arg_1 = 1i;
+ let x_20 : i32 = arg_1;
+ atomicStore(&(sb_rw.arg_0), x_20);
+ return;
+}
+
+fn fragment_main_1() {
+ atomicStore_d1e9a6();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicStore_d1e9a6();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm
new file mode 100644
index 0000000..f0d74fe
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 25
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicStore_cdc29e "atomicStore_cdc29e"
+ OpName %arg_1 "arg_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %12 = OpConstantNull %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicStore_cdc29e = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %12
+ OpStore %arg_1 %uint_1
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %18 = OpLoad %uint %arg_1
+ OpAtomicStore %17 %uint_1 %uint_0 %18
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %20 = OpLabel
+ %21 = OpFunctionCall %void %atomicStore_cdc29e
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicStore_cdc29e
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..7a8d693
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,68 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicStore_cdc29e() {
+ uint arg_1 = 0u;
+ arg_1 = 1u;
+ atomicExchange(sb_rw.arg_0, arg_1);
+ return;
+}
+
+void fragment_main_1() {
+ atomicStore_cdc29e();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicStore_cdc29e() {
+ uint arg_1 = 0u;
+ arg_1 = 1u;
+ atomicExchange(sb_rw.arg_0, arg_1);
+ return;
+}
+
+void compute_main_1() {
+ atomicStore_cdc29e();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..4550cdd
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,35 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+void tint_atomicStore(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint ignored;
+ buffer.InterlockedExchange(offset, value, ignored);
+}
+
+
+void atomicStore_cdc29e() {
+ uint arg_1 = 0u;
+ arg_1 = 1u;
+ tint_atomicStore(sb_rw, 0u, arg_1);
+ return;
+}
+
+void fragment_main_1() {
+ atomicStore_cdc29e();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicStore_cdc29e();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..21f9746
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicStore_cdc29e(device SB_RW_atomic* const tint_symbol) {
+ uint arg_1 = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ atomic_store_explicit(&((*(tint_symbol)).arg_0), x_18, memory_order_relaxed);
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicStore_cdc29e(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicStore_cdc29e(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..ababfa4
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,65 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicStore_cdc29e "atomicStore_cdc29e"
+ OpName %arg_1 "arg_1"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicStore_cdc29e = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %9
+ OpStore %arg_1 %9
+ OpStore %arg_1 %uint_1
+ %13 = OpLoad %uint %arg_1
+ %18 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ OpAtomicStore %18 %uint_1 %uint_0 %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %20 = OpLabel
+ %21 = OpFunctionCall %void %atomicStore_cdc29e
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicStore_cdc29e
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..1095ccc
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,37 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicStore_cdc29e() {
+ var arg_1 : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ atomicStore(&(sb_rw.arg_0), x_18);
+ return;
+}
+
+fn fragment_main_1() {
+ atomicStore_cdc29e();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicStore_cdc29e();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm
new file mode 100644
index 0000000..a0c7fb7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm
@@ -0,0 +1,54 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicStore_8bea94 "atomicStore_8bea94"
+ OpName %arg_1 "arg_1"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %14 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicStore_8bea94 = OpFunction %void None %7
+ %10 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %19
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicStore_8bea94
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %30 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %31 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..89e564c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicStore_8bea94() {
+ int arg_1 = 0;
+ arg_1 = 1;
+ atomicExchange(arg_0, arg_1);
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicStore_8bea94();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..68704dd
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,43 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicStore_8bea94() {
+ int arg_1 = 0;
+ arg_1 = 1;
+ int atomic_result = 0;
+ InterlockedExchange(arg_0, arg_1, atomic_result);
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicStore_8bea94();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..1e0fd57
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,40 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicStore_8bea94(threadgroup atomic_int* const tint_symbol) {
+ int arg_1 = 0;
+ arg_1 = 1;
+ int const x_19 = arg_1;
+ atomic_store_explicit(tint_symbol, x_19, memory_order_relaxed);
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicStore_8bea94(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_32 = *(tint_symbol_2);
+ compute_main_inner(x_32, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..63e9312
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,77 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 47
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicStore_8bea94 "atomicStore_8bea94"
+ OpName %arg_1 "arg_1"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %23 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicStore_8bea94 = OpFunction %void None %10
+ %13 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %14
+ OpStore %arg_1 %int_1
+ %18 = OpLoad %int %arg_1
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %18
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %23
+%local_invocation_index = OpFunctionParameter %uint
+ %26 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %31 = OpFunctionCall %void %atomicStore_8bea94
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %33 = OpLabel
+ %34 = OpLoad %uint %local_invocation_index_1
+ %35 = OpFunctionCall %void %compute_main_inner %34
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %23
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %38 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %42 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %44 = OpLabel
+ %46 = OpLoad %uint %local_invocation_index_1_param_1
+ %45 = OpFunctionCall %void %compute_main_inner_1 %46
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..0262122
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,30 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicStore_8bea94() {
+ var arg_1 : i32 = 0i;
+ arg_1 = 1i;
+ let x_19 : i32 = arg_1;
+ atomicStore(&(arg_0), x_19);
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicStore_8bea94();
+ return;
+}
+
+fn compute_main_1() {
+ let x_32 : u32 = local_invocation_index_1;
+ compute_main_inner(x_32);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm
new file mode 100644
index 0000000..72d2c5f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm
@@ -0,0 +1,53 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicStore_726882 "atomicStore_726882"
+ OpName %arg_1 "arg_1"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %13 = OpConstantNull %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %19 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicStore_726882 = OpFunction %void None %6
+ %9 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %13
+ OpStore %arg_1 %uint_1
+ %18 = OpLoad %uint %arg_1
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %18
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %19
+%local_invocation_index = OpFunctionParameter %uint
+ %22 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %13
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %27 = OpFunctionCall %void %atomicStore_726882
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %29 = OpLabel
+ %31 = OpLoad %uint %local_invocation_index_1
+ %30 = OpFunctionCall %void %compute_main_inner %31
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..dcceb31
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,37 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicStore_726882() {
+ uint arg_1 = 0u;
+ arg_1 = 1u;
+ atomicExchange(arg_0, arg_1);
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicStore_726882();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..5c41763
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,43 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicStore_726882() {
+ uint arg_1 = 0u;
+ arg_1 = 1u;
+ uint atomic_result = 0u;
+ InterlockedExchange(arg_0, arg_1, atomic_result);
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicStore_726882();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..fd36267
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,40 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicStore_726882(threadgroup atomic_uint* const tint_symbol) {
+ uint arg_1 = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ atomic_store_explicit(tint_symbol, x_18, memory_order_relaxed);
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicStore_726882(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_31 = *(tint_symbol_2);
+ compute_main_inner(x_31, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..2b50c09
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,75 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 45
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicStore_726882 "atomicStore_726882"
+ OpName %arg_1 "arg_1"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicStore_726882 = OpFunction %void None %9
+ %12 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %6
+ OpStore %arg_1 %6
+ OpStore %arg_1 %uint_1
+ %16 = OpLoad %uint %arg_1
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %16
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicStore_726882
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %31 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %33 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %21
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %36 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %40 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %42 = OpLabel
+ %44 = OpLoad %uint %local_invocation_index_1_param_1
+ %43 = OpFunctionCall %void %compute_main_inner_1 %44
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..fa0013a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicStore/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,30 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicStore_726882() {
+ var arg_1 : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ atomicStore(&(arg_0), x_18);
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicStore_726882();
+ return;
+}
+
+fn compute_main_1() {
+ let x_31 : u32 = local_invocation_index_1;
+ compute_main_inner(x_31);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm
new file mode 100644
index 0000000..3bbf26a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 28
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicSub_051100 "atomicSub_051100"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %12 = OpConstantNull %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicSub_051100 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %12
+ %res = OpVariable %_ptr_Function_int Function %12
+ OpStore %arg_1 %int_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %20 = OpLoad %int %arg_1
+ %13 = OpAtomicISub %int %19 %uint_1 %uint_0 %20
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicSub_051100
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicSub_051100
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..fcc4155
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicSub_051100() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicAdd(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicSub_051100();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicSub_051100() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicAdd(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicSub_051100();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..fca2ec1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicSub(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedAdd(offset, -value, original_value);
+ return original_value;
+}
+
+
+void atomicSub_051100() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ const int x_13 = tint_atomicSub(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicSub_051100();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicSub_051100();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..2a79213
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicSub_051100(device SB_RW_atomic* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_20 = arg_1;
+ int const x_13 = atomic_fetch_sub_explicit(&((*(tint_symbol)).arg_0), x_20, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicSub_051100(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicSub_051100(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..c40beba
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicSub_051100 "atomicSub_051100"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicSub_051100 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %9
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %int_1
+ %14 = OpLoad %int %arg_1
+ %21 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %15 = OpAtomicISub %int %21 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicSub_051100
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %atomicSub_051100
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %32 = OpLabel
+ %33 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..d47d886
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicSub_051100() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_20 : i32 = arg_1;
+ let x_13 : i32 = atomicSub(&(sb_rw.arg_0), x_20);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicSub_051100();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicSub_051100();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm
new file mode 100644
index 0000000..4d20c6d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm
@@ -0,0 +1,55 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicSub_15bfc9 "atomicSub_15bfc9"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %12 = OpConstantNull %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicSub_15bfc9 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %12
+ %res = OpVariable %_ptr_Function_uint Function %12
+ OpStore %arg_1 %uint_1
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %18 = OpLoad %uint %arg_1
+ %13 = OpAtomicISub %uint %17 %uint_1 %uint_0 %18
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicSub_15bfc9
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicSub_15bfc9
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..f91b7f8
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicSub_15bfc9() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicAdd(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicSub_15bfc9();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicSub_15bfc9() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicAdd(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicSub_15bfc9();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..f036c90
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicSub(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedAdd(offset, -value, original_value);
+ return original_value;
+}
+
+
+void atomicSub_15bfc9() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ const uint x_13 = tint_atomicSub(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicSub_15bfc9();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicSub_15bfc9();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..efb4526
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicSub_15bfc9(device SB_RW_atomic* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_13 = atomic_fetch_sub_explicit(&((*(tint_symbol)).arg_0), x_18, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicSub_15bfc9(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicSub_15bfc9(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..6704485
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,69 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicSub_15bfc9 "atomicSub_15bfc9"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicSub_15bfc9 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %9
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %uint_1
+ %14 = OpLoad %uint %arg_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %15 = OpAtomicISub %uint %19 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicSub_15bfc9
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicSub_15bfc9
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..bd9a80c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicSub_15bfc9() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_13 : u32 = atomicSub(&(sb_rw.arg_0), x_18);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicSub_15bfc9();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicSub_15bfc9();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm
new file mode 100644
index 0000000..d96432d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicSub_77883a "atomicSub_77883a"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %14 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicSub_77883a = OpFunction %void None %7
+ %10 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %15 = OpAtomicISub %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicSub_77883a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %31 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..e08bb7b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicSub_77883a() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_15 = atomicAdd(arg_0, arg_1);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicSub_77883a();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..988dbad
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicSub_77883a() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int atomic_result = 0;
+ InterlockedAdd(arg_0, -arg_1, atomic_result);
+ const int x_15 = atomic_result;
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicSub_77883a();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..208e18a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicSub_77883a(threadgroup atomic_int* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_19 = arg_1;
+ int const x_15 = atomic_fetch_sub_explicit(tint_symbol, x_19, memory_order_relaxed);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicSub_77883a(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_33 = *(tint_symbol_2);
+ compute_main_inner(x_33, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..9f3a065
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,81 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 48
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicSub_77883a "atomicSub_77883a"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %24 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicSub_77883a = OpFunction %void None %10
+ %13 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %14
+ OpStore %res %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %20 = OpAtomicISub %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %20
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %24
+%local_invocation_index = OpFunctionParameter %uint
+ %27 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %32 = OpFunctionCall %void %atomicSub_77883a
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %34 = OpLabel
+ %35 = OpLoad %uint %local_invocation_index_1
+ %36 = OpFunctionCall %void %compute_main_inner %35
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %24
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %39 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %43 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %45 = OpLabel
+ %47 = OpLoad %uint %local_invocation_index_1_param_1
+ %46 = OpFunctionCall %void %compute_main_inner_1 %47
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..b2781ce
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicSub_77883a() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_19 : i32 = arg_1;
+ let x_15 : i32 = atomicSub(&(arg_0), x_19);
+ res = x_15;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicSub_77883a();
+ return;
+}
+
+fn compute_main_1() {
+ let x_33 : u32 = local_invocation_index_1;
+ compute_main_inner(x_33);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm
new file mode 100644
index 0000000..2c6b98e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm
@@ -0,0 +1,56 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicSub_0d26c2 "atomicSub_0d26c2"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %13 = OpConstantNull %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicSub_0d26c2 = OpFunction %void None %6
+ %9 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %13
+ %res = OpVariable %_ptr_Function_uint Function %13
+ OpStore %arg_1 %uint_1
+ %18 = OpLoad %uint %arg_1
+ %14 = OpAtomicISub %uint %arg_0 %uint_2 %uint_0 %18
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %13
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicSub_0d26c2
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %30 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %31 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..a11a53e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicSub_0d26c2() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_14 = atomicAdd(arg_0, arg_1);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicSub_0d26c2();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..eb60c8a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicSub_0d26c2() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint atomic_result = 0u;
+ InterlockedAdd(arg_0, -arg_1, atomic_result);
+ const uint x_14 = atomic_result;
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicSub_0d26c2();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..ec9661d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicSub_0d26c2(threadgroup atomic_uint* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_14 = atomic_fetch_sub_explicit(tint_symbol, x_18, memory_order_relaxed);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicSub_0d26c2(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_32 = *(tint_symbol_2);
+ compute_main_inner(x_32, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..c1b5f7a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,79 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicSub_0d26c2 "atomicSub_0d26c2"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicSub_0d26c2 = OpFunction %void None %9
+ %12 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %6
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %arg_1 %6
+ OpStore %res %6
+ OpStore %arg_1 %uint_1
+ %17 = OpLoad %uint %arg_1
+ %18 = OpAtomicISub %uint %arg_0 %uint_2 %uint_0 %17
+ OpStore %res %18
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicSub_0d26c2
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..77f25f7
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicSub/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicSub_0d26c2() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_14 : u32 = atomicSub(&(arg_0), x_18);
+ res = x_14;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicSub_0d26c2();
+ return;
+}
+
+fn compute_main_1() {
+ let x_32 : u32 = local_invocation_index_1;
+ compute_main_inner(x_32);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm
new file mode 100644
index 0000000..cff5564
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 28
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicXor_c1b78c "atomicXor_c1b78c"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %12 = OpConstantNull %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicXor_c1b78c = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %12
+ %res = OpVariable %_ptr_Function_int Function %12
+ OpStore %arg_1 %int_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %20 = OpLoad %int %arg_1
+ %13 = OpAtomicXor %int %19 %uint_1 %uint_0 %20
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicXor_c1b78c
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicXor_c1b78c
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..4953346
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicXor_c1b78c() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicXor(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicXor_c1b78c();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicXor_c1b78c() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicXor(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicXor_c1b78c();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..195284c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicXor(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedXor(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicXor_c1b78c() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ const int x_13 = tint_atomicXor(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicXor_c1b78c();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicXor_c1b78c();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..1e98bee
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicXor_c1b78c(device SB_RW_atomic* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_20 = arg_1;
+ int const x_13 = atomic_fetch_xor_explicit(&((*(tint_symbol)).arg_0), x_20, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicXor_c1b78c(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicXor_c1b78c(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..74a9caa
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,71 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicXor_c1b78c "atomicXor_c1b78c"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicXor_c1b78c = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %9
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %int_1
+ %14 = OpLoad %int %arg_1
+ %21 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %15 = OpAtomicXor %int %21 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicXor_c1b78c
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %atomicXor_c1b78c
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %32 = OpLabel
+ %33 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..4325da1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicXor_c1b78c() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_20 : i32 = arg_1;
+ let x_13 : i32 = atomicXor(&(sb_rw.arg_0), x_20);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicXor_c1b78c();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicXor_c1b78c();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm
new file mode 100644
index 0000000..a16daff
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm
@@ -0,0 +1,55 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicXor_54510e "atomicXor_54510e"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %12 = OpConstantNull %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicXor_54510e = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %12
+ %res = OpVariable %_ptr_Function_uint Function %12
+ OpStore %arg_1 %uint_1
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %18 = OpLoad %uint %arg_1
+ %13 = OpAtomicXor %uint %17 %uint_1 %uint_0 %18
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicXor_54510e
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicXor_54510e
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..c382bff
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicXor_54510e() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicXor(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicXor_54510e();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicXor_54510e() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicXor(sb_rw.arg_0, arg_1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicXor_54510e();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..36ccd47
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicXor(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedXor(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicXor_54510e() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ const uint x_13 = tint_atomicXor(sb_rw, 0u, arg_1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicXor_54510e();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicXor_54510e();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..068d4aa
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicXor_54510e(device SB_RW_atomic* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_13 = atomic_fetch_xor_explicit(&((*(tint_symbol)).arg_0), x_18, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicXor_54510e(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicXor_54510e(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..786b9f60
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,69 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 32
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicXor_54510e "atomicXor_54510e"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicXor_54510e = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %9
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %uint_1
+ %14 = OpLoad %uint %arg_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %15 = OpAtomicXor %uint %19 %uint_1 %uint_0 %14
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicXor_54510e
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %27 = OpLabel
+ %28 = OpFunctionCall %void %atomicXor_54510e
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %30 = OpLabel
+ %31 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..2b3dd0d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,39 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicXor_54510e() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_13 : u32 = atomicXor(&(sb_rw.arg_0), x_18);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicXor_54510e();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicXor_54510e();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm
new file mode 100644
index 0000000..62e0351
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm
@@ -0,0 +1,57 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicXor_75dc95 "atomicXor_75dc95"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %14 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicXor_75dc95 = OpFunction %void None %7
+ %10 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %15 = OpAtomicXor %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicXor_75dc95
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %31 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..f568517
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicXor_75dc95() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_15 = atomicXor(arg_0, arg_1);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicXor_75dc95();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..2c71c9a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicXor_75dc95() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int atomic_result = 0;
+ InterlockedXor(arg_0, arg_1, atomic_result);
+ const int x_15 = atomic_result;
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicXor_75dc95();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..840c318
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicXor_75dc95(threadgroup atomic_int* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_19 = arg_1;
+ int const x_15 = atomic_fetch_xor_explicit(tint_symbol, x_19, memory_order_relaxed);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicXor_75dc95(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_33 = *(tint_symbol_2);
+ compute_main_inner(x_33, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..2bac01d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,81 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 48
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicXor_75dc95 "atomicXor_75dc95"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %24 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicXor_75dc95 = OpFunction %void None %10
+ %13 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %14
+ OpStore %res %14
+ OpStore %arg_1 %int_1
+ %19 = OpLoad %int %arg_1
+ %20 = OpAtomicXor %int %arg_0 %uint_2 %uint_0 %19
+ OpStore %res %20
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %24
+%local_invocation_index = OpFunctionParameter %uint
+ %27 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %32 = OpFunctionCall %void %atomicXor_75dc95
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %34 = OpLabel
+ %35 = OpLoad %uint %local_invocation_index_1
+ %36 = OpFunctionCall %void %compute_main_inner %35
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %24
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %39 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %43 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %45 = OpLabel
+ %47 = OpLoad %uint %local_invocation_index_1_param_1
+ %46 = OpFunctionCall %void %compute_main_inner_1 %47
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..54490e1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicXor_75dc95() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_19 : i32 = arg_1;
+ let x_15 : i32 = atomicXor(&(arg_0), x_19);
+ res = x_15;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicXor_75dc95();
+ return;
+}
+
+fn compute_main_1() {
+ let x_33 : u32 = local_invocation_index_1;
+ compute_main_inner(x_33);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm
new file mode 100644
index 0000000..ba98e8d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm
@@ -0,0 +1,56 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicXor_c8e6be "atomicXor_c8e6be"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %13 = OpConstantNull %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicXor_c8e6be = OpFunction %void None %6
+ %9 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %13
+ %res = OpVariable %_ptr_Function_uint Function %13
+ OpStore %arg_1 %uint_1
+ %18 = OpLoad %uint %arg_1
+ %14 = OpAtomicXor %uint %arg_0 %uint_2 %uint_0 %18
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %13
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicXor_c8e6be
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %30 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %31 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..2c88781
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicXor_c8e6be() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_14 = atomicXor(arg_0, arg_1);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicXor_c8e6be();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..e7ceab2
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicXor_c8e6be() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint atomic_result = 0u;
+ InterlockedXor(arg_0, arg_1, atomic_result);
+ const uint x_14 = atomic_result;
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicXor_c8e6be();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..3eb2509
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicXor_c8e6be(threadgroup atomic_uint* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_18 = arg_1;
+ uint const x_14 = atomic_fetch_xor_explicit(tint_symbol, x_18, memory_order_relaxed);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicXor_c8e6be(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_32 = *(tint_symbol_2);
+ compute_main_inner(x_32, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..83c9054
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,79 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 46
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicXor_c8e6be "atomicXor_c8e6be"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %22 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicXor_c8e6be = OpFunction %void None %9
+ %12 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %6
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %arg_1 %6
+ OpStore %res %6
+ OpStore %arg_1 %uint_1
+ %17 = OpLoad %uint %arg_1
+ %18 = OpAtomicXor %uint %arg_0 %uint_2 %uint_0 %17
+ OpStore %res %18
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %22
+%local_invocation_index = OpFunctionParameter %uint
+ %25 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %30 = OpFunctionCall %void %atomicXor_c8e6be
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %32 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %34 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %22
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %37 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %41 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %43 = OpLabel
+ %45 = OpLoad %uint %local_invocation_index_1_param_1
+ %44 = OpFunctionCall %void %compute_main_inner_1 %45
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..c75d808
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/atomicXor/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,32 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicXor_c8e6be() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_18 : u32 = arg_1;
+ let x_14 : u32 = atomicXor(&(arg_0), x_18);
+ res = x_14;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicXor_c8e6be();
+ return;
+}
+
+fn compute_main_1() {
+ let x_32 : u32 = local_invocation_index_1;
+ compute_main_inner(x_32);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm
new file mode 100644
index 0000000..fb43e2c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm
@@ -0,0 +1,56 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 28
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_d32fe4 "atomicAdd_d32fe4"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %12 = OpConstantNull %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicAdd_d32fe4 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %12
+ %res = OpVariable %_ptr_Function_int Function %12
+ OpStore %arg_1 %int_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %13 = OpAtomicIDecrement %int %19 %uint_1 %uint_0
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..167e99c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAdd_d32fe4() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicAdd(sb_rw.arg_0, 1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAdd_d32fe4() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicAdd(sb_rw.arg_0, 1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..abf10b5
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicSub(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedAdd(offset, -value, original_value);
+ return original_value;
+}
+
+
+void atomicAdd_d32fe4() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ const int x_13 = tint_atomicSub(sb_rw, 0u, 1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..8bbb600
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.msl
@@ -0,0 +1,40 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicAdd_d32fe4(device SB_RW_atomic* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_13 = atomic_fetch_sub_explicit(&((*(tint_symbol)).arg_0), 1, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAdd_d32fe4(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAdd_d32fe4(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..870704e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,70 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_d32fe4 "atomicAdd_d32fe4"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicAdd_d32fe4 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %9
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %int_1
+ %20 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %14 = OpAtomicISub %int %20 %uint_1 %uint_0 %int_1
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %31 = OpLabel
+ %32 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..1e011b0
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,38 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAdd_d32fe4() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_13 : i32 = atomicSub(&(sb_rw.arg_0), 1i);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm
new file mode 100644
index 0000000..9e693ca
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm
@@ -0,0 +1,54 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_8a199a "atomicAdd_8a199a"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %12 = OpConstantNull %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicAdd_8a199a = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %12
+ %res = OpVariable %_ptr_Function_uint Function %12
+ OpStore %arg_1 %uint_1
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %13 = OpAtomicIDecrement %uint %17 %uint_1 %uint_0
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..d9e0515
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAdd_8a199a() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicAdd(sb_rw.arg_0, 1u);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAdd_8a199a() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicAdd(sb_rw.arg_0, 1u);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..4e6bb86
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicSub(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedAdd(offset, -value, original_value);
+ return original_value;
+}
+
+
+void atomicAdd_8a199a() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ const uint x_13 = tint_atomicSub(sb_rw, 0u, 1u);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..7fe160f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.msl
@@ -0,0 +1,40 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicAdd_8a199a(device SB_RW_atomic* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_13 = atomic_fetch_sub_explicit(&((*(tint_symbol)).arg_0), 1u, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAdd_8a199a(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAdd_8a199a(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..63b3eeb
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,68 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_8a199a "atomicAdd_8a199a"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicAdd_8a199a = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %9
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %uint_1
+ %18 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %14 = OpAtomicISub %uint %18 %uint_1 %uint_0 %uint_1
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %20 = OpLabel
+ %21 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..f12b29e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,38 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAdd_8a199a() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_13 : u32 = atomicSub(&(sb_rw.arg_0), 1u);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm
new file mode 100644
index 0000000..9f14c53
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm
@@ -0,0 +1,56 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_794055 "atomicAdd_794055"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %14 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_794055 = OpFunction %void None %7
+ %10 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %int_1
+ %15 = OpAtomicIDecrement %int %arg_0 %uint_2 %uint_0
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicAdd_794055
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %31 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..ef3ffb1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicAdd_794055() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_15 = atomicAdd(arg_0, 1);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicAdd_794055();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..181873a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicAdd_794055() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int atomic_result = 0;
+ InterlockedAdd(arg_0, -1, atomic_result);
+ const int x_15 = atomic_result;
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAdd_794055();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..9f11082
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAdd_794055(threadgroup atomic_int* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_15 = atomic_fetch_sub_explicit(tint_symbol, 1, memory_order_relaxed);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAdd_794055(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_33 = *(tint_symbol_2);
+ compute_main_inner(x_33, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..843bd5a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,80 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 47
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_794055 "atomicAdd_794055"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %23 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_794055 = OpFunction %void None %10
+ %13 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %14
+ OpStore %res %14
+ OpStore %arg_1 %int_1
+ %19 = OpAtomicISub %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %19
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %23
+%local_invocation_index = OpFunctionParameter %uint
+ %26 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %31 = OpFunctionCall %void %atomicAdd_794055
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %33 = OpLabel
+ %34 = OpLoad %uint %local_invocation_index_1
+ %35 = OpFunctionCall %void %compute_main_inner %34
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %23
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %38 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %42 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %44 = OpLabel
+ %46 = OpLoad %uint %local_invocation_index_1_param_1
+ %45 = OpFunctionCall %void %compute_main_inner_1 %46
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..540501a
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,31 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicAdd_794055() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_15 : i32 = atomicSub(&(arg_0), 1i);
+ res = x_15;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicAdd_794055();
+ return;
+}
+
+fn compute_main_1() {
+ let x_33 : u32 = local_invocation_index_1;
+ compute_main_inner(x_33);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm
new file mode 100644
index 0000000..1d1b5bd
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm
@@ -0,0 +1,55 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %13 = OpConstantNull %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_d5db1d = OpFunction %void None %6
+ %9 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %13
+ %res = OpVariable %_ptr_Function_uint Function %13
+ OpStore %arg_1 %uint_1
+ %14 = OpAtomicIDecrement %uint %arg_0 %uint_2 %uint_0
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %13
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicAdd_d5db1d
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %30 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %31 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..b9c2faf
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicAdd_d5db1d() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_14 = atomicAdd(arg_0, 1u);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicAdd_d5db1d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..16aaa1c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicAdd_d5db1d() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint atomic_result = 0u;
+ InterlockedAdd(arg_0, -1u, atomic_result);
+ const uint x_14 = atomic_result;
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAdd_d5db1d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..74b7a0d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAdd_d5db1d(threadgroup atomic_uint* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_14 = atomic_fetch_sub_explicit(tint_symbol, 1u, memory_order_relaxed);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAdd_d5db1d(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_32 = *(tint_symbol_2);
+ compute_main_inner(x_32, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..77041b4
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,78 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 45
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_d5db1d = OpFunction %void None %9
+ %12 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %6
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %arg_1 %6
+ OpStore %res %6
+ OpStore %arg_1 %uint_1
+ %17 = OpAtomicISub %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicAdd_d5db1d
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %31 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %33 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %21
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %36 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %40 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %42 = OpLabel
+ %44 = OpLoad %uint %local_invocation_index_1_param_1
+ %43 = OpFunctionCall %void %compute_main_inner_1 %44
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..64dabf4
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicDecrement/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,31 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicAdd_d5db1d() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_14 : u32 = atomicSub(&(arg_0), 1u);
+ res = x_14;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicAdd_d5db1d();
+ return;
+}
+
+fn compute_main_1() {
+ let x_32 : u32 = local_invocation_index_1;
+ compute_main_inner(x_32);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm
new file mode 100644
index 0000000..9bacaec
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm
@@ -0,0 +1,56 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 28
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_d32fe4 "atomicAdd_d32fe4"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+ %SB_RW = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %12 = OpConstantNull %int
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicAdd_d32fe4 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %12
+ %res = OpVariable %_ptr_Function_int Function %12
+ OpStore %arg_1 %int_1
+ %19 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %13 = OpAtomicIIncrement %int %19 %uint_1 %uint_0
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..167e99c
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAdd_d32fe4() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicAdd(sb_rw.arg_0, 1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ int arg_0;
+} sb_rw;
+void atomicAdd_d32fe4() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_13 = atomicAdd(sb_rw.arg_0, 1);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..9be7a9e
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+int tint_atomicAdd(RWByteAddressBuffer buffer, uint offset, int value) {
+ int original_value = 0;
+ buffer.InterlockedAdd(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicAdd_d32fe4() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ const int x_13 = tint_atomicAdd(sb_rw, 0u, 1);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.msl
new file mode 100644
index 0000000..acfdf7f
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.msl
@@ -0,0 +1,40 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_int arg_0;
+};
+
+struct SB_RW {
+ int arg_0;
+};
+
+void atomicAdd_d32fe4(device SB_RW_atomic* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_13 = atomic_fetch_add_explicit(&((*(tint_symbol)).arg_0), 1, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAdd_d32fe4(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAdd_d32fe4(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..f206f17
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.spvasm
@@ -0,0 +1,70 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_d32fe4 "atomicAdd_d32fe4"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %int = OpTypeInt 32 1
+%SB_RW_atomic = OpTypeStruct %int
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
+%atomicAdd_d32fe4 = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %9
+ %res = OpVariable %_ptr_Function_int Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %int_1
+ %20 = OpAccessChain %_ptr_StorageBuffer_int %sb_rw %uint_0
+ %14 = OpAtomicIAdd %int %20 %uint_1 %uint_0 %int_1
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %22 = OpLabel
+ %23 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %25 = OpLabel
+ %26 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %28 = OpLabel
+ %29 = OpFunctionCall %void %atomicAdd_d32fe4
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %31 = OpLabel
+ %32 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..da3a03b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_i32.spvasm.expected.wgsl
@@ -0,0 +1,38 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<i32>,
+}
+
+struct SB_RW {
+ arg_0 : i32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAdd_d32fe4() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_13 : i32 = atomicAdd(&(sb_rw.arg_0), 1i);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAdd_d32fe4();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm
new file mode 100644
index 0000000..8aad806
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm
@@ -0,0 +1,54 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 26
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW "SB_RW"
+ OpMemberName %SB_RW 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_8a199a "atomicAdd_8a199a"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW Block
+ OpMemberDecorate %SB_RW 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+ %SB_RW = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW = OpTypePointer StorageBuffer %SB_RW
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %12 = OpConstantNull %uint
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicAdd_8a199a = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %12
+ %res = OpVariable %_ptr_Function_uint Function %12
+ OpStore %arg_1 %uint_1
+ %17 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %13 = OpAtomicIIncrement %uint %17 %uint_1 %uint_0
+ OpStore %res %13
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %21 = OpLabel
+ %22 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %24 = OpLabel
+ %25 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..d9e0515
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.glsl
@@ -0,0 +1,72 @@
+#version 310 es
+precision mediump float;
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAdd_8a199a() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicAdd(sb_rw.arg_0, 1u);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+}
+
+void main() {
+ fragment_main();
+ return;
+}
+#version 310 es
+
+struct SB_RW_atomic {
+ uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+layout(binding = 0, std430) buffer SB_RW_atomic_1 {
+ uint arg_0;
+} sb_rw;
+void atomicAdd_8a199a() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_13 = atomicAdd(sb_rw.arg_0, 1u);
+ res = x_13;
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void compute_main() {
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..442a1ff
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.hlsl
@@ -0,0 +1,38 @@
+RWByteAddressBuffer sb_rw : register(u0, space0);
+
+uint tint_atomicAdd(RWByteAddressBuffer buffer, uint offset, uint value) {
+ uint original_value = 0;
+ buffer.InterlockedAdd(offset, value, original_value);
+ return original_value;
+}
+
+
+void atomicAdd_8a199a() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ const uint x_13 = tint_atomicAdd(sb_rw, 0u, 1u);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+void fragment_main() {
+ fragment_main_1();
+ return;
+}
+
+void compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+[numthreads(1, 1, 1)]
+void compute_main() {
+ compute_main_1();
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.msl
new file mode 100644
index 0000000..b3d0ecd
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.msl
@@ -0,0 +1,40 @@
+#include <metal_stdlib>
+
+using namespace metal;
+struct SB_RW_atomic {
+ /* 0x0000 */ atomic_uint arg_0;
+};
+
+struct SB_RW {
+ uint arg_0;
+};
+
+void atomicAdd_8a199a(device SB_RW_atomic* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_13 = atomic_fetch_add_explicit(&((*(tint_symbol)).arg_0), 1u, memory_order_relaxed);
+ res = x_13;
+ return;
+}
+
+void fragment_main_1(device SB_RW_atomic* const tint_symbol_1) {
+ atomicAdd_8a199a(tint_symbol_1);
+ return;
+}
+
+fragment void fragment_main(device SB_RW_atomic* tint_symbol_2 [[buffer(0)]]) {
+ fragment_main_1(tint_symbol_2);
+ return;
+}
+
+void compute_main_1(device SB_RW_atomic* const tint_symbol_3) {
+ atomicAdd_8a199a(tint_symbol_3);
+ return;
+}
+
+kernel void compute_main(device SB_RW_atomic* tint_symbol_4 [[buffer(0)]]) {
+ compute_main_1(tint_symbol_4);
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..17ebf7b
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.spvasm
@@ -0,0 +1,68 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 31
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %fragment_main "fragment_main"
+ OpEntryPoint GLCompute %compute_main "compute_main"
+ OpExecutionMode %fragment_main OriginUpperLeft
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %SB_RW_atomic "SB_RW_atomic"
+ OpMemberName %SB_RW_atomic 0 "arg_0"
+ OpName %sb_rw "sb_rw"
+ OpName %atomicAdd_8a199a "atomicAdd_8a199a"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %fragment_main_1 "fragment_main_1"
+ OpName %fragment_main "fragment_main"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main "compute_main"
+ OpDecorate %SB_RW_atomic Block
+ OpMemberDecorate %SB_RW_atomic 0 Offset 0
+ OpDecorate %sb_rw DescriptorSet 0
+ OpDecorate %sb_rw Binding 0
+ %uint = OpTypeInt 32 0
+%SB_RW_atomic = OpTypeStruct %uint
+%_ptr_StorageBuffer_SB_RW_atomic = OpTypePointer StorageBuffer %SB_RW_atomic
+ %sb_rw = OpVariable %_ptr_StorageBuffer_SB_RW_atomic StorageBuffer
+ %void = OpTypeVoid
+ %5 = OpTypeFunction %void
+ %9 = OpConstantNull %uint
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%atomicAdd_8a199a = OpFunction %void None %5
+ %8 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %9
+ %res = OpVariable %_ptr_Function_uint Function %9
+ OpStore %arg_1 %9
+ OpStore %res %9
+ OpStore %arg_1 %uint_1
+ %18 = OpAccessChain %_ptr_StorageBuffer_uint %sb_rw %uint_0
+ %14 = OpAtomicIAdd %uint %18 %uint_1 %uint_0 %uint_1
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%fragment_main_1 = OpFunction %void None %5
+ %20 = OpLabel
+ %21 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%fragment_main = OpFunction %void None %5
+ %23 = OpLabel
+ %24 = OpFunctionCall %void %fragment_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %5
+ %26 = OpLabel
+ %27 = OpFunctionCall %void %atomicAdd_8a199a
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %5
+ %29 = OpLabel
+ %30 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..61fbe49
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/storage_u32.spvasm.expected.wgsl
@@ -0,0 +1,38 @@
+struct SB_RW_atomic {
+ arg_0 : atomic<u32>,
+}
+
+struct SB_RW {
+ arg_0 : u32,
+}
+
+@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW_atomic;
+
+fn atomicAdd_8a199a() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_13 : u32 = atomicAdd(&(sb_rw.arg_0), 1u);
+ res = x_13;
+ return;
+}
+
+fn fragment_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+@fragment
+fn fragment_main() {
+ fragment_main_1();
+}
+
+fn compute_main_1() {
+ atomicAdd_8a199a();
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main() {
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm
new file mode 100644
index 0000000..2fb3e8d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm
@@ -0,0 +1,56 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 34
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_794055 "atomicAdd_794055"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %7 = OpTypeFunction %void
+ %int_1 = OpConstant %int 1
+%_ptr_Function_int = OpTypePointer Function %int
+ %14 = OpConstantNull %int
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_794055 = OpFunction %void None %7
+ %10 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %int_1
+ %15 = OpAtomicIIncrement %int %arg_0 %uint_2 %uint_0
+ OpStore %res %15
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicAdd_794055
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %7
+ %31 = OpLabel
+ %33 = OpLoad %uint %local_invocation_index_1
+ %32 = OpFunctionCall %void %compute_main_inner %33
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl
new file mode 100644
index 0000000..ef3ffb1
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared int arg_0;
+void atomicAdd_794055() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int x_15 = atomicAdd(arg_0, 1);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0);
+ barrier();
+ atomicAdd_794055();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.hlsl
new file mode 100644
index 0000000..6270b9d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared int arg_0;
+
+void atomicAdd_794055() {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int atomic_result = 0;
+ InterlockedAdd(arg_0, 1, atomic_result);
+ const int x_15 = atomic_result;
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ int atomic_result_1 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAdd_794055();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ int atomic_result_2 = 0;
+ InterlockedExchange(arg_0, 0, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl
new file mode 100644
index 0000000..dc059dd
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAdd_794055(threadgroup atomic_int* const tint_symbol) {
+ int arg_1 = 0;
+ int res = 0;
+ arg_1 = 1;
+ int const x_15 = atomic_fetch_add_explicit(tint_symbol, 1, memory_order_relaxed);
+ res = x_15;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_int* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAdd_794055(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_int* const tint_symbol_3) {
+ uint const x_33 = *(tint_symbol_2);
+ compute_main_inner(x_33, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_int* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_int tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm
new file mode 100644
index 0000000..ed49501
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.spvasm
@@ -0,0 +1,80 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 47
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_794055 "atomicAdd_794055"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+ %int = OpTypeInt 32 1
+%_ptr_Workgroup_int = OpTypePointer Workgroup %int
+ %arg_0 = OpVariable %_ptr_Workgroup_int Workgroup
+ %void = OpTypeVoid
+ %10 = OpTypeFunction %void
+ %14 = OpConstantNull %int
+%_ptr_Function_int = OpTypePointer Function %int
+ %int_1 = OpConstant %int 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %23 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_794055 = OpFunction %void None %10
+ %13 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_int Function %14
+ %res = OpVariable %_ptr_Function_int Function %14
+ OpStore %arg_1 %14
+ OpStore %res %14
+ OpStore %arg_1 %int_1
+ %19 = OpAtomicIAdd %int %arg_0 %uint_2 %uint_0 %int_1
+ OpStore %res %19
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %23
+%local_invocation_index = OpFunctionParameter %uint
+ %26 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %31 = OpFunctionCall %void %atomicAdd_794055
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %10
+ %33 = OpLabel
+ %34 = OpLoad %uint %local_invocation_index_1
+ %35 = OpFunctionCall %void %compute_main_inner %34
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %23
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %38 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %14
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %42 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %10
+ %44 = OpLabel
+ %46 = OpLoad %uint %local_invocation_index_1_param_1
+ %45 = OpFunctionCall %void %compute_main_inner_1 %46
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl
new file mode 100644
index 0000000..b5076c3
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_i32.spvasm.expected.wgsl
@@ -0,0 +1,31 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<i32>;
+
+fn atomicAdd_794055() {
+ var arg_1 : i32 = 0i;
+ var res : i32 = 0i;
+ arg_1 = 1i;
+ let x_15 : i32 = atomicAdd(&(arg_0), 1i);
+ res = x_15;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0i);
+ workgroupBarrier();
+ atomicAdd_794055();
+ return;
+}
+
+fn compute_main_1() {
+ let x_33 : u32 = local_invocation_index_1;
+ compute_main_inner(x_33);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm
new file mode 100644
index 0000000..48d906d
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm
@@ -0,0 +1,55 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 33
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %uint_1 = OpConstant %uint 1
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %13 = OpConstantNull %uint
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %20 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_d5db1d = OpFunction %void None %6
+ %9 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %13
+ %res = OpVariable %_ptr_Function_uint Function %13
+ OpStore %arg_1 %uint_1
+ %14 = OpAtomicIIncrement %uint %arg_0 %uint_2 %uint_0
+ OpStore %res %14
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %20
+%local_invocation_index = OpFunctionParameter %uint
+ %23 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %13
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %28 = OpFunctionCall %void %atomicAdd_d5db1d
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %6
+ %30 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %31 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl
new file mode 100644
index 0000000..b9c2faf
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.glsl
@@ -0,0 +1,39 @@
+#version 310 es
+
+uint local_invocation_index_1 = 0u;
+shared uint arg_0;
+void atomicAdd_d5db1d() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint x_14 = atomicAdd(arg_0, 1u);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ atomicExchange(arg_0, 0u);
+ barrier();
+ atomicAdd_d5db1d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+void compute_main(uint local_invocation_index_1_param) {
+ {
+ atomicExchange(arg_0, 0u);
+ }
+ barrier();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+ compute_main(gl_LocalInvocationIndex);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.hlsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.hlsl
new file mode 100644
index 0000000..d2a0213
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.hlsl
@@ -0,0 +1,46 @@
+static uint local_invocation_index_1 = 0u;
+groupshared uint arg_0;
+
+void atomicAdd_d5db1d() {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint atomic_result = 0u;
+ InterlockedAdd(arg_0, 1u, atomic_result);
+ const uint x_14 = atomic_result;
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index) {
+ uint atomic_result_1 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_1);
+ GroupMemoryBarrierWithGroupSync();
+ atomicAdd_d5db1d();
+ return;
+}
+
+void compute_main_1() {
+ compute_main_inner(local_invocation_index_1);
+ return;
+}
+
+struct tint_symbol_1 {
+ uint local_invocation_index_1_param : SV_GroupIndex;
+};
+
+void compute_main_inner_1(uint local_invocation_index_1_param) {
+ {
+ uint atomic_result_2 = 0u;
+ InterlockedExchange(arg_0, 0u, atomic_result_2);
+ }
+ GroupMemoryBarrierWithGroupSync();
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}
+
+[numthreads(1, 1, 1)]
+void compute_main(tint_symbol_1 tint_symbol) {
+ compute_main_inner_1(tint_symbol.local_invocation_index_1_param);
+ return;
+}
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl
new file mode 100644
index 0000000..1b33ab8
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+void atomicAdd_d5db1d(threadgroup atomic_uint* const tint_symbol) {
+ uint arg_1 = 0u;
+ uint res = 0u;
+ arg_1 = 1u;
+ uint const x_14 = atomic_fetch_add_explicit(tint_symbol, 1u, memory_order_relaxed);
+ res = x_14;
+ return;
+}
+
+void compute_main_inner(uint local_invocation_index, threadgroup atomic_uint* const tint_symbol_1) {
+ atomic_store_explicit(tint_symbol_1, 0u, memory_order_relaxed);
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ atomicAdd_d5db1d(tint_symbol_1);
+ return;
+}
+
+void compute_main_1(thread uint* const tint_symbol_2, threadgroup atomic_uint* const tint_symbol_3) {
+ uint const x_32 = *(tint_symbol_2);
+ compute_main_inner(x_32, tint_symbol_3);
+ return;
+}
+
+void compute_main_inner_1(uint local_invocation_index_1_param, threadgroup atomic_uint* const tint_symbol_4, thread uint* const tint_symbol_5) {
+ {
+ atomic_store_explicit(tint_symbol_4, 0u, memory_order_relaxed);
+ }
+ threadgroup_barrier(mem_flags::mem_threadgroup);
+ *(tint_symbol_5) = local_invocation_index_1_param;
+ compute_main_1(tint_symbol_5, tint_symbol_4);
+}
+
+kernel void compute_main(uint local_invocation_index_1_param [[thread_index_in_threadgroup]]) {
+ threadgroup atomic_uint tint_symbol_6;
+ thread uint tint_symbol_7 = 0u;
+ compute_main_inner_1(local_invocation_index_1_param, &(tint_symbol_6), &(tint_symbol_7));
+ return;
+}
+
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm
new file mode 100644
index 0000000..1388894
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.spvasm
@@ -0,0 +1,78 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 0
+; Bound: 45
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %compute_main "compute_main" %local_invocation_index_1_param_1
+ OpExecutionMode %compute_main LocalSize 1 1 1
+ OpName %local_invocation_index_1_param_1 "local_invocation_index_1_param_1"
+ OpName %local_invocation_index_1 "local_invocation_index_1"
+ OpName %arg_0 "arg_0"
+ OpName %atomicAdd_d5db1d "atomicAdd_d5db1d"
+ OpName %arg_1 "arg_1"
+ OpName %res "res"
+ OpName %compute_main_inner "compute_main_inner"
+ OpName %local_invocation_index "local_invocation_index"
+ OpName %compute_main_1 "compute_main_1"
+ OpName %compute_main_inner_1 "compute_main_inner_1"
+ OpName %local_invocation_index_1_param "local_invocation_index_1_param"
+ OpName %compute_main "compute_main"
+ OpDecorate %local_invocation_index_1_param_1 BuiltIn LocalInvocationIndex
+ %uint = OpTypeInt 32 0
+%_ptr_Input_uint = OpTypePointer Input %uint
+%local_invocation_index_1_param_1 = OpVariable %_ptr_Input_uint Input
+%_ptr_Private_uint = OpTypePointer Private %uint
+ %6 = OpConstantNull %uint
+%local_invocation_index_1 = OpVariable %_ptr_Private_uint Private %6
+%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
+ %arg_0 = OpVariable %_ptr_Workgroup_uint Workgroup
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+%_ptr_Function_uint = OpTypePointer Function %uint
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+ %uint_0 = OpConstant %uint 0
+ %21 = OpTypeFunction %void %uint
+ %uint_264 = OpConstant %uint 264
+%atomicAdd_d5db1d = OpFunction %void None %9
+ %12 = OpLabel
+ %arg_1 = OpVariable %_ptr_Function_uint Function %6
+ %res = OpVariable %_ptr_Function_uint Function %6
+ OpStore %arg_1 %6
+ OpStore %res %6
+ OpStore %arg_1 %uint_1
+ %17 = OpAtomicIAdd %uint %arg_0 %uint_2 %uint_0 %uint_1
+ OpStore %res %17
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner = OpFunction %void None %21
+%local_invocation_index = OpFunctionParameter %uint
+ %24 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ %29 = OpFunctionCall %void %atomicAdd_d5db1d
+ OpReturn
+ OpFunctionEnd
+%compute_main_1 = OpFunction %void None %9
+ %31 = OpLabel
+ %32 = OpLoad %uint %local_invocation_index_1
+ %33 = OpFunctionCall %void %compute_main_inner %32
+ OpReturn
+ OpFunctionEnd
+%compute_main_inner_1 = OpFunction %void None %21
+%local_invocation_index_1_param = OpFunctionParameter %uint
+ %36 = OpLabel
+ OpAtomicStore %arg_0 %uint_2 %uint_0 %6
+ OpControlBarrier %uint_2 %uint_2 %uint_264
+ OpStore %local_invocation_index_1 %local_invocation_index_1_param
+ %40 = OpFunctionCall %void %compute_main_1
+ OpReturn
+ OpFunctionEnd
+%compute_main = OpFunction %void None %9
+ %42 = OpLabel
+ %44 = OpLoad %uint %local_invocation_index_1_param_1
+ %43 = OpFunctionCall %void %compute_main_inner_1 %44
+ OpReturn
+ OpFunctionEnd
diff --git a/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl
new file mode 100644
index 0000000..7faf057
--- /dev/null
+++ b/test/tint/builtins/atomics/from_gen/var/spvAtomicIncrement/workgroup_u32.spvasm.expected.wgsl
@@ -0,0 +1,31 @@
+var<private> local_invocation_index_1 : u32;
+
+var<workgroup> arg_0 : atomic<u32>;
+
+fn atomicAdd_d5db1d() {
+ var arg_1 : u32 = 0u;
+ var res : u32 = 0u;
+ arg_1 = 1u;
+ let x_14 : u32 = atomicAdd(&(arg_0), 1u);
+ res = x_14;
+ return;
+}
+
+fn compute_main_inner(local_invocation_index : u32) {
+ atomicStore(&(arg_0), 0u);
+ workgroupBarrier();
+ atomicAdd_d5db1d();
+ return;
+}
+
+fn compute_main_1() {
+ let x_32 : u32 = local_invocation_index_1;
+ compute_main_inner(x_32);
+ return;
+}
+
+@compute @workgroup_size(1i, 1i, 1i)
+fn compute_main(@builtin(local_invocation_index) local_invocation_index_1_param : u32) {
+ local_invocation_index_1 = local_invocation_index_1_param;
+ compute_main_1();
+}