[llvm] [X86] Prefer SIMD min/max/abs for scalars when staying in XMM domain (PR #210654)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 13 11:06:48 PDT 2026
================
@@ -54617,6 +54617,97 @@ static SDValue narrowBitOpRMW(StoreSDNode *St, const SDLoc &DL,
return NewStore;
}
+/// Fold store(abs/min/max(load…)) of scalar i16/i32/i64 into SIMD
+/// PABS/PMIN/PMAX to keep memory-bound sort2/abs in the XMM domain.
+static SDValue combineScalarMinMaxAbsStore(StoreSDNode *St, const SDLoc &DL,
+ SelectionDAG &DAG,
+ const X86Subtarget &Subtarget) {
+ if (!ISD::isNormalStore(St))
+ return SDValue();
+
+ SDValue StoredVal = St->getValue();
+ unsigned Opc = StoredVal.getOpcode();
+ bool IsAbs = Opc == ISD::ABS;
+ if ((!IsAbs && !ISD::isMinMaxOpcode(Opc)) || !StoredVal.hasOneUse())
+ return SDValue();
+
+ EVT VT = StoredVal.getValueType();
+ const Function &F = DAG.getMachineFunction().getFunction();
+ if (F.hasFnAttribute(Attribute::NoImplicitFloat) ||
+ Subtarget.useSoftFloat() || F.hasOptSize())
+ return SDValue();
+
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+
+ // Pick the widened vector type; require a legal vector op and that
+ // SCALAR_TO_VECTOR can fold the scalar load into XMM (i32/i64: SSE2
+ // movd/movq; i16: FP16 vmovw). i64 also needs VLX to avoid zmm widen +
+ // vzeroupper.
+ auto getVecVT = [&]() -> std::optional<MVT> {
+ MVT VecVT;
+ if (VT == MVT::i32)
+ VecVT = MVT::v4i32;
+ else if (VT == MVT::i64)
+ VecVT = MVT::v2i64;
+ else if (VT == MVT::i16)
+ VecVT = MVT::v8i16;
+ else
+ return std::nullopt;
+
+ if (VT == MVT::i16 ? !Subtarget.hasFP16() : !Subtarget.hasSSE2())
+ return std::nullopt;
+ if (VT == MVT::i64 && !Subtarget.hasVLX())
+ return std::nullopt;
+ if (!TLI.isOperationLegal(Opc, VecVT))
+ return std::nullopt;
+ return VecVT;
+ };
----------------
RKSimon wrote:
This should be all you need:
```
auto getVecVT = [&]() -> std::optional<MVT> {
MVT VecVT;
if (VT == MVT::i32 && Subtarget.hasSSE2())
VecVT = MVT::v4i32;
else if (VT == MVT::i64 && Subtarget.hasSSE2())
VecVT = MVT::v2i64;
else if (VT == MVT::i16 && Subtarget.hasFP16())
VecVT = MVT::v8i16;
else
return std::nullopt;
if (!DAG.getTargetLoweringInfo().isOperationLegal(Opc, VecVT))
return std::nullopt;
return VecVT;
};
```
https://github.com/llvm/llvm-project/pull/210654
More information about the llvm-commits
mailing list