[llvm] [X86] optimize ssse3 horizontal saturating add/sub (PR #169591)

Folkert de Vries via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 27 02:02:05 PST 2025


================
@@ -54071,45 +54072,32 @@ static SDValue combineToHorizontalAddSub(SDNode *N, SelectionDAG &DAG,
     break;
   case ISD::ADD:
   case ISD::SUB:
-    if (Subtarget.hasSSSE3() && (VT == MVT::v8i16 || VT == MVT::v4i32 ||
-                                 VT == MVT::v16i16 || VT == MVT::v8i32)) {
-      SDValue LHS = N->getOperand(0);
-      SDValue RHS = N->getOperand(1);
-      auto HorizOpcode = IsAdd ? X86ISD::HADD : X86ISD::HSUB;
-      if (isHorizontalBinOp(HorizOpcode, LHS, RHS, DAG, Subtarget, IsAdd,
-                            PostShuffleMask, MergableHorizOp(HorizOpcode))) {
-        auto HOpBuilder = [HorizOpcode](SelectionDAG &DAG, const SDLoc &DL,
-                                        ArrayRef<SDValue> Ops) {
-          return DAG.getNode(HorizOpcode, DL, Ops[0].getValueType(), Ops);
-        };
-        SDValue HorizBinOp = SplitOpsAndApply(DAG, Subtarget, SDLoc(N), VT,
-                                              {LHS, RHS}, HOpBuilder);
-        if (!PostShuffleMask.empty())
-          HorizBinOp = DAG.getVectorShuffle(VT, SDLoc(HorizBinOp), HorizBinOp,
-                                            DAG.getUNDEF(VT), PostShuffleMask);
-        return HorizBinOp;
-      }
-    }
-    break;
   case ISD::SADDSAT:
   case ISD::SSUBSAT:
-    if (Subtarget.hasSSSE3() && VT == MVT::v8i16) {
-      SDValue LHS = N->getOperand(0);
-      SDValue RHS = N->getOperand(1);
-      auto HorizOpcode = IsAdd ? X86ISD::HADDS : X86ISD::HSUBS;
-      if (isHorizontalBinOp(HorizOpcode, LHS, RHS, DAG, Subtarget, IsAdd,
-                            PostShuffleMask, MergableHorizOp(HorizOpcode))) {
-        auto HOpBuilder = [HorizOpcode](SelectionDAG &DAG, const SDLoc &DL,
-                                        ArrayRef<SDValue> Ops) {
-          return DAG.getNode(HorizOpcode, DL, Ops[0].getValueType(), Ops);
-        };
-        SDValue HorizBinOp = SplitOpsAndApply(DAG, Subtarget, SDLoc(N), VT,
-                                              {LHS, RHS}, HOpBuilder);
-        if (!PostShuffleMask.empty())
-          HorizBinOp = DAG.getVectorShuffle(VT, SDLoc(HorizBinOp), HorizBinOp,
-                                            DAG.getUNDEF(VT), PostShuffleMask);
-        return HorizBinOp;
-      }
+    if (IsSat && !((Subtarget.hasSSSE3() && VT == MVT::v8i16) ||
+                   (Subtarget.hasAVX2() && VT == MVT::v16i16)))
+      break;
+    if (!IsSat &&
+        !(Subtarget.hasSSSE3() && (VT == MVT::v8i16 || VT == MVT::v4i32 ||
+                                   VT == MVT::v16i16 || VT == MVT::v8i32)))
+      break;
----------------
folkertdev wrote:

That change causes a regression when using only SSSE3 or AVX and providing a wider vector:

```diff
 define <16 x i16> @phsubsw_v16i16_generic(<16 x i16> %a, <16 x i16> %b) {
 ; SSSE3-LABEL: phsubsw_v16i16_generic:
 ; SSSE3:       # %bb.0: # %entry
-; SSSE3-NEXT:    phsubsw xmm0, xmm1
-; SSSE3-NEXT:    phsubsw xmm2, xmm3
-; SSSE3-NEXT:    movdqa xmm1, xmm2
+; SSSE3-NEXT:    movdqa xmm4, xmm0
+; SSSE3-NEXT:    phsubsw xmm1, xmm3
+; SSSE3-NEXT:    phsubsw xmm4, xmm2
+; SSSE3-NEXT:    movdqa xmm0, xmm4
+; SSSE3-NEXT:    punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
+; SSSE3-NEXT:    punpckhqdq {{.*#+}} xmm4 = xmm4[1],xmm1[1]
+; SSSE3-NEXT:    movdqa xmm1, xmm4
 ; SSSE3-NEXT:    ret
```

Here we want the normal mechanism to split the vector, and then apply the logic in this function.

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


More information about the llvm-commits mailing list