[llvm] [X86] Optimize lowering of single-element load BUILD_VECTOR for pre-SSE4.1 (PR #217731)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 11:49:58 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: AZero13 (AZero13)

<details>
<summary>Changes</summary>

This PR optimizes the lowering of 128-bit `BUILD_VECTOR` operations that insert a single scalar load into an otherwise zero-initialized vector (e.g., the pattern generated by `_mm_set_ps(0, 0, x, 0)`).

---
Full diff: https://github.com/llvm/llvm-project/pull/217731.diff


2 Files Affected:

- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+27-4) 
- (modified) llvm/test/CodeGen/X86/vector-shuffle-combining.ll (+4-6) 


``````````diff
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index bf435b0c2f849..375aace096c82 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -9668,12 +9668,35 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
 
     // Otherwise, if this is a vector with i32 or f32 elements, and the element
     // is a non-constant being inserted into an element other than the low one,
-    // we can't use a constant pool load.  Instead, use SCALAR_TO_VECTOR (aka
-    // movd/movss) to move this into the low element, then shuffle it into
-    // place.
+    // we can't use a constant pool load.
     if (EVTBits == 32) {
+      // If the element is a load, we can emit a VZEXT_LOAD to zero-extend the
+      // scalar into a 128-bit vector, and then shuffle the element into place.
+      // This avoids emitting a separate zero vector and cross-domain penalties.
+      if (!Subtarget.hasSSE41() && NumZero > 0 &&
+          Item.getOpcode() == ISD::LOAD && Item.hasOneUse() &&
+          VT.is128BitVector() &&
+          cast<LoadSDNode>(Item)->getMemoryVT().getSizeInBits() == 32) {
+        auto *LN = cast<LoadSDNode>(Item);
+        SDVTList Tys = DAG.getVTList(VT, MVT::Other);
+        SDValue Ops[] = {LN->getChain(), LN->getBasePtr()};
+        SDValue VZLoad = DAG.getMemIntrinsicNode(
+            X86ISD::VZEXT_LOAD, dl, Tys, Ops, LN->getMemoryVT(),
+            LN->getPointerInfo(), LN->getBaseAlign(),
+            LN->getMemOperand()->getFlags());
+        DAG.makeEquivalentMemoryOrdering(LN, VZLoad);
+        SmallVector<int, 16> MaskVec(NumElems);
+        for (unsigned i = 0; i != NumElems; ++i)
+          MaskVec[i] = (i == Idx) ? 0 : 1;
+        return DAG.getVectorShuffle(VT, dl, VZLoad, VZLoad, MaskVec);
+      }
+
+      // For non-loads (or if the VZEXT_LOAD path isn't applicable), we fallback
+      // to using SCALAR_TO_VECTOR (aka movd/movss) to move this into the low
+      // element, then shuffle it into place.
       Item = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Item);
-      return getShuffleVectorZeroOrUndef(Item, Idx, NumZero > 0, Subtarget, DAG);
+      return getShuffleVectorZeroOrUndef(Item, Idx, NumZero > 0, Subtarget,
+                                         DAG);
     }
   }
 
diff --git a/llvm/test/CodeGen/X86/vector-shuffle-combining.ll b/llvm/test/CodeGen/X86/vector-shuffle-combining.ll
index f31c1d5667f2f..3013bdd6f2bdc 100644
--- a/llvm/test/CodeGen/X86/vector-shuffle-combining.ll
+++ b/llvm/test/CodeGen/X86/vector-shuffle-combining.ll
@@ -3626,19 +3626,17 @@ define <8 x float> @PR213251() {
 ; SSE2-LABEL: PR213251:
 ; SSE2:       # %bb.0:
 ; SSE2-NEXT:    movl $1, (%rax)
-; SSE2-NEXT:    movd {{.*#+}} xmm0 = [NaN,0.0E+0,0.0E+0,0.0E+0]
-; SSE2-NEXT:    movq {{.*#+}} xmm0 = xmm0[0],zero
+; SSE2-NEXT:    movss {{.*#+}} xmm0 = [NaN,0.0E+0,0.0E+0,0.0E+0]
+; SSE2-NEXT:    shufps {{.*#+}} xmm0 = xmm0[1,0,1,1]
 ; SSE2-NEXT:    xorps %xmm1, %xmm1
-; SSE2-NEXT:    shufps {{.*#+}} xmm0 = xmm0[2,0],xmm1[2,3]
 ; SSE2-NEXT:    retq
 ;
 ; SSSE3-LABEL: PR213251:
 ; SSSE3:       # %bb.0:
 ; SSSE3-NEXT:    movl $1, (%rax)
-; SSSE3-NEXT:    movd {{.*#+}} xmm0 = [NaN,0.0E+0,0.0E+0,0.0E+0]
-; SSSE3-NEXT:    movq {{.*#+}} xmm0 = xmm0[0],zero
+; SSSE3-NEXT:    movss {{.*#+}} xmm0 = [NaN,0.0E+0,0.0E+0,0.0E+0]
+; SSSE3-NEXT:    shufps {{.*#+}} xmm0 = xmm0[1,0,1,1]
 ; SSSE3-NEXT:    xorps %xmm1, %xmm1
-; SSSE3-NEXT:    shufps {{.*#+}} xmm0 = xmm0[2,0],xmm1[2,3]
 ; SSSE3-NEXT:    retq
 ;
 ; SSE41-LABEL: PR213251:

``````````

</details>


https://github.com/llvm/llvm-project/pull/217731


More information about the llvm-commits mailing list