[Mlir-commits] [mlir] [MLIR] Implement emulation of static indexing subbyte type vector stores (PR #115922)
Andrzej WarzyĆski
llvmlistbot at llvm.org
Wed Dec 4 08:27:43 PST 2024
================
@@ -309,6 +314,90 @@ emulatedVectorLoad(OpBuilder &rewriter, Location loc, Value base,
newLoad);
}
+/// Emits `memref.generic_atomic_rmw` op to store a subbyte-sized value to a
+/// byte in memory, with a mask. The `valueToStore` is a vector of subbyte-sized
+/// elements, with size of 8 bits, and the mask is used to select which elements
+/// to store.
+///
+/// Before:
+/// memory = |ab|cd|ef|12| : <4xi2> (<1xi8>)
+/// valueToStore = |01|23|45|67| : vector<4xi2>
+/// mask = |0|0|1|1| : vector<4xi1>
+/// After:
+/// memory = |ab|cd|45|67| : <4xi2> (<1xi8>)
+static void atomicStore(OpBuilder &builder, Location loc,
+ MemRefValue linearizedMemref, Value linearizedIndex,
+ VectorValue valueToStore, Value mask,
+ int64_t numSrcElemsPerDest) {
+ auto atomicOp = builder.create<memref::GenericAtomicRMWOp>(
+ loc, linearizedMemref, ValueRange{linearizedIndex});
+ Value origValue = atomicOp.getCurrentValue();
+
+ OpBuilder::InsertionGuard guard(builder);
+ builder.setInsertionPointToStart(atomicOp.getBody());
+
+ // i8 -> <1xi8> -> <numSrcElemsPerDest x i.>:
+ auto oneVectorType = VectorType::get({1}, origValue.getType());
+ auto fromElem = builder.create<vector::FromElementsOp>(loc, oneVectorType,
+ ValueRange{origValue});
+ auto vectorBitCast =
+ builder.create<vector::BitCastOp>(loc, valueToStore.getType(), fromElem);
+
+ auto select =
+ builder.create<arith::SelectOp>(loc, mask, valueToStore, vectorBitCast);
+ auto bitcast2 = builder.create<vector::BitCastOp>(loc, oneVectorType, select);
+ auto extract = builder.create<vector::ExtractOp>(loc, bitcast2, 0);
+ builder.create<memref::AtomicYieldOp>(loc, extract.getResult());
+}
+
+/// Generate a non-atomic read-modify-write sequence for subbyte storing.
+/// It has similar logic to `atomicStore`, but without the atomicity.
+static void rmwStore(OpBuilder &rewriter, Location loc,
+ MemRefValue linearizedMemref, Value linearizedIndex,
+ VectorValue value, Value mask,
+ int64_t numSrcElemsPerDest) {
+ auto emulatedIOType =
+ VectorType::get({1}, linearizedMemref.getType().getElementType());
+ auto elemLoad = rewriter.create<vector::LoadOp>(
+ loc, emulatedIOType, linearizedMemref, ValueRange{linearizedIndex});
+ auto fromBitcast = rewriter.create<vector::BitCastOp>(
+ loc,
+ VectorType::get({numSrcElemsPerDest}, value.getType().getElementType()),
+ elemLoad);
+ auto select = rewriter.create<arith::SelectOp>(loc, mask, fromBitcast, value);
+ auto toBitcast =
+ rewriter.create<vector::BitCastOp>(loc, emulatedIOType, select);
+ rewriter.create<vector::StoreOp>(loc, toBitcast, linearizedMemref,
+ linearizedIndex);
+}
+
+/// Extract a slice from vector `vector`, with the size of `sliceNumElements`,
+/// and insert it into a zero, byte vector at offset `byteOffset`. For example:
----------------
banach-space wrote:
```suggestion
/// Extract `sliceNumElements` from `vector`,
/// and insert it into an empty vector at offset `byteOffset`.
```
? What's the difference between `sliceOffset` and `byteOffset`?
https://github.com/llvm/llvm-project/pull/115922
More information about the Mlir-commits
mailing list