mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-21 02:39:11 +00:00
tint/utils: Add TINT_LIKELY / TINT_UNLIKELY macros
Emits branch prediction hints. Give unlikely hints about where we call TINT_ICE. Change-Id: Ied5bc3d7c8b3a838e96e5a0a64156048f90411c6 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/116875 Commit-Queue: Ben Clayton <bclayton@google.com> Auto-Submit: 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
2915fadce4
commit
884f95258d
@@ -218,7 +218,7 @@ struct ArrayLengthFromUniform::State {
|
||||
// arrayLength(&struct_var.array_member)
|
||||
// arrayLength(&array_var)
|
||||
auto* param = call_expr->args[0]->As<ast::UnaryOpExpression>();
|
||||
if (!param || param->op != ast::UnaryOp::kAddressOf) {
|
||||
if (TINT_UNLIKELY(!param || param->op != ast::UnaryOp::kAddressOf)) {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "expected form of arrayLength argument to be &array_var or "
|
||||
"&struct_var.array_member";
|
||||
@@ -229,7 +229,7 @@ struct ArrayLengthFromUniform::State {
|
||||
storage_buffer_expr = accessor->structure;
|
||||
}
|
||||
auto* storage_buffer_sem = sem.Get<sem::VariableUser>(storage_buffer_expr);
|
||||
if (!storage_buffer_sem) {
|
||||
if (TINT_UNLIKELY(!storage_buffer_sem)) {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "expected form of arrayLength argument to be &array_var or "
|
||||
"&struct_var.array_member";
|
||||
@@ -238,7 +238,7 @@ struct ArrayLengthFromUniform::State {
|
||||
|
||||
// Get the index to use for the buffer size array.
|
||||
auto* var = tint::As<sem::GlobalVariable>(storage_buffer_sem->Variable());
|
||||
if (!var) {
|
||||
if (TINT_UNLIKELY(!var)) {
|
||||
TINT_ICE(Transform, b.Diagnostics()) << "storage buffer is not a global variable";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -480,7 +480,7 @@ struct BuiltinPolyfill::State {
|
||||
uint32_t width = WidthOf(ty);
|
||||
|
||||
// Currently in WGSL parameters of insertBits must be i32, u32, vecN<i32> or vecN<u32>
|
||||
if (!type::Type::DeepestElementOf(ty)->IsAnyOf<type::I32, type::U32>()) {
|
||||
if (TINT_UNLIKELY(((!type::Type::DeepestElementOf(ty)->IsAnyOf<type::I32, type::U32>())))) {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "insertBits polyfill only support i32, u32, and vector of i32 or u32, got "
|
||||
<< b.FriendlyName(ty);
|
||||
|
||||
@@ -152,7 +152,7 @@ Transform::ApplyResult CalculateArrayLength::Apply(const Program* src,
|
||||
// arrayLength(&array_var)
|
||||
auto* arg = call_expr->args[0];
|
||||
auto* address_of = arg->As<ast::UnaryOpExpression>();
|
||||
if (!address_of || address_of->op != ast::UnaryOp::kAddressOf) {
|
||||
if (TINT_UNLIKELY(!address_of || address_of->op != ast::UnaryOp::kAddressOf)) {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "arrayLength() expected address-of, got " << arg->TypeInfo().name;
|
||||
}
|
||||
@@ -161,7 +161,7 @@ Transform::ApplyResult CalculateArrayLength::Apply(const Program* src,
|
||||
storage_buffer_expr = accessor->structure;
|
||||
}
|
||||
auto* storage_buffer_sem = sem.Get<sem::VariableUser>(storage_buffer_expr);
|
||||
if (!storage_buffer_sem) {
|
||||
if (TINT_UNLIKELY(!storage_buffer_sem)) {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "expected form of arrayLength argument to be &array_var or "
|
||||
"&struct_var.array_member";
|
||||
@@ -213,7 +213,7 @@ Transform::ApplyResult CalculateArrayLength::Apply(const Program* src,
|
||||
},
|
||||
[&](const type::Array* arr) { return arr; });
|
||||
|
||||
if (!array_type) {
|
||||
if (TINT_UNLIKELY(!array_type)) {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "expected form of arrayLength argument to be "
|
||||
"&array_var or &struct_var.array_member";
|
||||
|
||||
@@ -354,7 +354,7 @@ struct CanonicalizeEntryPointIO::State {
|
||||
// list to pass them through to the inner function.
|
||||
utils::Vector<const ast::Expression*, 8> inner_struct_values;
|
||||
for (auto* member : str->Members()) {
|
||||
if (member->Type()->Is<sem::Struct>()) {
|
||||
if (TINT_UNLIKELY(member->Type()->Is<sem::Struct>())) {
|
||||
TINT_ICE(Transform, ctx.dst->Diagnostics()) << "nested IO struct";
|
||||
continue;
|
||||
}
|
||||
@@ -383,7 +383,7 @@ struct CanonicalizeEntryPointIO::State {
|
||||
bool do_interpolate = func_ast->PipelineStage() != ast::PipelineStage::kFragment;
|
||||
if (auto* str = inner_ret_type->As<sem::Struct>()) {
|
||||
for (auto* member : str->Members()) {
|
||||
if (member->Type()->Is<sem::Struct>()) {
|
||||
if (TINT_UNLIKELY(member->Type()->Is<sem::Struct>())) {
|
||||
TINT_ICE(Transform, ctx.dst->Diagnostics()) << "nested IO struct";
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ Transform::ApplyResult ClampFragDepth::Apply(const Program* src, const DataMap&,
|
||||
// Abort on any use of push constants in the module.
|
||||
for (auto* global : src->AST().GlobalVariables()) {
|
||||
if (auto* var = global->As<ast::Var>()) {
|
||||
if (var->declared_address_space == ast::AddressSpace::kPushConstant) {
|
||||
if (TINT_UNLIKELY(var->declared_address_space == ast::AddressSpace::kPushConstant)) {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "ClampFragDepth doesn't know how to handle module that already use push "
|
||||
"constants.";
|
||||
|
||||
@@ -503,7 +503,7 @@ struct DecomposeMemoryAccess::State {
|
||||
auto* i = b.Var(b.Symbols().New("i"), b.Expr(0_u));
|
||||
auto* for_init = b.Decl(i);
|
||||
auto arr_cnt = arr_ty->ConstantCount();
|
||||
if (!arr_cnt) {
|
||||
if (TINT_UNLIKELY(!arr_cnt)) {
|
||||
// Non-constant counts should not be possible:
|
||||
// * Override-expression counts can only be applied to workgroup arrays, and
|
||||
// this method only handles storage and uniform.
|
||||
@@ -607,7 +607,7 @@ struct DecomposeMemoryAccess::State {
|
||||
auto* i = b.Var(b.Symbols().New("i"), b.Expr(0_u));
|
||||
auto* for_init = b.Decl(i);
|
||||
auto arr_cnt = arr_ty->ConstantCount();
|
||||
if (!arr_cnt) {
|
||||
if (TINT_UNLIKELY(!arr_cnt)) {
|
||||
// Non-constant counts should not be possible:
|
||||
// * Override-expression counts can only be applied to workgroup
|
||||
// arrays, and this method only handles storage and uniform.
|
||||
@@ -700,7 +700,7 @@ struct DecomposeMemoryAccess::State {
|
||||
}
|
||||
|
||||
auto* atomic = IntrinsicAtomicFor(ctx.dst, op, el_ty);
|
||||
if (atomic == nullptr) {
|
||||
if (TINT_UNLIKELY(!atomic)) {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "IntrinsicAtomicFor() returned nullptr for op " << op << " and type "
|
||||
<< el_ty->TypeInfo().name;
|
||||
|
||||
@@ -1097,7 +1097,8 @@ struct DirectVariableAccess::State {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto* member = std::get_if<Symbol>(&op)) {
|
||||
auto* member = std::get_if<Symbol>(&op);
|
||||
if (TINT_LIKELY(member)) {
|
||||
ss << sym.NameFor(*member);
|
||||
continue;
|
||||
}
|
||||
@@ -1145,7 +1146,8 @@ struct DirectVariableAccess::State {
|
||||
return b.IndexAccessor(expr, idx);
|
||||
}
|
||||
|
||||
if (auto* member = std::get_if<Symbol>(&access)) {
|
||||
auto* member = std::get_if<Symbol>(&access);
|
||||
if (TINT_LIKELY(member)) {
|
||||
/// The access is a member access.
|
||||
return b.MemberAccessor(expr, ctx.Clone(*member));
|
||||
}
|
||||
|
||||
@@ -187,24 +187,27 @@ struct LocalizeStructArrayAssignment::State {
|
||||
std::pair<const type::Type*, ast::AddressSpace> GetOriginatingTypeAndAddressSpace(
|
||||
const ast::AssignmentStatement* assign_stmt) {
|
||||
auto* root_ident = src->Sem().Get(assign_stmt->lhs)->RootIdentifier();
|
||||
if (!root_ident) {
|
||||
if (TINT_UNLIKELY(!root_ident)) {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "Unable to determine originating variable for lhs of assignment "
|
||||
"statement";
|
||||
return {};
|
||||
}
|
||||
|
||||
auto* type = root_ident->Type();
|
||||
if (auto* ref = type->As<type::Reference>()) {
|
||||
return {ref->StoreType(), ref->AddressSpace()};
|
||||
} else if (auto* ptr = type->As<type::Pointer>()) {
|
||||
return {ptr->StoreType(), ptr->AddressSpace()};
|
||||
}
|
||||
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "Expecting to find variable of type pointer or reference on lhs "
|
||||
"of assignment statement";
|
||||
return {};
|
||||
return Switch(
|
||||
root_ident->Type(), //
|
||||
[&](const type::Reference* ref) {
|
||||
return std::make_pair(ref->StoreType(), ref->AddressSpace());
|
||||
},
|
||||
[&](const type::Pointer* ptr) {
|
||||
return std::make_pair(ptr->StoreType(), ptr->AddressSpace());
|
||||
},
|
||||
[&](Default) {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "Expecting to find variable of type pointer or reference on lhs "
|
||||
"of assignment statement";
|
||||
return std::pair<const type::Type*, ast::AddressSpace>{};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -402,7 +402,7 @@ struct MultiplanarExternalTexture::State {
|
||||
NewBindingSymbols syms) {
|
||||
const ast::Expression* plane_0_binding_param = ctx.Clone(expr->args[0]);
|
||||
|
||||
if (expr->args.Length() != 3) {
|
||||
if (TINT_UNLIKELY(expr->args.Length() != 3)) {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "expected textureSampleBaseClampToEdge call with a "
|
||||
"texture_external to have 3 parameters, found "
|
||||
@@ -447,7 +447,7 @@ struct MultiplanarExternalTexture::State {
|
||||
/// @param syms the expanded symbols to be used in the new call
|
||||
/// @returns a call expression to textureLoadExternal
|
||||
const ast::CallExpression* createTextureLoad(const sem::Call* call, NewBindingSymbols syms) {
|
||||
if (call->Arguments().Length() != 2) {
|
||||
if (TINT_UNLIKELY(call->Arguments().Length() != 2)) {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "expected textureLoad call with a texture_external to have 2 arguments, found "
|
||||
<< call->Arguments().Length() << " arguments";
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "src/tint/sem/module.h"
|
||||
#include "src/tint/sem/struct.h"
|
||||
#include "src/tint/sem/variable.h"
|
||||
#include "src/tint/utils/compiler_macros.h"
|
||||
#include "src/tint/utils/hashmap.h"
|
||||
#include "src/tint/utils/transform.h"
|
||||
|
||||
@@ -433,7 +434,7 @@ struct Std140::State {
|
||||
attrs.Push(b.create<ast::StrideAttribute>(arr->Stride()));
|
||||
}
|
||||
auto count = arr->ConstantCount();
|
||||
if (!count) {
|
||||
if (TINT_UNLIKELY(!count)) {
|
||||
// Non-constant counts should not be possible:
|
||||
// * Override-expression counts can only be applied to workgroup arrays, and
|
||||
// this method only handles types transitively used as uniform buffers.
|
||||
@@ -518,7 +519,7 @@ struct Std140::State {
|
||||
access.indices.Push(UniformVariable{});
|
||||
return Action::kStop;
|
||||
}
|
||||
if (user->Variable()->Type()->Is<type::Pointer>()) {
|
||||
if (TINT_LIKELY(user->Variable()->Type()->Is<type::Pointer>())) {
|
||||
// Found a pointer. As the root identifier is a uniform buffer variable,
|
||||
// this must be a pointer-let. Continue traversing from the let
|
||||
// initializer.
|
||||
@@ -633,7 +634,7 @@ struct Std140::State {
|
||||
[&](const sem::Struct* str) { return sym.NameFor(str->Name()); },
|
||||
[&](const type::Array* arr) {
|
||||
auto count = arr->ConstantCount();
|
||||
if (!count) {
|
||||
if (TINT_UNLIKELY(!count)) {
|
||||
// Non-constant counts should not be possible:
|
||||
// * Override-expression counts can only be applied to workgroup arrays, and
|
||||
// this method only handles types transitively used as uniform buffers.
|
||||
@@ -717,7 +718,8 @@ struct Std140::State {
|
||||
}, //
|
||||
[&](const type::Matrix* mat) {
|
||||
// Reassemble a std140 matrix from the structure of column vector members.
|
||||
if (auto std140_mat = std140_mats.Get(mat)) {
|
||||
auto std140_mat = std140_mats.Get(mat);
|
||||
if (TINT_LIKELY(std140_mat)) {
|
||||
utils::Vector<const ast::Expression*, 8> args;
|
||||
// std140 decomposed matrix. Reassemble.
|
||||
auto* mat_ty = CreateASTTypeFor(ctx, mat);
|
||||
@@ -739,7 +741,7 @@ struct Std140::State {
|
||||
auto* dst_el = b.IndexAccessor(var, i);
|
||||
auto* src_el = Convert(arr->ElemType(), b.IndexAccessor(param, i));
|
||||
auto count = arr->ConstantCount();
|
||||
if (!count) {
|
||||
if (TINT_UNLIKELY(!count)) {
|
||||
// Non-constant counts should not be possible:
|
||||
// * Override-expression counts can only be applied to workgroup arrays, and
|
||||
// this method only handles types transitively used as uniform buffers.
|
||||
|
||||
@@ -65,7 +65,7 @@ void Transform::RemoveStatement(CloneContext& ctx, const ast::Statement* stmt) {
|
||||
ctx.Remove(block->Declaration()->statements, stmt);
|
||||
return;
|
||||
}
|
||||
if (tint::Is<sem::ForLoopStatement>(sem->Parent())) {
|
||||
if (TINT_LIKELY(tint::Is<sem::ForLoopStatement>(sem->Parent()))) {
|
||||
ctx.Replace(stmt, static_cast<ast::Expression*>(nullptr));
|
||||
return;
|
||||
}
|
||||
@@ -130,11 +130,12 @@ const ast::Type* Transform::CreateASTTypeFor(CloneContext& ctx, const type::Type
|
||||
auto* count = ctx.Clone(override->expr->Declaration());
|
||||
return ctx.dst->ty.array(el, count, std::move(attrs));
|
||||
}
|
||||
if (auto count = a->ConstantCount()) {
|
||||
return ctx.dst->ty.array(el, u32(count.value()), std::move(attrs));
|
||||
auto count = a->ConstantCount();
|
||||
if (TINT_UNLIKELY(!count)) {
|
||||
TINT_ICE(Transform, ctx.dst->Diagnostics()) << type::Array::kErrExpectedConstantCount;
|
||||
return ctx.dst->ty.array(el, u32(1), std::move(attrs));
|
||||
}
|
||||
TINT_ICE(Transform, ctx.dst->Diagnostics()) << type::Array::kErrExpectedConstantCount;
|
||||
return ctx.dst->ty.array(el, u32(1), std::move(attrs));
|
||||
return ctx.dst->ty.array(el, u32(count.value()), std::move(attrs));
|
||||
}
|
||||
if (auto* s = ty->As<sem::Struct>()) {
|
||||
return ctx.dst->create<ast::TypeName>(ctx.Clone(s->Declaration()->name));
|
||||
|
||||
@@ -83,7 +83,7 @@ Transform::ApplyResult TruncateInterstageVariables::Apply(const Program* src,
|
||||
auto* func_sem = sem.Get(func_ast);
|
||||
auto* str = func_sem->ReturnType()->As<sem::Struct>();
|
||||
|
||||
if (!str) {
|
||||
if (TINT_UNLIKELY(!str)) {
|
||||
TINT_ICE(Transform, ctx.dst->Diagnostics())
|
||||
<< "Entrypoint function return type is non-struct.\n"
|
||||
<< "TruncateInterstageVariables transform needs to run after "
|
||||
|
||||
@@ -336,7 +336,8 @@ struct HoistToDeclBefore::State {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (auto* fl = parent->As<sem::ForLoopStatement>()) {
|
||||
auto* fl = parent->As<sem::ForLoopStatement>();
|
||||
if (TINT_LIKELY(fl)) {
|
||||
// Insertion point is a for-loop initializer or continuing statement.
|
||||
// These require special care.
|
||||
if (fl->Declaration()->initializer == ip) {
|
||||
@@ -349,7 +350,7 @@ struct HoistToDeclBefore::State {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fl->Declaration()->continuing == ip) {
|
||||
if (TINT_LIKELY(fl->Declaration()->continuing == ip)) {
|
||||
// Insertion point is a for-loop continuing statement.
|
||||
// For-loop needs to be decomposed to a loop.
|
||||
|
||||
|
||||
@@ -93,7 +93,8 @@ Transform::ApplyResult VectorizeMatrixConversions::Apply(const Program* src,
|
||||
}
|
||||
|
||||
// The source and destination type of a matrix conversion must have a same shape.
|
||||
if (!(src_type->rows() == dst_type->rows() && src_type->columns() == dst_type->columns())) {
|
||||
if (TINT_UNLIKELY(!(src_type->rows() == dst_type->rows() &&
|
||||
src_type->columns() == dst_type->columns()))) {
|
||||
TINT_ICE(Transform, b.Diagnostics())
|
||||
<< "source and destination matrix has different shape in matrix conversion";
|
||||
return nullptr;
|
||||
|
||||
@@ -128,7 +128,7 @@ Transform::ApplyResult VectorizeScalarMatrixInitializers::Apply(const Program* s
|
||||
return b.Call(fn, ctx.Clone(args[0]->Declaration()));
|
||||
}
|
||||
|
||||
if (args.Length() == mat_type->columns() * mat_type->rows()) {
|
||||
if (TINT_LIKELY(args.Length() == mat_type->columns() * mat_type->rows())) {
|
||||
return build_mat([&](uint32_t c, uint32_t r) {
|
||||
return ctx.Clone(args[c * mat_type->rows() + r]->Declaration());
|
||||
});
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "src/tint/ast/variable_decl_statement.h"
|
||||
#include "src/tint/program_builder.h"
|
||||
#include "src/tint/sem/variable.h"
|
||||
#include "src/tint/utils/compiler_macros.h"
|
||||
#include "src/tint/utils/map.h"
|
||||
#include "src/tint/utils/math.h"
|
||||
|
||||
@@ -766,12 +767,17 @@ struct VertexPulling::State {
|
||||
auto* sem = src->Sem().Get<sem::Parameter>(param);
|
||||
info.type = sem->Type();
|
||||
|
||||
if (!sem->Location().has_value()) {
|
||||
if (TINT_UNLIKELY(!sem->Location().has_value())) {
|
||||
TINT_ICE(Transform, b.Diagnostics()) << "Location missing value";
|
||||
return;
|
||||
}
|
||||
location_info[sem->Location().value()] = info;
|
||||
} else if (auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(param->attributes)) {
|
||||
} else {
|
||||
auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(param->attributes);
|
||||
if (TINT_UNLIKELY(!builtin)) {
|
||||
TINT_ICE(Transform, b.Diagnostics()) << "Invalid entry point parameter";
|
||||
return;
|
||||
}
|
||||
// Check for existing vertex_index and instance_index builtins.
|
||||
if (builtin->builtin == ast::BuiltinValue::kVertexIndex) {
|
||||
vertex_index_expr = [this, param]() { return b.Expr(ctx.Clone(param->symbol)); };
|
||||
@@ -779,8 +785,6 @@ struct VertexPulling::State {
|
||||
instance_index_expr = [this, param]() { return b.Expr(ctx.Clone(param->symbol)); };
|
||||
}
|
||||
new_function_parameters.Push(ctx.Clone(param));
|
||||
} else {
|
||||
TINT_ICE(Transform, b.Diagnostics()) << "Invalid entry point parameter";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -817,8 +821,12 @@ struct VertexPulling::State {
|
||||
TINT_ASSERT(Transform, sem->Location().has_value());
|
||||
location_info[sem->Location().value()] = info;
|
||||
has_locations = true;
|
||||
} else if (auto* builtin =
|
||||
ast::GetAttribute<ast::BuiltinAttribute>(member->attributes)) {
|
||||
} else {
|
||||
auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(member->attributes);
|
||||
if (TINT_UNLIKELY(!builtin)) {
|
||||
TINT_ICE(Transform, b.Diagnostics()) << "Invalid entry point parameter";
|
||||
return;
|
||||
}
|
||||
// Check for existing vertex_index and instance_index builtins.
|
||||
if (builtin->builtin == ast::BuiltinValue::kVertexIndex) {
|
||||
vertex_index_expr = member_expr;
|
||||
@@ -826,8 +834,6 @@ struct VertexPulling::State {
|
||||
instance_index_expr = member_expr;
|
||||
}
|
||||
members_to_clone.Push(member);
|
||||
} else {
|
||||
TINT_ICE(Transform, b.Diagnostics()) << "Invalid entry point parameter";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user