Skip to content

Commit 75481a7

Browse files
Use effects for indirect call expressions
1 parent 512dad6 commit 75481a7

File tree

6 files changed

+69
-172
lines changed

6 files changed

+69
-172
lines changed

src/ir/effects.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,12 @@ class EffectAnalyzer {
770770
}
771771
}
772772
void visitCallIndirect(CallIndirect* curr) {
773+
if (auto it = parent.module.typeEffects.find(curr->heapType);
774+
it != parent.module.typeEffects.end()) {
775+
parent.mergeIn(*it->second);
776+
return;
777+
}
778+
773779
parent.calls = true;
774780
if (curr->isReturn) {
775781
parent.branchesOut = true;
@@ -1040,6 +1046,14 @@ class EffectAnalyzer {
10401046
if (trapOnNull(curr->target)) {
10411047
return;
10421048
}
1049+
1050+
if (auto it =
1051+
parent.module.typeEffects.find(curr->target->type.getHeapType());
1052+
it != parent.module.typeEffects.end()) {
1053+
parent.mergeIn(*it->second);
1054+
return;
1055+
}
1056+
10431057
if (curr->isReturn) {
10441058
parent.branchesOut = true;
10451059
if (parent.features.hasExceptionHandling()) {

src/passes/GlobalEffects.cpp

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "ir/module-utils.h"
2626
#include "pass.h"
2727
#include "support/strongly_connected_components.h"
28+
#include "support/utilities.h"
2829
#include "wasm.h"
2930

3031
namespace wasm {
@@ -210,10 +211,13 @@ void mergeMaybeEffects(std::optional<EffectAnalyzer>& dest,
210211
// - Merge all of the effects of functions within the CC
211212
// - Also merge the (already computed) effects of each callee CC
212213
// - Add trap effects for potentially recursive call chains
213-
void propagateEffects(const Module& module,
214-
const PassOptions& passOptions,
215-
std::map<Function*, FuncInfo>& funcInfos,
216-
const CallGraph& callGraph) {
214+
void propagateEffects(
215+
const Module& module,
216+
const PassOptions& passOptions,
217+
std::map<Function*, FuncInfo>& funcInfos,
218+
std::unordered_map<HeapType, std::shared_ptr<const EffectAnalyzer>>&
219+
typeEffects,
220+
const CallGraph& callGraph) {
217221
// We only care about Functions that are roots, not types.
218222
// A type would be a root if a function exists with that type, but no-one
219223
// indirect calls the type.
@@ -302,12 +306,21 @@ void propagateEffects(const Module& module,
302306
}
303307

304308
// Assign each function's effects to its CC effects.
305-
for (Function* f : ccFuncs) {
306-
if (!ccEffects) {
307-
funcInfos.at(f).effects = UnknownEffects;
308-
} else {
309-
funcInfos.at(f).effects.emplace(*ccEffects);
310-
}
309+
for (auto node : cc) {
310+
std::visit(overloaded{[&](HeapType type) {
311+
if (ccEffects != UnknownEffects) {
312+
typeEffects[type] =
313+
std::make_shared<EffectAnalyzer>(*ccEffects);
314+
}
315+
},
316+
[&](Function* f) {
317+
if (!ccEffects) {
318+
funcInfos.at(f).effects = UnknownEffects;
319+
} else {
320+
funcInfos.at(f).effects.emplace(*ccEffects);
321+
}
322+
}},
323+
node);
311324
}
312325
}
313326
}
@@ -331,7 +344,8 @@ struct GenerateGlobalEffects : public Pass {
331344
auto callGraph =
332345
buildCallGraph(*module, funcInfos, getPassOptions().closedWorld);
333346

334-
propagateEffects(*module, getPassOptions(), funcInfos, callGraph);
347+
propagateEffects(
348+
*module, getPassOptions(), funcInfos, module->typeEffects, callGraph);
335349

336350
copyEffectsToFunctions(funcInfos);
337351
}

src/support/utilities.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ class Fatal {
9494
#define WASM_UNREACHABLE(msg) wasm::handle_unreachable()
9595
#endif
9696

97+
template<class... Ts> struct overloaded : Ts... {
98+
using Ts::operator()...;
99+
};
100+
97101
} // namespace wasm
98102

99103
#endif // wasm_support_utilities_h

src/wasm.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2682,6 +2682,11 @@ class Module {
26822682
std::unordered_map<HeapType, TypeNames> typeNames;
26832683
std::unordered_map<HeapType, Index> typeIndices;
26842684

2685+
// Potential effects for bodies of indirect calls to this type.
2686+
// TODO: make this into Type
2687+
std::unordered_map<HeapType, std::shared_ptr<const EffectAnalyzer>>
2688+
typeEffects;
2689+
26852690
MixedArena allocator;
26862691

26872692
private:

test/lit/passes/global-effects-closed-world-tnh.wast

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,9 @@
1313
)
1414

1515
;; CHECK: (func $calls-nop-via-nullable-ref (type $1) (param $ref (ref null $nopType))
16-
;; CHECK-NEXT: (call_ref $nopType
17-
;; CHECK-NEXT: (i32.const 1)
18-
;; CHECK-NEXT: (local.get $ref)
19-
;; CHECK-NEXT: )
16+
;; CHECK-NEXT: (nop)
2017
;; CHECK-NEXT: )
2118
(func $calls-nop-via-nullable-ref (param $ref (ref null $nopType))
2219
(call_ref $nopType (i32.const 1) (local.get $ref))
2320
)
24-
25-
;; CHECK: (func $f (type $1) (param $ref (ref null $nopType))
26-
;; CHECK-NEXT: (nop)
27-
;; CHECK-NEXT: )
28-
(func $f (param $ref (ref null $nopType))
29-
;; The only possible implementation of $nopType has no effects.
30-
;; $calls-nop-via-nullable-ref may trap from a null reference, but
31-
;; --traps-never-happen is enabled, so we're free to optimize this out.
32-
(call $calls-nop-via-nullable-ref (local.get $ref))
33-
)
3421
)

0 commit comments

Comments
 (0)