summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r--src/passes/OptimizeInstructions.cpp26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 37fb37ace..06f3d5b02 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -562,6 +562,32 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
}
}
}
+ // bitwise operations
+ if (binary->op == AndInt32) {
+ // try de-morgan's AND law,
+ // (eqz X) and (eqz Y) === eqz (X or Y)
+ // Note that the OR and XOR laws do not work here, as these
+ // are not booleans (we could check if they are, but a boolean
+ // would already optimize with the eqz anyhow, unless propagating).
+ // But for AND, the left is true iff X and Y are each all zero bits,
+ // and the right is true if the union of their bits is zero; same.
+ if (auto* left = binary->left->dynCast<Unary>()) {
+ if (left->op == EqZInt32) {
+ if (auto* right = binary->right->dynCast<Unary>()) {
+ if (right->op == EqZInt32) {
+ // reuse one unary, drop the other
+ auto* leftValue = left->value;
+ left->value = binary;
+ binary->left = leftValue;
+ binary->right = right->value;
+ binary->op = OrInt32;
+ return left;
+ }
+ }
+ }
+ }
+ }
+ // for and and or, we can potentially conditionalize
if (binary->op == AndInt32 || binary->op == OrInt32) {
return conditionalizeExpensiveOnBitwise(binary);
}