[llvm] [Utils][Local] Preserve !nosanitize in combineMetadata when merging instructions (PR #148376)

Kunqiu Chen via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 13 23:39:52 PDT 2025


https://github.com/Camsyn updated https://github.com/llvm/llvm-project/pull/148376

>From a5c98957a8ecc0b59136d36afe447cbc024ee7e7 Mon Sep 17 00:00:00 2001
From: Camsyn <camsyn at foxmail.com>
Date: Sat, 12 Jul 2025 21:25:46 +0800
Subject: [PATCH 1/3] fix mssing handling for nosanitize in combineMetadata |
 add test and regenerate the test

---
 llvm/lib/Transforms/Utils/Local.cpp  |  4 +++
 llvm/test/Transforms/GVN/metadata.ll | 41 ++++++++++++++++++++++------
 2 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index f5208d50c6aae..6f4760ebaf81a 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -3381,6 +3381,10 @@ static void combineMetadata(Instruction *K, const Instruction *J,
           K->setMetadata(Kind,
                          MDNode::getMostGenericNoaliasAddrspace(JMD, KMD));
         break;
+      case LLVMContext::MD_nosanitize:
+        // Preserve !nosanitize if both K and J have it.
+        K->setMetadata(Kind, JMD);
+        break;
     }
   }
   // Set !invariant.group from J if J has it. If both instructions have it
diff --git a/llvm/test/Transforms/GVN/metadata.ll b/llvm/test/Transforms/GVN/metadata.ll
index a5dbb5ee06070..98e3a8fee7cc3 100644
--- a/llvm/test/Transforms/GVN/metadata.ll
+++ b/llvm/test/Transforms/GVN/metadata.ll
@@ -112,7 +112,7 @@ define i32 @test8(ptr %p) {
 define i32 @load_noundef_load(ptr %p) {
 ; CHECK-LABEL: define i32 @load_noundef_load
 ; CHECK-SAME: (ptr [[P:%.*]]) {
-; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0]], !noundef !6
+; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0]], !noundef [[META6:![0-9]+]]
 ; CHECK-NEXT:    [[C:%.*]] = add i32 [[A]], [[A]]
 ; CHECK-NEXT:    ret i32 [[C]]
 ;
