Skip to content

Commit e2b41f2

Browse files
authored
[NFC] Simplify Array2Struct type replacement (#7539)
Array2Struct has to update the types of every expression that interacts with and produces a reference to the optimized array type. It previously did this by separately checking whether a nullable or non-nullable reference to the array was a subtype of the expression's type. Simplify this logic by doing only a single check that considers only the heap types of the references. Also remove some unnecessary variables in which various reference types were cached since it is extremely cheap to materialize a reference type now. These simplifications will also make it easier to update the pass to handle exact reference types once `array.new` instructions are typed as exact.
1 parent 647a2e1 commit e2b41f2

File tree

1 file changed

+13
-19
lines changed

1 file changed

+13
-19
lines changed

src/passes/Heap2Local.cpp

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,8 +1029,7 @@ struct Array2Struct : PostWalker<Array2Struct> {
10291029

10301030
// The type of the struct we are changing to (nullable and non-nullable
10311031
// variations).
1032-
Type nullStruct;
1033-
Type nonNullStruct;
1032+
HeapType structType;
10341033

10351034
Array2Struct(Expression* allocation,
10361035
EscapeAnalyzer& analyzer,
@@ -1048,7 +1047,7 @@ struct Array2Struct : PostWalker<Array2Struct> {
10481047
for (Index i = 0; i < numFields; i++) {
10491048
fields.push_back(element);
10501049
}
1051-
HeapType structType = Struct(fields);
1050+
structType = Struct(fields);
10521051

10531052
// Generate a StructNew to replace the ArrayNew*.
10541053
if (auto* arrayNew = allocation->dynCast<ArrayNew>()) {
@@ -1097,30 +1096,25 @@ struct Array2Struct : PostWalker<Array2Struct> {
10971096
// the array type (which can be the case of an array of arrays). But that is
10981097
// fine to do as the array.get is rewritten to a struct.get which is then
10991098
// lowered away to locals anyhow.
1100-
auto nullArray = Type(arrayType, Nullable);
1101-
auto nonNullArray = Type(arrayType, NonNullable);
1102-
nullStruct = Type(structType, Nullable);
1103-
nonNullStruct = Type(structType, NonNullable);
11041099
for (auto& [reached, _] : analyzer.reachedInteractions) {
11051100
if (reached->is<RefCast>()) {
11061101
// Casts must be handled later: We need to see the old type, and to
11071102
// potentially replace the cast based on that, see below.
11081103
continue;
11091104
}
11101105

1111-
// We must check subtyping here because the allocation may be upcast as it
1112-
// flows around. If we do see such upcasting then we are refining here and
1113-
// must refinalize.
1114-
if (Type::isSubType(nullArray, reached->type)) {
1115-
if (nullArray != reached->type) {
1116-
refinalize = true;
1117-
}
1118-
reached->type = nullStruct;
1119-
} else if (Type::isSubType(nonNullArray, reached->type)) {
1120-
if (nonNullArray != reached->type) {
1106+
if (!reached->type.isRef()) {
1107+
continue;
1108+
}
1109+
1110+
// The allocation type may be generalized as it flows around. If we do see
1111+
// such generalizing, then we are refining here and must refinalize.
1112+
auto reachedHeapType = reached->type.getHeapType();
1113+
if (HeapType::isSubType(arrayType, reachedHeapType)) {
1114+
if (arrayType != reachedHeapType) {
11211115
refinalize = true;
11221116
}
1123-
reached->type = nonNullStruct;
1117+
reached->type = Type(structType, reached->type.getNullability());
11241118
}
11251119
}
11261120

@@ -1248,7 +1242,7 @@ struct Array2Struct : PostWalker<Array2Struct> {
12481242
// type here unconditionally, since we know the allocation flows through
12491243
// here, and anyhow we will be removing the reference during Struct2Local,
12501244
// later.)
1251-
curr->type = nonNullStruct;
1245+
curr->type = Type(structType, NonNullable);
12521246
}
12531247

12541248
// Regardless of how we altered the type here, refinalize.

0 commit comments

Comments
 (0)