We can fold the complex.mul if the right value is obvious 1 or 0.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Does complex allow for special fp values like NaN, +/- Inf, or -0? I remember this being the case for complex in C. If yes, is the '* 0' fold valid when the non-constant values are NaN/Inf/-0/etc.?
mlir/lib/Dialect/Complex/IR/ComplexOps.cpp | ||
---|---|---|
256 | Prefer early exits: https://llvm.org/docs/CodingStandards.html#use-early-exits-and-continue-to-simplify-code. Also in the code below. | |
257–259 | nit: I would prefer to see the exact types spelled out here, it's not immediately obvious what each .getValue(); returns. |
As @kuhar mentioned, multiplying by zero isn't necessarily zero, unless the appropriate fastmath flags are set. (LLVM won't simplify multiplication scalar values by zero unless the nnan and nsz flags are set.)
I would think the "right" thing to do here is add fastmath flags to the complex dialect operations and make the fold conditional.
@kuhar @jfurtek Thank you for the comment. I found a related discussion here for the arithmetic dialect. (you are already leading the one, @jfurtek)
https://discourse.llvm.org/t/rfc-fastmath-flags-support-in-mlir-arith-dialect/6049
I think we can add similar flag as the arith dialect right?
IIRC mul_one case should not be affected by the fast math flag this time. Can I separate mul_zero from the patch so that we can work on after supporting fast math flag?
Limiting the scope SGTM. We should make sure to add test cases with those special fp values to show that these folds handle them as intended, provided they won't be matched against directly in the fold.
mlir/lib/Dialect/Complex/IR/ComplexOps.cpp | ||
---|---|---|
264–265 | @kuhar Sorry, I might have missed what you meant. Which part should we do early exit for this case? To do if (real != APFloat(...)) type of check, we need to check the size in bits first (64 bit real will always fail to check real != APFloat(1.0f) but it should be caught in the case of 32 bit. ) |
mlir/lib/Dialect/Complex/IR/ComplexOps.cpp | ||
---|---|---|
264–265 | I was thinking of something like: if (!imag.isZero()) return {}; if (real != APFloat(1.0)) return {}; if (!llvm::is_contained({32, 64}, real.getSizeInBits(real.getSemantics())) return {}; return getLhs(); |
mlir/lib/Dialect/Complex/IR/ComplexOps.cpp | ||
---|---|---|
264–265 | Gah, I'm sorry, I missed the 1.0 vs. 1.0f distinction. In this case I think we can use the m_OneFloat matcher: https://mlir.llvm.org/doxygen/namespacemlir.html#af0495d84f34cf3238a7741fa6974a485 |
mlir/lib/Dialect/Complex/IR/ComplexOps.cpp | ||
---|---|---|
264–265 | Thank you. Let me try! |
mlir/lib/Dialect/Complex/IR/ComplexOps.cpp | ||
---|---|---|
264–265 | Apparently, m_OneFloat (or any other matcher) does not work with APFloat derived from the attribute. It's only working with the value type. https://discord.com/channels/636084430946959380/642426447167881246/1123498353129426994 |
mlir/lib/Dialect/Complex/IR/ComplexOps.cpp | ||
---|---|---|
264–265 | I changed to exit earlier in the case of non-zero imaginary part instead. |
mlir/lib/Dialect/Complex/IR/ComplexOps.cpp | ||
---|---|---|
264–265 | In this case, should we use the same implementation as they do to support any bitwidth? inline detail::constant_float_predicate_matcher m_OneFloat() { return {[](const APFloat &value) { return APFloat(value.getSemantics(), 1) == value; }}; } |
Prefer early exits: https://llvm.org/docs/CodingStandards.html#use-early-exits-and-continue-to-simplify-code.
Also in the code below.