Skip to content

Commit e65a243

Browse files
Use effects for indirect call expressions
1 parent 35ba23c commit e65a243

6 files changed

Lines changed: 64 additions & 178 deletions

File tree

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
@@ -26,6 +26,7 @@
2626
#include "pass.h"
2727
#include "support/graph_traversal.h"
2828
#include "support/strongly_connected_components.h"
29+
#include "support/utilities.h"
2930
#include "wasm.h"
3031

3132
namespace wasm {
@@ -227,10 +228,13 @@ void mergeMaybeEffects(std::optional<EffectAnalyzer>& dest,
227228
// - Merge all of the effects of functions within the CC
228229
// - Also merge the (already computed) effects of each callee CC
229230
// - Add trap effects for potentially recursive call chains
230-
void propagateEffects(const Module& module,
231-
const PassOptions& passOptions,
232-
std::map<Function*, FuncInfo>& funcInfos,
233-
const CallGraph& callGraph) {
231+
void propagateEffects(
232+
const Module& module,
233+
const PassOptions& passOptions,
234+
std::map<Function*, FuncInfo>& funcInfos,
235+
std::unordered_map<HeapType, std::shared_ptr<const EffectAnalyzer>>&
236+
typeEffects,
237+
const CallGraph& callGraph) {
234238
// We only care about Functions that are roots, not types.
235239
// A type would be a root if a function exists with that type, but no-one
236240
// indirect calls the type.
@@ -319,12 +323,21 @@ void propagateEffects(const Module& module,
319323
}
320324

321325
// Assign each function's effects to its CC effects.
322-
for (Function* f : ccFuncs) {
323-
if (!ccEffects) {
324-
funcInfos.at(f).effects = UnknownEffects;
325-
} else {
326-
funcInfos.at(f).effects.emplace(*ccEffects);
327-
}
326+
for (auto node : cc) {
327+
std::visit(overloaded{[&](HeapType type) {
328+
if (ccEffects != UnknownEffects) {
329+
typeEffects[type] =
330+
std::make_shared<EffectAnalyzer>(*ccEffects);
331+
}
332+
},
333+
[&](Function* f) {
334+
if (!ccEffects) {
335+
funcInfos.at(f).effects = UnknownEffects;
336+
} else {
337+
funcInfos.at(f).effects.emplace(*ccEffects);
338+
}
339+
}},
340+
node);
328341
}
329342
}
330343
}
@@ -348,7 +361,8 @@ struct GenerateGlobalEffects : public Pass {
348361
auto callGraph =
349362
buildCallGraph(*module, funcInfos, getPassOptions().closedWorld);
350363

351-
propagateEffects(*module, getPassOptions(), funcInfos, callGraph);
364+
propagateEffects(
365+
*module, getPassOptions(), funcInfos, module->typeEffects, callGraph);
352366

353367
copyEffectsToFunctions(funcInfos);
354368
}

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
@@ -2684,6 +2684,11 @@ class Module {
26842684
std::unordered_map<HeapType, TypeNames> typeNames;
26852685
std::unordered_map<HeapType, Index> typeIndices;
26862686

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

26892694
private:

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

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,9 @@
1616
)
1717

1818
;; CHECK: (func $calls-nop-via-nullable-ref (type $1) (param $ref (ref null $nopType))
19-
;; CHECK-NEXT: (call_ref $nopType
20-
;; CHECK-NEXT: (i32.const 1)
21-
;; CHECK-NEXT: (local.get $ref)
22-
;; CHECK-NEXT: )
19+
;; CHECK-NEXT: (nop)
2320
;; CHECK-NEXT: )
2421
(func $calls-nop-via-nullable-ref (param $ref (ref null $nopType))
2522
(call_ref $nopType (i32.const 1) (local.get $ref))
2623
)
27-
28-
;; CHECK: (func $f (type $1) (param $ref (ref null $nopType))
29-
;; CHECK-NEXT: (nop)
30-
;; CHECK-NEXT: )
31-
(func $f (param $ref (ref null $nopType))
32-
;; The only possible implementation of $nopType has no effects.
33-
;; $calls-nop-via-nullable-ref may trap from a null reference, but
34-
;; --traps-never-happen is enabled, so we're free to optimize this out.
35-
(call $calls-nop-via-nullable-ref (local.get $ref))
36-
)
3724
)

0 commit comments

Comments
 (0)