Skip to content

Conversation

@Men-cotton
Copy link
Contributor

@Men-cotton Men-cotton commented Dec 22, 2025

Update NVVMTargetAttr builder in NVVMOps.td to use $_get instead of Base::get.

Now the auto-generated parser calls getChecked, allowing graceful error handling for invalid parameters (e.g., O=4) instead of crashing with an assertion failure.

Add a regression test in mlir/test/Dialect/LLVMIR/nvvm-target-invalid.mlir.

Fixes: #130014

@llvmbot
Copy link
Member

llvmbot commented Dec 22, 2025

@llvm/pr-subscribers-mlir

@llvm/pr-subscribers-mlir-llvm

Author: Akimasa Watanuki (Men-cotton)

Changes

Relax NVVMTargetAttr::verify to accept any integer value for optLevel, preventing parser crashes on invalid inputs (e.g., O=4).

Move the strict range check (0-3) to NVVMTargetAttr::verifyTarget. This ensures that invalid optimization levels are reported as graceful errors during module verification.

Add a regression test in attach-targets.mlir.

Fixes: #130014


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

2 Files Affected:

  • (modified) mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp (+5-4)
  • (modified) mlir/test/Dialect/LLVMIR/attach-targets.mlir (+18-9)
diff --git a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
index 331d7a244310f..95451c5c7f4d1 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
@@ -5537,10 +5537,6 @@ NVVMTargetAttr::verify(function_ref<InFlightDiagnostic()> emitError,
                        int optLevel, StringRef triple, StringRef chip,
                        StringRef features, DictionaryAttr flags,
                        ArrayAttr files, bool verifyTarget) {
-  if (optLevel < 0 || optLevel > 3) {
-    emitError() << "The optimization level must be a number between 0 and 3.";
-    return failure();
-  }
   if (triple.empty()) {
     emitError() << "The target triple cannot be empty.";
     return failure();
@@ -5559,6 +5555,11 @@ NVVMTargetAttr::verify(function_ref<InFlightDiagnostic()> emitError,
 }
 
 LogicalResult NVVMTargetAttr::verifyTarget(Operation *gpuModule) {
+  if (getO() < 0 || getO() > 3) {
+    return emitError(
+        gpuModule->getLoc(),
+        "The optimization level must be a number between 0 and 3.");
+  }
   if (!getVerifyTarget())
     return success();
 
diff --git a/mlir/test/Dialect/LLVMIR/attach-targets.mlir b/mlir/test/Dialect/LLVMIR/attach-targets.mlir
index d1112f7411aae..753a00085d7bf 100644
--- a/mlir/test/Dialect/LLVMIR/attach-targets.mlir
+++ b/mlir/test/Dialect/LLVMIR/attach-targets.mlir
@@ -1,38 +1,47 @@
-// RUN: mlir-opt %s --nvvm-attach-target='module=nvvm.* O=3 chip=sm_90' --rocdl-attach-target='module=rocdl.* O=3 chip=gfx90a' --xevm-attach-target='module=xevm.* O=3 chip=pvc' | FileCheck %s
-// RUN: mlir-opt %s --nvvm-attach-target='module=options.* O=1 chip=sm_70 fast=true ftz=true' --rocdl-attach-target='module=options.* l=file1.bc,file2.bc wave64=false finite-only=true' --xevm-attach-target='module=options.* O=1 chip=pvc' | FileCheck %s --check-prefix=CHECK_OPTS
+// RUN: mlir-opt %s --nvvm-attach-target='module=nvvm.* O=3 chip=sm_90' --rocdl-attach-target='module=rocdl.* O=3 chip=gfx90a' --xevm-attach-target='module=xevm.* O=3 chip=pvc' -split-input-file -verify-diagnostics | FileCheck %s
+// RUN: mlir-opt %s --nvvm-attach-target='module=options.* O=1 chip=sm_70 fast=true ftz=true' --rocdl-attach-target='module=options.* l=file1.bc,file2.bc wave64=false finite-only=true' --xevm-attach-target='module=options.* O=1 chip=pvc' -split-input-file -verify-diagnostics | FileCheck %s --check-prefix=CHECK_OPTS
+// RUN: mlir-opt %s --nvvm-attach-target -verify-diagnostics -split-input-file
 
 module attributes {gpu.container_module} {
 // Verify the target is appended.
-// CHECK: @nvvm_module_1 [#nvvm.target<O = 3, chip = "sm_90">] {
+// CHECK: @nvvm_module_1 [#nvvm.target<O = 3, chip = "sm_90">]
 gpu.module @nvvm_module_1 {
 }
 // Verify the target is appended.
-// CHECK: @nvvm_module_2 [#nvvm.target<chip = "sm_60">, #nvvm.target<O = 3, chip = "sm_90">] {
+// CHECK: @nvvm_module_2 [#nvvm.target<chip = "sm_60">, #nvvm.target<O = 3, chip = "sm_90">]
 gpu.module @nvvm_module_2 [#nvvm.target<chip = "sm_60">] {
 }
 // Verify the target is not added multiple times.
-// CHECK: @nvvm_module_3 [#nvvm.target<O = 3, chip = "sm_90">] {
+// CHECK: @nvvm_module_3 [#nvvm.target<O = 3, chip = "sm_90">]
 gpu.module @nvvm_module_3 [#nvvm.target<O = 3, chip = "sm_90">] {
 }
 // Verify the NVVM target is not added as it fails to match the regex, but the ROCDL does get appended.
-// CHECK: @rocdl_module [#rocdl.target<O = 3, chip = "gfx90a">] {
+// CHECK: @rocdl_module [#rocdl.target<O = 3, chip = "gfx90a">]
 gpu.module @rocdl_module {
 }
 // Verify that other targets are not added as they fail to match the regex, but XeVM does get appended.
-// CHECK: @xevm_module [#xevm.target<O = 3, chip = "pvc">] {
+// CHECK: @xevm_module [#xevm.target<O = 3, chip = "pvc">]
 gpu.module @xevm_module {
 }
 // Check the options were added.
 // CHECK_OPTS: @options_module_1 [#nvvm.target<O = 1, chip = "sm_70", flags = {fast, ftz}>,
 // CHECK_OPTS-SAME: #rocdl.target<flags = {finite_only, no_wave64}, link = ["file1.bc", "file2.bc"]>,
-// CHECK_OPTS-SAME: #xevm.target<O = 1, chip = "pvc">]  {
+// CHECK_OPTS-SAME: #xevm.target<O = 1, chip = "pvc">]
 gpu.module @options_module_1 {
 }
 // Check the options were added and that the first target was preserved.
 // CHECK_OPTS: @options_module_2 [#nvvm.target<O = 3, chip = "sm_90">,
 // CHECK_OPTS-SAME: #nvvm.target<O = 1, chip = "sm_70", flags = {fast, ftz}>,
 // CHECK_OPTS-SAME: #rocdl.target<flags = {finite_only, no_wave64}, link = ["file1.bc", "file2.bc"]>,
-// CHECK_OPTS-SAME: #xevm.target<O = 1, chip = "pvc">]  {
+// CHECK_OPTS-SAME: #xevm.target<O = 1, chip = "pvc">]
 gpu.module @options_module_2 [#nvvm.target<O = 3, chip = "sm_90">] {
 }
 }
+
+// -----
+
+module attributes {gpu.container_module} {
+  // expected-error @+1 {{The optimization level must be a number between 0 and 3}}
+  gpu.module @nvvm_module_example_3 [#nvvm.target<chip = "sm_90", features = "ftz", O = 4>] {
+  }
+}

@Men-cotton
Copy link
Contributor Author

CC: @Wolfram70

Copy link
Contributor

@Wolfram70 Wolfram70 left a comment

Choose a reason for hiding this comment

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

LGTM with a nit, thanks for the fix!

CC: @durga4github

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Could we move the invalid test to nvvm-target-invalid.mlir since this is nvvm-specific?

Copy link
Contributor

Choose a reason for hiding this comment

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

+1. Let us keep it under test/Target/LLVMIR/nvvm/ ...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I moved the test to mlir/test/Dialect/LLVMIR/nvvm-target-invalid.mlir.
Please merge it if there are no problems.

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.

[MLIR] Assertion `succeeded( ConcreteT::verifyInvariants(getDefaultDiagnosticEmitFn(ctx), args...))' failed.

4 participants