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
