[Mlir-commits] [mlir] [mlir][SPIR-V][VectorToSPIRV] Add conversion patterns for vector.gather/scatter to SPIR-V (PR #193422)
Jakub Kuderski
llvmlistbot at llvm.org
Wed May 6 13:55:25 PDT 2026
================
@@ -853,6 +853,175 @@ struct VectorStoreOpConverter final
}
};
+struct VectorGatherOpConverter final
+ : public OpConversionPattern<vector::GatherOp> {
+ using Base::Base;
+
+ LogicalResult
+ matchAndRewrite(vector::GatherOp gatherOp, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ // Only support 1-D result vectors.
+ auto vectorType = gatherOp.getVectorType();
+ if (vectorType.getRank() != 1)
+ return rewriter.notifyMatchFailure(gatherOp,
+ "only 1-D vectors supported");
+
+ // Only support memref base (not tensor).
+ auto memrefType = dyn_cast<MemRefType>(gatherOp.getBaseType());
+ if (!memrefType)
+ return rewriter.notifyMatchFailure(gatherOp,
+ "only memref base supported");
+
+ auto attr =
+ dyn_cast_or_null<spirv::StorageClassAttr>(memrefType.getMemorySpace());
+ if (!attr)
+ return rewriter.notifyMatchFailure(gatherOp,
+ "expected spirv.storage_class");
+
+ const auto &typeConverter = *getTypeConverter<SPIRVTypeConverter>();
+ if (!typeConverter.getTargetEnv().allows(
+ spirv::Extension::SPV_INTEL_masked_gather_scatter))
+ return rewriter.notifyMatchFailure(gatherOp,
+ "target environment does not enable "
+ "SPV_INTEL_masked_gather_scatter");
+ auto loc = gatherOp.getLoc();
+
+ // Compute base element pointer from memref + offsets.
+ Value basePtr =
+ spirv::getElementPtr(typeConverter, memrefType, adaptor.getBase(),
+ adaptor.getOffsets(), loc, rewriter);
+ if (!basePtr)
+ return rewriter.notifyMatchFailure(gatherOp,
+ "failed to get element pointer");
+
+ // Convert element type and construct pointer vector type.
+ auto storageClass = attr.getValue();
+ Type elementType = typeConverter.convertType(memrefType.getElementType());
+ if (!elementType)
+ return rewriter.notifyMatchFailure(gatherOp, "unsupported element type");
+ auto ptrType = spirv::PointerType::get(elementType, storageClass);
+ int64_t numElements = vectorType.getDimSize(0);
+ auto ptrVectorType = VectorType::get({numElements}, ptrType);
+
+ // Build pointer vector: for each index, compute ptr via PtrAccessChain.
+ auto indexType = typeConverter.getIndexType();
+ SmallVector<Value> pointers;
+ for (int64_t i = 0; i < numElements; ++i) {
+ auto i32Type = rewriter.getI32Type();
+ Value idx = spirv::ConstantOp::create(rewriter, loc, i32Type,
+ rewriter.getI32IntegerAttr(i));
+ Value scalarIndex = spirv::VectorExtractDynamicOp::create(
+ rewriter, loc, adaptor.getIndices(), idx);
+ // Cast index to the SPIR-V index type if needed.
+ if (scalarIndex.getType() != indexType)
+ scalarIndex =
+ spirv::SConvertOp::create(rewriter, loc, indexType, scalarIndex);
+ Value ptr = spirv::PtrAccessChainOp::create(rewriter, loc, basePtr,
+ scalarIndex, /*indices=*/{});
+ pointers.push_back(ptr);
----------------
kuhar wrote:
Have you confirmed this produces the same addresses at the llvm lowering? vector.gather is underspecified for non-1d and non-stride-1 memrefs/tensors, so maybe it would be better to restrict this to 1d types only for the time being... See https://discourse.llvm.org/t/rfc-vector-gather-vector-scatter-must-take-multiple-index-vectors/90728
cc: @krzysz00
https://github.com/llvm/llvm-project/pull/193422
More information about the Mlir-commits
mailing list