Skip to content

Commit e42cbb0

Browse files
committed
use exactness more generally
1 parent 590f43e commit e42cbb0

2 files changed

Lines changed: 24 additions & 37 deletions

File tree

src/passes/ConstantFieldPropagation.cpp

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,11 @@ struct FunctionOptimizer : public WalkerPass<PostWalker<FunctionOptimizer>> {
114114
return heapType;
115115
}
116116

117-
PossibleConstantValues getInfo(HeapType type, Index index) {
118-
if (auto it = propagatedInfos.find(type); it != propagatedInfos.end()) {
117+
PossibleConstantValues getInfo(HeapType type, Index index, Exactness exact) {
118+
// If the reference is inexact, we must consider subtypes, who we
119+
// propagated for that purpose.
120+
auto& infos = exact == Inexact ? propagatedInfos : rawNewInfos;
121+
if (auto it = infos.find(type); it != infos.end()) {
119122
// There is information on this type, fetch it.
120123
return it->second[index];
121124
}
@@ -177,7 +180,8 @@ struct FunctionOptimizer : public WalkerPass<PostWalker<FunctionOptimizer>> {
177180
// Find the info for this field, and see if we can optimize. First, see if
178181
// there is any information for this heap type at all. If there isn't, it is
179182
// as if nothing was ever noted for that field.
180-
PossibleConstantValues info = getInfo(heapType, index);
183+
PossibleConstantValues info =
184+
getInfo(heapType, index, ref->type.getExactness());
181185
if (!info.hasNoted()) {
182186
// This field is never written at all. That means that we do not even
183187
// construct any data of this type, and so it is a logic error to reach
@@ -219,15 +223,7 @@ struct FunctionOptimizer : public WalkerPass<PostWalker<FunctionOptimizer>> {
219223
// ref.as_non_null (we need to trap as the get would have done so), plus the
220224
// constant value. (Leave it to further optimizations to get rid of the
221225
// ref.)
222-
optimizeSingleValue(info, heapType, curr, ref);
223-
}
224-
225-
void optimizeSingleValue(const PossibleConstantValues& info,
226-
HeapType type,
227-
Expression* curr,
228-
Expression* ref) {
229-
auto* value = makeExpression(info, type, curr);
230-
Builder builder(*getModule());
226+
auto* value = makeExpression(info, heapType, curr);
231227
auto* replacement =
232228
builder.blockify(builder.makeDrop(builder.makeRefAs(RefAsNonNull, ref)));
233229
replacement->list.push_back(value);
@@ -290,11 +286,6 @@ struct FunctionOptimizer : public WalkerPass<PostWalker<FunctionOptimizer>> {
290286
return;
291287
}
292288

293-
if (refType.isExact() && depth > 0) {
294-
// We do not need to handle subtypes, and this is a subtype.
295-
return;
296-
}
297-
298289
auto iter = rawNewInfos.find(type);
299290
if (iter == rawNewInfos.end()) {
300291
// This type has no struct.news, so we can ignore it: it is abstract.
@@ -344,14 +335,8 @@ struct FunctionOptimizer : public WalkerPass<PostWalker<FunctionOptimizer>> {
344335
assert(values[0].used() || !values[1].used());
345336

346337
if (!values[1].used()) {
347-
// We did not see two constant values, so this is a simple case that does
348-
// not need a ref.test.
349-
if (values[0].used()) {
350-
// We found exactly one value. This can happen because we consider
351-
// subtyping more carefully than the non-reftest logic (specifically, we
352-
// notice exact types). Optimize to the single possible value.
353-
optimizeSingleValue(values[0].constant, refHeapType, curr, ref);
354-
}
338+
// We did not see two constant values (we might have seen just one, or
339+
// even no constant values at all).
355340
return;
356341
}
357342

@@ -518,12 +503,9 @@ struct ConstantFieldPropagation : public Pass {
518503
// Prepare data we will need later.
519504
SubTypes subTypes(*module);
520505

521-
PCVStructValuesMap rawNewInfos;
522-
if (refTest) {
523-
// The refTest optimizations require the raw new infos (see above), but we
524-
// can skip copying here if we'll never read this.
525-
rawNewInfos = combinedNewInfos;
526-
}
506+
// Copy the unpropagated data before we propagate. We use this in precise
507+
// lookups.
508+
auto rawNewInfos = combinedNewInfos;
527509

528510
// Handle subtyping. |combinedInfo| so far contains data that represents
529511
// each struct.new and struct.set's operation on the struct type used in

test/lit/passes/cfp.wast

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2329,10 +2329,10 @@
23292329
;; CHECK: (func $test (type $2) (param $0 i32) (result i32)
23302330
;; CHECK-NEXT: (local $A (ref $A))
23312331
;; CHECK-NEXT: (local $B (ref $B))
2332-
;; CHECK-NEXT: (struct.set $A 0
2333-
;; CHECK-NEXT: (select (result (ref null $A))
2332+
;; CHECK-NEXT: (struct.set $B 0
2333+
;; CHECK-NEXT: (select (result (ref null $B))
23342334
;; CHECK-NEXT: (ref.null none)
2335-
;; CHECK-NEXT: (block (result (ref null $A))
2335+
;; CHECK-NEXT: (block (result (ref $B))
23362336
;; CHECK-NEXT: (local.tee $B
23372337
;; CHECK-NEXT: (struct.new $B
23382338
;; CHECK-NEXT: (i32.const 20)
@@ -2341,10 +2341,15 @@
23412341
;; CHECK-NEXT: )
23422342
;; CHECK-NEXT: (i32.const 0)
23432343
;; CHECK-NEXT: )
2344-
;; CHECK-NEXT: (struct.get $A 0
2345-
;; CHECK-NEXT: (struct.new $A
2346-
;; CHECK-NEXT: (i32.const 10)
2344+
;; CHECK-NEXT: (block (result i32)
2345+
;; CHECK-NEXT: (drop
2346+
;; CHECK-NEXT: (ref.as_non_null
2347+
;; CHECK-NEXT: (struct.new $A
2348+
;; CHECK-NEXT: (i32.const 10)
2349+
;; CHECK-NEXT: )
2350+
;; CHECK-NEXT: )
23472351
;; CHECK-NEXT: )
2352+
;; CHECK-NEXT: (i32.const 10)
23482353
;; CHECK-NEXT: )
23492354
;; CHECK-NEXT: )
23502355
;; CHECK-NEXT: (struct.get $B 0

0 commit comments

Comments
 (0)