[llvm-branch-commits] [llvm] [GVN] Preserve scoped-alias metadata on coerced loads (PR #206417)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jun 29 00:32:55 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Madhur Amilkanthwar (madhur13490)
<details>
<summary>Changes</summary>
When forwarding a wider load to a narrower load at an offset, GVN drops
the wider load's metadata. !noalias and !alias.scope are independent of
the load type and offset, and the wider load is not moved and still
accesses the same memory, so they remain valid and are now kept instead
of dropped.
---
Full diff: https://github.com/llvm/llvm-project/pull/206417.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Scalar/GVN.cpp (+5-3)
- (modified) llvm/test/Transforms/GVN/rle-coerced-noalias.ll (+12-7)
``````````diff
diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index a619dcc588350..517d33bfba103 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -1163,13 +1163,15 @@ Value *AvailableValue::MaterializeAdjustedValue(LoadInst *Load,
// Drop all metadata that is not known to cause immediate UB on violation,
// unless the load has !noundef, in which case all metadata violations
// will be promoted to UB.
- // TODO: We can combine noalias/alias.scope metadata here, because it is
- // independent of the load type.
+ // !noalias and !alias.scope are kept: the load is not moved and still
+ // accesses the same memory, and these are independent of the load type
+ // and offset, so they remain valid for the coerced result.
if (!CoercedLoad->hasMetadata(LLVMContext::MD_noundef))
CoercedLoad->dropUnknownNonDebugMetadata(
{LLVMContext::MD_dereferenceable,
LLVMContext::MD_dereferenceable_or_null,
- LLVMContext::MD_invariant_load, LLVMContext::MD_invariant_group});
+ LLVMContext::MD_invariant_load, LLVMContext::MD_invariant_group,
+ LLVMContext::MD_alias_scope, LLVMContext::MD_noalias});
LLVM_DEBUG(dbgs() << "GVN COERCED NONLOCAL LOAD:\nOffset: " << Offset
<< " " << *getCoercedLoadValue() << '\n'
<< *Res << '\n'
diff --git a/llvm/test/Transforms/GVN/rle-coerced-noalias.ll b/llvm/test/Transforms/GVN/rle-coerced-noalias.ll
index 277e054fdccd5..67f7f58543aa8 100644
--- a/llvm/test/Transforms/GVN/rle-coerced-noalias.ll
+++ b/llvm/test/Transforms/GVN/rle-coerced-noalias.ll
@@ -1,10 +1,10 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -S -passes=gvn < %s | FileCheck %s
-; When GVN coerces a wider load into a narrower load at an offset, it strips
-; !noalias and !alias.scope from the surviving wider load. That load is
-; unchanged and still accesses the same memory, so the metadata stays valid
-; and should be kept. It is currently dropped.
+; When GVN coerces a wider load into a narrower load at an offset, the wider
+; load is not moved and still accesses the same memory. Its !noalias and
+; !alias.scope are independent of the load type and offset, so they are
+; preserved on the surviving wider load rather than dropped.
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
@@ -14,7 +14,7 @@ define i32 @noalias_dropped_local(ptr %p) {
; CHECK-LABEL: define i32 @noalias_dropped_local(
; CHECK-SAME: ptr [[P:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[WIDE:%.*]] = load i32, ptr [[P]], align 4
+; CHECK-NEXT: [[WIDE:%.*]] = load i32, ptr [[P]], align 4, !noalias [[META0:![0-9]+]]
; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 1
; CHECK-NEXT: [[TMP0:%.*]] = lshr i32 [[WIDE]], 8
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
@@ -36,7 +36,7 @@ define i32 @alias_scope_dropped_local(ptr %p) {
; CHECK-LABEL: define i32 @alias_scope_dropped_local(
; CHECK-SAME: ptr [[P:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[WIDE:%.*]] = load i32, ptr [[P]], align 4
+; CHECK-NEXT: [[WIDE:%.*]] = load i32, ptr [[P]], align 4, !alias.scope [[META0]]
; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 1
; CHECK-NEXT: [[TMP0:%.*]] = lshr i32 [[WIDE]], 8
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
@@ -60,7 +60,7 @@ define i32 @noalias_dropped_nonlocal(ptr %p) {
; CHECK-LABEL: define i32 @noalias_dropped_nonlocal(
; CHECK-SAME: ptr [[P:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[WIDE:%.*]] = load i32, ptr [[P]], align 4
+; CHECK-NEXT: [[WIDE:%.*]] = load i32, ptr [[P]], align 4, !noalias [[META0]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[WIDE]], 127
; CHECK-NEXT: [[TMP0:%.*]] = lshr i32 [[WIDE]], 8
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[TMP0]] to i8
@@ -92,3 +92,8 @@ f:
!2 = distinct !{!2, !"test domain"}
!0 = !{!1}
+;.
+; CHECK: [[META0]] = !{[[META1:![0-9]+]]}
+; CHECK: [[META1]] = distinct !{[[META1]], [[META2:![0-9]+]], !"scope A"}
+; CHECK: [[META2]] = distinct !{[[META2]], !"test domain"}
+;.
``````````
</details>
https://github.com/llvm/llvm-project/pull/206417
More information about the llvm-branch-commits
mailing list