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>
diff --git a/src/tint/transform/array_length_from_uniform.cc b/src/tint/transform/array_length_from_uniform.cc
index fc59021..3f470fa 100644
--- a/src/tint/transform/array_length_from_uniform.cc
+++ b/src/tint/transform/array_length_from_uniform.cc
@@ -218,7 +218,7 @@
// 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 @@
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 @@
// 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;
}
diff --git a/src/tint/transform/builtin_polyfill.cc b/src/tint/transform/builtin_polyfill.cc
index 58c3925..2bab400 100644
--- a/src/tint/transform/builtin_polyfill.cc
+++ b/src/tint/transform/builtin_polyfill.cc
@@ -480,7 +480,7 @@
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);
diff --git a/src/tint/transform/calculate_array_length.cc b/src/tint/transform/calculate_array_length.cc
index 65821c9..0469dc9 100644
--- a/src/tint/transform/calculate_array_length.cc
+++ b/src/tint/transform/calculate_array_length.cc
@@ -152,7 +152,7 @@
// 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 @@
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 @@
},
[&](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";
diff --git a/src/tint/transform/canonicalize_entry_point_io.cc b/src/tint/transform/canonicalize_entry_point_io.cc
index 48e2948..1afad12 100644
--- a/src/tint/transform/canonicalize_entry_point_io.cc
+++ b/src/tint/transform/canonicalize_entry_point_io.cc
@@ -354,7 +354,7 @@
// 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 @@
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;
}
diff --git a/src/tint/transform/clamp_frag_depth.cc b/src/tint/transform/clamp_frag_depth.cc
index 4551925..94deee5 100644
--- a/src/tint/transform/clamp_frag_depth.cc
+++ b/src/tint/transform/clamp_frag_depth.cc
@@ -89,7 +89,7 @@
// 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.";
diff --git a/src/tint/transform/decompose_memory_access.cc b/src/tint/transform/decompose_memory_access.cc
index 7c96875..e760bd2 100644
--- a/src/tint/transform/decompose_memory_access.cc
+++ b/src/tint/transform/decompose_memory_access.cc
@@ -503,7 +503,7 @@
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 @@
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 @@
}
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;
diff --git a/src/tint/transform/direct_variable_access.cc b/src/tint/transform/direct_variable_access.cc
index 1dbb51e..70479be 100644
--- a/src/tint/transform/direct_variable_access.cc
+++ b/src/tint/transform/direct_variable_access.cc
@@ -1097,7 +1097,8 @@
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 @@
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));
}
diff --git a/src/tint/transform/localize_struct_array_assignment.cc b/src/tint/transform/localize_struct_array_assignment.cc
index 3bf1a410..b389b61 100644
--- a/src/tint/transform/localize_struct_array_assignment.cc
+++ b/src/tint/transform/localize_struct_array_assignment.cc
@@ -187,24 +187,27 @@
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>{};
+ });
}
};
diff --git a/src/tint/transform/multiplanar_external_texture.cc b/src/tint/transform/multiplanar_external_texture.cc
index f5770fb..d81d186 100644
--- a/src/tint/transform/multiplanar_external_texture.cc
+++ b/src/tint/transform/multiplanar_external_texture.cc
@@ -402,7 +402,7 @@
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 @@
/// @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";
diff --git a/src/tint/transform/std140.cc b/src/tint/transform/std140.cc
index 0b8665a..d8f1610 100644
--- a/src/tint/transform/std140.cc
+++ b/src/tint/transform/std140.cc
@@ -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 @@
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 @@
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 @@
[&](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 @@
}, //
[&](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 @@
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.
diff --git a/src/tint/transform/transform.cc b/src/tint/transform/transform.cc
index 55bb715..b0c7596 100644
--- a/src/tint/transform/transform.cc
+++ b/src/tint/transform/transform.cc
@@ -65,7 +65,7 @@
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 @@
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));
diff --git a/src/tint/transform/truncate_interstage_variables.cc b/src/tint/transform/truncate_interstage_variables.cc
index bbb27fd..b2d7ff1 100644
--- a/src/tint/transform/truncate_interstage_variables.cc
+++ b/src/tint/transform/truncate_interstage_variables.cc
@@ -83,7 +83,7 @@
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 "
diff --git a/src/tint/transform/utils/hoist_to_decl_before.cc b/src/tint/transform/utils/hoist_to_decl_before.cc
index fa18934..5852573 100644
--- a/src/tint/transform/utils/hoist_to_decl_before.cc
+++ b/src/tint/transform/utils/hoist_to_decl_before.cc
@@ -336,7 +336,8 @@
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 @@
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.
diff --git a/src/tint/transform/vectorize_matrix_conversions.cc b/src/tint/transform/vectorize_matrix_conversions.cc
index 714e61e..26f27c3 100644
--- a/src/tint/transform/vectorize_matrix_conversions.cc
+++ b/src/tint/transform/vectorize_matrix_conversions.cc
@@ -93,7 +93,8 @@
}
// 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;
diff --git a/src/tint/transform/vectorize_scalar_matrix_initializers.cc b/src/tint/transform/vectorize_scalar_matrix_initializers.cc
index 2a3a37c..9e989bc 100644
--- a/src/tint/transform/vectorize_scalar_matrix_initializers.cc
+++ b/src/tint/transform/vectorize_scalar_matrix_initializers.cc
@@ -128,7 +128,7 @@
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());
});
diff --git a/src/tint/transform/vertex_pulling.cc b/src/tint/transform/vertex_pulling.cc
index a5cb94a..42dbbe3 100644
--- a/src/tint/transform/vertex_pulling.cc
+++ b/src/tint/transform/vertex_pulling.cc
@@ -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 @@
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 @@
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 @@
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 @@
instance_index_expr = member_expr;
}
members_to_clone.Push(member);
- } else {
- TINT_ICE(Transform, b.Diagnostics()) << "Invalid entry point parameter";
}
}