@@ -257,6 +257,95 @@ expressing `vector`s in the IR directly and simple pattern-rewrites.
257257[ EDSC] ( https://github.com/llvm/llvm-project/blob/main/mlir/docs/EDSC.md ) s
258258provide a simple way of driving such a notional language directly in C++.
259259
260+ ### Taxonomy for "Read"/"Write" Operations
261+
262+ Below is a list of vector dialect operations that move values from an abstract
263+ ** source** to an abstract ** destination** (i.e., these are "read"/"write"
264+ operations):
265+
266+ * ` vector.load ` , ` vector.store ` , ` vector.transfer_read ` ,
267+ ` vector.transfer_write ` , ` vector.gather ` , ` vector.scatter ` ,
268+ ` vector.compressstore ` , ` vector.expandload ` , ` vector.maskedload ` ,
269+ ` vector.maskedstore ` , ` vector.extract ` , ` vector.insert ` ,
270+ ` vector.scalable_extract ` , ` vector.scalable_insert ` ,
271+ ` vector.extract_strided_slice ` , ` vector.insert_strided_slice ` .
272+
273+ Additionally, "write" operation require "value-to-store" as an argument.
274+
275+ #### Current Naming in Vector Dialect
276+ | ** Vector Dialect Op** | ** Operand Names** | ** Operand Types** | ** Result Name** | ** Result Type** |
277+ | --------------------------------| --------------------------| -------------------------------| ------------------| ----------------------|
278+ | ` vector.load ` | ` base ` | ` memref ` | ` result ` | ` vector ` |
279+ | ` vector.store ` | ` valueToStore ` , ` base ` | ` vector ` , ` memref ` | - | - |
280+ | ` vector.transfer_read ` | ` source ` | ` memref ` / ` tensor ` | ` vector ` | ` vector ` |
281+ | ` vector.transfer_write ` | ` vector ` , ` source ` | ` vector ` , ` memref ` / ` tensor ` | ` result ` | ` vector ` |
282+ | ` vector.gather ` | ` base ` | ` memref ` | ` result ` | ` vector ` |
283+ | ` vector.scatter ` | ` valueToStore ` , ` base ` | ` vector ` , ` memref ` | - | - |
284+ | ` vector.expandload ` | ` base ` | ` memref ` | ` result ` | ` vector ` |
285+ | ` vector.compressstore ` | ` valueToStore ` ,` base ` | ` vector ` , ` memref ` | - | - |
286+ | ` vector.maskedload ` | ` base ` | ` memref ` | ` result ` | ` vector ` |
287+ | ` vector.maskedstore ` | ` valueToStore ` , ` base ` | ` vector ` , ` memref ` | - | - |
288+ | ` vector.extract ` | ` vector ` | ` vector ` | ` result ` | ` scalar ` / ` vector ` |
289+ | ` vector.insert ` | ` source ` , ` dest ` | ` scalar ` / ` vector ` , ` vector ` | ` result ` | ` vector ` |
290+ | ` vector.scalable_extract ` | ` source ` | ` vector ` | ` res ` | ` scalar ` / ` vector ` |
291+ | ` vector.scalable_insert ` | ` source ` , ` dest ` | ` scalar ` / ` vector ` , ` vector ` | ` res ` | ` vector ` |
292+ | ` vector.extract_strided_slice ` | ` vector ` | ` vector ` | (missing name) | ` vector ` |
293+ | ` vector.insert_strided_slice ` | ` source ` , ` dest ` | ` vector ` | ` res ` | ` vector ` |
294+
295+ Note that "read" operations take one operand ("from"), whereas "write"
296+ operations require two ("value-to-store" and "to").
297+
298+ ### Observations
299+ Each "read" operation has a "from" argument, while each "write" operation has a
300+ "to" and a "value-to-store" operand. However, the naming conventions are
301+ ** inconsistent** , making it difficult to extract common patterns or determine
302+ operand roles. Here are some inconsistencies:
303+
304+ - ` getBase() ` in ` vector.load ` refers to the ** "from"** operand (source).
305+ - ` getBase() ` in ` vector.store ` refers to the ** "to"** operand (destination).
306+ - ` vector.transfer_read ` and ` vector.transfer_write ` use ` getSource() ` , which:
307+ - ** Conflicts** with the ` vector.load ` / ` vector.store ` naming pattern.
308+ - ** Does not clearly indicate** whether the operand represents a ** source**
309+ or ** destination** .
310+ - ` vector.insert ` defines ` getSource() ` and ` getDest() ` , making the distinction
311+ between "to" and "from" operands ** clear** . However, its sibling operation,
312+ ` vector.extract ` , only defines ` getVector() ` , making it unclear whether it
313+ represents a ** source** or ** destination** .
314+ - ` vector.store ` uses ` getValueToStore() ` , whereas
315+ ` vector.insert_strided_slice ` does not.
316+
317+ There is ** no consistent way** to identify:
318+ - ` "from" ` (read operand)
319+ - ` "to" ` (write operand)
320+ - ` "value-to-store" ` (written value)
321+
322+ ### Indexed vs. Non-Indexed Taxonomy
323+ A more consistent way to classify "to", "from", and "value-to-store" arguments
324+ is by determining whether an operand is _ indexed_ or _ non-indexed_ .
325+
326+ #### ** Example: ` vector.transfer_read ` and ` vector.transfer_write ` **
327+ ``` mlir
328+ Indexed Operand
329+ |
330+ vector.transfer_read %A[%expr1, %expr2, %expr3, %expr4]
331+ { permutation_map : (d0,d1,d2,d3) -> (d2,0,d0) } :
332+ memref<?x?x?x?xf32>, vector<3x4x5xf32>
333+
334+ Non-Indexed Operand Indexed Operand
335+ \ /
336+ vector.transfer_write %4, %arg1[%c3, %c3]
337+ {permutation_map = (d0, d1)->(d0, d1)}
338+ : vector<1x1x4x3xf32>, memref<?x?xvector<4x3xf32>>
339+ ```
340+
341+ Using the "indexed" vs. "non-indexed" classification, we can systematically
342+ differentiate between "to", "from" and "value-to-store" arguments across
343+ operations:
344+ * "to" is always _ indexed_ for "write" operations, "value-to-store" is
345+ _ non-indexed_ ,
346+ * "from" is always _ indexed_ for "read" operations.
347+
348+
260349## Bikeshed Naming Discussion
261350
262351There are arguments against naming an n-D level of abstraction ` vector ` because
0 commit comments