On Tue, 28 Jul 2026 20:59:02 GMT, Vladimir Ivanov <[email protected]> wrote:
> Overall, looks reasonable. > > You change the default in favor of GEMM-style usages, but it means that some > code shapes which benefitted from the original treatment are penalized now. > Does it make sense to come up with generalized solution which chooses between > different encodings on case-by-case basis? Hi @iwanowww, thanks for looking. The Scalar and Vector FMA patterns and their memory flavors already emit the 231 form unconditionally — destination tied to the addend, both multiplicands preserved. Before this change the Float16 rules were the lone outlier, tying the destination to a multiplicand and emitting vfmadd132ph. So this PR removes an inconsistency and brings FmaVHF/FmaHF to parity with the existing float/double behavior rather than introducing a new asymmetry. 231 is optimal for the accumulation/reduction shapes where the loop-carried value is the FMA addend (GEMM, dot-product, and the general acc = m1*m2 + acc micro-kernels). These are the dominant vectorized FMA shapes. Following is the Ideal IR for fma operation `Vector.fma(b, c) => FmaVF/VD/VHF c , (Binary this, b)` The proper general fix is to let the matcher choose among 132 / 213 / 231 based on operand liveness, applied uniformly to FmaVF/FmaVD/FmaVHF (scalar + vector) rather than special-casing HF here. Sketch: The matcher runs pre-RA, and RA inserts a MachSpillCopy whenever the operand tied to dst is live past the FMA (has additional uses). So the selection criterion is "tie dst to the input that is not live afterwards." This is expressible as three predicated AD variants of the same node, each tying dst to a different input: 231 — Set dst (FmaVHF dst (Binary src1 src2)) (overwrite addend, in(1)) 132 — Set dst (FmaVHF src2 (Binary dst src1)) (overwrite a multiplicand, in(2)) 213 — Set dst (FmaVHF src2 (Binary src1 dst)) (overwrite the other multiplicand, in(3)) with mutually-exclusive predicates keyed on fanout of the FMA inputs — n->in(1)->outcnt() (addend) vs n->in(2)->in(1)->outcnt() / n->in(2)->in(2)->outcnt() (multiplicands) — preferring to overwrite an operand with outcnt() == 1 and preserve one with outcnt() > 1, defaulting to 231. Doing the selection at emission (ins_encode, post-RA) doesn't work: by then the two-address binding is fixed and RA has already coalesced/spilled under it, so the inputs can't be re-assigned to a different form. Would it be fine to bring Float16 FMA to parity with single/double precision in this PR, and experiment with generalized encoding selection for all three (FmaVF/VD/VHF) in a follow-up? Let me know your view ------------- PR Comment: https://git.openjdk.org/jdk/pull/31724#issuecomment-5115491572
