summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/properties.h5
-rw-r--r--src/passes/OptimizeInstructions.cpp27
2 files changed, 30 insertions, 2 deletions
diff --git a/src/ir/properties.h b/src/ir/properties.h
index f38773bd8..56723631a 100644
--- a/src/ir/properties.h
+++ b/src/ir/properties.h
@@ -51,6 +51,11 @@ inline bool isSymmetric(Binary* binary) {
case XorInt64:
case EqInt64:
case NeInt64:
+
+ case EqFloat32:
+ case NeFloat32:
+ case EqFloat64:
+ case NeFloat64:
return true;
default:
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 676e753ce..04661af2d 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -202,7 +202,7 @@ struct OptimizeInstructions
return nullptr;
}
if (auto* binary = curr->dynCast<Binary>()) {
- if (Properties::isSymmetric(binary)) {
+ if (isSymmetric(binary)) {
canonicalize(binary);
}
if (auto* ext = Properties::getAlmostSignExt(binary)) {
@@ -731,7 +731,7 @@ private:
// Canonicalizing the order of a symmetric binary helps us
// write more concise pattern matching code elsewhere.
void canonicalize(Binary* binary) {
- assert(Properties::isSymmetric(binary));
+ assert(isSymmetric(binary));
FeatureSet features = getModule()->features;
auto swap = [&]() {
assert(EffectAnalyzer::canReorder(
@@ -1591,6 +1591,29 @@ private:
return InvalidBinary;
}
}
+
+ bool isSymmetric(Binary* binary) {
+ if (Properties::isSymmetric(binary)) {
+ return true;
+ }
+ switch (binary->op) {
+ case AddFloat32:
+ case MulFloat32:
+ case AddFloat64:
+ case MulFloat64: {
+ // If the LHS is known to be non-NaN, the operands can commute.
+ // We don't care about the RHS because right now we only know if
+ // an expression is non-NaN if it is constant, but if the RHS is
+ // constant, then this expression is already canonicalized.
+ if (auto* c = binary->left->dynCast<Const>()) {
+ return !c->value.isNaN();
+ }
+ return false;
+ }
+ default:
+ return false;
+ }
+ }
};
Pass* createOptimizeInstructionsPass() { return new OptimizeInstructions(); }