diff options
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 27 |
1 files changed, 25 insertions, 2 deletions
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(); } |