[llvm] [RISCV] Improve lowering of spread(2) shuffles (PR #118658)
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 4 07:52:56 PST 2024
================
@@ -5331,17 +5331,36 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG,
// Extract the halves of the vectors.
MVT HalfVT = VT.getHalfNumVectorElementsVT();
+ // Recognize if one half is actually undef; the matching above will
+ // otherwise reuse the even stream for the undef one. This improves
+ // spread(2) shuffles.
+ bool EvenIsUndef = true, OddIsUndef = true;
+ for (unsigned i = 0; i < Mask.size(); i++) {
+ if (i % 2 == 0)
+ EvenIsUndef &= (Mask[i] == -1);
+ else
+ OddIsUndef &= (Mask[i] == -1);
+ }
+
int Size = Mask.size();
SDValue EvenV, OddV;
- assert(EvenSrc >= 0 && "Undef source?");
- EvenV = (EvenSrc / Size) == 0 ? V1 : V2;
- EvenV = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HalfVT, EvenV,
- DAG.getVectorIdxConstant(EvenSrc % Size, DL));
-
- assert(OddSrc >= 0 && "Undef source?");
- OddV = (OddSrc / Size) == 0 ? V1 : V2;
- OddV = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HalfVT, OddV,
- DAG.getVectorIdxConstant(OddSrc % Size, DL));
+ if (EvenIsUndef) {
+ EvenV = DAG.getUNDEF(HalfVT);
+ } else {
+ assert(EvenSrc >= 0 && "Undef source?");
+ EvenV = (EvenSrc / Size) == 0 ? V1 : V2;
+ EvenV = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HalfVT, EvenV,
+ DAG.getVectorIdxConstant(EvenSrc % Size, DL));
+ }
+
+ if (OddIsUndef) {
+ OddV = DAG.getUNDEF(HalfVT);
+ } else {
+ assert(OddSrc >= 0 && "Undef source?");
+ OddV = (OddSrc / Size) == 0 ? V1 : V2;
+ OddV = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HalfVT, OddV,
+ DAG.getVectorIdxConstant(OddSrc % Size, DL));
+ }
return getWideningInterleave(EvenV, OddV, DL, DAG, Subtarget);
----------------
preames wrote:
Note that we already have the required undef handling in getWideningInterleave because it's used by the deinterleave2 intrinsic lowering.
https://github.com/llvm/llvm-project/pull/118658
More information about the llvm-commits
mailing list