[llvm] 27f0f83 - [GVN] Preserve scoped-alias metadata on coerced loads (#206417)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 29 02:49:19 PDT 2026
Author: Madhur Amilkanthwar
Date: 2026-06-29T09:49:14Z
New Revision: 27f0f834f0c1136a81452ca0f171352117ba8198
URL: https://github.com/llvm/llvm-project/commit/27f0f834f0c1136a81452ca0f171352117ba8198
DIFF: https://github.com/llvm/llvm-project/commit/27f0f834f0c1136a81452ca0f171352117ba8198.diff
LOG: [GVN] Preserve scoped-alias metadata on coerced loads (#206417)
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.
Added:
Modified:
llvm/lib/Transforms/Scalar/GVN.cpp
llvm/test/Transforms/GVN/rle-coerced-noalias.ll
Removed:
################################################################################
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"}
+;.
More information about the llvm-commits
mailing list