mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-21 18:59:21 +00:00
tint: Optimize sem node lookup
Add a 'NodeID' to each ast::Node which is the sequentially allocated
index of the node. Use this in sem::Info to map the AST node to the
semantic node, instead of using a std::unordered_map.
Optimised very hot code by entirely eliminating map lookups, and
dramatically reducing cache misses (lookups are usually sequentually
ordered).
Timings running
'webgpu:shader,execution,expression,call,builtin,atan2:f32:inputSource="const";vectorize="_undef_"'
with dawn/node, using SwiftShader:
Without change: 3.22647107s
With change: 3.10578879s
Bug: tint:1613
Change-Id: I22ec48d933b2e5f9da04494bff4e979e6f7b1982
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/96140
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
8d73198aca
commit
4a92a3c904
@@ -70,7 +70,8 @@ void AddSpirvBlockAttribute::Run(CloneContext& ctx, const DataMap&, DataMap&) co
|
||||
// This is a non-struct or a struct that is nested somewhere else, so we
|
||||
// need to wrap it first.
|
||||
auto* wrapper = utils::GetOrCreate(wrapper_structs, ty, [&]() {
|
||||
auto* block = ctx.dst->ASTNodes().Create<SpirvBlockAttribute>(ctx.dst->ID());
|
||||
auto* block = ctx.dst->ASTNodes().Create<SpirvBlockAttribute>(
|
||||
ctx.dst->ID(), ctx.dst->AllocateNodeID());
|
||||
auto wrapper_name = ctx.src->Symbols().NameFor(var->symbol) + "_block";
|
||||
auto* ret = ctx.dst->create<ast::Struct>(
|
||||
ctx.dst->Symbols().New(wrapper_name),
|
||||
@@ -89,7 +90,8 @@ void AddSpirvBlockAttribute::Run(CloneContext& ctx, const DataMap&, DataMap&) co
|
||||
}
|
||||
} else {
|
||||
// Add a block attribute to this struct directly.
|
||||
auto* block = ctx.dst->ASTNodes().Create<SpirvBlockAttribute>(ctx.dst->ID());
|
||||
auto* block = ctx.dst->ASTNodes().Create<SpirvBlockAttribute>(
|
||||
ctx.dst->ID(), ctx.dst->AllocateNodeID());
|
||||
ctx.InsertFront(str->Declaration()->attributes, block);
|
||||
}
|
||||
}
|
||||
@@ -97,7 +99,8 @@ void AddSpirvBlockAttribute::Run(CloneContext& ctx, const DataMap&, DataMap&) co
|
||||
ctx.Clone();
|
||||
}
|
||||
|
||||
AddSpirvBlockAttribute::SpirvBlockAttribute::SpirvBlockAttribute(ProgramID pid) : Base(pid) {}
|
||||
AddSpirvBlockAttribute::SpirvBlockAttribute::SpirvBlockAttribute(ProgramID pid, ast::NodeID nid)
|
||||
: Base(pid, nid) {}
|
||||
AddSpirvBlockAttribute::SpirvBlockAttribute::~SpirvBlockAttribute() = default;
|
||||
std::string AddSpirvBlockAttribute::SpirvBlockAttribute::InternalName() const {
|
||||
return "spirv_block";
|
||||
@@ -105,7 +108,8 @@ std::string AddSpirvBlockAttribute::SpirvBlockAttribute::InternalName() const {
|
||||
|
||||
const AddSpirvBlockAttribute::SpirvBlockAttribute*
|
||||
AddSpirvBlockAttribute::SpirvBlockAttribute::Clone(CloneContext* ctx) const {
|
||||
return ctx->dst->ASTNodes().Create<AddSpirvBlockAttribute::SpirvBlockAttribute>(ctx->dst->ID());
|
||||
return ctx->dst->ASTNodes().Create<AddSpirvBlockAttribute::SpirvBlockAttribute>(
|
||||
ctx->dst->ID(), ctx->dst->AllocateNodeID());
|
||||
}
|
||||
|
||||
} // namespace tint::transform
|
||||
|
||||
@@ -35,7 +35,8 @@ class AddSpirvBlockAttribute final : public Castable<AddSpirvBlockAttribute, Tra
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
explicit SpirvBlockAttribute(ProgramID program_id);
|
||||
/// @param nid the unique node identifier
|
||||
SpirvBlockAttribute(ProgramID program_id, ast::NodeID nid);
|
||||
/// Destructor
|
||||
~SpirvBlockAttribute() override;
|
||||
|
||||
|
||||
@@ -57,7 +57,8 @@ struct ArrayUsage {
|
||||
|
||||
} // namespace
|
||||
|
||||
CalculateArrayLength::BufferSizeIntrinsic::BufferSizeIntrinsic(ProgramID pid) : Base(pid) {}
|
||||
CalculateArrayLength::BufferSizeIntrinsic::BufferSizeIntrinsic(ProgramID pid, ast::NodeID nid)
|
||||
: Base(pid, nid) {}
|
||||
CalculateArrayLength::BufferSizeIntrinsic::~BufferSizeIntrinsic() = default;
|
||||
std::string CalculateArrayLength::BufferSizeIntrinsic::InternalName() const {
|
||||
return "intrinsic_buffer_size";
|
||||
@@ -65,7 +66,8 @@ std::string CalculateArrayLength::BufferSizeIntrinsic::InternalName() const {
|
||||
|
||||
const CalculateArrayLength::BufferSizeIntrinsic* CalculateArrayLength::BufferSizeIntrinsic::Clone(
|
||||
CloneContext* ctx) const {
|
||||
return ctx->dst->ASTNodes().Create<CalculateArrayLength::BufferSizeIntrinsic>(ctx->dst->ID());
|
||||
return ctx->dst->ASTNodes().Create<CalculateArrayLength::BufferSizeIntrinsic>(
|
||||
ctx->dst->ID(), ctx->dst->AllocateNodeID());
|
||||
}
|
||||
|
||||
CalculateArrayLength::CalculateArrayLength() = default;
|
||||
@@ -109,7 +111,8 @@ void CalculateArrayLength::Run(CloneContext& ctx, const DataMap&, DataMap&) cons
|
||||
},
|
||||
ctx.dst->ty.void_(), nullptr,
|
||||
ast::AttributeList{
|
||||
ctx.dst->ASTNodes().Create<BufferSizeIntrinsic>(ctx.dst->ID()),
|
||||
ctx.dst->ASTNodes().Create<BufferSizeIntrinsic>(ctx.dst->ID(),
|
||||
ctx.dst->AllocateNodeID()),
|
||||
},
|
||||
ast::AttributeList{}));
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ class CalculateArrayLength final : public Castable<CalculateArrayLength, Transfo
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
explicit BufferSizeIntrinsic(ProgramID program_id);
|
||||
/// @param nid the unique node identifier
|
||||
BufferSizeIntrinsic(ProgramID program_id, ast::NodeID nid);
|
||||
/// Destructor
|
||||
~BufferSizeIntrinsic() override;
|
||||
|
||||
|
||||
@@ -202,7 +202,8 @@ DecomposeMemoryAccess::Intrinsic* IntrinsicLoadFor(ProgramBuilder* builder,
|
||||
return nullptr;
|
||||
}
|
||||
return builder->ASTNodes().Create<DecomposeMemoryAccess::Intrinsic>(
|
||||
builder->ID(), DecomposeMemoryAccess::Intrinsic::Op::kLoad, storage_class, type);
|
||||
builder->ID(), builder->AllocateNodeID(), DecomposeMemoryAccess::Intrinsic::Op::kLoad,
|
||||
storage_class, type);
|
||||
}
|
||||
|
||||
/// @returns a DecomposeMemoryAccess::Intrinsic attribute that can be applied
|
||||
@@ -215,7 +216,8 @@ DecomposeMemoryAccess::Intrinsic* IntrinsicStoreFor(ProgramBuilder* builder,
|
||||
return nullptr;
|
||||
}
|
||||
return builder->ASTNodes().Create<DecomposeMemoryAccess::Intrinsic>(
|
||||
builder->ID(), DecomposeMemoryAccess::Intrinsic::Op::kStore, storage_class, type);
|
||||
builder->ID(), builder->AllocateNodeID(), DecomposeMemoryAccess::Intrinsic::Op::kStore,
|
||||
storage_class, type);
|
||||
}
|
||||
|
||||
/// @returns a DecomposeMemoryAccess::Intrinsic attribute that can be applied
|
||||
@@ -270,7 +272,7 @@ DecomposeMemoryAccess::Intrinsic* IntrinsicAtomicFor(ProgramBuilder* builder,
|
||||
return nullptr;
|
||||
}
|
||||
return builder->ASTNodes().Create<DecomposeMemoryAccess::Intrinsic>(
|
||||
builder->ID(), op, ast::StorageClass::kStorage, type);
|
||||
builder->ID(), builder->AllocateNodeID(), op, ast::StorageClass::kStorage, type);
|
||||
}
|
||||
|
||||
/// BufferAccess describes a single storage or uniform buffer access
|
||||
@@ -681,8 +683,12 @@ struct DecomposeMemoryAccess::State {
|
||||
}
|
||||
};
|
||||
|
||||
DecomposeMemoryAccess::Intrinsic::Intrinsic(ProgramID pid, Op o, ast::StorageClass sc, DataType ty)
|
||||
: Base(pid), op(o), storage_class(sc), type(ty) {}
|
||||
DecomposeMemoryAccess::Intrinsic::Intrinsic(ProgramID pid,
|
||||
ast::NodeID nid,
|
||||
Op o,
|
||||
ast::StorageClass sc,
|
||||
DataType ty)
|
||||
: Base(pid, nid), op(o), storage_class(sc), type(ty) {}
|
||||
DecomposeMemoryAccess::Intrinsic::~Intrinsic() = default;
|
||||
std::string DecomposeMemoryAccess::Intrinsic::InternalName() const {
|
||||
std::stringstream ss;
|
||||
@@ -771,8 +777,8 @@ std::string DecomposeMemoryAccess::Intrinsic::InternalName() const {
|
||||
|
||||
const DecomposeMemoryAccess::Intrinsic* DecomposeMemoryAccess::Intrinsic::Clone(
|
||||
CloneContext* ctx) const {
|
||||
return ctx->dst->ASTNodes().Create<DecomposeMemoryAccess::Intrinsic>(ctx->dst->ID(), op,
|
||||
storage_class, type);
|
||||
return ctx->dst->ASTNodes().Create<DecomposeMemoryAccess::Intrinsic>(
|
||||
ctx->dst->ID(), ctx->dst->AllocateNodeID(), op, storage_class, type);
|
||||
}
|
||||
|
||||
bool DecomposeMemoryAccess::Intrinsic::IsAtomic() const {
|
||||
|
||||
@@ -72,11 +72,12 @@ class DecomposeMemoryAccess final : public Castable<DecomposeMemoryAccess, Trans
|
||||
};
|
||||
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param nid the unique node identifier
|
||||
/// @param o the op of the intrinsic
|
||||
/// @param sc the storage class of the buffer
|
||||
/// @param ty the data type of the intrinsic
|
||||
Intrinsic(ProgramID program_id, Op o, ast::StorageClass sc, DataType ty);
|
||||
Intrinsic(ProgramID pid, ast::NodeID nid, Op o, ast::StorageClass sc, DataType ty);
|
||||
/// Destructor
|
||||
~Intrinsic() override;
|
||||
|
||||
|
||||
@@ -273,14 +273,16 @@ struct SpirvAtomic::State {
|
||||
SpirvAtomic::SpirvAtomic() = default;
|
||||
SpirvAtomic::~SpirvAtomic() = default;
|
||||
|
||||
SpirvAtomic::Stub::Stub(ProgramID pid, sem::BuiltinType b) : Base(pid), builtin(b) {}
|
||||
SpirvAtomic::Stub::Stub(ProgramID pid, ast::NodeID nid, sem::BuiltinType b)
|
||||
: Base(pid, nid), 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);
|
||||
return ctx->dst->ASTNodes().Create<SpirvAtomic::Stub>(ctx->dst->ID(),
|
||||
ctx->dst->AllocateNodeID(), builtin);
|
||||
}
|
||||
|
||||
bool SpirvAtomic::ShouldRun(const Program* program, const DataMap&) const {
|
||||
|
||||
@@ -43,9 +43,10 @@ class SpirvAtomic final : public Castable<SpirvAtomic, Transform> {
|
||||
/// 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 pid the identifier of the program that owns this node
|
||||
/// @param nid the unique node identifier
|
||||
/// @param builtin the atomic builtin this stub represents
|
||||
Stub(ProgramID program_id, sem::BuiltinType builtin);
|
||||
Stub(ProgramID pid, ast::NodeID nid, sem::BuiltinType builtin);
|
||||
/// Destructor
|
||||
~Stub() override;
|
||||
|
||||
|
||||
@@ -49,14 +49,14 @@ class SpirvAtomicTest : public TransformTest {
|
||||
b.Param("p1", b.ty.u32()),
|
||||
},
|
||||
b.ty.u32(), {b.Return(0_u)},
|
||||
{b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), a)});
|
||||
{b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), b.AllocateNodeID(), 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.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), b.AllocateNodeID(), a)});
|
||||
}
|
||||
|
||||
b.Func("stub_atomicLoad_u32",
|
||||
@@ -65,7 +65,8 @@ class SpirvAtomicTest : public TransformTest {
|
||||
},
|
||||
b.ty.u32(), {b.Return(0_u)},
|
||||
{
|
||||
b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), sem::BuiltinType::kAtomicLoad),
|
||||
b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), b.AllocateNodeID(),
|
||||
sem::BuiltinType::kAtomicLoad),
|
||||
});
|
||||
b.Func("stub_atomicLoad_i32",
|
||||
{
|
||||
@@ -73,7 +74,8 @@ class SpirvAtomicTest : public TransformTest {
|
||||
},
|
||||
b.ty.i32(), {b.Return(0_i)},
|
||||
{
|
||||
b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), sem::BuiltinType::kAtomicLoad),
|
||||
b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), b.AllocateNodeID(),
|
||||
sem::BuiltinType::kAtomicLoad),
|
||||
});
|
||||
|
||||
b.Func("stub_atomicStore_u32",
|
||||
@@ -83,7 +85,8 @@ class SpirvAtomicTest : public TransformTest {
|
||||
},
|
||||
b.ty.void_(), {},
|
||||
{
|
||||
b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), sem::BuiltinType::kAtomicStore),
|
||||
b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), b.AllocateNodeID(),
|
||||
sem::BuiltinType::kAtomicStore),
|
||||
});
|
||||
b.Func("stub_atomicStore_i32",
|
||||
{
|
||||
@@ -92,7 +95,8 @@ class SpirvAtomicTest : public TransformTest {
|
||||
},
|
||||
b.ty.void_(), {},
|
||||
{
|
||||
b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), sem::BuiltinType::kAtomicStore),
|
||||
b.ASTNodes().Create<SpirvAtomic::Stub>(b.ID(), b.AllocateNodeID(),
|
||||
sem::BuiltinType::kAtomicStore),
|
||||
});
|
||||
|
||||
b.Func("stub_atomic_compare_exchange_weak_u32",
|
||||
@@ -104,14 +108,14 @@ class SpirvAtomicTest : public TransformTest {
|
||||
b.ty.u32(), {b.Return(0_u)},
|
||||
{
|
||||
b.ASTNodes().Create<SpirvAtomic::Stub>(
|
||||
b.ID(), sem::BuiltinType::kAtomicCompareExchangeWeak),
|
||||
b.ID(), b.AllocateNodeID(), 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),
|
||||
b.ID(), b.AllocateNodeID(), sem::BuiltinType::kAtomicCompareExchangeWeak),
|
||||
});
|
||||
|
||||
// Keep this pointer alive after Transform() returns
|
||||
|
||||
Reference in New Issue
Block a user