diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/bits.h | 2 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 19 |
2 files changed, 21 insertions, 0 deletions
diff --git a/src/ir/bits.h b/src/ir/bits.h index 950864a23..dc02bd8f8 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -413,6 +413,8 @@ Index getMaxBits(Expression* curr, // a tee passes through the value return getMaxBits(set->value, localInfoProvider); } else if (auto* get = curr->dynCast<LocalGet>()) { + // TODO: Should this be optional? + assert(localInfoProvider); return localInfoProvider->getMaxBitsForLocal(get); } else if (auto* load = curr->dynCast<Load>()) { // if signed, then the sign-extension might fill all the bits diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 357f172d9..768ea5702 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1819,6 +1819,25 @@ private: } } } + if (curr->type == Type::i32 && + Bits::getMaxBits(curr->condition, this) <= 1 && + Bits::getMaxBits(curr->ifTrue, this) <= 1 && + Bits::getMaxBits(curr->ifFalse, this) <= 1) { + // The condition and both arms are i32 booleans, which allows us to do + // boolean optimizations. + Expression* x; + Expression* y; + + // x ? y : 0 ==> x & y + if (matches(curr, select(any(&y), ival(0), any(&x)))) { + return builder.makeBinary(AndInt32, y, x); + } + + // x ? 1 : y ==> x | y + if (matches(curr, select(ival(1), any(&y), any(&x)))) { + return builder.makeBinary(OrInt32, y, x); + } + } { // Sides are identical, fold Expression *ifTrue, *ifFalse, *c; |