[llvm-branch-commits] [llvm] [X86] keep upper-16-bit f32 extractions in XMM for f16/v8i16 (PR #230698)
Emilio Cota via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Oct 12 03:09:08 PDT 2026
https://github.com/cota updated https://github.com/llvm/llvm-project/pull/230698
>From 2cc8bae2867fa59c7f8a4f0f23b79b17f109241d Mon Sep 17 00:00:00 2001
From: Emilio Cota <ecg at google.com>
Date: Fri, 9 Oct 2026 22:05:15 +0000
Subject: [PATCH] [X86] Keep upper-16-bit f32 extractions in XMM for f16/v8i16
Teach combineBitcast and combineVectorInsert to keep this upper-16-bit
f32 extraction in XMM registers rather than bouncing through a GPR.
Depends on PR: https://github.com/llvm/llvm-project/pull/231112
Follow-up PR: https://github.com/llvm/llvm-project/pull/230557
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 32 +++++++++++++++++++++
llvm/test/CodeGen/X86/bfloat.ll | 37 ++++++-------------------
2 files changed, 40 insertions(+), 29 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 6e705d1800a03..62e04e6ea320f 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -47241,6 +47241,22 @@ static SDValue combineBitcast(SDNode *N, SelectionDAG &DAG,
DAG.getBitcast(MVT::v8f16, Src.getOperand(0)),
DAG.getVectorIdxConstant(0, DL));
}
+ using namespace SDPatternMatch;
+ SDValue FpOp;
+ if (Subtarget.hasSSE2() && N0.hasOneUse() &&
+ sd_match(Src, m_OneUse(m_Srl(m_OneUse(m_BitCast(m_Value(
+ FpOp, m_SpecificVT(MVT::f32)))),
+ m_SpecificInt(16)))) &&
+ !ISD::isNormalLoad(FpOp.getNode())) {
+ SDLoc DL(N);
+ SDValue Vec = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4f32, FpOp);
+ Vec = DAG.getBitcast(MVT::v4i32, Vec);
+ Vec = getTargetVShiftByConstNode(X86ISD::VSRLI, DL, MVT::v4i32, Vec, 16,
+ DAG);
+ return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT,
+ DAG.getBitcast(MVT::v8f16, Vec),
+ DAG.getVectorIdxConstant(0, DL));
+ }
}
// Since MMX types are special and don't usually play with other vector types,
@@ -52344,6 +52360,22 @@ static SDValue combineVectorInsert(SDNode *N, SelectionDAG &DAG,
return SDValue(N, 0);
}
+ if (Opcode == X86ISD::PINSRW && Subtarget.hasSSE41()) {
+ using namespace SDPatternMatch;
+ SDValue FpOp;
+ if (sd_match(Scl, m_OneUse(m_Srl(m_OneUse(m_BitCast(m_Value(
+ FpOp, m_SpecificVT(MVT::f32)))),
+ m_SpecificInt(16)))) &&
+ !ISD::isNormalLoad(FpOp.getNode())) {
+ SDLoc DL(N);
+ SDValue SrcVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4f32, FpOp);
+ int Mask[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+ Mask[N->getConstantOperandVal(2)] = 9;
+ return DAG.getVectorShuffle(VT, DL, Vec, DAG.getBitcast(VT, SrcVec),
+ Mask);
+ }
+ }
+
// Attempt to combine insertion patterns to a shuffle.
if (VT.isSimple() && DCI.isAfterLegalizeDAG()) {
SDValue Op(N, 0);
diff --git a/llvm/test/CodeGen/X86/bfloat.ll b/llvm/test/CodeGen/X86/bfloat.ll
index ec7b190664a62..eb9dcae47910c 100644
--- a/llvm/test/CodeGen/X86/bfloat.ll
+++ b/llvm/test/CodeGen/X86/bfloat.ll
@@ -2717,31 +2717,13 @@ define half @bitcast_f32_hi16(float %f) {
;
; SSE2-LABEL: bitcast_f32_hi16:
; SSE2: # %bb.0:
-; SSE2-NEXT: movd %xmm0, %eax
-; SSE2-NEXT: shrl $16, %eax
-; SSE2-NEXT: pinsrw $0, %eax, %xmm0
+; SSE2-NEXT: psrld $16, %xmm0
; SSE2-NEXT: retq
;
-; AVX512BF16-LABEL: bitcast_f32_hi16:
-; AVX512BF16: # %bb.0:
-; AVX512BF16-NEXT: vmovd %xmm0, %eax
-; AVX512BF16-NEXT: shrl $16, %eax
-; AVX512BF16-NEXT: vpinsrw $0, %eax, %xmm0, %xmm0
-; AVX512BF16-NEXT: retq
-;
-; AVX512FP16-LABEL: bitcast_f32_hi16:
-; AVX512FP16: # %bb.0:
-; AVX512FP16-NEXT: vmovd %xmm0, %eax
-; AVX512FP16-NEXT: shrl $16, %eax
-; AVX512FP16-NEXT: vmovw %eax, %xmm0
-; AVX512FP16-NEXT: retq
-;
-; AVXNC-LABEL: bitcast_f32_hi16:
-; AVXNC: # %bb.0:
-; AVXNC-NEXT: vmovd %xmm0, %eax
-; AVXNC-NEXT: shrl $16, %eax
-; AVXNC-NEXT: vpinsrw $0, %eax, %xmm0, %xmm0
-; AVXNC-NEXT: retq
+; AVX-LABEL: bitcast_f32_hi16:
+; AVX: # %bb.0:
+; AVX-NEXT: vpsrld $16, %xmm0, %xmm0
+; AVX-NEXT: retq
%i = bitcast float %f to i32
%s = lshr i32 %i, 16
%t = trunc i32 %s to i16
@@ -2764,9 +2746,7 @@ define <8 x i16> @insert_f32_hi16(<8 x i16> %vec, float %f) {
;
; AVX-LABEL: insert_f32_hi16:
; AVX: # %bb.0:
-; AVX-NEXT: vmovd %xmm1, %eax
-; AVX-NEXT: shrl $16, %eax
-; AVX-NEXT: vpinsrw $1, %eax, %xmm0, %xmm0
+; AVX-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0],xmm1[1],xmm0[2,3,4,5,6,7]
; AVX-NEXT: retq
%i = bitcast float %f to i32
%s = lshr i32 %i, 16
@@ -2790,9 +2770,8 @@ define <8 x i16> @insert_f32_hi16_lane2(<8 x i16> %vec, float %f) {
;
; AVX-LABEL: insert_f32_hi16_lane2:
; AVX: # %bb.0:
-; AVX-NEXT: vmovd %xmm1, %eax
-; AVX-NEXT: shrl $16, %eax
-; AVX-NEXT: vpinsrw $2, %eax, %xmm0, %xmm0
+; AVX-NEXT: vpmovzxwd {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero
+; AVX-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1],xmm1[2],xmm0[3,4,5,6,7]
; AVX-NEXT: retq
%i = bitcast float %f to i32
%s = lshr i32 %i, 16
More information about the llvm-branch-commits
mailing list