[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