From 884f95258d50845d4ea28e901599750099040c8c Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Thu, 12 Jan 2023 22:52:57 +0000 Subject: [PATCH] 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 Auto-Submit: Ben Clayton Kokoro: Kokoro Reviewed-by: Dan Sinclair --- src/tint/ast/module.cc | 2 +- src/tint/ast/traverse_expressions.h | 4 +- src/tint/clone_context.h | 17 +- src/tint/inspector/inspector.cc | 2 +- src/tint/program_builder.cc | 3 +- src/tint/reader/wgsl/parser_impl.cc | 8 +- src/tint/resolver/const_eval.cc | 6 +- src/tint/resolver/dependency_graph.cc | 10 +- src/tint/resolver/intrinsic_table.cc | 2 +- src/tint/resolver/resolver.cc | 21 +- src/tint/resolver/sem_helper.h | 2 +- src/tint/resolver/validator.cc | 11 +- .../transform/array_length_from_uniform.cc | 6 +- src/tint/transform/builtin_polyfill.cc | 2 +- src/tint/transform/calculate_array_length.cc | 6 +- .../transform/canonicalize_entry_point_io.cc | 4 +- src/tint/transform/clamp_frag_depth.cc | 2 +- src/tint/transform/decompose_memory_access.cc | 6 +- src/tint/transform/direct_variable_access.cc | 6 +- .../localize_struct_array_assignment.cc | 27 +-- .../transform/multiplanar_external_texture.cc | 4 +- src/tint/transform/std140.cc | 12 +- src/tint/transform/transform.cc | 11 +- .../truncate_interstage_variables.cc | 2 +- .../transform/utils/hoist_to_decl_before.cc | 5 +- .../transform/vectorize_matrix_conversions.cc | 3 +- .../vectorize_scalar_matrix_initializers.cc | 2 +- src/tint/transform/vertex_pulling.cc | 22 +- src/tint/utils/compiler_macros.h | 12 ++ src/tint/writer/glsl/generator_impl.cc | 115 +++++----- src/tint/writer/hlsl/generator_impl.cc | 33 +-- src/tint/writer/msl/generator_impl.cc | 29 +-- src/tint/writer/spirv/builder.cc | 198 +++++++++--------- src/tint/writer/spirv/builder.h | 2 +- src/tint/writer/text_generator.cc | 4 +- src/tint/writer/wgsl/generator_impl.cc | 2 +- 36 files changed, 321 insertions(+), 282 deletions(-) diff --git a/src/tint/ast/module.cc b/src/tint/ast/module.cc index 3faab6c56e..50039960e1 100644 --- a/src/tint/ast/module.cc +++ b/src/tint/ast/module.cc @@ -134,7 +134,7 @@ void Module::Copy(CloneContext* ctx, const Module* src) { enables_.Clear(); for (auto* decl : global_declarations_) { - if (!decl) { + if (TINT_UNLIKELY(!decl)) { TINT_ICE(AST, ctx->dst->Diagnostics()) << "src global declaration was nullptr"; continue; } diff --git a/src/tint/ast/traverse_expressions.h b/src/tint/ast/traverse_expressions.h index bcf0bfde1c..3b3b9ba0a4 100644 --- a/src/tint/ast/traverse_expressions.h +++ b/src/tint/ast/traverse_expressions.h @@ -25,6 +25,7 @@ #include "src/tint/ast/member_accessor_expression.h" #include "src/tint/ast/phony_expression.h" #include "src/tint/ast/unary_op_expression.h" +#include "src/tint/utils/compiler_macros.h" #include "src/tint/utils/reverse.h" #include "src/tint/utils/vector.h" @@ -147,7 +148,8 @@ bool TraverseExpressions(const ast::Expression* root, diag::List& diags, CALLBAC return true; }, [&](Default) { - if (expr->IsAnyOf()) { + if (TINT_LIKELY((expr->IsAnyOf()))) { return true; // Leaf expression } TINT_ICE(AST, diags) << "unhandled expression type: " << expr->TypeInfo().name; diff --git a/src/tint/clone_context.h b/src/tint/clone_context.h index 508932aa03..1ec34224e7 100644 --- a/src/tint/clone_context.h +++ b/src/tint/clone_context.h @@ -26,6 +26,7 @@ #include "src/tint/program_id.h" #include "src/tint/symbol.h" #include "src/tint/traits.h" +#include "src/tint/utils/compiler_macros.h" #include "src/tint/utils/hashmap.h" #include "src/tint/utils/hashset.h" #include "src/tint/utils/vector.h" @@ -300,8 +301,9 @@ class CloneContext { using TPtr = traits::ParameterType; using T = typename std::remove_pointer::type; for (auto& transform : transforms_) { - if (transform.typeinfo->Is(&TypeInfo::Of()) || - TypeInfo::Of().Is(transform.typeinfo)) { + bool already_registered = transform.typeinfo->Is(&TypeInfo::Of()) || + TypeInfo::Of().Is(transform.typeinfo); + if (TINT_UNLIKELY(already_registered)) { TINT_ICE(Clone, Diagnostics()) << "ReplaceAll() called with a handler for type " << TypeInfo::Of().name << " that is already handled by a handler for type " @@ -326,7 +328,7 @@ class CloneContext { /// register a SymbolTransform more than once will result in an ICE. /// @returns this CloneContext so calls can be chained CloneContext& ReplaceAll(const SymbolTransform& replacer) { - if (symbol_transform_) { + if (TINT_UNLIKELY(symbol_transform_)) { TINT_ICE(Clone, Diagnostics()) << "ReplaceAll(const SymbolTransform&) called " "multiple times on the same CloneContext"; return *this; @@ -383,7 +385,7 @@ class CloneContext { template CloneContext& Remove(const utils::Vector& vector, OBJECT* object) { TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, object); - if (std::find(vector.begin(), vector.end(), object) == vector.end()) { + if (TINT_UNLIKELY((std::find(vector.begin(), vector.end(), object) == vector.end()))) { TINT_ICE(Clone, Diagnostics()) << "CloneContext::Remove() vector does not contain object"; return *this; @@ -450,7 +452,7 @@ class CloneContext { const OBJECT* object) { TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, before); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, object); - if (std::find(vector.begin(), vector.end(), before) == vector.end()) { + if (TINT_UNLIKELY((std::find(vector.begin(), vector.end(), before) == vector.end()))) { TINT_ICE(Clone, Diagnostics()) << "CloneContext::InsertBefore() vector does not contain before"; return *this; @@ -492,7 +494,7 @@ class CloneContext { const OBJECT* object) { TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, after); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, object); - if (std::find(vector.begin(), vector.end(), after) == vector.end()) { + if (TINT_UNLIKELY((std::find(vector.begin(), vector.end(), after) == vector.end()))) { TINT_ICE(Clone, Diagnostics()) << "CloneContext::InsertAfter() vector does not contain after"; return *this; @@ -583,7 +585,8 @@ class CloneContext { if (obj == nullptr) { return nullptr; } - if (const TO* cast = obj->template As()) { + const TO* cast = obj->template As(); + if (TINT_LIKELY(cast)) { return cast; } CheckedCastFailure(obj, TypeInfo::Of()); diff --git a/src/tint/inspector/inspector.cc b/src/tint/inspector/inspector.cc index 75c4863c73..e69c3b5bde 100644 --- a/src/tint/inspector/inspector.cc +++ b/src/tint/inspector/inspector.cc @@ -887,7 +887,7 @@ void Inspector::GenerateSamplerTargets() { template void Inspector::GetOriginatingResources(std::array exprs, F&& callback) { - if (!program_->IsValid()) { + if (TINT_UNLIKELY(!program_->IsValid())) { TINT_ICE(Inspector, diagnostics_) << "attempting to get originating resources in invalid program"; return; diff --git a/src/tint/program_builder.cc b/src/tint/program_builder.cc index a219de3156..9c2019e2e2 100644 --- a/src/tint/program_builder.cc +++ b/src/tint/program_builder.cc @@ -21,6 +21,7 @@ #include "src/tint/demangler.h" #include "src/tint/sem/expression.h" #include "src/tint/sem/variable.h" +#include "src/tint/utils/compiler_macros.h" using namespace tint::number_suffixes; // NOLINT @@ -89,7 +90,7 @@ void ProgramBuilder::MarkAsMoved() { } void ProgramBuilder::AssertNotMoved() const { - if (moved_) { + if (TINT_UNLIKELY(moved_)) { TINT_ICE(ProgramBuilder, const_cast(this)->diagnostics_) << "Attempting to use ProgramBuilder after it has been moved"; } diff --git a/src/tint/reader/wgsl/parser_impl.cc b/src/tint/reader/wgsl/parser_impl.cc index 3e03bab6f7..d35a87e826 100644 --- a/src/tint/reader/wgsl/parser_impl.cc +++ b/src/tint/reader/wgsl/parser_impl.cc @@ -296,15 +296,15 @@ bool ParserImpl::peek_is(Token::Type tok, size_t idx) { } void ParserImpl::split_token(Token::Type lhs, Token::Type rhs) { - if (next_token_idx_ == 0) { + if (TINT_UNLIKELY(next_token_idx_ == 0)) { TINT_ICE(Reader, builder_.Diagnostics()) << "attempt to update placeholder at beginning of tokens"; } - if (next_token_idx_ >= tokens_.size()) { + if (TINT_UNLIKELY(next_token_idx_ >= tokens_.size())) { TINT_ICE(Reader, builder_.Diagnostics()) << "attempt to update placeholder past end of tokens"; } - if (!tokens_[next_token_idx_].IsPlaceholder()) { + if (TINT_UNLIKELY(!tokens_[next_token_idx_].IsPlaceholder())) { TINT_ICE(Reader, builder_.Diagnostics()) << "attempt to update non-placeholder token"; } tokens_[next_token_idx_ - 1].SetType(lhs); @@ -3852,7 +3852,7 @@ T ParserImpl::sync(Token::Type tok, F&& body) { auto result = body(); --parse_depth_; - if (sync_tokens_.back() != tok) { + if (TINT_UNLIKELY(sync_tokens_.back() != tok)) { TINT_ICE(Reader, builder_.Diagnostics()) << "sync_tokens is out of sync"; } sync_tokens_.pop_back(); diff --git a/src/tint/resolver/const_eval.cc b/src/tint/resolver/const_eval.cc index b52f4aa1a2..7fa435c40d 100644 --- a/src/tint/resolver/const_eval.cc +++ b/src/tint/resolver/const_eval.cc @@ -332,7 +332,7 @@ ConstEval::Result CompositeConvert(const constant::Composite* composite, std::function target_el_ty; if (auto* str = target_ty->As()) { - if (str->Members().Length() != composite->elements.Length()) { + if (TINT_UNLIKELY(str->Members().Length() != composite->elements.Length())) { TINT_ICE(Resolver, builder.Diagnostics()) << "const-eval conversion of structure has mismatched element counts"; return utils::Failure; @@ -1837,7 +1837,7 @@ ConstEval::Result ConstEval::OpShiftLeft(const type::Type* ty, return Dispatch_ia_iu32(create, c0, c1); }; - if (!type::Type::DeepestElementOf(args[1]->Type())->Is()) { + if (TINT_UNLIKELY(!type::Type::DeepestElementOf(args[1]->Type())->Is())) { TINT_ICE(Resolver, builder.Diagnostics()) << "Element type of rhs of ShiftLeft must be a u32"; return utils::Failure; @@ -1901,7 +1901,7 @@ ConstEval::Result ConstEval::OpShiftRight(const type::Type* ty, return Dispatch_ia_iu32(create, c0, c1); }; - if (!type::Type::DeepestElementOf(args[1]->Type())->Is()) { + if (TINT_UNLIKELY(!type::Type::DeepestElementOf(args[1]->Type())->Is())) { TINT_ICE(Resolver, builder.Diagnostics()) << "Element type of rhs of ShiftLeft must be a u32"; return utils::Failure; diff --git a/src/tint/resolver/dependency_graph.cc b/src/tint/resolver/dependency_graph.cc index 9d2e0da088..a3803058a4 100644 --- a/src/tint/resolver/dependency_graph.cc +++ b/src/tint/resolver/dependency_graph.cc @@ -71,6 +71,7 @@ #include "src/tint/symbol_table.h" #include "src/tint/type/short_name.h" #include "src/tint/utils/block_allocator.h" +#include "src/tint/utils/compiler_macros.h" #include "src/tint/utils/defer.h" #include "src/tint/utils/map.h" #include "src/tint/utils/scoped_assignment.h" @@ -319,8 +320,8 @@ class DependencyScanner { }, [&](const ast::StaticAssert* assertion) { TraverseExpression(assertion->condition); }, [&](Default) { - if (!stmt->IsAnyOf()) { + if (TINT_UNLIKELY((!stmt->IsAnyOf()))) { UnhandledNode(diagnostics_, stmt); } }); @@ -697,7 +698,7 @@ struct DependencyAnalysis { sorted_.Add(global->node); - if (!stack.IsEmpty()) { + if (TINT_UNLIKELY(!stack.IsEmpty())) { // Each stack.push() must have a corresponding stack.pop_back(). TINT_ICE(Resolver, diagnostics_) << "stack not empty after returning from TraverseDependencies()"; @@ -709,7 +710,8 @@ struct DependencyAnalysis { /// of global `from` depending on `to`. /// @note will raise an ICE if the edge is not found. DependencyInfo DepInfoFor(const Global* from, const Global* to) const { - if (auto info = dependency_edges_.Find(DependencyEdge{from, to})) { + auto info = dependency_edges_.Find(DependencyEdge{from, to}); + if (TINT_LIKELY(info)) { return *info; } TINT_ICE(Resolver, diagnostics_) diff --git a/src/tint/resolver/intrinsic_table.cc b/src/tint/resolver/intrinsic_table.cc index c311597b58..4b507b8db4 100644 --- a/src/tint/resolver/intrinsic_table.cc +++ b/src/tint/resolver/intrinsic_table.cc @@ -1546,7 +1546,7 @@ IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic, Any any; return_type = Match(match.templates, match.overload, indices, earliest_eval_stage).Type(&any); - if (!return_type) { + if (TINT_UNLIKELY(!return_type)) { TINT_ICE(Resolver, builder.Diagnostics()) << "MatchState.Match() returned null"; return {}; } diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc index 19b870ed62..48c310f5df 100644 --- a/src/tint/resolver/resolver.cc +++ b/src/tint/resolver/resolver.cc @@ -83,6 +83,7 @@ #include "src/tint/type/sampler.h" #include "src/tint/type/short_name.h" #include "src/tint/type/storage_texture.h" +#include "src/tint/utils/compiler_macros.h" #include "src/tint/utils/defer.h" #include "src/tint/utils/math.h" #include "src/tint/utils/reverse.h" @@ -130,7 +131,7 @@ bool Resolver::Resolve() { bool result = ResolveInternal(); - if (!result && !diagnostics_.contains_errors()) { + if (TINT_UNLIKELY(!result && !diagnostics_.contains_errors())) { TINT_ICE(Resolver, diagnostics_) << "resolving failed, but no error was raised"; return false; } @@ -188,7 +189,7 @@ bool Resolver::ResolveInternal() { bool result = true; for (auto* node : builder_->ASTNodes().Objects()) { - if (!marked_[node->node_id.value]) { + if (TINT_UNLIKELY(!marked_[node->node_id.value])) { TINT_ICE(Resolver, diagnostics_) << "AST node '" << node->TypeInfo().name << "' was not reached by the resolver\n" << "At: " << node->source << "\n" @@ -884,7 +885,7 @@ bool Resolver::AllocateOverridableConstantIds() { void Resolver::SetShadows() { for (auto it : dependencies_.shadows) { CastableBase* b = sem_.Get(it.value); - if (!b) { + if (TINT_UNLIKELY(!b)) { TINT_ICE(Resolver, builder_->Diagnostics()) << "AST node '" << it.value->TypeInfo().name << "' had no semantic info\n" << "At: " << it.value->source << "\n" @@ -1073,7 +1074,7 @@ sem::Function* Resolver::Function(const ast::Function* decl) { if (decl->body) { Mark(decl->body); - if (current_compound_statement_) { + if (TINT_UNLIKELY(current_compound_statement_)) { TINT_ICE(Resolver, diagnostics_) << "Resolver::Function() called with a current compound statement"; return nullptr; @@ -1804,7 +1805,7 @@ const sem::Expression* Resolver::Materialize(const sem::Expression* expr, const constant::Value* materialized_val = nullptr; if (!skip_const_eval_.Contains(decl)) { auto expr_val = expr->ConstantValue(); - if (!expr_val) { + if (TINT_UNLIKELY(!expr_val)) { TINT_ICE(Resolver, builder_->Diagnostics()) << decl->source << "Materialize(" << decl->TypeInfo().name << ") called on expression with no constant value"; @@ -1817,7 +1818,7 @@ const sem::Expression* Resolver::Materialize(const sem::Expression* expr, return nullptr; } materialized_val = val.Get(); - if (!materialized_val) { + if (TINT_UNLIKELY(!materialized_val)) { TINT_ICE(Resolver, builder_->Diagnostics()) << decl->source << "ConvertValue(" << builder_->FriendlyName(expr_val->Type()) << " -> " << builder_->FriendlyName(concrete_ty) << ") returned invalid value"; @@ -2488,7 +2489,7 @@ void Resolver::CollectTextureSamplerPairs(const sem::Builtin* builtin, // Collect a texture/sampler pair for this builtin. const auto& signature = builtin->Signature(); int texture_index = signature.IndexOf(sem::ParameterUsage::kTexture); - if (texture_index == -1) { + if (TINT_UNLIKELY(texture_index == -1)) { TINT_ICE(Resolver, diagnostics_) << "texture builtin without texture parameter"; } if (auto* user = @@ -3445,7 +3446,7 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) { AddError(msg.str(), str->source); return nullptr; } - if (struct_align > std::numeric_limits::max()) { + if (TINT_UNLIKELY(struct_align > std::numeric_limits::max())) { TINT_ICE(Resolver, diagnostics_) << "calculated struct stride exceeds uint32"; return nullptr; } @@ -3842,12 +3843,12 @@ SEM* Resolver::StatementScope(const ast::Statement* ast, SEM* sem, F&& callback) } bool Resolver::Mark(const ast::Node* node) { - if (node == nullptr) { + if (TINT_UNLIKELY(node == nullptr)) { TINT_ICE(Resolver, diagnostics_) << "Resolver::Mark() called with nullptr"; return false; } auto marked_bit_ref = marked_[node->node_id.value]; - if (!marked_bit_ref) { + if (TINT_LIKELY(!marked_bit_ref)) { marked_bit_ref = true; return true; } diff --git a/src/tint/resolver/sem_helper.h b/src/tint/resolver/sem_helper.h index 8e4a5b634c..d6a51308d8 100644 --- a/src/tint/resolver/sem_helper.h +++ b/src/tint/resolver/sem_helper.h @@ -40,7 +40,7 @@ class SemHelper { auto* Get(const AST_OR_TYPE* ast) const { using T = sem::Info::GetResultType; auto* sem = builder_->Sem().Get(ast); - if (!sem) { + if (TINT_UNLIKELY(!sem)) { TINT_ICE(Resolver, builder_->Diagnostics()) << "AST node '" << ast->TypeInfo().name << "' had no semantic info\n" << "At: " << ast->source << "\n" diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc index b199eb0d37..6c05df2399 100644 --- a/src/tint/resolver/validator.cc +++ b/src/tint/resolver/validator.cc @@ -1007,8 +1007,8 @@ bool Validator::Function(const sem::Function* func, ast::PipelineStage stage) co AddError("missing return at end of function", decl->source); return false; } - } else if (IsValidationEnabled(decl->attributes, - ast::DisabledValidation::kFunctionHasNoBody)) { + } else if (TINT_UNLIKELY(IsValidationEnabled( + decl->attributes, ast::DisabledValidation::kFunctionHasNoBody))) { TINT_ICE(Resolver, diagnostics_) << "Function " << symbols_.NameFor(decl->symbol) << " has no body"; } @@ -1040,7 +1040,8 @@ bool Validator::Function(const sem::Function* func, ast::PipelineStage stage) co // https://www.w3.org/TR/WGSL/#behaviors-rules // a function behavior is always one of {}, or {Next}. - if (func->Behaviors() != sem::Behaviors{} && func->Behaviors() != sem::Behavior::kNext) { + if (TINT_UNLIKELY(func->Behaviors() != sem::Behaviors{} && + func->Behaviors() != sem::Behavior::kNext)) { auto name = symbols_.NameFor(decl->symbol); TINT_ICE(Resolver, diagnostics_) << "function '" << name << "' behaviors are: " << func->Behaviors(); @@ -1111,7 +1112,7 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage) bool is_input = param_or_ret == ParamOrRetType::kParameter; - if (!location.has_value()) { + if (TINT_UNLIKELY(!location.has_value())) { TINT_ICE(Resolver, diagnostics_) << "Location has no value"; return false; } @@ -1810,7 +1811,7 @@ bool Validator::ArrayInitializer(const ast::CallExpression* ctor, return false; } - if (!c->Is()) { + if (TINT_UNLIKELY(!c->Is())) { TINT_ICE(Resolver, diagnostics_) << "Invalid ArrayCount found"; return false; } diff --git a/src/tint/transform/array_length_from_uniform.cc b/src/tint/transform/array_length_from_uniform.cc index fc59021da4..3f470fa6bb 100644 --- a/src/tint/transform/array_length_from_uniform.cc +++ b/src/tint/transform/array_length_from_uniform.cc @@ -218,7 +218,7 @@ struct ArrayLengthFromUniform::State { // arrayLength(&struct_var.array_member) // arrayLength(&array_var) auto* param = call_expr->args[0]->As(); - 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(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(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 58c39252f4..2bab40006e 100644 --- a/src/tint/transform/builtin_polyfill.cc +++ b/src/tint/transform/builtin_polyfill.cc @@ -480,7 +480,7 @@ struct BuiltinPolyfill::State { uint32_t width = WidthOf(ty); // Currently in WGSL parameters of insertBits must be i32, u32, vecN or vecN - if (!type::Type::DeepestElementOf(ty)->IsAnyOf()) { + if (TINT_UNLIKELY(((!type::Type::DeepestElementOf(ty)->IsAnyOf())))) { 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 65821c96cd..0469dc93c4 100644 --- a/src/tint/transform/calculate_array_length.cc +++ b/src/tint/transform/calculate_array_length.cc @@ -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(); - 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(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"; diff --git a/src/tint/transform/canonicalize_entry_point_io.cc b/src/tint/transform/canonicalize_entry_point_io.cc index 48e2948a1a..1afad12a86 100644 --- a/src/tint/transform/canonicalize_entry_point_io.cc +++ b/src/tint/transform/canonicalize_entry_point_io.cc @@ -354,7 +354,7 @@ struct CanonicalizeEntryPointIO::State { // list to pass them through to the inner function. utils::Vector inner_struct_values; for (auto* member : str->Members()) { - if (member->Type()->Is()) { + if (TINT_UNLIKELY(member->Type()->Is())) { 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()) { for (auto* member : str->Members()) { - if (member->Type()->Is()) { + if (TINT_UNLIKELY(member->Type()->Is())) { 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 455192593d..94deee544f 100644 --- a/src/tint/transform/clamp_frag_depth.cc +++ b/src/tint/transform/clamp_frag_depth.cc @@ -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()) { - 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 7c968753ad..e760bd29eb 100644 --- a/src/tint/transform/decompose_memory_access.cc +++ b/src/tint/transform/decompose_memory_access.cc @@ -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; diff --git a/src/tint/transform/direct_variable_access.cc b/src/tint/transform/direct_variable_access.cc index 1dbb51ee36..70479be745 100644 --- a/src/tint/transform/direct_variable_access.cc +++ b/src/tint/transform/direct_variable_access.cc @@ -1097,7 +1097,8 @@ struct DirectVariableAccess::State { continue; } - if (auto* member = std::get_if(&op)) { + auto* member = std::get_if(&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(&access)) { + auto* member = std::get_if(&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 3bf1a4109c..b389b61212 100644 --- a/src/tint/transform/localize_struct_array_assignment.cc +++ b/src/tint/transform/localize_struct_array_assignment.cc @@ -187,24 +187,27 @@ struct LocalizeStructArrayAssignment::State { std::pair 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()) { - return {ref->StoreType(), ref->AddressSpace()}; - } else if (auto* ptr = type->As()) { - 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{}; + }); } }; diff --git a/src/tint/transform/multiplanar_external_texture.cc b/src/tint/transform/multiplanar_external_texture.cc index f5770fb6a8..d81d1868eb 100644 --- a/src/tint/transform/multiplanar_external_texture.cc +++ b/src/tint/transform/multiplanar_external_texture.cc @@ -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"; diff --git a/src/tint/transform/std140.cc b/src/tint/transform/std140.cc index 0b8665a464..d8f1610c45 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 @@ struct Std140::State { attrs.Push(b.create(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()) { + if (TINT_LIKELY(user->Variable()->Type()->Is())) { // 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 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. diff --git a/src/tint/transform/transform.cc b/src/tint/transform/transform.cc index 55bb715b1c..b0c759697a 100644 --- a/src/tint/transform/transform.cc +++ b/src/tint/transform/transform.cc @@ -65,7 +65,7 @@ void Transform::RemoveStatement(CloneContext& ctx, const ast::Statement* stmt) { ctx.Remove(block->Declaration()->statements, stmt); return; } - if (tint::Is(sem->Parent())) { + if (TINT_LIKELY(tint::Is(sem->Parent()))) { ctx.Replace(stmt, static_cast(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()) { return ctx.dst->create(ctx.Clone(s->Declaration()->name)); diff --git a/src/tint/transform/truncate_interstage_variables.cc b/src/tint/transform/truncate_interstage_variables.cc index bbb27fdf92..b2d7ff1dd8 100644 --- a/src/tint/transform/truncate_interstage_variables.cc +++ b/src/tint/transform/truncate_interstage_variables.cc @@ -83,7 +83,7 @@ Transform::ApplyResult TruncateInterstageVariables::Apply(const Program* src, auto* func_sem = sem.Get(func_ast); auto* str = func_sem->ReturnType()->As(); - 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 fa18934859..5852573f47 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 @@ struct HoistToDeclBefore::State { return true; } - if (auto* fl = parent->As()) { + auto* fl = parent->As(); + 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. diff --git a/src/tint/transform/vectorize_matrix_conversions.cc b/src/tint/transform/vectorize_matrix_conversions.cc index 714e61e0fb..26f27c3640 100644 --- a/src/tint/transform/vectorize_matrix_conversions.cc +++ b/src/tint/transform/vectorize_matrix_conversions.cc @@ -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; diff --git a/src/tint/transform/vectorize_scalar_matrix_initializers.cc b/src/tint/transform/vectorize_scalar_matrix_initializers.cc index 2a3a37c778..9e989bc3f2 100644 --- a/src/tint/transform/vectorize_scalar_matrix_initializers.cc +++ b/src/tint/transform/vectorize_scalar_matrix_initializers.cc @@ -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()); }); diff --git a/src/tint/transform/vertex_pulling.cc b/src/tint/transform/vertex_pulling.cc index a5cb94a659..42dbbe376a 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 @@ struct VertexPulling::State { auto* sem = src->Sem().Get(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(param->attributes)) { + } else { + auto* builtin = ast::GetAttribute(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(member->attributes)) { + } else { + auto* builtin = ast::GetAttribute(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"; } } diff --git a/src/tint/utils/compiler_macros.h b/src/tint/utils/compiler_macros.h index 1a0404283d..087a02f732 100644 --- a/src/tint/utils/compiler_macros.h +++ b/src/tint/utils/compiler_macros.h @@ -41,6 +41,9 @@ __pragma(warning(pop)) \ TINT_REQUIRE_SEMICOLON // clang-format on + +#define TINT_UNLIKELY(x) x /* currently no-op */ +#define TINT_LIKELY(x) x /* currently no-op */ #elif defined(__clang__) //////////////////////////////////////////////////////////////////////////////// // Clang @@ -64,6 +67,9 @@ _Pragma("clang diagnostic pop") \ TINT_REQUIRE_SEMICOLON // clang-format on + +#define TINT_UNLIKELY(x) __builtin_expect(!!(x), false) +#define TINT_LIKELY(x) __builtin_expect(!!(x), true) #elif defined(__GNUC__) //////////////////////////////////////////////////////////////////////////////// // GCC @@ -87,12 +93,18 @@ _Pragma("GCC diagnostic pop") \ TINT_REQUIRE_SEMICOLON // clang-format on + +#define TINT_UNLIKELY(x) __builtin_expect(!!(x), false) +#define TINT_LIKELY(x) __builtin_expect(!!(x), true) #else //////////////////////////////////////////////////////////////////////////////// // Other //////////////////////////////////////////////////////////////////////////////// #define TINT_BEGIN_DISABLE_WARNING(name) TINT_REQUIRE_SEMICOLON #define TINT_END_DISABLE_WARNING(name) TINT_REQUIRE_SEMICOLON +#define TINT_UNLIKELY(x) x +#define TINT_LIKELY(x) x + #endif #endif // SRC_TINT_UTILS_COMPILER_MACROS_H_ diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc index bc52f15044..b5d897d89d 100644 --- a/src/tint/writer/glsl/generator_impl.cc +++ b/src/tint/writer/glsl/generator_impl.cc @@ -292,41 +292,41 @@ bool GeneratorImpl::Generate() { continue; // These are not emitted. } - if (auto* global = decl->As()) { - if (!EmitGlobalVariable(global)) { + bool ok = Switch( + decl, // + [&](const ast::Variable* global) { return EmitGlobalVariable(global); }, + [&](const ast::Struct* str) { + auto* sem = builder_.Sem().Get(str); + bool has_rt_arr = false; + if (auto* arr = sem->Members().Back()->Type()->As()) { + has_rt_arr = arr->Count()->Is(); + } + bool is_block = ast::HasAttribute( + str->attributes); + if (!has_rt_arr && !is_block) { + if (!EmitStructType(current_buffer_, sem)) { + return false; + } + } + return true; + }, + [&](const ast::Function* func) { + if (func->IsEntryPoint()) { + return EmitEntryPointFunction(func); + } + return EmitFunction(func); + }, + [&](const ast::Enable* enable) { + // Record the required extension for generating extension directive later + return RecordExtension(enable); + }, + [&](Default) { + TINT_ICE(Writer, diagnostics_) + << "unhandled module-scope declaration: " << decl->TypeInfo().name; return false; - } - } else if (auto* str = decl->As()) { - auto* sem = builder_.Sem().Get(str); - bool has_rt_arr = false; - if (auto* arr = sem->Members().Back()->Type()->As()) { - has_rt_arr = arr->Count()->Is(); - } - bool is_block = - ast::HasAttribute(str->attributes); - if (!has_rt_arr && !is_block) { - if (!EmitStructType(current_buffer_, sem)) { - return false; - } - } - } else if (auto* func = decl->As()) { - if (func->IsEntryPoint()) { - if (!EmitEntryPointFunction(func)) { - return false; - } - } else { - if (!EmitFunction(func)) { - return false; - } - } - } else if (auto* ext = decl->As()) { - // Record the required extension for generating extension directive later - if (!RecordExtension(ext)) { - return false; - } - } else { - TINT_ICE(Writer, diagnostics_) - << "unhandled module-scope declaration: " << decl->TypeInfo().name; + }); + + if (TINT_UNLIKELY(!ok)) { return false; } } @@ -493,7 +493,7 @@ bool GeneratorImpl::EmitBitwiseBoolOp(std::ostream& out, const ast::BinaryExpres // Emit operator. if (expr->op == ast::BinaryOp::kAnd) { out << " & "; - } else if (expr->op == ast::BinaryOp::kOr) { + } else if (TINT_LIKELY(expr->op == ast::BinaryOp::kOr)) { out << " | "; } else { TINT_ICE(Writer, diagnostics_) << "unexpected binary op: " << FriendlyName(expr->op); @@ -742,22 +742,17 @@ bool GeneratorImpl::EmitBreakIf(const ast::BreakIfStatement* b) { bool GeneratorImpl::EmitCall(std::ostream& out, const ast::CallExpression* expr) { auto* call = builder_.Sem().Get(expr); - auto* target = call->Target(); - - if (target->Is()) { - return EmitFunctionCall(out, call); - } - if (auto* builtin = target->As()) { - return EmitBuiltinCall(out, call, builtin); - } - if (auto* cast = target->As()) { - return EmitTypeConversion(out, call, cast); - } - if (auto* ctor = target->As()) { - return EmitTypeInitializer(out, call, ctor); - } - TINT_ICE(Writer, diagnostics_) << "unhandled call target: " << target->TypeInfo().name; - return false; + return Switch( + call->Target(), // + [&](const sem::Function*) { return EmitFunctionCall(out, call); }, + [&](const sem::Builtin* builtin) { return EmitBuiltinCall(out, call, builtin); }, + [&](const sem::TypeConversion* conv) { return EmitTypeConversion(out, call, conv); }, + [&](const sem::TypeInitializer* init) { return EmitTypeInitializer(out, call, init); }, + [&](Default) { + TINT_ICE(Writer, diagnostics_) + << "unhandled call target: " << call->Target()->TypeInfo().name; + return false; + }); } bool GeneratorImpl::EmitFunctionCall(std::ostream& out, const sem::Call* call) { @@ -1379,7 +1374,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out, }; auto* texture = arg(Usage::kTexture); - if (!texture) { + if (TINT_UNLIKELY(!texture)) { TINT_ICE(Writer, diagnostics_) << "missing texture argument"; return false; } @@ -1579,7 +1574,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out, out << ", "; auto* param_coords = arg(Usage::kCoords); - if (!param_coords) { + if (TINT_UNLIKELY(!param_coords)) { TINT_ICE(Writer, diagnostics_) << "missing coords argument"; return false; } @@ -1678,7 +1673,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out, out << "xyz"[i]; } } - if (wgsl_ret_width > glsl_ret_width) { + if (TINT_UNLIKELY(wgsl_ret_width > glsl_ret_width)) { TINT_ICE(Writer, diagnostics_) << "WGSL return width (" << wgsl_ret_width << ") is wider than GLSL return width (" << glsl_ret_width << ") for " << builtin->Type(); @@ -2028,7 +2023,7 @@ bool GeneratorImpl::EmitGlobalVariable(const ast::Variable* global) { bool GeneratorImpl::EmitUniformVariable(const ast::Var* var, const sem::Variable* sem) { auto* type = sem->Type()->UnwrapRef(); auto* str = type->As(); - if (!str) { + if (TINT_UNLIKELY(!str)) { TINT_ICE(Writer, builder_.Diagnostics()) << "storage variable must be of struct type"; return false; } @@ -2049,7 +2044,7 @@ bool GeneratorImpl::EmitUniformVariable(const ast::Var* var, const sem::Variable bool GeneratorImpl::EmitStorageVariable(const ast::Var* var, const sem::Variable* sem) { auto* type = sem->Type()->UnwrapRef(); auto* str = type->As(); - if (!str) { + if (TINT_UNLIKELY(!str)) { TINT_ICE(Writer, builder_.Diagnostics()) << "storage variable must be of struct type"; return false; } @@ -2254,7 +2249,7 @@ bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) { for (auto* var : func->params) { auto* sem = builder_.Sem().Get(var); auto* type = sem->Type(); - if (!type->Is()) { + if (TINT_UNLIKELY(!type->Is())) { // ICE likely indicates that the CanonicalizeEntryPointIO transform was // not run, or a builtin parameter was added after it was run. TINT_ICE(Writer, diagnostics_) << "Unsupported non-struct entry point parameter"; @@ -2893,7 +2888,7 @@ bool GeneratorImpl::EmitType(std::ostream& out, if (mat->rows() != mat->columns()) { out << "x" << mat->rows(); } - } else if (type->Is()) { + } else if (TINT_UNLIKELY(type->Is())) { TINT_ICE(Writer, diagnostics_) << "Attempting to emit pointer type. These should have been removed " "with the InlinePointerLets transform"; @@ -2903,7 +2898,7 @@ bool GeneratorImpl::EmitType(std::ostream& out, } else if (auto* str = type->As()) { out << StructName(str); } else if (auto* tex = type->As()) { - if (tex->Is()) { + if (TINT_UNLIKELY(tex->Is())) { TINT_ICE(Writer, diagnostics_) << "Multiplanar external texture transform was not run."; return false; } @@ -2925,7 +2920,7 @@ bool GeneratorImpl::EmitType(std::ostream& out, if (!subtype || subtype->Is()) { } else if (subtype->Is()) { out << "i"; - } else if (subtype->Is()) { + } else if (TINT_LIKELY(subtype->Is())) { out << "u"; } else { TINT_ICE(Writer, diagnostics_) << "Unsupported texture type"; diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc index fe10b2b930..d9afe1dbe7 100644 --- a/src/tint/writer/hlsl/generator_impl.cc +++ b/src/tint/writer/hlsl/generator_impl.cc @@ -69,6 +69,7 @@ #include "src/tint/type/multisampled_texture.h" #include "src/tint/type/sampled_texture.h" #include "src/tint/type/storage_texture.h" +#include "src/tint/utils/compiler_macros.h" #include "src/tint/utils/defer.h" #include "src/tint/utils/map.h" #include "src/tint/utils/scoped_assignment.h" @@ -2289,7 +2290,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out, }; auto* texture = arg(Usage::kTexture); - if (!texture) { + if (TINT_UNLIKELY(!texture)) { TINT_ICE(Writer, diagnostics_) << "missing texture argument"; return false; } @@ -2412,7 +2413,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out, } } - if (num_dimensions > 4) { + if (TINT_UNLIKELY(num_dimensions > 4)) { TINT_ICE(Writer, diagnostics_) << "Texture query builtin temporary vector has " << num_dimensions << " dimensions"; return false; @@ -2446,7 +2447,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out, pre << dims; } else { static constexpr char xyzw[] = {'x', 'y', 'z', 'w'}; - if (num_dimensions < 0 || num_dimensions > 4) { + if (TINT_UNLIKELY(num_dimensions < 0 || num_dimensions > 4)) { TINT_ICE(Writer, diagnostics_) << "vector dimensions are " << num_dimensions; return false; @@ -2553,7 +2554,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out, } auto* param_coords = arg(Usage::kCoords); - if (!param_coords) { + if (TINT_UNLIKELY(!param_coords)) { TINT_ICE(Writer, diagnostics_) << "missing coords argument"; return false; } @@ -2636,7 +2637,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out, out << "xyz"[i]; } } - if (wgsl_ret_width > hlsl_ret_width) { + if (TINT_UNLIKELY(wgsl_ret_width > hlsl_ret_width)) { TINT_ICE(Writer, diagnostics_) << "WGSL return width (" << wgsl_ret_width << ") is wider than HLSL return width (" << hlsl_ret_width << ") for " << builtin->Type(); @@ -3241,7 +3242,7 @@ bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) { for (auto* var : func->params) { auto* sem = builder_.Sem().Get(var); auto* type = sem->Type(); - if (!type->Is()) { + if (TINT_UNLIKELY(!type->Is())) { // ICE likely indicates that the CanonicalizeEntryPointIO transform was // not run, or a builtin parameter was added after it was run. TINT_ICE(Writer, diagnostics_) << "Unsupported non-struct entry point parameter"; @@ -3944,7 +3945,7 @@ bool GeneratorImpl::EmitType(std::ostream& out, const type::Type* base_type = ary; std::vector sizes; while (auto* arr = base_type->As()) { - if (arr->Count()->Is()) { + if (TINT_UNLIKELY(arr->Count()->Is())) { TINT_ICE(Writer, diagnostics_) << "runtime arrays may only exist in storage buffers, which should have " "been transformed into a ByteAddressBuffer"; @@ -4032,7 +4033,7 @@ bool GeneratorImpl::EmitType(std::ostream& out, return true; }, [&](const type::Texture* tex) { - if (tex->Is()) { + if (TINT_UNLIKELY(tex->Is())) { TINT_ICE(Writer, diagnostics_) << "Multiplanar external texture transform was not run."; return false; @@ -4075,7 +4076,7 @@ bool GeneratorImpl::EmitType(std::ostream& out, if (storage) { auto* component = image_format_to_rwtexture_type(storage->texel_format()); - if (component == nullptr) { + if (TINT_UNLIKELY(!component)) { TINT_ICE(Writer, diagnostics_) << "Unsupported StorageTexture TexelFormat: " << static_cast(storage->texel_format()); return false; @@ -4090,7 +4091,7 @@ bool GeneratorImpl::EmitType(std::ostream& out, out << "float4"; } else if (subtype->Is()) { out << "int4"; - } else if (subtype->Is()) { + } else if (TINT_LIKELY(subtype->Is())) { out << "uint4"; } else { TINT_ICE(Writer, diagnostics_) << "Unsupported multisampled texture type"; @@ -4170,7 +4171,7 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) { for (auto* attr : decl->attributes) { if (attr->Is()) { auto& pipeline_stage_uses = str->PipelineStageUses(); - if (pipeline_stage_uses.size() != 1) { + if (TINT_UNLIKELY(pipeline_stage_uses.size() != 1)) { TINT_ICE(Writer, diagnostics_) << "invalid entry point IO struct uses"; } @@ -4183,8 +4184,8 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) { } else if (pipeline_stage_uses.count( type::PipelineStageUsage::kFragmentInput)) { post += " : TEXCOORD" + std::to_string(loc); - } else if (pipeline_stage_uses.count( - type::PipelineStageUsage::kFragmentOutput)) { + } else if (TINT_LIKELY(pipeline_stage_uses.count( + type::PipelineStageUsage::kFragmentOutput))) { post += " : SV_Target" + std::to_string(loc); } else { TINT_ICE(Writer, diagnostics_) << "invalid use of location attribute"; @@ -4211,9 +4212,9 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) { // stricter and therefore provides the necessary guarantees. // See discussion here: https://github.com/gpuweb/gpuweb/issues/893 pre += "precise "; - } else if (!attr->IsAnyOf()) { + } else if (TINT_UNLIKELY((!attr->IsAnyOf()))) { TINT_ICE(Writer, diagnostics_) << "unhandled struct member attribute: " << attr->Name(); return false; diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc index fae668202b..4889d7df91 100644 --- a/src/tint/writer/msl/generator_impl.cc +++ b/src/tint/writer/msl/generator_impl.cc @@ -993,7 +993,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out, }; auto* texture = arg(Usage::kTexture)->Declaration(); - if (!texture) { + if (TINT_UNLIKELY(!texture)) { TINT_ICE(Writer, diagnostics_) << "missing texture arg"; return false; } @@ -1976,14 +1976,14 @@ bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) { // attribute have a value of zero. const uint32_t kInvalidBindingIndex = std::numeric_limits::max(); auto get_binding_index = [&](const ast::Parameter* param) -> uint32_t { - if (!param->HasBindingPoint()) { + if (TINT_UNLIKELY(!param->HasBindingPoint())) { TINT_ICE(Writer, diagnostics_) << "missing binding attributes for entry point parameter"; return kInvalidBindingIndex; } auto* param_sem = program_->Sem().Get(param); auto bp = param_sem->BindingPoint(); - if (bp.group != 0) { + if (TINT_UNLIKELY(bp.group != 0)) { TINT_ICE(Writer, diagnostics_) << "encountered non-zero resource group index (use " "BindingRemapper to fix)"; return kInvalidBindingIndex; @@ -2026,7 +2026,7 @@ bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) { } if (param->type->Is()) { out << " [[sampler(" << binding << ")]]"; - } else if (param->type->Is()) { + } else if (TINT_LIKELY(param->type->Is())) { out << " [[texture(" << binding << ")]]"; } else { TINT_ICE(Writer, diagnostics_) << "invalid handle type entry point parameter"; @@ -2038,7 +2038,8 @@ bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) { auto& allocations = workgroup_allocations_[func_name]; out << " [[threadgroup(" << allocations.size() << ")]]"; allocations.push_back(program_->Sem().Get(ptr->type)->Size()); - } else if (sc == ast::AddressSpace::kStorage || sc == ast::AddressSpace::kUniform) { + } else if (TINT_LIKELY(sc == ast::AddressSpace::kStorage || + sc == ast::AddressSpace::kUniform)) { uint32_t binding = get_binding_index(param); if (binding == kInvalidBindingIndex) { return false; @@ -2067,7 +2068,7 @@ bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) { } out << " [[" << name << "]]"; } - if (!builtin_found) { + if (TINT_UNLIKELY(!builtin_found)) { TINT_ICE(Writer, diagnostics_) << "Unsupported entry point parameter"; } } @@ -2530,7 +2531,7 @@ bool GeneratorImpl::EmitType(std::ostream& out, out << "atomic_int"; return true; } - if (atomic->Type()->Is()) { + if (TINT_LIKELY(atomic->Type()->Is())) { out << "atomic_uint"; return true; } @@ -2610,7 +2611,7 @@ bool GeneratorImpl::EmitType(std::ostream& out, return true; }, [&](const type::Texture* tex) { - if (tex->Is()) { + if (TINT_UNLIKELY(tex->Is())) { TINT_ICE(Writer, diagnostics_) << "Multiplanar external texture transform was not run."; return false; @@ -2793,7 +2794,7 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) { auto wgsl_offset = mem->Offset(); if (is_host_shareable) { - if (wgsl_offset < msl_offset) { + if (TINT_UNLIKELY(wgsl_offset < msl_offset)) { // Unimplementable layout TINT_ICE(Writer, diagnostics_) << "Structure member WGSL offset (" << wgsl_offset << ") is behind MSL offset (" << msl_offset << ")"; @@ -2837,7 +2838,7 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) { }, [&](const ast::LocationAttribute*) { auto& pipeline_stage_uses = str->PipelineStageUses(); - if (pipeline_stage_uses.size() != 1) { + if (TINT_UNLIKELY(pipeline_stage_uses.size() != 1)) { TINT_ICE(Writer, diagnostics_) << "invalid entry point IO struct uses"; return false; } @@ -2851,8 +2852,8 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) { } else if (pipeline_stage_uses.count( type::PipelineStageUsage::kFragmentInput)) { out << " [[user(locn" + std::to_string(loc) + ")]]"; - } else if (pipeline_stage_uses.count( - type::PipelineStageUsage::kFragmentOutput)) { + } else if (TINT_LIKELY(pipeline_stage_uses.count( + type::PipelineStageUsage::kFragmentOutput))) { out << " [[color(" + std::to_string(loc) + ")]]"; } else { TINT_ICE(Writer, diagnostics_) << "invalid use of location decoration"; @@ -2898,7 +2899,7 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) { if (is_host_shareable) { // Calculate new MSL offset auto size_align = MslPackedTypeSizeAndAlign(ty); - if (msl_offset % size_align.align) { + if (TINT_UNLIKELY(msl_offset % size_align.align)) { TINT_ICE(Writer, diagnostics_) << "Misaligned MSL structure member " << ty->FriendlyName(program_->Symbols()) << " " << mem_name; @@ -3167,7 +3168,7 @@ GeneratorImpl::SizeAndAlign GeneratorImpl::MslPackedTypeSizeAndAlign(const type: }, [&](const type::Array* arr) { - if (!arr->IsStrideImplicit()) { + if (TINT_UNLIKELY(!arr->IsStrideImplicit())) { TINT_ICE(Writer, diagnostics_) << "arrays with explicit strides should not exist past the SPIR-V reader"; return SizeAndAlign{}; diff --git a/src/tint/writer/spirv/builder.cc b/src/tint/writer/spirv/builder.cc index 9d1092e0b4..c252f8c562 100644 --- a/src/tint/writer/spirv/builder.cc +++ b/src/tint/writer/spirv/builder.cc @@ -45,6 +45,7 @@ #include "src/tint/type/reference.h" #include "src/tint/type/sampled_texture.h" #include "src/tint/type/vector.h" +#include "src/tint/utils/compiler_macros.h" #include "src/tint/utils/defer.h" #include "src/tint/utils/map.h" #include "src/tint/writer/append_vector.h" @@ -756,7 +757,7 @@ bool Builder::GenerateGlobalVariable(const ast::Variable* v) { } auto* sem = builder_.Sem().Get(v); - if (!sem) { + if (TINT_UNLIKELY(!sem)) { TINT_ICE(Writer, builder_.Diagnostics()) << "attempted to generate a global from a non-global variable"; return false; @@ -927,7 +928,7 @@ bool Builder::GenerateIndexAccessor(const ast::IndexAccessorExpression* expr, Ac } // If the source is a vector, we use OpVectorExtractDynamic. - if (info->source_type->Is()) { + if (TINT_LIKELY(info->source_type->Is())) { if (!push_function_inst( spv::Op::OpVectorExtractDynamic, {Operand(result_type_id), extract, Operand(info->source_id), Operand(idx_id)})) { @@ -949,125 +950,128 @@ bool Builder::GenerateMemberAccessor(const ast::MemberAccessorExpression* expr, auto* expr_sem = builder_.Sem().Get(expr)->UnwrapLoad(); auto* expr_type = expr_sem->Type(); - if (auto* access = expr_sem->As()) { - uint32_t idx = access->Member()->Index(); + return Switch( + expr_sem, // + [&](const sem::StructMemberAccess* access) { + uint32_t idx = access->Member()->Index(); - if (info->source_type->Is()) { - auto idx_id = GenerateConstantIfNeeded(ScalarConstant::U32(idx)); - if (idx_id == 0) { - return 0; - } - info->access_chain_indices.push_back(idx_id); - info->source_type = expr_type; - } else { - auto result_type_id = GenerateTypeIfNeeded(expr_type); - if (result_type_id == 0) { - return false; - } - - auto extract = result_op(); - auto extract_id = std::get(extract); - if (!push_function_inst( - spv::Op::OpCompositeExtract, - {Operand(result_type_id), extract, Operand(info->source_id), Operand(idx)})) { - return false; - } - - info->source_id = extract_id; - info->source_type = expr_type; - } - - return true; - } - - if (auto* swizzle = expr_sem->As()) { - // Single element swizzle is either an access chain or a composite extract - auto& indices = swizzle->Indices(); - if (indices.Length() == 1) { if (info->source_type->Is()) { - auto idx_id = GenerateConstantIfNeeded(ScalarConstant::U32(indices[0])); - if (idx_id == 0) { - return 0; + auto idx_id = GenerateConstantIfNeeded(ScalarConstant::U32(idx)); + if (TINT_UNLIKELY(idx_id == 0)) { + return false; } info->access_chain_indices.push_back(idx_id); + info->source_type = expr_type; } else { auto result_type_id = GenerateTypeIfNeeded(expr_type); - if (result_type_id == 0) { - return 0; + if (TINT_UNLIKELY(result_type_id == 0)) { + return false; } auto extract = result_op(); auto extract_id = std::get(extract); if (!push_function_inst(spv::Op::OpCompositeExtract, {Operand(result_type_id), extract, Operand(info->source_id), - Operand(indices[0])})) { + Operand(idx)})) { return false; } info->source_id = extract_id; info->source_type = expr_type; } + return true; - } + }, + [&](const sem::Swizzle* swizzle) { + // Single element swizzle is either an access chain or a composite extract + auto& indices = swizzle->Indices(); + if (indices.Length() == 1) { + if (info->source_type->Is()) { + auto idx_id = GenerateConstantIfNeeded(ScalarConstant::U32(indices[0])); + if (TINT_UNLIKELY(idx_id == 0)) { + return false; + } + info->access_chain_indices.push_back(idx_id); + } else { + auto result_type_id = GenerateTypeIfNeeded(expr_type); + if (TINT_UNLIKELY(result_type_id == 0)) { + return false; + } - // Store the type away as it may change if we run the access chain - auto* incoming_type = info->source_type; + auto extract = result_op(); + auto extract_id = std::get(extract); + if (!push_function_inst(spv::Op::OpCompositeExtract, + {Operand(result_type_id), extract, + Operand(info->source_id), Operand(indices[0])})) { + return false; + } - // Multi-item extract is a VectorShuffle. We have to emit any existing - // access chain data, then load the access chain and shuffle that. - if (!info->access_chain_indices.empty()) { - auto result_type_id = GenerateTypeIfNeeded(info->source_type); - if (result_type_id == 0) { - return 0; - } - auto extract = result_op(); - auto extract_id = std::get(extract); - - OperandList ops = {Operand(result_type_id), extract, Operand(info->source_id)}; - for (auto id : info->access_chain_indices) { - ops.push_back(Operand(id)); + info->source_id = extract_id; + info->source_type = expr_type; + } + return true; } - if (!push_function_inst(spv::Op::OpAccessChain, ops)) { + // Store the type away as it may change if we run the access chain + auto* incoming_type = info->source_type; + + // Multi-item extract is a VectorShuffle. We have to emit any existing + // access chain data, then load the access chain and shuffle that. + if (!info->access_chain_indices.empty()) { + auto result_type_id = GenerateTypeIfNeeded(info->source_type); + if (TINT_UNLIKELY(result_type_id == 0)) { + return false; + } + auto extract = result_op(); + auto extract_id = std::get(extract); + + OperandList ops = {Operand(result_type_id), extract, Operand(info->source_id)}; + for (auto id : info->access_chain_indices) { + ops.push_back(Operand(id)); + } + + if (!push_function_inst(spv::Op::OpAccessChain, ops)) { + return false; + } + + info->source_id = GenerateLoadIfNeeded(expr_type, extract_id); + info->source_type = expr_type->UnwrapRef(); + info->access_chain_indices.clear(); + } + + auto result_type_id = GenerateTypeIfNeeded(expr_type); + if (TINT_UNLIKELY(result_type_id == 0)) { return false; } - info->source_id = GenerateLoadIfNeeded(expr_type, extract_id); - info->source_type = expr_type->UnwrapRef(); - info->access_chain_indices.clear(); - } + auto vec_id = GenerateLoadIfNeeded(incoming_type, info->source_id); - auto result_type_id = GenerateTypeIfNeeded(expr_type); - if (result_type_id == 0) { + auto result = result_op(); + auto result_id = std::get(result); + + OperandList ops = {Operand(result_type_id), result, Operand(vec_id), Operand(vec_id)}; + + for (auto idx : indices) { + ops.push_back(Operand(idx)); + } + + if (!push_function_inst(spv::Op::OpVectorShuffle, ops)) { + return false; + } + info->source_id = result_id; + info->source_type = expr_type; + return true; + }, + [&](Default) { + TINT_ICE(Writer, builder_.Diagnostics()) + << "unhandled member index type: " << expr_sem->TypeInfo().name; return false; - } - - auto vec_id = GenerateLoadIfNeeded(incoming_type, info->source_id); - - auto result = result_op(); - auto result_id = std::get(result); - - OperandList ops = {Operand(result_type_id), result, Operand(vec_id), Operand(vec_id)}; - - for (auto idx : indices) { - ops.push_back(Operand(idx)); - } - - if (!push_function_inst(spv::Op::OpVectorShuffle, ops)) { - return false; - } - info->source_id = result_id; - info->source_type = expr_type; - return true; - } - - TINT_ICE(Writer, builder_.Diagnostics()) - << "unhandled member index type: " << expr_sem->TypeInfo().name; - return false; + }); } uint32_t Builder::GenerateAccessorExpression(const ast::Expression* expr) { - if (!expr->IsAnyOf()) { + if (TINT_UNLIKELY( + (!expr->IsAnyOf()))) { TINT_ICE(Writer, builder_.Diagnostics()) << "expression is not an accessor"; return 0; } @@ -1448,7 +1452,7 @@ uint32_t Builder::GenerateCastOrCopyOrPassthrough(const type::Type* to_type, bool is_global_init) { // This should not happen as we rely on constant folding to obviate // casts/conversions for module-scope variables - if (is_global_init) { + if (TINT_UNLIKELY(is_global_init)) { TINT_ICE(Writer, builder_.Diagnostics()) << "Module-level conversions are not supported. Conversions should " "have already been constant-folded by the FoldConstants transform."; @@ -1565,13 +1569,13 @@ uint32_t Builder::GenerateCastOrCopyOrPassthrough(const type::Type* to_type, } return result_id; - } else if (from_type->Is() && to_type->Is()) { + } else if (TINT_LIKELY(from_type->Is() && to_type->Is())) { // SPIRV does not support matrix conversion, the only valid case is matrix identity // initializer. Matrix conversion between f32 and f16 should be transformed into vector // conversions for each column vectors by VectorizeMatrixConversions. auto* from_mat = from_type->As(); auto* to_mat = to_type->As(); - if (from_mat == to_mat) { + if (TINT_LIKELY(from_mat == to_mat)) { return val_id; } TINT_ICE(Writer, builder_.Diagnostics()) @@ -2631,7 +2635,7 @@ bool Builder::GenerateTextureBuiltin(const sem::Call* call, // Generates the argument with the given usage, returning the operand ID auto gen_arg = [&](Usage usage) { auto* argument = arg(usage); - if (!argument) { + if (TINT_UNLIKELY(!argument)) { TINT_ICE(Writer, builder_.Diagnostics()) << "missing argument " << static_cast(usage); } @@ -2639,7 +2643,7 @@ bool Builder::GenerateTextureBuiltin(const sem::Call* call, }; auto* texture = arg(Usage::kTexture); - if (!texture) { + if (TINT_UNLIKELY(!texture)) { TINT_ICE(Writer, builder_.Diagnostics()) << "missing texture argument"; } @@ -3752,7 +3756,7 @@ uint32_t Builder::GenerateTypeIfNeeded(const type::Type* type) { } bool Builder::GenerateTextureType(const type::Texture* texture, const Operand& result) { - if (texture->Is()) { + if (TINT_UNLIKELY(texture->Is())) { TINT_ICE(Writer, builder_.Diagnostics()) << "Multiplanar external texture transform was not run."; return false; @@ -4008,7 +4012,7 @@ SpvBuiltIn Builder::ConvertBuiltin(ast::BuiltinValue builtin, ast::AddressSpace case ast::BuiltinValue::kPosition: if (storage == ast::AddressSpace::kIn) { return SpvBuiltInFragCoord; - } else if (storage == ast::AddressSpace::kOut) { + } else if (TINT_LIKELY(storage == ast::AddressSpace::kOut)) { return SpvBuiltInPosition; } else { TINT_ICE(Writer, builder_.Diagnostics()) << "invalid address space for builtin"; diff --git a/src/tint/writer/spirv/builder.h b/src/tint/writer/spirv/builder.h index 6ac749e883..0704074783 100644 --- a/src/tint/writer/spirv/builder.h +++ b/src/tint/writer/spirv/builder.h @@ -194,7 +194,7 @@ class Builder { /// Pushes a variable to the current function /// @param operands the variable operands void push_function_var(const OperandList& operands) { - if (functions_.empty()) { + if (TINT_UNLIKELY(functions_.empty())) { TINT_ICE(Writer, builder_.Diagnostics()) << "push_function_var() called without a function"; } diff --git a/src/tint/writer/text_generator.cc b/src/tint/writer/text_generator.cc index 3dabb5caaf..6d29844ba1 100644 --- a/src/tint/writer/text_generator.cc +++ b/src/tint/writer/text_generator.cc @@ -77,7 +77,7 @@ void TextGenerator::TextBuffer::Append(const std::string& line) { } void TextGenerator::TextBuffer::Insert(const std::string& line, size_t before, uint32_t indent) { - if (before >= lines.size()) { + if (TINT_UNLIKELY(before >= lines.size())) { diag::List d; TINT_ICE(Writer, d) << "TextBuffer::Insert() called with before >= lines.size()\n" << " before:" << before << "\n" @@ -96,7 +96,7 @@ void TextGenerator::TextBuffer::Append(const TextBuffer& tb) { } void TextGenerator::TextBuffer::Insert(const TextBuffer& tb, size_t before, uint32_t indent) { - if (before >= lines.size()) { + if (TINT_UNLIKELY(before >= lines.size())) { diag::List d; TINT_ICE(Writer, d) << "TextBuffer::Insert() called with before >= lines.size()\n" << " before:" << before << "\n" diff --git a/src/tint/writer/wgsl/generator_impl.cc b/src/tint/writer/wgsl/generator_impl.cc index cfd512b1f7..f02d96c2c9 100644 --- a/src/tint/writer/wgsl/generator_impl.cc +++ b/src/tint/writer/wgsl/generator_impl.cc @@ -224,7 +224,7 @@ bool GeneratorImpl::EmitCall(std::ostream& out, const ast::CallExpression* expr) if (!EmitExpression(out, expr->target.name)) { return false; } - } else if (expr->target.type) { + } else if (TINT_LIKELY(expr->target.type)) { if (!EmitType(out, expr->target.type)) { return false; }