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

Reply via email to