Skip to content

[mlir][emitc] Support 'emitc::LValueType' in 'emitc::VerbatimOp' #144151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 16, 2025

Conversation

EtoAndruwa
Copy link
Contributor

This PR introduces support for emitc::LvalueType in emitc::VerbatimOp, providing a mechanism to reduce the number of operations required when working with verbatim operations whose arguments are of type emitc::LvalueType.

Before:

emitc.func @foo() {
  %a = "emitc.variable"() <{value = #emitc.opaque<"1">}> : () -> !emitc.lvalue<i32>
  %loaded_a = load %a : !emitc.lvalue<i32>
  emitc.verbatim "{} + {};" args %loaded_a, %loaded_a : i32, i32

  return
}

After:

emitc.func @bar() {
  %a = "emitc.variable"() <{value = #emitc.opaque<"1">}> : () -> !emitc.lvalue<i32>
  emitc.verbatim "{} + {};" args %a, %a : !emitc.lvalue<i32>, !emitc.lvalue<i32>

  return
}

You can now write something like this:

emitc.func @baz() {
  %a = "emitc.variable"() <{value = #emitc.opaque<"1">}> : () -> !emitc.lvalue<i32>
  emitc.verbatim "++{};" args %a : !emitc.lvalue<i32>

  return
}

This PR introduces support for `emitc::LvalueType` in `emitc::VerbatimOp`,
providing a mechanism to reduce the number of operations required when
working with verbatim operations whose arguments are of type `emitc::LvalueType`.

An example of this would be:
```mlir
emitc.func @foo() {
  %a = "emitc.variable"() <{value = #emitc.opaque<"1">}> : () -> !emitc.lvalue<i32>
  emitc.verbatim "++{};" args %a : !emitc.lvalue<i32>

  return
}
```
@llvmbot
Copy link
Member

llvmbot commented Jun 13, 2025

@llvm/pr-subscribers-mlir

@llvm/pr-subscribers-mlir-emitc

Author: Andrey Timonin (EtoAndruwa)

Changes

This PR introduces support for emitc::LvalueType in emitc::VerbatimOp, providing a mechanism to reduce the number of operations required when working with verbatim operations whose arguments are of type emitc::LvalueType.

Before:

emitc.func @<!-- -->foo() {
  %a = "emitc.variable"() &lt;{value = #emitc.opaque&lt;"1"&gt;}&gt; : () -&gt; !emitc.lvalue&lt;i32&gt;
  %loaded_a = load %a : !emitc.lvalue&lt;i32&gt;
  emitc.verbatim "{} + {};" args %loaded_a, %loaded_a : i32, i32

  return
}

After:

emitc.func @<!-- -->bar() {
  %a = "emitc.variable"() &lt;{value = #emitc.opaque&lt;"1"&gt;}&gt; : () -&gt; !emitc.lvalue&lt;i32&gt;
  emitc.verbatim "{} + {};" args %a, %a : !emitc.lvalue&lt;i32&gt;, !emitc.lvalue&lt;i32&gt;

  return
}

You can now write something like this:

emitc.func @<!-- -->baz() {
  %a = "emitc.variable"() &lt;{value = #emitc.opaque&lt;"1"&gt;}&gt; : () -&gt; !emitc.lvalue&lt;i32&gt;
  emitc.verbatim "++{};" args %a : !emitc.lvalue&lt;i32&gt;

  return
}

Full diff: https://github.com/llvm/llvm-project/pull/144151.diff

2 Files Affected:

  • (modified) mlir/include/mlir/Dialect/EmitC/IR/EmitC.td (+1-1)
  • (modified) mlir/test/Dialect/EmitC/ops.mlir (+12-4)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index d4aea52a0d485..e53d3e45875d5 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -1304,7 +1304,7 @@ def EmitC_VerbatimOp : EmitC_Op<"verbatim"> {
     FailureOr<SmallVector<::mlir::emitc::ReplacementItem>> parseFormatString();
   }];
 
-  let arguments = (ins StrAttr:$value, Variadic<EmitCType>:$fmtArgs);
+  let arguments = (ins StrAttr:$value, Variadic<AnyTypeOf<[EmitCType, EmitC_LValueType]>>:$fmtArgs);
 
   let builders = [OpBuilder<(ins "::mlir::StringAttr":$value),
                             [{ build($_builder, $_state, value, {}); }]>];
diff --git a/mlir/test/Dialect/EmitC/ops.mlir b/mlir/test/Dialect/EmitC/ops.mlir
index 36d12e763afc7..2ca7c4bc3bbb5 100644
--- a/mlir/test/Dialect/EmitC/ops.mlir
+++ b/mlir/test/Dialect/EmitC/ops.mlir
@@ -246,12 +246,20 @@ emitc.verbatim "typedef float f32;"
 // The value is not interpreted as format string if there are no operands.
 emitc.verbatim "{} {  }"
 
-func.func @test_verbatim(%arg0 : !emitc.ptr<i32>, %arg1 : i32) {
+func.func @test_verbatim(%arg0 : !emitc.ptr<i32>, %arg1 : i32, %arg3: !emitc.array<3x!emitc.ptr<i32>>) {
+  %a = "emitc.variable"() <{value = #emitc.opaque<"1">}> : () -> !emitc.lvalue<i32>
+
+  // Check that the lvalue type can be used by verbatim.
+  emitc.verbatim "++{};" args %a : !emitc.lvalue<i32>
+
+  // Check that the array type can be used by verbatim.
+  emitc.verbatim "*{}[0] = 1;" args %arg3 : !emitc.array<3x!emitc.ptr<i32>>
+
   emitc.verbatim "{} + {};" args %arg0, %arg1 : !emitc.ptr<i32>, i32
 
-  // Check there is no ambiguity whether %a is the argument to the emitc.verbatim op.
-  emitc.verbatim "a"
-  %a = "emitc.constant"(){value = 42 : i32} : () -> i32
+  // Check there is no ambiguity whether %b is the argument to the emitc.verbatim op.
+  emitc.verbatim "b"
+  %b = "emitc.constant"(){value = 42 : i32} : () -> i32
 
   return
 }

@EtoAndruwa EtoAndruwa changed the title [mlir][emitc] Support 'emitc::LValueType' in 'emitc::verbatimOp' [mlir][emitc] Support 'emitc::LValueType' in 'emitc::VerbatimOp' Jun 13, 2025
Copy link
Member

@marbre marbre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@simon-camp do you see any problem with using an LValue in the VerbatimOp I might miss?

Copy link
Contributor

@mgehre-amd mgehre-amd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

Copy link
Contributor

@simon-camp simon-camp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, besides the Argument Name.

@marbre
Copy link
Member

marbre commented Jun 16, 2025

Build failures seem unrelated.

@EtoAndruwa
Copy link
Contributor Author

Build failures seem unrelated.

Also noticed this.

Flang's test fails:

Failed Tests (1):
  Flang :: Profile/gcc-flag-compatibility.f90

@EtoAndruwa
Copy link
Contributor Author

EtoAndruwa commented Jun 16, 2025

I don't have rights to merge, so someone should merge this. Thanks!

@marbre marbre merged commit 595a273 into llvm:main Jun 16, 2025
8 of 10 checks passed
fschlimb pushed a commit to fschlimb/llvm-project that referenced this pull request Jun 18, 2025
…m#144151)

This PR introduces support for `emitc::LvalueType` in
`emitc::VerbatimOp`, providing a mechanism to reduce the number of
operations required when working with verbatim operations whose
arguments are of type `emitc::LvalueType`.

Before:
```mlir
emitc.func @foo() {
  %a = "emitc.variable"() <{value = #emitc.opaque<"1">}> : () -> !emitc.lvalue<i32>
  %loaded_a = load %a : !emitc.lvalue<i32>
  emitc.verbatim "{} + {};" args %loaded_a, %loaded_a : i32, i32

  return
}
```

After:
```mlir
emitc.func @bar() {
  %a = "emitc.variable"() <{value = #emitc.opaque<"1">}> : () -> !emitc.lvalue<i32>
  emitc.verbatim "{} + {};" args %a, %a : !emitc.lvalue<i32>, !emitc.lvalue<i32>

  return
}
```

You can now write something like this:
```mlir
emitc.func @baz() {
  %a = "emitc.variable"() <{value = #emitc.opaque<"1">}> : () -> !emitc.lvalue<i32>
  emitc.verbatim "++{};" args %a : !emitc.lvalue<i32>

  return
}
```
akuhlens pushed a commit to akuhlens/llvm-project that referenced this pull request Jun 24, 2025
…m#144151)

This PR introduces support for `emitc::LvalueType` in
`emitc::VerbatimOp`, providing a mechanism to reduce the number of
operations required when working with verbatim operations whose
arguments are of type `emitc::LvalueType`.

Before:
```mlir
emitc.func @foo() {
  %a = "emitc.variable"() <{value = #emitc.opaque<"1">}> : () -> !emitc.lvalue<i32>
  %loaded_a = load %a : !emitc.lvalue<i32>
  emitc.verbatim "{} + {};" args %loaded_a, %loaded_a : i32, i32

  return
}
```

After:
```mlir
emitc.func @bar() {
  %a = "emitc.variable"() <{value = #emitc.opaque<"1">}> : () -> !emitc.lvalue<i32>
  emitc.verbatim "{} + {};" args %a, %a : !emitc.lvalue<i32>, !emitc.lvalue<i32>

  return
}
```

You can now write something like this:
```mlir
emitc.func @baz() {
  %a = "emitc.variable"() <{value = #emitc.opaque<"1">}> : () -> !emitc.lvalue<i32>
  emitc.verbatim "++{};" args %a : !emitc.lvalue<i32>

  return
}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants