[spirv-reader][ir] Convert load/store usages of atomics
With the atomic types changed, we need to update any load/store of the
original SPIR-V value to the atomic equivalents.
Bug: 404501988
Change-Id: Idc48fa529bbf593a5a5ffda0693fe0ba355712e3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/236954
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/spirv/reader/lower/atomics.cc b/src/tint/lang/spirv/reader/lower/atomics.cc
index 23fe305..8b25e2b 100644
--- a/src/tint/lang/spirv/reader/lower/atomics.cc
+++ b/src/tint/lang/spirv/reader/lower/atomics.cc
@@ -58,8 +58,14 @@
/// The `ir::Value`s to be converted to atomics
Vector<core::ir::Value*, 8> values_to_convert_{};
+ /// The `ir::Values`s which have had their types changed, they then need to have their
+ /// loads/stores updated to match. This maps to the root FunctionParam or Var for each atomic.
+ Hashset<core::ir::Value*, 8> values_to_fix_usages_{};
+
/// The `ir::Value`s which have been converted
Hashset<core::ir::Value*, 8> converted_{};
+ /// The `ir::Value`s which have had their usages updated
+ Hashset<core::ir::Value*, 8> usages_updated_{};
struct ForkedStruct {
const core::type::Struct* src_struct = nullptr;
@@ -264,14 +270,19 @@
auto* atomic_ty = AtomicTypeFor(val, orig_ty);
res->SetType(atomic_ty);
- tint::Switch( //
- res->Instruction(), //
+ tint::Switch(
+ res->Instruction(),
[&](core::ir::Access* a) {
CheckForStructForking(a);
values_to_convert_.Push(a->Object());
- }, //
- [&](core::ir::Let* l) { values_to_convert_.Push(l->Value()); }, //
- [&](core::ir::Var*) {}, //
+ },
+ [&](core::ir::Let* l) { values_to_convert_.Push(l->Value()); },
+ [&](core::ir::Var* v) {
+ auto* var_res = v->Result();
+ if (usages_updated_.Add(var_res)) {
+ ConvertUsages(var_res);
+ }
+ },
TINT_ICE_ON_NO_MATCH);
},
[&](core::ir::FunctionParam* param) {
@@ -279,6 +290,10 @@
auto* atomic_ty = AtomicTypeFor(val, orig_ty);
param->SetType(atomic_ty);
+ if (usages_updated_.Add(param)) {
+ ConvertUsages(param);
+ }
+
for (auto& usage : param->Function()->UsagesUnsorted()) {
if (usage->instruction->Is<core::ir::Return>()) {
continue;
@@ -292,6 +307,28 @@
TINT_ICE_ON_NO_MATCH);
}
+ void ConvertUsages(core::ir::Value* val) {
+ val->ForEachUseUnsorted([&](const core::ir::Usage& usage) {
+ auto* inst = usage.instruction;
+
+ tint::Switch( //
+ inst,
+ [&](core::ir::Load* ld) {
+ b.InsertBefore(ld, [&] {
+ b.CallWithResult(ld->DetachResult(), core::BuiltinFn::kAtomicLoad,
+ ld->From());
+ });
+ ld->Destroy();
+ },
+ [&](core::ir::Store* st) {
+ b.InsertBefore(st, [&] {
+ b.Call(ty.void_(), core::BuiltinFn::kAtomicStore, st->To(), st->From());
+ });
+ st->Destroy();
+ });
+ });
+ }
+
void CheckForStructForking(core::ir::Access* access) {
auto* cur_ty = access->Object()->Type()->UnwrapPtr();
for (auto* idx : access->Indices()) {
diff --git a/src/tint/lang/spirv/reader/lower/atomics_test.cc b/src/tint/lang/spirv/reader/lower/atomics_test.cc
index aef1ce2..3a163d4 100644
--- a/src/tint/lang/spirv/reader/lower/atomics_test.cc
+++ b/src/tint/lang/spirv/reader/lower/atomics_test.cc
@@ -1973,7 +1973,7 @@
ASSERT_EQ(expect, str());
}
-TEST_F(SpirvReader_AtomicsTest, DISABLED_ReplaceAssignsAndDecls_Scalar) {
+TEST_F(SpirvReader_AtomicsTest, ReplaceAssignsAndDecls_Scalar) {
auto* f = b.ComputeFunction("main");
core::ir::Var* wg = nullptr;
@@ -2013,7 +2013,22 @@
Run(Atomics);
auto* expect = R"(
-UNIMPLEMENTED
+$B1: { # root
+ %wg:ptr<workgroup, atomic<u32>, read_write> = var undef
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+ $B2: {
+ %b:ptr<function, u32, read_write> = var undef
+ %4:u32 = atomicAdd %wg, 0u
+ %5:void = atomicStore %wg, 0u
+ %6:u32 = atomicLoad %wg
+ %7:u32 = let %6
+ %8:u32 = atomicLoad %wg
+ store %b, %8
+ ret
+ }
+}
)";
ASSERT_EQ(expect, str());
}