@@ -138,7 +138,7 @@ define i32 @load_load_noundef(ptr %p) {
 define void @load_dereferenceable_dominating(ptr %p) {
 ; CHECK-LABEL: define void @load_dereferenceable_dominating
 ; CHECK-SAME: (ptr [[P:%.*]]) {
-; CHECK-NEXT:    [[A:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable !7
+; CHECK-NEXT:    [[A:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable [[META7:![0-9]+]]
 ; CHECK-NEXT:    call void @use.ptr(ptr [[A]])
 ; CHECK-NEXT:    call void @use.ptr(ptr [[A]])
 ; CHECK-NEXT:    ret void
@@ -185,7 +185,7 @@ define void @load_ptr_nonnull_to_i64(ptr %p) {
 define void @load_ptr_nonnull_noundef_to_i64(ptr %p) {
 ; CHECK-LABEL: define void @load_ptr_nonnull_noundef_to_i64
 ; CHECK-SAME: (ptr [[P:%.*]]) {
-; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !nonnull !6, !noundef !6
+; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !nonnull [[META6]], !noundef [[META6]]
 ; CHECK-NEXT:    [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64
 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
@@ -202,7 +202,7 @@ define void @load_ptr_nonnull_noundef_to_i64(ptr %p) {
 define void @load_ptr_invariant_load_to_i64(ptr %p) {
 ; CHECK-LABEL: define void @load_ptr_invariant_load_to_i64
 ; CHECK-SAME: (ptr [[P:%.*]]) {
-; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !invariant.load !6
+; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !invariant.load [[META6]]
 ; CHECK-NEXT:    [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64
 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
@@ -219,7 +219,7 @@ define void @load_ptr_invariant_load_to_i64(ptr %p) {
 define void @load_ptr_dereferenceable_to_i64(ptr %p) {
 ; CHECK-LABEL: define void @load_ptr_dereferenceable_to_i64
 ; CHECK-SAME: (ptr [[P:%.*]]) {
-; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable !7
+; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable [[META7]]
 ; CHECK-NEXT:    [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64
 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
@@ -236,7 +236,7 @@ define void @load_ptr_dereferenceable_to_i64(ptr %p) {
 define void @load_ptr_dereferenceable_or_null_to_i64(ptr %p) {
 ; CHECK-LABEL: define void @load_ptr_dereferenceable_or_null_to_i64
 ; CHECK-SAME: (ptr [[P:%.*]]) {
-; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable_or_null !7
+; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable_or_null [[META7]]
 ; CHECK-NEXT:    [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64
 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
@@ -409,6 +409,31 @@ join:
   ret void
 }
 
+define void @test_nosanitize(ptr %p) {
+; CHECK-LABEL: define void @test_nosanitize
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4, !nosanitize [[META6]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[V1]], 0
+; CHECK-NEXT:    br i1 [[COND]], label [[IF:%.*]], label [[JOIN:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    call void @use.i32(i32 0)
+; CHECK-NEXT:    br label [[JOIN]]
+; CHECK:       join:
+; CHECK-NEXT:    ret void
+;
+  %v1 = load i32, ptr %p, !nosanitize !11
+  %cond = icmp eq i32 %v1, 0
+  br i1 %cond, label %if, label %join
+
+if:
+  %v2 = load i32, ptr %p, !nosanitize !11
+  call void @use.i32(i32 %v2)
+  br label %join
+
+join:
+  ret void
+}
+
 !0 = !{i32 0, i32 2}
 !1 = !{i32 3, i32 5}
 !2 = !{i32 2, i32 5}
@@ -430,8 +455,8 @@ join:
 ; CHECK: [[RNG3]] = !{i32 -5, i32 -2, i32 1, i32 5}
 ; CHECK: [[RNG4]] = !{i32 10, i32 1}
 ; CHECK: [[RNG5]] = !{i32 3, i32 4, i32 5, i32 2}
-; CHECK: [[META6:![0-9]+]] = !{}
-; CHECK: [[META7:![0-9]+]] = !{i64 10}
+; CHECK: [[META6]] = !{}
+; CHECK: [[META7]] = !{i64 10}
 ; CHECK: [[RNG8]] = !{i64 0, i64 10}
 ; CHECK: [[RNG9]] = !{i64 0, i64 10, i64 20, i64 30}
 ; CHECK: [[RNG10]] = !{i64 10, i64 30}

>From e17df7e6e32ca6b4808bc8c98236d6ca42295cef Mon Sep 17 00:00:00 2001
From: Camsyn <camsyn at foxmail.com>
Date: Sat, 12 Jul 2025 23:02:30 +0800
Subject: [PATCH 2/3] Make the formatter happy

---
 llvm/lib/Transforms/Utils/Local.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 6f4760ebaf81a..81d85375b9e1d 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -3385,7 +3385,7 @@ static void combineMetadata(Instruction *K, const Instruction *J,
         // Preserve !nosanitize if both K and J have it.
         K->setMetadata(Kind, JMD);
         break;
-    }
+      }
   }
   // Set !invariant.group from J if J has it. If both instructions have it
   // then we will just pick it from J - even when they are different.

>From 8f3c41a7b6c74f16d71384b660c261322b2c9310 Mon Sep 17 00:00:00 2001
From: Camsyn <camsyn at foxmail.com>
Date: Mon, 14 Jul 2025 14:39:39 +0800
Subject: [PATCH 3/3] regenerate the test

---
 llvm/test/Transforms/GVN/metadata.ll | 55 +++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/GVN/metadata.ll b/llvm/test/Transforms/GVN/metadata.ll
index 98e3a8fee7cc3..ff055d889eac2 100644
--- a/llvm/test/Transforms/GVN/metadata.ll
+++ b/llvm/test/Transforms/GVN/metadata.ll
@@ -409,8 +409,9 @@ join:
   ret void
 }
 
-define void @test_nosanitize(ptr %p) {
-; CHECK-LABEL: define void @test_nosanitize
+; We should preserve the !nosanitize if both insns have it.
+define void @test_nosanitize1(ptr %p) {
+; CHECK-LABEL: define void @test_nosanitize1
 ; CHECK-SAME: (ptr [[P:%.*]]) {
 ; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4, !nosanitize [[META6]]
 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[V1]], 0
@@ -434,6 +435,56 @@ join:
   ret void
 }
 
+define void @test_nosanitize2(ptr %p) {
+; CHECK-LABEL: define void @test_nosanitize2
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[V1]], 0
+; CHECK-NEXT:    br i1 [[COND]], label [[IF:%.*]], label [[JOIN:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    call void @use.i32(i32 0)
+; CHECK-NEXT:    br label [[JOIN]]
+; CHECK:       join:
+; CHECK-NEXT:    ret void
+;
+  %v1 = load i32, ptr %p, !nosanitize !11
+  %cond = icmp eq i32 %v1, 0
+  br i1 %cond, label %if, label %join
+
+if:
+  %v2 = load i32, ptr %p
+  call void @use.i32(i32 %v2)
+  br label %join
+
+join:
+  ret void
+}
+
+define void @test_nosanitize3(ptr %p) {
+; CHECK-LABEL: define void @test_nosanitize3
+; CHECK-SAME: (ptr [[P:%.*]]) {
+; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P]], align 4
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[V1]], 0
+; CHECK-NEXT:    br i1 [[COND]], label [[IF:%.*]], label [[JOIN:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    call void @use.i32(i32 0)
+; CHECK-NEXT:    br label [[JOIN]]
+; CHECK:       join:
+; CHECK-NEXT:    ret void
+;
+  %v1 = load i32, ptr %p
+  %cond = icmp eq i32 %v1, 0
+  br i1 %cond, label %if, label %join
+
+if:
+  %v2 = load i32, ptr %p, !nosanitize !11
+  call void @use.i32(i32 %v2)
+  br label %join
+
+join:
+  ret void
+}
+
 !0 = !{i32 0, i32 2}
 !1 = !{i32 3, i32 5}
 !2 = !{i32 2, i32 5}



More information about the llvm-commits mailing list