[Mlir-commits] [mlir] [mlir][Transforms] Dialect Conversion: No target mat. for 1:N replacement (PR #117513)

Matthias Springer llvmlistbot at llvm.org
Mon Nov 25 18:26:35 PST 2024


================
@@ -199,24 +211,34 @@ LLVMTypeConverter::LLVMTypeConverter(MLIRContext *ctx,
     // original memref type.
     return builder.create<UnrealizedConversionCastOp>(loc, resultType, desc)
         .getResult(0);
-  });
-  // Add generic source and target materializations to handle cases where
-  // non-LLVM types persist after an LLVM conversion.
-  addSourceMaterialization([&](OpBuilder &builder, Type resultType,
-                               ValueRange inputs, Location loc) {
-    if (inputs.size() != 1)
-      return Value();
+  };
 
-    return builder.create<UnrealizedConversionCastOp>(loc, resultType, inputs)
-        .getResult(0);
-  });
+  // Argument materializations convert from the new block argument types
+  // (multiple SSA values that make up a memref descriptor) back to the
+  // original block argument type.
+  addArgumentMaterialization(unrakedMemRefMaterialization);
+  addArgumentMaterialization(rankedMemRefMaterialization);
+  addSourceMaterialization(unrakedMemRefMaterialization);
+  addSourceMaterialization(rankedMemRefMaterialization);
+
+  // Bare pointer -> Packed MemRef descriptor
----------------
matthias-springer wrote:

"Legality" is a bit of a misnomer in the context of types. Legality is a property of operations (specified via `ConversionTarget`), not types. The type converter converts a type `A` to a type `B`. When when we say "type B is legal", we usually mean that "type B is converted to type B". But we should really say "type B is legal for type A".

Example: In the LLVM type converter, we have the following type conversion rule:
```
ranked memref -> !llvm.struct
```

However, when the bare pointer calling convention is enabled, the `func.func` conversion pattern converts ranked memref block arguments to `!llvm.ptr` block arguments (instead of `!llvm.struct`).

Is `!llvm.ptr` a legal type? Yes, because `!llvm.ptr` converts to `!llvm.ptr`. Is it a legal type for a ranked memref? No, because the type conversion rule states that ranked memrefs should be converted to `!llvm.struct`. And all subsequent lowering patterns expect to receive an `!llvm.struct` from the adaptor. (It's just that the `func.func` conversion pattern chose to convert the memref block argument in a different way.)

> Am I right that this is an issue with the `builtin.unrealized_cast` simplifications? I.e. `!llvm.ptr -> memref -> !llvm.struct` being simplified to `!llvm.ptr -> !llvm.struct`, making this target materialization required?

Not quite. In the case of a bare pointer, there is only one materialization. (There used to be the two materializations that you described.) This is the lowering flow:
1. `func.func` lowering pattern replaces ranked memref block argument with `!llvm.ptr` block argument. No materialization is inserted. That's new. Before this PR, we used to insert an argument materialization and a target materialization. But these materializations are not necessary and increase the complexity of the driver. The argument materialization is not needed because it's a 1:1 replacement. The target materialization is not needed because the lowering pattern of the user of the block argument will insert it.
2. User of memref block argument is lowered. The type converter states that the ranked memref should be converted to `!llvm.struct`, but the pattern finds an `!llvm.ptr` instead. Therefore, it inserts a target materialization from `!llvm.ptr` -> `!llvm.struct`. (This functionality is in `remapValues`.)

Side note: For 1:N replacements (e.g., ranked memref block argument *without* bare pointer calling convention), we still insert an argument materialization in Step 1.


https://github.com/llvm/llvm-project/pull/117513


More information about the Mlir-commits mailing list