[Mlir-commits] [mlir] [MLIR][LLVM] Add noundef metadata to llvm.load (PR #228517)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Fri Oct 2 09:46:57 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: Arseniy Obolenskiy (aobolensk)

<details>
<summary>Changes</summary>



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


5 Files Affected:

- (modified) mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td (+14-3) 
- (modified) mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp (+1-1) 
- (modified) mlir/test/Dialect/LLVMIR/roundtrip.mlir (+7) 
- (modified) mlir/test/Target/LLVMIR/Import/instructions.ll (+13) 
- (modified) mlir/test/Target/LLVMIR/llvmir.mlir (+11) 


``````````diff
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 2df02fae26d20e..129d62ab97fea4 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -393,7 +393,8 @@ def LLVM_LoadOp : LLVM_MemAccessOpBase<"load",
               DefaultValuedAttr<
                 AtomicOrdering, "AtomicOrdering::not_atomic">:$ordering,
               OptionalAttr<StrAttr>:$syncscope,
-              OptionalAttr<LLVM_DereferenceableAttr>:$dereferenceable);
+              OptionalAttr<LLVM_DereferenceableAttr>:$dereferenceable,
+              UnitAttr:$noundef);
   // Append the aliasing related attributes defined in LLVM_MemAccessOpBase.
   let arguments = !con(args, aliasAttrs);
   let results = (outs LLVM_LoadableType:$res);
@@ -414,6 +415,9 @@ def LLVM_LoadOp : LLVM_MemAccessOpBase<"load",
     // A nontemporal load of a float variable.
     %0 = llvm.load %ptr <nontemporal> : !llvm.ptr -> f32
 
+    // A load of a value that is neither undef nor poison.
+    %0 = llvm.load %ptr noundef : !llvm.ptr -> i32
+
     // An atomic load of an integer variable.
     %0 = llvm.load %ptr atomic monotonic <alignment = 8>
         : !llvm.ptr -> i64
@@ -428,6 +432,7 @@ def LLVM_LoadOp : LLVM_MemAccessOpBase<"load",
     (`invariant` $invariant^)?
     (`invariant_group` $invariantGroup^)?
     (`dereferenceable` `` $dereferenceable^)?
+    (`noundef` $noundef^)?
     prop-dict
     attr-dict `:` qualified(type($addr)) `->` type($res)
   }];
@@ -440,6 +445,10 @@ def LLVM_LoadOp : LLVM_MemAccessOpBase<"load",
     }
     if ($dereferenceable)
       moduleTranslation.setDereferenceableMetadata(op, inst);
+    if ($noundef) {
+      llvm::MDNode *metadata = llvm::MDNode::get(inst->getContext(), {});
+      inst->setMetadata(llvm::LLVMContext::MD_noundef, metadata);
+    }
   }] # setOrderingCode
      # setSyncScopeCode
      # setAlignmentCode
