Skip to content

Commit 7b817d6

Browse files
authored
Costs: Adjust the cost of calls (#8047)
The cost of "4" earlier was in place because call costs don't really matter (the effects prevent removing/replacing them), but there are calls without effects, like with the proper intrinsic. Model call costs as very expensive. The monomorphize test change is because it has hardcoded costs, and calls are now too "heavy" for what it wants. The calls are replaced by other code that does a bunch of work. Fixes #8044
1 parent a3a2c4f commit 7b817d6

File tree

4 files changed

+340
-97
lines changed

4 files changed

+340
-97
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ Current Trunk
2222
- The --mod-asyncify-never-unwind and --mod-asyncify-always-and-only-unwind
2323
passed were deleted. They only existed to support the lazy code loading
2424
support in emscripten that was removed. (#7893)
25+
- The cost modeling of calls was increased to a high number. That cost is
26+
usually not something you can notice (as calls have effects that make
27+
removing/replacing them impossible), but you may notice this when using
28+
call.without.effects (calls will no longer be assumed to be cheap enough to
29+
run unconditionally) or monomorphize (which inputs a cost factor as a
30+
number). (#8047)
2531

2632
v124
2733
----

src/ir/cost.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> {
4747
// cost due to shortening the time to the next collection.
4848
static const CostType AllocationCost = 100;
4949

50+
// Calls can have unpredictable, unknown cost. Model it as a large number.
51+
// TODO: For calls to functions in this module, we could in principle scan
52+
// them. However, call effects generally mean the cost is a moot point,
53+
// except for call.without.effects, which is rare.
54+
static const CostType CallCost = 100;
55+
5056
CostType maybeVisit(Expression* curr) { return curr ? visit(curr) : 0; }
5157

5258
CostType visitBlock(Block* curr) {
@@ -68,23 +74,23 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> {
6874
return 2 + visit(curr->condition) + maybeVisit(curr->value);
6975
}
7076
CostType visitCall(Call* curr) {
71-
// XXX this does not take into account if the call is to an import, which
72-
// may be costlier in general
73-
CostType ret = 4;
77+
CostType ret = CallCost;
7478
for (auto* child : curr->operands) {
7579
ret += visit(child);
7680
}
7781
return ret;
7882
}
7983
CostType visitCallIndirect(CallIndirect* curr) {
80-
CostType ret = 6 + visit(curr->target);
84+
// Model indirect calls as more expensive than direct ones.
85+
CostType ret = CallCost + 1 + visit(curr->target);
8186
for (auto* child : curr->operands) {
8287
ret += visit(child);
8388
}
8489
return ret;
8590
}
8691
CostType visitCallRef(CallRef* curr) {
87-
CostType ret = 5 + visit(curr->target);
92+
// Model call_refs as more expensive than direct calls.
93+
CostType ret = CallCost + 1 + visit(curr->target);
8894
for (auto* child : curr->operands) {
8995
ret += visit(child);
9096
}

0 commit comments

Comments
 (0)