[llvm] [WebAssembly] Fix nondeterminism by using MapVector for pointer-keyed maps [NFC] (PR #205184)
Derek Schuff via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 23 09:31:40 PDT 2026
https://github.com/dschuff updated https://github.com/llvm/llvm-project/pull/205184
>From 9bea55d106ef7ffc1902a9268b03c0f45031784b Mon Sep 17 00:00:00 2001
From: Derek Schuff <dschuff at chromium.org>
Date: Mon, 22 Jun 2026 19:53:10 +0000
Subject: [PATCH 1/4] [WebAssembly] Fix nondeterminism by using MapVector for
pointer-keyed maps [NFC]
Several DenseMaps in the WebAssembly backend keyed by pointers were being
iterated over, potentially leading to nondeterministiccodegen (differing
try/delegate nesting, virtual register allocation, or PHI node insertion)
due to nondeterministsic pointer values.
This patch replaces these DenseMaps with MapVectors to guarantee
deterministic iteration order: - UnwindDestToTryRanges in
WebAssemblyCFGStackify.cpp - EHPadToUnwindDest in
WebAssemblyCFGStackify.cpp - EHPadToRethrows in
WebAssemblyLateEHPrepare.cpp - UnwindDestToNewPreds in
WebAssemblyLowerEmscriptenEHSjLj.cpp
Fixes: #204883
Assisted-by: Antigravity
---
llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | 5 +++--
llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp | 3 ++-
.../Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp | 3 ++-
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index 7d39e1074b026..f69c73b111891 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -29,6 +29,7 @@
#include "WebAssemblySubtarget.h"
#include "WebAssemblyTargetMachine.h"
#include "WebAssemblyUtilities.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/CodeGen/MachineDominators.h"
@@ -1837,7 +1838,7 @@ bool WebAssemblyCFGStackify::fixCallUnwindMismatches(MachineFunction &MF) {
// multiple BBs.
using TryRange = std::pair<MachineInstr *, MachineInstr *>;
// In original CFG, <unwind destination BB, a vector of try/try_table ranges>
- DenseMap<MachineBasicBlock *, SmallVector<TryRange, 4>> UnwindDestToTryRanges;
+ MapVector<MachineBasicBlock *, SmallVector<TryRange, 4>> UnwindDestToTryRanges;
// Gather possibly throwing calls (i.e., previously invokes) whose current
// unwind destination is not the same as the original CFG. (Case 1)
@@ -2203,7 +2204,7 @@ bool WebAssemblyCFGStackify::fixCatchUnwindMismatches(MachineFunction &MF) {
SmallVector<const MachineBasicBlock *, 8> EHPadStack;
// For EH pads that have catch unwind mismatches, a map of <EH pad, its
// correct unwind destination>.
- DenseMap<MachineBasicBlock *, MachineBasicBlock *> EHPadToUnwindDest;
+ MapVector<MachineBasicBlock *, MachineBasicBlock *> EHPadToUnwindDest;
for (auto &MBB : reverse(MF)) {
for (auto &MI : reverse(MBB)) {
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
index 548624e26d869..5e05aa1a1f6e9 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
@@ -15,6 +15,7 @@
#include "WebAssemblySubtarget.h"
#include "WebAssemblyTargetMachine.h"
#include "WebAssemblyUtilities.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -297,7 +298,7 @@ bool WebAssemblyLateEHPrepare::replaceFuncletReturns(MachineFunction &MF) {
bool WebAssemblyLateEHPrepare::addCatchRefsAndThrowRefs(MachineFunction &MF) {
const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
auto &MRI = MF.getRegInfo();
- DenseMap<MachineBasicBlock *, SmallVector<MachineInstr *, 2>> EHPadToRethrows;
+ MapVector<MachineBasicBlock *, SmallVector<MachineInstr *, 2>> EHPadToRethrows;
// Create a map of <EH pad, a vector of RETHROWs rethrowing its exception>
for (auto &MBB : MF)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
index 51b71ba646b42..dd75e226509e2 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
@@ -263,6 +263,7 @@
#include "WebAssembly.h"
#include "WebAssemblyTargetMachine.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/WasmEHInfo.h"
@@ -1745,7 +1746,7 @@ void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForWasmSjLj(
}
}
- SmallDenseMap<BasicBlock *, SmallSetVector<BasicBlock *, 4>, 4>
+ MapVector<BasicBlock *, SmallSetVector<BasicBlock *, 4>>
UnwindDestToNewPreds;
for (auto *CI : LongjmpableCalls) {
// Even if the callee function has attribute 'nounwind', which is true for
>From e77a07a2db812d9ab63c7fbd5919974f538a291f Mon Sep 17 00:00:00 2001
From: Derek Schuff <dschuff at chromium.org>
Date: Mon, 22 Jun 2026 21:33:17 +0000
Subject: [PATCH 2/4] clang-format
---
llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | 3 ++-
llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp | 3 ++-
.../Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp | 3 +--
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index f69c73b111891..7e12b0861116e 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -1838,7 +1838,8 @@ bool WebAssemblyCFGStackify::fixCallUnwindMismatches(MachineFunction &MF) {
// multiple BBs.
using TryRange = std::pair<MachineInstr *, MachineInstr *>;
// In original CFG, <unwind destination BB, a vector of try/try_table ranges>
- MapVector<MachineBasicBlock *, SmallVector<TryRange, 4>> UnwindDestToTryRanges;
+ MapVector<MachineBasicBlock *, SmallVector<TryRange, 4>>
+ UnwindDestToTryRanges;
// Gather possibly throwing calls (i.e., previously invokes) whose current
// unwind destination is not the same as the original CFG. (Case 1)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
index 5e05aa1a1f6e9..56f74dce630df 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
@@ -298,7 +298,8 @@ bool WebAssemblyLateEHPrepare::replaceFuncletReturns(MachineFunction &MF) {
bool WebAssemblyLateEHPrepare::addCatchRefsAndThrowRefs(MachineFunction &MF) {
const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
auto &MRI = MF.getRegInfo();
- MapVector<MachineBasicBlock *, SmallVector<MachineInstr *, 2>> EHPadToRethrows;
+ MapVector<MachineBasicBlock *, SmallVector<MachineInstr *, 2>>
+ EHPadToRethrows;
// Create a map of <EH pad, a vector of RETHROWs rethrowing its exception>
for (auto &MBB : MF)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
index dd75e226509e2..e294ae7025af6 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
@@ -1746,8 +1746,7 @@ void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForWasmSjLj(
}
}
- MapVector<BasicBlock *, SmallSetVector<BasicBlock *, 4>>
- UnwindDestToNewPreds;
+ MapVector<BasicBlock *, SmallSetVector<BasicBlock *, 4>> UnwindDestToNewPreds;
for (auto *CI : LongjmpableCalls) {
// Even if the callee function has attribute 'nounwind', which is true for
// all C functions, it can longjmp, which means it can throw a Wasm
>From 7385b669ba0e79b7275db32da227b8842aade793 Mon Sep 17 00:00:00 2001
From: Derek Schuff <dschuff at chromium.org>
Date: Mon, 22 Jun 2026 21:54:12 +0000
Subject: [PATCH 3/4] use SmallMapVector
---
.../lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
index e294ae7025af6..9a2f658091946 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
@@ -1746,7 +1746,7 @@ void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForWasmSjLj(
}
}
- MapVector<BasicBlock *, SmallSetVector<BasicBlock *, 4>> UnwindDestToNewPreds;
+ SmallMapVector<BasicBlock *, SmallSetVector<BasicBlock *, 4>, 4> UnwindDestToNewPreds;
for (auto *CI : LongjmpableCalls) {
// Even if the callee function has attribute 'nounwind', which is true for
// all C functions, it can longjmp, which means it can throw a Wasm
>From a3c491b9ce3e6a16a01b704078da6bb72decbde7 Mon Sep 17 00:00:00 2001
From: Derek Schuff <dschuff at chromium.org>
Date: Tue, 23 Jun 2026 16:31:25 +0000
Subject: [PATCH 4/4] format
---
.../Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
index 9a2f658091946..8c5917fab90a2 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
@@ -1746,7 +1746,8 @@ void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForWasmSjLj(
}
}
- SmallMapVector<BasicBlock *, SmallSetVector<BasicBlock *, 4>, 4> UnwindDestToNewPreds;
+ SmallMapVector<BasicBlock *, SmallSetVector<BasicBlock *, 4>, 4>
+ UnwindDestToNewPreds;
for (auto *CI : LongjmpableCalls) {
// Even if the callee function has attribute 'nounwind', which is true for
// all C functions, it can longjmp, which means it can throw a Wasm
More information about the llvm-commits
mailing list