@@ -450,13 +459,15 @@ def LLVM_LoadOp : LLVM_MemAccessOpBase<"load",
   string mlirBuilder = [{
     auto *loadInst = cast<llvm::LoadInst>(inst);
     unsigned alignment = loadInst->getAlign().value();
-    $res = LLVM::LoadOp::create($_builder, $_location, $_resultType, $addr,
-        alignment, loadInst->isVolatile(),
+    auto loadOp = LLVM::LoadOp::create($_builder, $_location, $_resultType,
+        $addr, alignment, loadInst->isVolatile(),
         loadInst->hasMetadata(llvm::LLVMContext::MD_nontemporal),
         loadInst->hasMetadata(llvm::LLVMContext::MD_invariant_load),
         loadInst->hasMetadata(llvm::LLVMContext::MD_invariant_group),
         convertAtomicOrderingFromLLVM(loadInst->getOrdering()),
         getLLVMSyncScope(loadInst));
+    loadOp.setNoundef(loadInst->hasMetadata(llvm::LLVMContext::MD_noundef));
+    $res = loadOp;
   }];
   let builders = [
     OpBuilder<(ins "Type":$type, "Value":$addr,
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index ff75b5a7dfb2e3..cf08fa3bac9e76 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -933,7 +933,7 @@ void LoadOp::build(OpBuilder &builder, OperationState &state, Type type,
         alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isVolatile,
         isNonTemporal, isInvariant, isInvariantGroup, ordering,
         syncscope.empty() ? nullptr : builder.getStringAttr(syncscope),
-        /*dereferenceable=*/nullptr,
+        /*dereferenceable=*/nullptr, /*noundef=*/false,
         /*access_groups=*/nullptr,
         /*alias_scopes=*/nullptr, /*noalias_scopes=*/nullptr,
         /*tbaa=*/nullptr);
diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
index 6ef571efe5c51b..48d1a12eb43e12 100644
--- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir
@@ -598,6 +598,13 @@ func.func @invariant_load(%ptr : !llvm.ptr) -> i32 {
   func.return %0 : i32
 }
 
+// CHECK-LABEL: @noundef_load
+func.func @noundef_load(%ptr : !llvm.ptr) -> i32 {
+  // CHECK: llvm.load %{{.+}} noundef <alignment = 4> : !llvm.ptr -> i32
+  %0 = llvm.load %ptr noundef <alignment = 4> : !llvm.ptr -> i32
+  func.return %0 : i32
+}
+
 // CHECK-LABEL: @invariant_group_load
 func.func @invariant_group_load(%ptr : !llvm.ptr) -> i32 {
   // CHECK: llvm.load %{{.+}} invariant_group <alignment = 4> : !llvm.ptr -> i32
diff --git a/mlir/test/Target/LLVMIR/Import/instructions.ll b/mlir/test/Target/LLVMIR/Import/instructions.ll
index 28ab4bc44a40ab..0cdaa667b3dc50 100644
--- a/mlir/test/Target/LLVMIR/Import/instructions.ll
+++ b/mlir/test/Target/LLVMIR/Import/instructions.ll
@@ -375,6 +375,19 @@ define void @load_store(ptr %ptr) {
 
 ; // -----
 
+; CHECK-LABEL: @noundef_load
+; CHECK-SAME:  %[[PTR:[a-zA-Z0-9]+]]
+define i32 @noundef_load(ptr %ptr) {
+  ; CHECK:  %[[V:[0-9]+]] = llvm.load %[[PTR]] noundef <alignment = 4> : !llvm.ptr -> i32
+  %1 = load i32, ptr %ptr, align 4, !noundef !0
+  ; CHECK:  llvm.return %[[V]]
+  ret i32 %1
+}
+
+!0 = !{}
+
+; // -----
+
 ; CHECK-LABEL: @invariant_load
 ; CHECK-SAME:  %[[PTR:[a-zA-Z0-9]+]]
 define float @invariant_load(ptr %ptr) {
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index f29184beb6b4d6..cccf402d8e2ebe 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -2135,6 +2135,17 @@ llvm.func @nontemporal_store_and_load(%ptr : !llvm.ptr) -> i32 {
 
 // -----
 
+// CHECK-LABEL: @noundef_load
+llvm.func @noundef_load(%ptr : !llvm.ptr) -> i32 {
+  // CHECK: load i32, ptr %{{.*}}, align 4, !noundef ![[NODE:[0-9]+]]
+  %0 = llvm.load %ptr noundef : !llvm.ptr -> i32
+  llvm.return %0 : i32
+}
+
+// CHECK: ![[NODE]] = !{}
+
+// -----
+
 // Check that invariant group attribute is exported as metadata node.
 llvm.func @nontemporal_store_and_load(%ptr : !llvm.ptr) -> i32 {
   %val = llvm.mlir.constant(42 : i32) : i32

``````````

</details>


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


More information about the Mlir-commits mailing list