[llvm] [AArch64] Eliminate XTN/SSHLL for vector splats (PR #180913)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 12 01:09:56 PST 2026
================
@@ -24022,6 +24022,74 @@ static SDValue performZExtUZPCombine(SDNode *N, SelectionDAG &DAG) {
return DAG.getNode(ISD::AND, DL, VT, BC, DAG.getConstant(Mask, DL, VT));
}
+// Combine:
+// ext(duplane(insert_subvector(undef, trunc(X), 0), idx))
+// Into:
+// duplane(X, idx)
+// This eliminates XTN/SSHLL sequences when splatting from boolean vectors.
+static SDValue performExtendDuplaneTruncCombine(SDNode *N, SelectionDAG &DAG) {
+ SDValue Dup = N->getOperand(0);
+ unsigned DupOpc = Dup.getOpcode();
+ if (!Dup->hasOneUse() ||
+ (DupOpc != AArch64ISD::DUPLANE8 && DupOpc != AArch64ISD::DUPLANE16 &&
+ DupOpc != AArch64ISD::DUPLANE32))
+ return SDValue();
+
+ SDValue Insert = Dup.getOperand(0);
+ if (!Insert.hasOneUse() || Insert.getOpcode() != ISD::INSERT_SUBVECTOR ||
+ !Insert.getOperand(0).isUndef() || !isNullConstant(Insert.getOperand(2)))
+ return SDValue();
+
+ SDValue Trunc = Insert.getOperand(1);
+ if (!Trunc.hasOneUse() || Trunc.getOpcode() != ISD::TRUNCATE)
+ return SDValue();
+
+ SDValue Src = Trunc.getOperand(0);
+ EVT SrcVT = Src.getValueType();
+ EVT DstVT = N->getValueType(0);
+ if (SrcVT != DstVT || !SrcVT.isFixedLengthVector())
+ return SDValue();
+
+ // Verify that Src is already sign/zero-extended from the truncated bit width.
+ EVT TruncVT = Trunc.getValueType();
+ unsigned SrcBits = SrcVT.getScalarSizeInBits();
+ unsigned TruncBits = TruncVT.getScalarSizeInBits();
+ if (N->getOpcode() == ISD::SIGN_EXTEND) {
+ if (DAG.ComputeNumSignBits(Src) <= SrcBits - TruncBits)
+ return SDValue();
+ } else if (N->getOpcode() == ISD::ZERO_EXTEND) {
+ APInt Mask = APInt::getHighBitsSet(SrcBits, SrcBits - TruncBits);
+ if (!DAG.MaskedValueIsZero(Src, Mask))
+ return SDValue();
+ } else {
+ assert(N->getOpcode() == ISD::ANY_EXTEND);
+ }
+
+ unsigned NewDupOpc;
+ switch (SrcVT.getScalarSizeInBits()) {
+ case 16:
+ NewDupOpc = AArch64ISD::DUPLANE16;
+ break;
+ case 32:
+ NewDupOpc = AArch64ISD::DUPLANE32;
+ break;
+ case 64:
+ NewDupOpc = AArch64ISD::DUPLANE64;
+ break;
+ default:
+ return SDValue();
+ }
+
+ SDLoc DL(N);
+ EVT WideVT = SrcVT.is64BitVector()
----------------
davemgreen wrote:
I think that due to the legal types, providing that we are not using DUPLANE with VLS 256+bit vectors, SrcVT should always be 128bit? So the insert below is a nop too.
It might be worth checking the initial DstVT is a 128bit vector above to make sure nothing goes wrong with longer vectors enabled. And then this getDoubleNumVectorElementsVT / INSERT_SUBVECTOR is unnecessary.
https://github.com/llvm/llvm-project/pull/180913
More information about the llvm-commits
mailing list