Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/ir/LocalGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,12 +426,12 @@ struct LocalGraphFlower
// Ensure empty entries for each set of this index, to mark them as
// computed.
for (auto* set : setsByIndex[index]) {
setInfluences[set];
setInfluences.try_emplace(set);
}

// Also ensure |set| itself, that we were originally asked about. It may be
// in unreachable code, which means it is not listed in setsByIndex.
setInfluences[set];
setInfluences.try_emplace(set);

// Apply the info from the gets to the sets.
for (auto* get : getsByIndex[index]) {
Expand Down
2 changes: 1 addition & 1 deletion src/ir/module-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ struct ParallelFunctionAnalysis {
// Fill in the map as we operate on it in parallel (each function to its own
// entry).
for (auto& func : wasm.functions) {
map[func.get()];
map.insert({func.get(), {}});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why insert instead of try_emplace here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right I wanted to mention that. It's because map is actually an instance of wasm::InsertOrderedMap, (https://github.com/WebAssembly/binaryen/blob/main/src/support/insert_ordered.h#L92) and doesn't have try_emplace. So the other option would be to just fix that instead.

}

doAnalysis(work);
Expand Down
2 changes: 1 addition & 1 deletion src/ir/struct-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ struct FunctionStructValuesMap
// Initialize the data for each function in preparation for parallel
// computation.
for (auto& func : wasm.functions) {
(*this)[func.get()];
this->try_emplace(func.get());
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/ir/type-updating.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ struct TypeUpdater
} else {
BranchUtils::operateOnScopeNameUses(curr, [&](Name& name) {
// ensure info exists, discoverBreaks can then fill it
blockInfos[name];
blockInfos.try_emplace(name);
});
}
// add a break to the info, for break and switch
Expand Down
4 changes: 2 additions & 2 deletions src/passes/DeadArgumentElimination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,10 @@ struct DAE : public Pass {
// Ensure all entries exist so the parallel threads don't modify the data
// structure.
for (auto& func : module->functions) {
infoMap[func->name];
infoMap.try_emplace(func->name);
}
// The null name represents module-level code (not in a function).
infoMap[Name()];
infoMap.try_emplace(Name());

numFunctions = module->functions.size();

Expand Down
4 changes: 2 additions & 2 deletions src/passes/Inlining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1344,7 +1344,7 @@ struct Inlining : public Pass {
// fill in info, as we operate on it in parallel (each function to its own
// entry)
for (auto& func : module->functions) {
infos[func->name];
infos.try_emplace(func->name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These will definitely insert (the map is empty before), so perhaps emplace would be faster than try_emplace..? I admit I don't know if this would matter though.

The same might happen in a few other places, but this one is especially clear-cut (we clear the map right before the loop).

Copy link
Member Author

@dschuff dschuff Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I thought about that. The other difference between emplace and try_emplace is that the value is constructed with std::piecewise_construct, and that actually matters, for reasons I don't 100% understand. For example, this spot. Here's the error if you try to use emplace here:

[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/new_allocator.h:191:23: error: no matching constructor for initialization of 'std::pair<const wasm::Name, wasm::(anonymous namespace)::FunctionInfo>'
[build]   191 |         { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
[build]       |                              ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/alloc_traits.h:575:8: note: in instantiation of function template specialization 'std::__new_allocator<std::__detail::_Hash_node<std::pair<const wasm::Name, wasm::(anonymous namespace)::FunctionInfo>, true>>::construct<std::pair<const wasm::Name, wasm::(anonymous namespace)::FunctionInfo>, wasm::Name &>' requested here
[build]   575 |           __a.construct(__p, std::forward<_Args>(__args)...);
[build]       |               ^
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/hashtable_policy.h:2030:27: note: in instantiation of function template specialization 'std::allocator_traits<std::allocator<std::__detail::_Hash_node<std::pair<const wasm::Name, wasm::(anonymous namespace)::FunctionInfo>, true>>>::construct<std::pair<const wasm::Name, wasm::(anonymous namespace)::FunctionInfo>, wasm::Name &>' requested here
[build]  2030 |             __node_alloc_traits::construct(__alloc, __n->_M_valptr(),
[build]       |                                  ^
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/hashtable.h:312:19: note: in instantiation of function template specialization 'std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<const wasm::Name, wasm::(anonymous namespace)::FunctionInfo>, true>>>::_M_allocate_node<wasm::Name &>' requested here
[build]   312 |             _M_node(__h->_M_allocate_node(std::forward<_Args>(__args)...))
[build]       |                          ^
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/hashtable.h:2147:15: note: in instantiation of function template specialization 'std::_Hashtable<wasm::Name, std::pair<const wasm::Name, wasm::(anonymous namespace)::FunctionInfo>, std::allocator<std::pair<const wasm::Name, wasm::(anonymous namespace)::FunctionInfo>>, std::__detail::_Select1st, std::equal_to<wasm::Name>, std::hash<wasm::Name>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>>::_Scoped_node::_Scoped_node<wasm::Name &>' requested here
[build]  2147 |         _Scoped_node __node { this, std::forward<_Args>(__args)...  };
[build]       |                      ^
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/hashtable.h:1004:11: note: in instantiation of function template specialization 'std::_Hashtable<wasm::Name, std::pair<const wasm::Name, wasm::(anonymous namespace)::FunctionInfo>, std::allocator<std::pair<const wasm::Name, wasm::(anonymous namespace)::FunctionInfo>>, std::__detail::_Select1st, std::equal_to<wasm::Name>, std::hash<wasm::Name>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>>::_M_emplace<wasm::Name &>' requested here
[build]  1004 |         { return _M_emplace(__unique_keys{}, std::forward<_Args>(__args)...); }
[build]       |                  ^
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/unordered_map.h:396:16: note: in instantiation of function template specialization 'std::_Hashtable<wasm::Name, std::pair<const wasm::Name, wasm::(anonymous namespace)::FunctionInfo>, std::allocator<std::pair<const wasm::Name, wasm::(anonymous namespace)::FunctionInfo>>, std::__detail::_Select1st, std::equal_to<wasm::Name>, std::hash<wasm::Name>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>>::emplace<wasm::Name &>' requested here
[build]   396 |         { return _M_h.emplace(std::forward<_Args>(__args)...); }
[build]       |                       ^
[build] /usr/local/google/home/dschuff/s/emr/emscripten-releases/binaryen/src/passes/Inlining.cpp:1347:13: note: in instantiation of function template specialization 'std::unordered_map<wasm::Name, wasm::(anonymous namespace)::FunctionInfo>::emplace<wasm::Name &>' requested here
[build]  1347 |       infos.emplace(func->name);
[build]       |             ^
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:294:17: note: candidate constructor not viable: no known conversion from 'wasm::Name' to 'const pair<const Name, FunctionInfo>' for 1st argument
[build]   294 |       constexpr pair(const pair&) = default;    ///< Copy constructor
[build]       |                 ^    ~~~~~~~~~~~
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:779:12: note: candidate template ignored: could not match 'pair<_U1, _U2>' against 'wasm::Name'
[build]   779 |         constexpr pair(const pair<_U1, _U2>& __p)
[build]       |                   ^
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:789:21: note: candidate template ignored: could not match 'pair<_U1, _U2>' against 'wasm::Name'
[build]   789 |         explicit constexpr pair(const pair<_U1, _U2>& __p)
[build]       |                            ^
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:902:12: note: candidate template ignored: could not match 'pair<_U1, _U2>' against 'wasm::Name'
[build]   902 |         constexpr pair(pair<_U1, _U2>&& __p)
[build]       |                   ^
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:913:21: note: candidate template ignored: could not match 'pair<_U1, _U2>' against 'wasm::Name'
[build]   913 |         explicit constexpr pair(pair<_U1, _U2>&& __p)
[build]       |                            ^
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:725:17: note: candidate constructor template not viable: requires 0 arguments, but 1 was provided
[build]   725 |       constexpr pair()
[build]       |                 ^
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:737:26: note: candidate constructor template not viable: requires 0 arguments, but 1 was provided
[build]   737 |       explicit constexpr pair()
[build]       |                          ^
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:752:17: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
[build]   752 |       constexpr pair(const _T1& __a, const _T2& __b)
[build]       |                 ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:762:26: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
[build]   762 |       explicit constexpr pair(const _T1& __a, const _T2& __b)
[build]       |                          ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:830:2: note: candidate constructor template not viable: requires at least 2 arguments, but 1 was provided
[build]   830 |         pair(_U1&& __x, __zero_as_null_pointer_constant, ...)
[build]       |         ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:843:2: note: candidate constructor template not viable: requires at least 2 arguments, but 1 was provided
[build]   843 |         pair(_U1&& __x, __zero_as_null_pointer_constant, ...)
[build]       |         ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:856:2: note: candidate constructor template not viable: requires at least 2 arguments, but 1 was provided
[build]   856 |         pair(__zero_as_null_pointer_constant, _U2&& __y, ...)
[build]       |         ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:869:2: note: candidate constructor template not viable: requires at least 2 arguments, but 1 was provided
[build]   869 |         pair(__zero_as_null_pointer_constant, _U2&& __y, ...)
[build]       |         ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:881:12: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
[build]   881 |         constexpr pair(_U1&& __x, _U2&& __y)
[build]       |                   ^    ~~~~~~~~~~~~~~~~~~~~
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:891:21: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
[build]   891 |         explicit constexpr pair(_U1&& __x, _U2&& __y)
[build]       |                            ^    ~~~~~~~~~~~~~~~~~~~~
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:299:2: note: candidate constructor template not viable: requires 3 arguments, but 1 was provided
[build]   299 |         pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
[build]       |         ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_pair.h:335:2: note: candidate constructor template not viable: requires 4 arguments, but 1 was provided
[build]   335 |         pair(tuple<_Args1...>&, tuple<_Args2...>&,
[build]       |         ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build]   336 |              _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>);
[build]       |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Copy link
Member Author

@dschuff dschuff Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I think it's because emplace forwards all of the arguments to the constructor of the underlying pair (e.g. std::pair<const wasm::Name, wasm::(anonymous namespace)::FunctionInfo>, and we are passing just the key, but a std::pair can't be constructed from just the first element. However try_emplace takes its first argument explicitly as the key, and forwards the rest of its arguments (none in this case) to construct the value. So it default-constructs the value, and creates the pair from the explicit key and the default-constructed value, and succeeds.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, sounds good.

lgtm

}
{
FunctionInfoScanner scanner(infos);
Expand Down Expand Up @@ -1388,7 +1388,7 @@ struct Inlining : public Pass {
// without iterator invalidation.
std::vector<Name> funcNames;
for (auto& func : module->functions) {
state.actionsForFunction[func->name];
state.actionsForFunction.try_emplace(func->name);
funcNames.push_back(func->name);
}

Expand Down
2 changes: 1 addition & 1 deletion src/passes/OnceReduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ struct OnceReduction : public Pass {
// Initialize all the items in the new data structure that will be
// populated.
for (auto& func : module->functions) {
optInfo.newOnceGlobalsSetInFuncs[func->name];
optInfo.newOnceGlobalsSetInFuncs.try_emplace(func->name);
}

Optimizer(optInfo).run(getPassRunner(), module);
Expand Down
2 changes: 1 addition & 1 deletion src/passes/ReorderFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ struct ReorderFunctions : public Pass {
// fill in info, as we operate on it in parallel (each function to its own
// entry)
for (auto& func : module->functions) {
counts[func->name];
counts.try_emplace(func->name, 0);
}
// find counts on function calls
CallCountScanner(&counts).run(getPassRunner(), module);
Expand Down
2 changes: 1 addition & 1 deletion src/passes/ReorderGlobals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ struct ReorderGlobals : public Pass {
AtomicNameCountMap atomicCounts;
// Fill in info, as we'll operate on it in parallel.
for (auto& global : globals) {
atomicCounts[global->name];
atomicCounts.try_emplace(global->name, 0);
}

// Count uses.
Expand Down
4 changes: 2 additions & 2 deletions src/wasm/wasm-validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ struct FunctionValidator : public WalkerPass<PostWalker<FunctionValidator>> {
static void visitPreBlock(FunctionValidator* self, Expression** currp) {
auto* curr = (*currp)->cast<Block>();
if (curr->name.is()) {
self->breakTypes[curr->name];
self->breakTypes.try_emplace(curr->name);
}
}

Expand All @@ -309,7 +309,7 @@ struct FunctionValidator : public WalkerPass<PostWalker<FunctionValidator>> {
static void visitPreLoop(FunctionValidator* self, Expression** currp) {
auto* curr = (*currp)->cast<Loop>();
if (curr->name.is()) {
self->breakTypes[curr->name];
self->breakTypes.try_emplace(curr->name);
}
}

Expand Down
Loading