[llvm] [X86] Lower scalar bf16 arithmetic on AVX10.2 via packed ops (PR #212245)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 28 08:49:50 PDT 2026
================
@@ -34513,6 +34522,37 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
}
}
+/// Lower a scalar bf16 arithmetic node whose type is being soft-promoted.
+///
+/// AVX10.2 has no scalar bf16 arithmetic instructions, and bf16 is a
+/// soft-promoted-half type, so scalar ops would otherwise be promoted to f32.
+/// Instead widen each operand to a v8bf16 vector, perform the legal packed
+/// operation, and extract the low element afterwards.
+///
+/// Each operand is reinterpreted as f16 before building the vector. bf16 has no
+/// scalar register class of its own, but f16 does (FR16X), and bf16/f16 share
+/// the same bits and vector register class (VR128X). Going through f16 keeps the
+/// value in an XMM register: bf16->f16 bitcast, f16->v8f16 SCALAR_TO_VECTOR
+/// (a free COPY_TO_REGCLASS), and v8f16->v8bf16 bitcast are all free. Feeding a
+/// scalar bf16 to SCALAR_TO_VECTOR directly would instead route through bf16's
+/// i16 soft-promote carrier, forcing xmm<->GPR vmovw roundtrips.
+///
+/// Returns a bf16-typed value.
+static SDValue LowerScalarBF16ArithViaVector(SDNode *N, SelectionDAG &DAG) {
+ SDLoc dl(N);
+ assert(N->getValueType(0) == MVT::bf16 && "Expected scalar bf16 result");
+ SmallVector<SDValue, 3> VecOps;
+ for (const SDValue &Op : N->ops()) {
+ SDValue AsF16 = DAG.getBitcast(MVT::f16, Op);
+ SDValue VecF16 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v8f16, AsF16);
+ VecOps.push_back(DAG.getBitcast(MVT::v8bf16, VecF16));
+ }
+ SDValue Vec =
+ DAG.getNode(N->getOpcode(), dl, MVT::v8bf16, VecOps, N->getFlags());
+ return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::bf16, Vec,
----------------
RKSimon wrote:
DAG.getExtractVectorElt
https://github.com/llvm/llvm-project/pull/212245
More information about the llvm-commits
mailing list