summaryrefslogtreecommitdiff
path: root/src/ir/possible-constant.h
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2022-05-13 16:39:08 -0700
committerGitHub <noreply@github.com>2022-05-13 16:39:08 -0700
commit4edfcc9f8cfc6a340411b791e7d7889b836dc772 (patch)
tree69d1fb3722ae03747decb612aaa49ff512ec50a2 /src/ir/possible-constant.h
parente4b3370c755125cc717cf7c017eada8109cda7f1 (diff)
downloadbinaryen-4edfcc9f8cfc6a340411b791e7d7889b836dc772.tar.gz
binaryen-4edfcc9f8cfc6a340411b791e7d7889b836dc772.tar.bz2
binaryen-4edfcc9f8cfc6a340411b791e7d7889b836dc772.zip
Ensure symmetric results in PossibleConstantValues (#4662)
Previously we could return different results depending on the order we noted things: note(anyref.null); note(funcref.null); get() => anyref.null note(funcref.null); note(anyref.null); get() => funcref.null This is correct, as nulls are equal anyhow, and any could be used in the location we are optimizing. However, it can lead to nondeterminism if the caller's order of notes is nondeterministic. That is the case in DeadArgumentElimination, where we scan functions in parallel, then merge them without special ordering. To fix this, make the note operation symmetric. That seems simplest and least likely to be confusing. We can use the LUB to do that. To avoid duplicating the null logic, refactor note() to use combine().
Diffstat (limited to 'src/ir/possible-constant.h')
-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());