@@ -1761,6 +1761,70 @@ struct VectorInterleaveOpLowering
1761
1761
}
1762
1762
};
1763
1763
1764
+ // / Conversion pattern for a `vector.deinterleave`.
1765
+ // / This supports for fixed-sized vectors and scalable vectors.
1766
+ struct VectorDeinterleaveOpLowering
1767
+ : public ConvertOpToLLVMPattern<vector::DeinterleaveOp> {
1768
+ using ConvertOpToLLVMPattern::ConvertOpToLLVMPattern;
1769
+
1770
+ LogicalResult
1771
+ matchAndRewrite (vector::DeinterleaveOp deinterleaveOp, OpAdaptor adaptor,
1772
+ ConversionPatternRewriter &rewriter) const override {
1773
+ VectorType resultType = deinterleaveOp.getResultVectorType ();
1774
+ VectorType sourceType = deinterleaveOp.getSourceVectorType ();
1775
+ auto loc = deinterleaveOp.getLoc ();
1776
+
1777
+ // Note: n-D deinterleave operations should be lowered to the 1-D before
1778
+ // converting to LLVM.
1779
+ if (resultType.getRank () != 1 )
1780
+ return rewriter.notifyMatchFailure (deinterleaveOp,
1781
+ " DeinterleaveOp not rank 1" );
1782
+
1783
+ if (resultType.isScalable ()) {
1784
+ auto llvmTypeConverter = this ->getTypeConverter ();
1785
+ auto deinterleaveResults = deinterleaveOp.getResultTypes ();
1786
+ auto packedOpResults =
1787
+ llvmTypeConverter->packOperationResults (deinterleaveResults);
1788
+ auto intrinsic = rewriter.create <LLVM::vector_deinterleave2>(
1789
+ loc, packedOpResults, adaptor.getSource ());
1790
+
1791
+ auto evenResult = rewriter.create <LLVM::ExtractValueOp>(
1792
+ loc, intrinsic->getResult (0 ), 0 );
1793
+ auto oddResult = rewriter.create <LLVM::ExtractValueOp>(
1794
+ loc, intrinsic->getResult (0 ), 1 );
1795
+
1796
+ rewriter.replaceOp (deinterleaveOp, ValueRange{evenResult, oddResult});
1797
+ return success ();
1798
+ }
1799
+ // Lower fixed-size deinterleave to two shufflevectors. While the
1800
+ // vector.deinterleave2 intrinsic supports fixed and scalable vectors, the
1801
+ // langref still recommends fixed-vectors use shufflevector, see:
1802
+ // https://llvm.org/docs/LangRef.html#id889.
1803
+ int64_t resultVectorSize = resultType.getNumElements ();
1804
+ SmallVector<int32_t > evenShuffleMask;
1805
+ SmallVector<int32_t > oddShuffleMask;
1806
+
1807
+ evenShuffleMask.reserve (resultVectorSize);
1808
+ oddShuffleMask.reserve (resultVectorSize);
1809
+
1810
+ for (int i = 0 ; i < sourceType.getNumElements (); ++i) {
1811
+ if (i % 2 == 0 )
1812
+ evenShuffleMask.push_back (i);
1813
+ else
1814
+ oddShuffleMask.push_back (i);
1815
+ }
1816
+
1817
+ auto poison = rewriter.create <LLVM::PoisonOp>(loc, sourceType);
1818
+ auto evenShuffle = rewriter.create <LLVM::ShuffleVectorOp>(
1819
+ loc, adaptor.getSource (), poison, evenShuffleMask);
1820
+ auto oddShuffle = rewriter.create <LLVM::ShuffleVectorOp>(
1821
+ loc, adaptor.getSource (), poison, oddShuffleMask);
1822
+
1823
+ rewriter.replaceOp (deinterleaveOp, ValueRange{evenShuffle, oddShuffle});
1824
+ return success ();
1825
+ }
1826
+ };
1827
+
1764
1828
} // namespace
1765
1829
1766
1830
// / Populate the given list with patterns that convert from Vector to LLVM.
@@ -1785,8 +1849,8 @@ void mlir::populateVectorToLLVMConversionPatterns(
1785
1849
VectorExpandLoadOpConversion, VectorCompressStoreOpConversion,
1786
1850
VectorSplatOpLowering, VectorSplatNdOpLowering,
1787
1851
VectorScalableInsertOpLowering, VectorScalableExtractOpLowering,
1788
- MaskedReductionOpConversion, VectorInterleaveOpLowering>(
1789
- converter);
1852
+ MaskedReductionOpConversion, VectorInterleaveOpLowering,
1853
+ VectorDeinterleaveOpLowering>( converter);
1790
1854
// Transfer ops with rank > 1 are handled by VectorToSCF.
1791
1855
populateVectorTransferLoweringPatterns (patterns, /* maxTransferRank=*/ 1 );
1792
1856
}
0 commit comments