@@ -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
0 commit comments