summaryrefslogtreecommitdiff
path: root/src/ir/properties.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir/properties.h')
-rw-r--r--src/ir/properties.h68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/ir/properties.h b/src/ir/properties.h
index d47cf774b..7f247f72f 100644
--- a/src/ir/properties.h
+++ b/src/ir/properties.h
@@ -362,6 +362,74 @@ inline Expression* getFallthrough(
}
}
+// Look at all the intermediate fallthrough expressions and return the most
+// precise type we know this value will have.
+inline Type getFallthroughType(Expression* curr,
+ const PassOptions& passOptions,
+ Module& module) {
+ Type type = curr->type;
+ if (!type.isRef()) {
+ // Only reference types can be improved (excepting improvements to
+ // unreachable, which we leave to refinalization).
+ // TODO: Handle tuples if that ever becomes important.
+ return type;
+ }
+ while (1) {
+ auto* next = getImmediateFallthrough(curr, passOptions, module);
+ if (next == curr) {
+ return type;
+ }
+ type = Type::getGreatestLowerBound(type, next->type);
+ if (type == Type::unreachable) {
+ return type;
+ }
+ curr = next;
+ }
+}
+
+// Find the best fallthrough value ordered by refinement of heaptype, refinement
+// of nullability, and closeness to the current expression. The type of the
+// expression this function returns may be nullable even if `getFallthroughType`
+// is non-nullable, but the heap type will definitely match.
+inline Expression** getMostRefinedFallthrough(Expression** currp,
+ const PassOptions& passOptions,
+ Module& module) {
+ Expression* curr = *currp;
+ if (!curr->type.isRef()) {
+ return currp;
+ }
+ auto bestType = curr->type.getHeapType();
+ auto bestNullability = curr->type.getNullability();
+ auto** bestp = currp;
+ while (1) {
+ curr = *currp;
+ auto** nextp =
+ Properties::getImmediateFallthroughPtr(currp, passOptions, module);
+ auto* next = *nextp;
+ if (next == curr || next->type == Type::unreachable) {
+ return bestp;
+ }
+ assert(next->type.isRef());
+ auto nextType = next->type.getHeapType();
+ auto nextNullability = next->type.getNullability();
+ if (nextType == bestType) {
+ // Heap types match: refine nullability if possible.
+ if (bestNullability == Nullable && nextNullability == NonNullable) {
+ bestp = nextp;
+ bestNullability = NonNullable;
+ }
+ } else {
+ // Refine heap type if possible, resetting nullability.
+ if (HeapType::isSubType(nextType, bestType)) {
+ bestp = nextp;
+ bestNullability = nextNullability;
+ bestType = nextType;
+ }
+ }
+ currp = nextp;
+ }
+}
+
inline Index getNumChildren(Expression* curr) {
Index ret = 0;