[llvm] 0c611ab - [Verifier] Reject an empty non-'distinct' !llvm.access.group node (#214703)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 11 01:50:21 PDT 2026


Author: mikaoP
Date: 2026-08-11T16:50:15+08:00
New Revision: 0c611abc1ec88161c4ee8b818fa78027e13300e6

URL: https://github.com/llvm/llvm-project/commit/0c611abc1ec88161c4ee8b818fa78027e13300e6
DIFF: https://github.com/llvm/llvm-project/commit/0c611abc1ec88161c4ee8b818fa78027e13300e6.diff

LOG: [Verifier] Reject an empty non-'distinct' !llvm.access.group node (#214703)

visitAccessGroupMetadata misses one case: a node that is empty but not
'distinct'. It is not a valid access group, and the list loop runs zero
times, so nothing is reported:

  store double %v, ptr %q, !llvm.access.group !0
  !0 = !{}

That IR reaches addToAccessGroupList(), which reads a node with no
operands as an access group and trips its isValidAsAccessGroup() assert.

Check the operand count first, so an empty node must be 'distinct'. Two
tests used !{} as an access group and now use distinct !{}.

Unlocks #214509

Added: 
    

Modified: 
    llvm/lib/IR/Verifier.cpp
    llvm/test/Transforms/InstCombine/bitcast-store.ll
    llvm/test/Transforms/InstCombine/loadstore-metadata.ll
    llvm/test/Verifier/access_group.ll
    mlir/test/Target/LLVMIR/Import/import-failure.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 09429024e3ae8..8aa93ae132717 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5572,11 +5572,15 @@ void Verifier::visitAccessGroupMetadata(const MDNode *MD) {
     return MD->getNumOperands() == 0 && MD->isDistinct();
   };
 
-  // It must be either an access scope itself...
-  if (IsValidAccessScope(MD))
+  // An empty node is an access scope, and it must be 'distinct'. It is never a
+  // list, because an empty list is not allowed: it would look the same as an
+  // access scope.
+  if (MD->getNumOperands() == 0) {
+    Check(MD->isDistinct(), "Access scope must be 'distinct'", MD);
     return;
+  }
 
-  // ...or a list of access scopes.
+  // A non-empty node is a list of access scopes.
   for (const MDOperand &Op : MD->operands()) {
     const auto *OpMD = dyn_cast<MDNode>(Op);
     Check(OpMD != nullptr, "Access scope list must consist of MDNodes", MD);

diff  --git a/llvm/test/Transforms/InstCombine/bitcast-store.ll b/llvm/test/Transforms/InstCombine/bitcast-store.ll
index a387a60407d0b..3f5dac8bf0f45 100644
--- a/llvm/test/Transforms/InstCombine/bitcast-store.ll
+++ b/llvm/test/Transforms/InstCombine/bitcast-store.ll
@@ -14,7 +14,7 @@ define void @foo(i32 %x, ptr %p) nounwind {
 ; CHECK-LABEL: define void @foo
 ; CHECK-SAME: (i32 [[X:%.*]], ptr [[P:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    store i32 [[X]], ptr [[P]], align 16, !noalias !0, !llvm.access.group [[ACC_GRP3:![0-9]+]]
+; CHECK-NEXT:    store i32 [[X]], ptr [[P]], align 16, !noalias [[META0:![0-9]+]], !llvm.access.group [[ACC_GRP3:![0-9]+]]
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -72,4 +72,4 @@ entry:
 !0 = !{!1}
 !1 = !{!1, !2}
 !2 = !{!2}
-!3 = !{}
+!3 = distinct !{}

diff  --git a/llvm/test/Transforms/InstCombine/loadstore-metadata.ll b/llvm/test/Transforms/InstCombine/loadstore-metadata.ll
index 02552df831196..3de4c2dd8df15 100644
--- a/llvm/test/Transforms/InstCombine/loadstore-metadata.ll
+++ b/llvm/test/Transforms/InstCombine/loadstore-metadata.ll
@@ -162,7 +162,7 @@ define void @test_load_cast_combine_nonnull(ptr %ptr) {
 ; CHECK-LABEL: define void @test_load_cast_combine_nonnull(
 ; CHECK-SAME: ptr [[PTR:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[P:%.*]] = load ptr, ptr [[PTR]], align 8, !nonnull [[META6]]
+; CHECK-NEXT:    [[P:%.*]] = load ptr, ptr [[PTR]], align 8, !nonnull [[META10:![0-9]+]]
 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[PTR]], i64 336
 ; CHECK-NEXT:    store ptr [[P]], ptr [[GEP]], align 8
 ; CHECK-NEXT:    ret void
@@ -177,7 +177,7 @@ entry:
 define i32 @test_load_cast_combine_noundef(ptr %ptr) {
 ; CHECK-LABEL: define i32 @test_load_cast_combine_noundef(
 ; CHECK-SAME: ptr [[PTR:%.*]]) {
-; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[PTR]], align 4, !noundef [[META6]]
+; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[PTR]], align 4, !noundef [[META10]]
 ; CHECK-NEXT:    ret i32 [[L1]]
 ;
   %l = load float, ptr %ptr, !noundef !{}
@@ -190,7 +190,7 @@ define i32 @test_load_cast_combine_noalias_addrspace(ptr %ptr) {
 ; CHECK-LABEL: define i32 @test_load_cast_combine_noalias_addrspace(
 ; CHECK-SAME: ptr [[PTR:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[PTR]], align 4, !noalias.addrspace [[META10:![0-9]+]]
+; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[PTR]], align 4, !noalias.addrspace [[META11:![0-9]+]]
 ; CHECK-NEXT:    ret i32 [[L1]]
 ;
 entry:
@@ -204,8 +204,8 @@ define ptr @preserve_load_metadata_after_select_transform1(i1 %c, ptr dereferenc
 ; CHECK-LABEL: define ptr @preserve_load_metadata_after_select_transform1(
 ; CHECK-SAME: i1 [[C:%.*]], ptr dereferenceable(8) [[A:%.*]], ptr dereferenceable(8) [[B:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[B_VAL:%.*]] = load ptr, ptr [[B]], align 1, !nonnull [[META6]], !align [[META8]]
-; CHECK-NEXT:    [[A_VAL:%.*]] = load ptr, ptr [[A]], align 1, !nonnull [[META6]], !align [[META8]]
+; CHECK-NEXT:    [[B_VAL:%.*]] = load ptr, ptr [[B]], align 1, !nonnull [[META10]], !align [[META8]]
+; CHECK-NEXT:    [[A_VAL:%.*]] = load ptr, ptr [[A]], align 1, !nonnull [[META10]], !align [[META8]]
 ; CHECK-NEXT:    [[L_SEL:%.*]] = select i1 [[C]], ptr [[B_VAL]], ptr [[A_VAL]]
 ; CHECK-NEXT:    ret ptr [[L_SEL]]
 ;
@@ -220,8 +220,8 @@ define i32 @preserve_load_metadata_after_select_transform_range(i1 %c, ptr deref
 ; CHECK-LABEL: define i32 @preserve_load_metadata_after_select_transform_range(
 ; CHECK-SAME: i1 [[C:%.*]], ptr dereferenceable(8) [[A:%.*]], ptr dereferenceable(8) [[B:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[B_VAL:%.*]] = load i32, ptr [[B]], align 1, !range [[RNG11:![0-9]+]]
-; CHECK-NEXT:    [[A_VAL:%.*]] = load i32, ptr [[A]], align 1, !range [[RNG11]]
+; CHECK-NEXT:    [[B_VAL:%.*]] = load i32, ptr [[B]], align 1, !range [[RNG12:![0-9]+]]
+; CHECK-NEXT:    [[A_VAL:%.*]] = load i32, ptr [[A]], align 1, !range [[RNG12]]
 ; CHECK-NEXT:    [[L_SEL:%.*]] = select i1 [[C]], i32 [[B_VAL]], i32 [[A_VAL]]
 ; CHECK-NEXT:    ret i32 [[L_SEL]]
 ;
@@ -314,7 +314,7 @@ define double @preserve_load_metadata_after_select_transform_metadata_missing_4(
 ; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
 ; CHECK-NEXT:    [[L_A:%.*]] = load double, ptr [[A]], align 8, !tbaa [[SCALAR_TYPE_TBAA0]], !alias.scope [[META3]], !noalias [[META3]], !llvm.access.group [[META6]]
-; CHECK-NEXT:    [[L_B:%.*]] = load double, ptr [[B]], align 8, !tbaa [[SCALAR_TYPE_TBAA0]], !alias.scope [[META12:![0-9]+]], !noalias [[META12]], !llvm.access.group [[ACC_GRP15:![0-9]+]]
+; CHECK-NEXT:    [[L_B:%.*]] = load double, ptr [[B]], align 8, !tbaa [[SCALAR_TYPE_TBAA0]], !alias.scope [[META13:![0-9]+]], !noalias [[META13]], !llvm.access.group [[ACC_GRP16:![0-9]+]]
 ; CHECK-NEXT:    [[CMP_I:%.*]] = fcmp fast olt double [[L_A]], [[L_B]]
 ; CHECK-NEXT:    [[L_SEL:%.*]] = select i1 [[CMP_I]], double [[L_B]], double [[L_A]]
 ; CHECK-NEXT:    ret double [[L_SEL]]
@@ -332,8 +332,8 @@ define float @preserve_load_metadata_after_select_transform_nofpclass(i1 %c, ptr
 ; CHECK-LABEL: define float @preserve_load_metadata_after_select_transform_nofpclass(
 ; CHECK-SAME: i1 [[C:%.*]], ptr dereferenceable(8) [[A:%.*]], ptr dereferenceable(8) [[B:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[B_VAL:%.*]] = load float, ptr [[B]], align 1, !nofpclass [[META16:![0-9]+]]
-; CHECK-NEXT:    [[A_VAL:%.*]] = load float, ptr [[A]], align 1, !nofpclass [[META16]]
+; CHECK-NEXT:    [[B_VAL:%.*]] = load float, ptr [[B]], align 1, !nofpclass [[META17:![0-9]+]]
+; CHECK-NEXT:    [[A_VAL:%.*]] = load float, ptr [[A]], align 1, !nofpclass [[META17]]
 ; CHECK-NEXT:    [[L_SEL:%.*]] = select i1 [[C]], float [[B_VAL]], float [[A_VAL]]
 ; CHECK-NEXT:    ret float [[L_SEL]]
 ;
@@ -375,7 +375,7 @@ define float @test_load_cast_combine_nofpclass_1xvec_to_scalar(ptr %ptr) {
 ; CHECK-LABEL: define float @test_load_cast_combine_nofpclass_1xvec_to_scalar(
 ; CHECK-SAME: ptr [[PTR:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[L1:%.*]] = load float, ptr [[PTR]], align 4, !nofpclass [[META16]]
+; CHECK-NEXT:    [[L1:%.*]] = load float, ptr [[PTR]], align 4, !nofpclass [[META17]]
 ; CHECK-NEXT:    ret float [[L1]]
 ;
 entry:
@@ -388,7 +388,7 @@ define <1 x float> @test_load_cast_combine_nofpclass_scalar_to_1xvec(ptr %ptr) {
 ; CHECK-LABEL: define <1 x float> @test_load_cast_combine_nofpclass_scalar_to_1xvec(
 ; CHECK-SAME: ptr [[PTR:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[L1:%.*]] = load <1 x float>, ptr [[PTR]], align 4, !nofpclass [[META16]]
+; CHECK-NEXT:    [[L1:%.*]] = load <1 x float>, ptr [[PTR]], align 4, !nofpclass [[META17]]
 ; CHECK-NEXT:    ret <1 x float> [[L1]]
 ;
 entry:
@@ -401,7 +401,7 @@ define i32 @test_load_cast_combine_mem_cache_hint(ptr %ptr) {
 ; CHECK-LABEL: define i32 @test_load_cast_combine_mem_cache_hint(
 ; CHECK-SAME: ptr [[PTR:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[PTR]], align 4, !mem.cache_hint [[META17:![0-9]+]]
+; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[PTR]], align 4, !mem.cache_hint [[META18:![0-9]+]]
 ; CHECK-NEXT:    ret i32 [[L1]]
 ;
 entry:
@@ -417,7 +417,7 @@ entry:
 !4 = distinct !{!4, !5}
 !5 = distinct !{!5}
 !6 = !{i32 0, i32 42}
-!7 = !{}
+!7 = distinct !{}
 !8 = !{i32 1}
 !9 = !{i64 8}
 !10 = distinct !{}
@@ -437,17 +437,18 @@ entry:
 ; CHECK: [[META3]] = !{[[META4:![0-9]+]]}
 ; CHECK: [[META4]] = distinct !{[[META4]], [[META5:![0-9]+]]}
 ; CHECK: [[META5]] = distinct !{[[META5]]}
-; CHECK: [[META6]] = !{}
+; CHECK: [[META6]] = distinct !{}
 ; CHECK: [[META7]] = !{i32 1}
 ; CHECK: [[META8]] = !{i64 8}
 ; CHECK: [[ACC_GRP9]] = distinct !{}
-; CHECK: [[META10]] = !{i32 5, i32 6}
-; CHECK: [[RNG11]] = !{i32 0, i32 42}
-; CHECK: [[META12]] = !{[[META13:![0-9]+]]}
-; CHECK: [[META13]] = distinct !{[[META13]], [[META14:![0-9]+]]}
-; CHECK: [[META14]] = distinct !{[[META14]]}
-; CHECK: [[ACC_GRP15]] = distinct !{}
-; CHECK: [[META16]] = !{i32 3}
-; CHECK: [[META17]] = !{i32 0, [[META18:![0-9]+]]}
-; CHECK: [[META18]] = !{!"nvvm.l1_eviction", !"first"}
+; CHECK: [[META10]] = !{}
+; CHECK: [[META11]] = !{i32 5, i32 6}
+; CHECK: [[RNG12]] = !{i32 0, i32 42}
+; CHECK: [[META13]] = !{[[META14:![0-9]+]]}
+; CHECK: [[META14]] = distinct !{[[META14]], [[META15:![0-9]+]]}
+; CHECK: [[META15]] = distinct !{[[META15]]}
+; CHECK: [[ACC_GRP16]] = distinct !{}
+; CHECK: [[META17]] = !{i32 3}
+; CHECK: [[META18]] = !{i32 0, [[META19:![0-9]+]]}
+; CHECK: [[META19]] = !{!"nvvm.l1_eviction", !"first"}
 ;.

diff  --git a/llvm/test/Verifier/access_group.ll b/llvm/test/Verifier/access_group.ll
index 8d6beadf7f2f4..73098acace777 100644
--- a/llvm/test/Verifier/access_group.ll
+++ b/llvm/test/Verifier/access_group.ll
@@ -5,6 +5,8 @@ define void @test(ptr %p) {
   load i8, ptr %p, !llvm.access.group !1
 ; CHECK: Access scope list must consist of MDNodes
   load i8, ptr %p, !llvm.access.group !2
+; CHECK: Access scope must be 'distinct'
+  load i8, ptr %p, !llvm.access.group !0
 ; CHECK-NOT: Access scope
   load i8, ptr %p, !llvm.access.group !3
   load i8, ptr %p, !llvm.access.group !4

diff  --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll
index 6600e201174cc..30165195cdd82 100644
--- a/mlir/test/Target/LLVMIR/Import/import-failure.ll
+++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll
@@ -52,9 +52,7 @@ define dso_local void @tbaa(ptr %0) {
 
 ; // -----
 
-; CHECK:      import-failure.ll
-; CHECK-SAME: warning: expected an access group node to be empty and distinct
-; CHECK:      error: unsupported access group node: !0 = !{}
+; CHECK: Access scope must be 'distinct'
 define void @access_group(ptr %arg1) {
   %1 = load i32, ptr %arg1, !llvm.access.group !0
   ret void


        


More information about the llvm-commits mailing list