summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/possible-constant.h39
1 files changed, 23 insertions, 16 deletions
diff --git a/src/ir/possible-constant.h b/src/ir/possible-constant.h
index c75669dab..f8b690a93 100644
--- a/src/ir/possible-constant.h
+++ b/src/ir/possible-constant.h
@@ -72,22 +72,9 @@ public:
// Note either a Literal or a Name.
template<typename T> void note(T curr) {
- if (std::get_if<None>(&value)) {
- // This is the first value.
- value = curr;
- return;
- }
-
- if (std::get_if<Many>(&value)) {
- // This was already representing multiple values; nothing changes.
- return;
- }
-
- // This is a subsequent value. Check if it is different from all previous
- // ones.
- if (Variant(curr) != value) {
- noteUnknown();
- }
+ PossibleConstantValues other;
+ other.value = curr;
+ combine(other);
}
// Notes a value that is unknown - it can be anything. We have failed to
@@ -118,6 +105,22 @@ public:
return true;
}
+ // Nulls compare equal, and we could consider any of the input nulls as the
+ // combination of the two (as any of them would be valid to place in the
+ // location we are working to optimize). In order to have simple symmetric
+ // behavior here, which does not depend on the order of the inputs, use the
+ // LUB.
+ if (isNull() && other.isNull()) {
+ auto type = getConstantLiteral().type.getHeapType();
+ auto otherType = other.getConstantLiteral().type.getHeapType();
+ auto lub = HeapType::getLeastUpperBound(type, otherType);
+ if (lub != type) {
+ value = Literal::makeNull(lub);
+ return true;
+ }
+ return false;
+ }
+
return false;
}
@@ -130,6 +133,10 @@ public:
bool isConstantGlobal() const { return std::get_if<Name>(&value); }
+ bool isNull() const {
+ return isConstantLiteral() && getConstantLiteral().isNull();
+ }
+
// Returns the single constant value.
Literal getConstantLiteral() const {
assert(isConstant());