https://github.com/jdoerfert updated 
https://github.com/llvm/llvm-project/pull/207866

>From f3f427f9f707a07a46d2901d2cb61baa89e30d12 Mon Sep 17 00:00:00 2001
From: Johannes Doerfert <[email protected]>
Date: Mon, 6 Jul 2026 15:03:18 -0700
Subject: [PATCH] [Attributor] AAAddressSpace should use the AA for recursive
 lookups

If we stripped some values, we can use the AAAddressSpace again for
an optimistic AS value. If we didn't strip any value, we can still use
the TLI.
---
 .../Transforms/IPO/AttributorAttributes.cpp   |  14 +-
 .../Attributor/AddrSpaceIndirect.ll           | 171 ++++++++++++++++++
 2 files changed, 181 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/Transforms/Attributor/AddrSpaceIndirect.ll

diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp 
b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 6c780226c3fdf..f76e2dcc77b16 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -13100,7 +13100,6 @@ struct AAAddressSpaceImpl : public AAAddressSpace {
   void initialize(Attributor &A) override {
     assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
            "Associated value is not a pointer");
-
     if (!A.getInfoCache().getFlatAddressSpace().has_value()) {
       indicatePessimisticFixpoint();
       return;
@@ -13118,6 +13117,7 @@ struct AAAddressSpaceImpl : public AAAddressSpace {
   ChangeStatus updateImpl(Attributor &A) override {
     uint32_t OldAddressSpace = AssumedAddressSpace;
     unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
+    Value &AssociatedValue = getAssociatedValue();
 
     auto CheckAddressSpace = [&](Value &Obj) {
       // Ignore undef.
@@ -13125,9 +13125,15 @@ struct AAAddressSpaceImpl : public AAAddressSpace {
         return true;
 
       // If the object already has a non-flat address space, we simply take it.
-      unsigned ObjAS = Obj.getType()->getPointerAddressSpace();
-      if (ObjAS != FlatAS)
-        return takeAddressSpace(ObjAS);
+      if (&Obj != &AssociatedValue) {
+        auto *ObjAA = A.getAAFor<AAAddressSpace>(*this, IRPosition::value(Obj),
+                                                 DepClassTy::OPTIONAL);
+        unsigned ObjAS = Obj.getType()->getPointerAddressSpace();
+        if (ObjAA && ObjAA->isValidState())
+          ObjAS = ObjAA->getAddressSpace();
+        if (ObjAS != FlatAS)
+          return takeAddressSpace(ObjAS);
+      }
 
       // At this point, we know Obj is in the flat address space. For a final
       // attempt, we want to use getAssumedAddrSpace, but first we must get the
diff --git a/llvm/test/Transforms/Attributor/AddrSpaceIndirect.ll 
b/llvm/test/Transforms/Attributor/AddrSpaceIndirect.ll
new file mode 100644
index 0000000000000..59ddfd22bad28
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/AddrSpaceIndirect.ll
@@ -0,0 +1,171 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 
UTC_ARGS: --function-signature --check-attributes --check-globals 
--prefix-filecheck-ir-name true
+; RUN: opt -mtriple=nvptx-unknown-unknown -aa-pipeline=basic-aa 
-passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs 
-S < %s | FileCheck %s --check-prefix=CHECK
+
+@_ZZ27mcasi_digit_counters_kernelE14shared_storage = internal addrspace(3) 
global [256 x i32] undef, align 4
+
+; Function Attrs: convergent mustprogress noinline norecurse nounwind
+;.
+; CHECK: @_ZZ27mcasi_digit_counters_kernelE14shared_storage = internal 
addrspace(3) global [256 x i32] undef, align 4
+;.
+define ptx_kernel void @mcasi_digit_counters_kernel(ptr nofree noundef 
writeonly captures(none) %arg, ptr nofree noundef readonly captures(none) 
%arg1, i32 noundef %arg2) #0 {
+; CHECK: Function Attrs: convergent mustprogress noinline norecurse nounwind
+; CHECK-LABEL: define {{[^@]+}}@mcasi_digit_counters_kernel
+; CHECK-SAME: (ptr nofree noundef writeonly captures(none) [[ARG:%.*]], ptr 
nofree noundef readonly captures(none) [[ARG1:%.*]], i32 noundef [[ARG2:%.*]]) 
#[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = alloca [4 x ptr], align 8
+; CHECK-NEXT:    [[I3:%.*]] = tail call noundef i32 
@llvm.nvvm.read.ptx.sreg.tid.x() #[[ATTR4:[0-9]+]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp samesign ult i32 [[I3]], 256
+; CHECK-NEXT:    br i1 [[I4]], label [[BB5:%.*]], label [[BB10:%.*]]
+; CHECK:       bb5:
+; CHECK-NEXT:    [[I6:%.*]] = zext nneg i32 [[I3]] to i64
+; CHECK-NEXT:    [[I7:%.*]] = getelementptr inbounds nuw [4 x i8], ptr 
[[ARG1]], i64 [[I6]]
+; CHECK-NEXT:    [[TMP0:%.*]] = addrspacecast ptr [[I7]] to ptr addrspace(1)
+; CHECK-NEXT:    [[I8:%.*]] = load i32, ptr addrspace(1) [[TMP0]], align 4
+; CHECK-NEXT:    [[I9:%.*]] = getelementptr inbounds nuw [4 x i8], ptr 
addrspacecast (ptr addrspace(3) 
@_ZZ27mcasi_digit_counters_kernelE14shared_storage to ptr), i64 [[I6]]
+; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast ptr [[I9]] to ptr addrspace(3)
+; CHECK-NEXT:    store i32 [[I8]], ptr addrspace(3) [[TMP1]], align 4
+; CHECK-NEXT:    br label [[BB10]]
+; CHECK:       bb10:
+; CHECK-NEXT:    tail call void @llvm.nvvm.barrier.cta.sync.aligned.all(i32 
noundef 0)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr noalias nofree noundef 
nonnull align 8 captures(none) dereferenceable(28) [[I]]) #[[ATTR5:[0-9]+]]
+; CHECK-NEXT:    [[I11:%.*]] = shl nuw nsw i32 [[I3]], 2
+; CHECK-NEXT:    [[I12:%.*]] = and i32 [[I11]], 124
+; CHECK-NEXT:    [[I13:%.*]] = zext nneg i32 [[I12]] to i64
+; CHECK-NEXT:    [[I14:%.*]] = getelementptr inbounds nuw [4 x i8], ptr 
addrspacecast (ptr addrspace(3) 
@_ZZ27mcasi_digit_counters_kernelE14shared_storage to ptr), i64 [[I13]]
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr [[I]] to ptr addrspace(5)
+; CHECK-NEXT:    store ptr [[I14]], ptr addrspace(5) [[TMP2]], align 8
+; CHECK-NEXT:    [[I15:%.*]] = getelementptr inbounds nuw i8, ptr [[I14]], i64 
4
+; CHECK-NEXT:    [[I16:%.*]] = getelementptr inbounds nuw i8, ptr [[I]], i64 8
+; CHECK-NEXT:    [[TMP3:%.*]] = addrspacecast ptr [[I16]] to ptr addrspace(5)
+; CHECK-NEXT:    store ptr [[I15]], ptr addrspace(5) [[TMP3]], align 8
+; CHECK-NEXT:    [[I17:%.*]] = getelementptr inbounds nuw i8, ptr [[I14]], i64 
8
+; CHECK-NEXT:    [[I18:%.*]] = getelementptr inbounds nuw i8, ptr [[I]], i64 16
+; CHECK-NEXT:    [[TMP4:%.*]] = addrspacecast ptr [[I18]] to ptr addrspace(5)
+; CHECK-NEXT:    store ptr [[I17]], ptr addrspace(5) [[TMP4]], align 8
+; CHECK-NEXT:    [[I19:%.*]] = getelementptr inbounds nuw i8, ptr [[I14]], i64 
12
+; CHECK-NEXT:    [[I20:%.*]] = getelementptr inbounds nuw i8, ptr [[I]], i64 24
+; CHECK-NEXT:    [[TMP5:%.*]] = addrspacecast ptr [[I20]] to ptr addrspace(5)
+; CHECK-NEXT:    store ptr [[I19]], ptr addrspace(5) [[TMP5]], align 8
+; CHECK-NEXT:    [[I21:%.*]] = and i32 [[ARG2]], 3
+; CHECK-NEXT:    [[I22:%.*]] = zext nneg i32 [[I21]] to i64
+; CHECK-NEXT:    [[I23:%.*]] = getelementptr inbounds nuw [8 x i8], ptr [[I]], 
i64 [[I22]]
+; CHECK-NEXT:    [[TMP6:%.*]] = addrspacecast ptr [[I23]] to ptr addrspace(5)
+; CHECK-NEXT:    [[I24:%.*]] = load ptr, ptr addrspace(5) [[TMP6]], align 8
+; CHECK-NEXT:    [[TMP7:%.*]] = addrspacecast ptr [[I24]] to ptr addrspace(3)
+; CHECK-NEXT:    [[I25:%.*]] = load i32, ptr addrspace(3) [[TMP7]], align 4, 
!invariant.load [[META15:![0-9]+]]
+; CHECK-NEXT:    [[I26:%.*]] = add i32 [[I25]], [[I21]]
+; CHECK-NEXT:    [[I27:%.*]] = zext nneg i32 [[I3]] to i64
+; CHECK-NEXT:    [[I28:%.*]] = getelementptr inbounds nuw [4 x i8], ptr 
[[ARG]], i64 [[I27]]
+; CHECK-NEXT:    [[TMP8:%.*]] = addrspacecast ptr [[I28]] to ptr addrspace(1)
+; CHECK-NEXT:    store i32 [[I26]], ptr addrspace(1) [[TMP8]], align 4
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr noalias nofree noundef 
nonnull align 8 captures(none) dereferenceable(28) [[I]]) #[[ATTR5]]
+; CHECK-NEXT:    ret void
+;
+bb:
+  %i = alloca [4 x ptr], align 8
+  %i3 = tail call noundef i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+  %i4 = icmp samesign ult i32 %i3, 256
+  br i1 %i4, label %bb5, label %bb10
+
+bb5:                                              ; preds = %bb
+  %i6 = zext nneg i32 %i3 to i64
+  %i7 = getelementptr inbounds nuw [4 x i8], ptr %arg1, i64 %i6
+  %i8 = load i32, ptr %i7, align 4
+  %i9 = getelementptr inbounds nuw [4 x i8], ptr addrspacecast (ptr 
addrspace(3) @_ZZ27mcasi_digit_counters_kernelE14shared_storage to ptr), i64 %i6
+  store i32 %i8, ptr %i9, align 4
+  br label %bb10
+
+bb10:                                             ; preds = %bb5, %bb
+  tail call void @llvm.nvvm.barrier.cta.sync.aligned.all(i32 0)
+  call void @llvm.lifetime.start.p0(ptr nonnull %i) #4
+  %i11 = shl nuw nsw i32 %i3, 2
+  %i12 = and i32 %i11, 124
+  %i13 = zext nneg i32 %i12 to i64
+  %i14 = getelementptr inbounds nuw [4 x i8], ptr addrspacecast (ptr 
addrspace(3) @_ZZ27mcasi_digit_counters_kernelE14shared_storage to ptr), i64 
%i13
+  store ptr %i14, ptr %i, align 8
+  %i15 = getelementptr inbounds nuw i8, ptr %i14, i64 4
+  %i16 = getelementptr inbounds nuw i8, ptr %i, i64 8
+  store ptr %i15, ptr %i16, align 8
+  %i17 = getelementptr inbounds nuw i8, ptr %i14, i64 8
+  %i18 = getelementptr inbounds nuw i8, ptr %i, i64 16
+  store ptr %i17, ptr %i18, align 8
+  %i19 = getelementptr inbounds nuw i8, ptr %i14, i64 12
+  %i20 = getelementptr inbounds nuw i8, ptr %i, i64 24
+  store ptr %i19, ptr %i20, align 8
+  %i21 = and i32 %arg2, 3
+  %i22 = zext nneg i32 %i21 to i64
+  %i23 = getelementptr inbounds nuw [8 x i8], ptr %i, i64 %i22
+  %i24 = load ptr, ptr %i23, align 8
+  %i25 = load i32, ptr %i24, align 4
+  %i26 = add i32 %i25, %i21
+  %i27 = zext nneg i32 %i3 to i64
+  %i28 = getelementptr inbounds nuw [4 x i8], ptr %arg, i64 %i27
+  store i32 %i26, ptr %i28, align 4
+  call void @llvm.lifetime.end.p0(ptr nonnull %i) #4
+  ret void
+}
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: 
readwrite)
+declare void @llvm.lifetime.start.p0(ptr captures(none)) #1
+
+; Function Attrs: convergent nocallback nounwind
+declare void @llvm.nvvm.barrier.cta.sync.aligned.all(i32) #2
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: 
readwrite)
+declare void @llvm.lifetime.end.p0(ptr captures(none)) #1
+
+; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn 
memory(none)
+declare noundef range(i32 0, 1024) i32 @llvm.nvvm.read.ptx.sreg.tid.x() #3
+
+attributes #0 = { convergent mustprogress noinline norecurse nounwind 
"frame-pointer"="all" "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "target-cpu"="sm_120a" 
"target-features"="+ptx91,+sm_120a" "uniform-work-group-size" }
+attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: 
readwrite) }
+attributes #2 = { convergent nocallback nounwind }
+attributes #3 = { nocallback nofree nosync nounwind speculatable willreturn 
memory(none) }
+attributes #4 = { nounwind }
+
+!llvm.module.flags = !{!0, !1, !2, !3, !4}
+!llvm.dbg.cu = !{!5}
+!llvm.ident = !{!7, !8}
+!llvm.errno.tbaa = !{!9}
+!nvvmir.version = !{!14}
+
+!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 13, i32 1]}
+!1 = !{i32 7, !"Dwarf Version", i32 2}
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = !{i32 4, !"nvvm-reflect-ftz", i32 0}
+!4 = !{i32 7, !"frame-pointer", i32 2}
+!5 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !6, 
producer: "clang version 23.0.0git (https://github.com/llvm/llvm-project.git 
774f8a0b868cf526ffbd8af0a7e83c6b70d1b4fb)", isOptimized: true, runtimeVersion: 
0, emissionKind: DebugDirectivesOnly, splitDebugInlining: false, nameTableKind: 
None)
+!6 = !DIFile(filename: "/app/example.cu", directory: "/app")
+!7 = !{!"clang version 23.0.0git (https://github.com/llvm/llvm-project.git 
774f8a0b868cf526ffbd8af0a7e83c6b70d1b4fb)"}
+!8 = !{!"clang version 3.8.0 (tags/RELEASE_380/final)"}
+!9 = !{!10, !11, i64 0}
+!10 = !{!"__libc_errno", !11, i64 0}
+!11 = !{!"int", !12, i64 0}
+!12 = !{!"omnipotent char", !13, i64 0}
+!13 = !{!"Simple C++ TBAA"}
+!14 = !{i32 2, i32 0}
+;.
+; CHECK: attributes #[[ATTR0]] = { convergent mustprogress noinline norecurse 
nounwind "frame-pointer"="all" "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "target-cpu"="sm_120a" 
"target-features"="+ptx91,+sm_120a" "uniform-work-group-size" }
+; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind 
willreturn memory(argmem: readwrite) }
+; CHECK: attributes #[[ATTR2:[0-9]+]] = { convergent nocallback nounwind }
+; CHECK: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nosync nounwind 
speculatable willreturn memory(none) }
+; CHECK: attributes #[[ATTR4]] = { willreturn }
+; CHECK: attributes #[[ATTR5]] = { nounwind }
+;.
+; CHECK: [[META0:![0-9]+]] = !{i32 2, !"SDK Version", [2 x i32] [i32 13, i32 
1]}
+; CHECK: [[META1:![0-9]+]] = !{i32 7, !"Dwarf Version", i32 2}
+; CHECK: [[META2:![0-9]+]] = !{i32 2, !"Debug Info Version", i32 3}
+; CHECK: [[META3:![0-9]+]] = !{i32 4, !"nvvm-reflect-ftz", i32 0}
+; CHECK: [[META4:![0-9]+]] = !{i32 7, !"frame-pointer", i32 2}
+; CHECK: [[META5:![0-9]+]] = distinct !DICompileUnit(language: 
DW_LANG_C_plus_plus_14, file: [[META6:![0-9]+]], producer: "{{.*}}clang version 
{{.*}}", isOptimized: true, runtimeVersion: 0, emissionKind: 
DebugDirectivesOnly, splitDebugInlining: false, nameTableKind: None)
+; CHECK: [[META6]] = !DIFile(filename: "{{.*}}example.cu", directory: {{.*}})
+; CHECK: [[META7:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
+; CHECK: [[META8:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
+; CHECK: [[META9:![0-9]+]] = !{[[META10:![0-9]+]], [[META11:![0-9]+]], i64 0}
+; CHECK: [[META10]] = !{!"__libc_errno", [[META11]], i64 0}
+; CHECK: [[META11]] = !{!"int", [[META12:![0-9]+]], i64 0}
+; CHECK: [[META12]] = !{!"omnipotent char", [[META13:![0-9]+]], i64 0}
+; CHECK: [[META13]] = !{!"Simple C++ TBAA"}
+; CHECK: [[META14:![0-9]+]] = !{i32 2, i32 0}
+; CHECK: [[META15]] = !{}
+;.

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to