Files
clang-p2996/llvm/test/Transforms/Attributor/value-simplify-gpu.ll
Shilei Tian bcba20b5d0 [Attributor] Add AAAddressSpace to deduce address spaces
This patch adds initial support for the `AAAddressSpace` abstract
attributor interface to deduce and query address space information for a
pointer. We simply query the underlying objects that a pointer can point
to and find a common address space if they exist. This is the minimal
support for the interface, we currently manifest changes on loads and
stores. Additionally we should use the target transform information to
deduce if an address space transformation is a no-op for the target
machine when calculating compatibility.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D120586
2023-07-12 15:47:41 -04:00

376 lines
16 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
target triple = "amdgcn-amd-amdhsa"
%struct.ident_t = type { i32, i32, i32, i32, ptr }
@ReachableKernel = internal addrspace(3) global i32 3, align 4
@UnreachableKernel = internal addrspace(3) global i32 42, align 4
@ReachableKernelAS0 = internal global i32 7, align 4
;.
; CHECK: @[[REACHABLEKERNEL:[a-zA-Z0-9_$"\\.-]+]] = internal addrspace(3) global i32 3, align 4
; CHECK: @[[UNREACHABLEKERNEL:[a-zA-Z0-9_$"\\.-]+]] = internal addrspace(3) global i32 42, align 4
; CHECK: @[[REACHABLEKERNELAS0:[a-zA-Z0-9_$"\\.-]+]] = internal global i32 7, align 4
; CHECK: @[[REACHABLENONKERNEL:[a-zA-Z0-9_$"\\.-]+]] = internal addrspace(3) global i32 0, align 4
; CHECK: @[[UNREACHABLENONKERNEL:[a-zA-Z0-9_$"\\.-]+]] = internal addrspace(3) global i32 0, align 4
;.
define dso_local void @kernel(i32 %C) norecurse "kernel" {
; TUNIT: Function Attrs: norecurse nosync nounwind
; TUNIT-LABEL: define {{[^@]+}}@kernel
; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR0:[0-9]+]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: call void @level1Kernel(i32 [[C]]) #[[ATTR1:[0-9]+]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: norecurse nosync nounwind
; CGSCC-LABEL: define {{[^@]+}}@kernel
; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR0:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: call void @level1Kernel(i32 [[C]]) #[[ATTR4:[0-9]+]]
; CGSCC-NEXT: ret void
;
entry:
call void @level1Kernel(i32 %C)
ret void
}
define internal void @level1Kernel(i32 %C) {
; TUNIT: Function Attrs: norecurse nosync nounwind
; TUNIT-LABEL: define {{[^@]+}}@level1Kernel
; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: call void @level2Kernelall_early() #[[ATTR3:[0-9]+]]
; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0
; TUNIT-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; TUNIT: if.then:
; TUNIT-NEXT: call void @level2Kernela() #[[ATTR4:[0-9]+]]
; TUNIT-NEXT: br label [[IF_END:%.*]]
; TUNIT: if.else:
; TUNIT-NEXT: call void @level2Kernelb() #[[ATTR4]]
; TUNIT-NEXT: br label [[IF_END]]
; TUNIT: if.end:
; TUNIT-NEXT: call void @level2Kernelall_late() #[[ATTR5:[0-9]+]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: norecurse nosync nounwind
; CGSCC-LABEL: define {{[^@]+}}@level1Kernel
; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR1:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: call void @level2Kernelall_early() #[[ATTR5:[0-9]+]]
; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0
; CGSCC-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; CGSCC: if.then:
; CGSCC-NEXT: call void @level2Kernela() #[[ATTR4]]
; CGSCC-NEXT: br label [[IF_END:%.*]]
; CGSCC: if.else:
; CGSCC-NEXT: call void @level2Kernelb() #[[ATTR4]]
; CGSCC-NEXT: br label [[IF_END]]
; CGSCC: if.end:
; CGSCC-NEXT: call void @level2Kernelall_late() #[[ATTR6:[0-9]+]]
; CGSCC-NEXT: ret void
;
entry:
call void @level2Kernelall_early()
%tobool = icmp ne i32 %C, 0
br i1 %tobool, label %if.then, label %if.else
if.then: ; preds = %entry
call void @level2Kernela()
br label %if.end
if.else: ; preds = %entry
call void @level2Kernelb()
br label %if.end
if.end: ; preds = %if.else, %if.then
call void @level2Kernelall_late()
ret void
}
define internal void @level2Kernelall_early() {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; CHECK-LABEL: define {{[^@]+}}@level2Kernelall_early
; CHECK-SAME: () #[[ATTR2:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: store i32 1, ptr @ReachableKernelAS0, align 4
; CHECK-NEXT: store i32 1, ptr addrspace(3) @ReachableKernel, align 4
; CHECK-NEXT: ret void
;
entry:
store i32 1, ptr @ReachableKernelAS0, align 4
store i32 1, ptr addrspacecast (ptr addrspace(3) @ReachableKernel to ptr), align 4
ret void
}
define internal void @level2Kernela() {
; TUNIT: Function Attrs: norecurse nosync nounwind
; TUNIT-LABEL: define {{[^@]+}}@level2Kernela
; TUNIT-SAME: () #[[ATTR1]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(3) @ReachableKernel, align 4
; TUNIT-NEXT: [[TMP1:%.*]] = load i32, ptr @ReachableKernelAS0, align 4
; TUNIT-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(3) @UnreachableKernel, align 4
; TUNIT-NEXT: call void @use(i32 noundef [[TMP0]], i32 noundef [[TMP1]], i32 noundef [[TMP2]]) #[[ATTR6:[0-9]+]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: nosync nounwind
; CGSCC-LABEL: define {{[^@]+}}@level2Kernela
; CGSCC-SAME: () #[[ATTR3:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(3) @ReachableKernel, align 4
; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr @ReachableKernelAS0, align 4
; CGSCC-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(3) @UnreachableKernel, align 4
; CGSCC-NEXT: call void @use(i32 noundef [[TMP0]], i32 noundef [[TMP1]], i32 noundef [[TMP2]]) #[[ATTR4]]
; CGSCC-NEXT: ret void
;
entry:
%0 = load i32, ptr addrspacecast (ptr addrspace(3) @ReachableKernel to ptr), align 4
%1 = load i32, ptr @ReachableKernelAS0, align 4
%2 = load i32, ptr addrspacecast (ptr addrspace(3) @UnreachableKernel to ptr), align 4
call void @use(i32 %0, i32 %1, i32 %2)
ret void
}
define internal void @level2Kernelb() {
; TUNIT: Function Attrs: norecurse nosync nounwind
; TUNIT-LABEL: define {{[^@]+}}@level2Kernelb
; TUNIT-SAME: () #[[ATTR1]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(3) @ReachableKernel, align 4
; TUNIT-NEXT: [[TMP1:%.*]] = load i32, ptr @ReachableKernelAS0, align 4
; TUNIT-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(3) @UnreachableKernel, align 4
; TUNIT-NEXT: call void @use(i32 noundef [[TMP0]], i32 noundef [[TMP1]], i32 noundef [[TMP2]]) #[[ATTR6]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: nosync nounwind
; CGSCC-LABEL: define {{[^@]+}}@level2Kernelb
; CGSCC-SAME: () #[[ATTR3]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(3) @ReachableKernel, align 4
; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr @ReachableKernelAS0, align 4
; CGSCC-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(3) @UnreachableKernel, align 4
; CGSCC-NEXT: call void @use(i32 noundef [[TMP0]], i32 noundef [[TMP1]], i32 noundef [[TMP2]]) #[[ATTR4]]
; CGSCC-NEXT: ret void
;
entry:
%0 = load i32, ptr addrspacecast (ptr addrspace(3) @ReachableKernel to ptr), align 4
%1 = load i32, ptr @ReachableKernelAS0, align 4
%2 = load i32, ptr addrspacecast (ptr addrspace(3) @UnreachableKernel to ptr), align 4
call void @use(i32 %0, i32 %1, i32 %2)
ret void
}
define internal void @level2Kernelall_late() {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; CHECK-LABEL: define {{[^@]+}}@level2Kernelall_late
; CHECK-SAME: () #[[ATTR2]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: store i32 1, ptr addrspace(3) @UnreachableKernel, align 4
; CHECK-NEXT: ret void
;
entry:
store i32 1, ptr addrspacecast (ptr addrspace(3) @UnreachableKernel to ptr), align 4
ret void
}
@ReachableNonKernel = internal addrspace(3) global i32 0, align 4
@UnreachableNonKernel = internal addrspace(3) global i32 0, align 4
define dso_local void @non_kernel(i32 %C) norecurse {
; TUNIT: Function Attrs: norecurse nosync nounwind
; TUNIT-LABEL: define {{[^@]+}}@non_kernel
; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: call void @level1(i32 [[C]]) #[[ATTR1]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: norecurse nosync nounwind
; CGSCC-LABEL: define {{[^@]+}}@non_kernel
; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: call void @level1(i32 [[C]]) #[[ATTR4]]
; CGSCC-NEXT: ret void
;
entry:
call void @level1(i32 %C)
ret void
}
define internal void @level1(i32 %C) {
; TUNIT: Function Attrs: norecurse nosync nounwind
; TUNIT-LABEL: define {{[^@]+}}@level1
; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[LOCAL:%.*]] = alloca i32, align 4
; TUNIT-NEXT: call void @level2all_early(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR3]]
; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0
; TUNIT-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; TUNIT: if.then:
; TUNIT-NEXT: call void @level2a() #[[ATTR4]]
; TUNIT-NEXT: br label [[IF_END:%.*]]
; TUNIT: if.else:
; TUNIT-NEXT: call void @level2b() #[[ATTR4]]
; TUNIT-NEXT: br label [[IF_END]]
; TUNIT: if.end:
; TUNIT-NEXT: call void @level2all_late(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR5]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: norecurse nosync nounwind
; CGSCC-LABEL: define {{[^@]+}}@level1
; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[LOCAL:%.*]] = alloca i32, align 4
; CGSCC-NEXT: call void @level2all_early(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR5]]
; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[C]], 0
; CGSCC-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; CGSCC: if.then:
; CGSCC-NEXT: call void @level2a(ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR4]]
; CGSCC-NEXT: br label [[IF_END:%.*]]
; CGSCC: if.else:
; CGSCC-NEXT: call void @level2b(ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR4]]
; CGSCC-NEXT: br label [[IF_END]]
; CGSCC: if.end:
; CGSCC-NEXT: call void @level2all_late(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[LOCAL]]) #[[ATTR6]]
; CGSCC-NEXT: ret void
;
entry:
%local = alloca i32
call void @level2all_early(ptr %local)
%tobool = icmp ne i32 %C, 0
br i1 %tobool, label %if.then, label %if.else
if.then: ; preds = %entry
call void @level2a(ptr %local)
br label %if.end
if.else: ; preds = %entry
call void @level2b(ptr %local)
br label %if.end
if.end: ; preds = %if.else, %if.then
call void @level2all_late(ptr %local)
ret void
}
define internal void @level2all_early(ptr %addr) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@level2all_early
; TUNIT-SAME: (ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[ADDR:%.*]]) #[[ATTR2]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: store i32 1, ptr addrspace(3) @ReachableNonKernel, align 4
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; CGSCC-LABEL: define {{[^@]+}}@level2all_early
; CGSCC-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[ADDR:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: store i32 1, ptr addrspace(3) @ReachableNonKernel, align 4
; CGSCC-NEXT: store i32 17, ptr [[ADDR]], align 4
; CGSCC-NEXT: ret void
;
entry:
store i32 1, ptr addrspacecast (ptr addrspace(3) @ReachableNonKernel to ptr), align 4
store i32 17, ptr %addr, align 4
ret void
}
define internal void @level2a(ptr %addr) {
; TUNIT: Function Attrs: norecurse nosync nounwind
; TUNIT-LABEL: define {{[^@]+}}@level2a
; TUNIT-SAME: () #[[ATTR1]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(3) @ReachableNonKernel, align 4
; TUNIT-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(3) @UnreachableNonKernel, align 4
; TUNIT-NEXT: call void @use(i32 noundef [[TMP0]], i32 noundef [[TMP1]], i32 17) #[[ATTR6]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: nosync nounwind
; CGSCC-LABEL: define {{[^@]+}}@level2a
; CGSCC-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ADDR:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(3) @ReachableNonKernel, align 4
; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(3) @UnreachableNonKernel, align 4
; CGSCC-NEXT: [[QQQQ2:%.*]] = load i32, ptr [[ADDR]], align 4
; CGSCC-NEXT: call void @use(i32 noundef [[TMP0]], i32 noundef [[TMP1]], i32 [[QQQQ2]]) #[[ATTR4]]
; CGSCC-NEXT: ret void
;
entry:
%0 = load i32, ptr addrspacecast (ptr addrspace(3) @ReachableNonKernel to ptr), align 4
%1 = load i32, ptr addrspacecast (ptr addrspace(3) @UnreachableNonKernel to ptr), align 4
%qqqq2 = load i32, ptr %addr
call void @use(i32 %0, i32 %1, i32 %qqqq2)
ret void
}
define internal void @level2b(ptr %addr) {
; TUNIT: Function Attrs: norecurse nosync nounwind
; TUNIT-LABEL: define {{[^@]+}}@level2b
; TUNIT-SAME: () #[[ATTR1]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(3) @ReachableNonKernel, align 4
; TUNIT-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(3) @UnreachableNonKernel, align 4
; TUNIT-NEXT: call void @use(i32 noundef [[TMP0]], i32 noundef [[TMP1]], i32 17) #[[ATTR6]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: nosync nounwind
; CGSCC-LABEL: define {{[^@]+}}@level2b
; CGSCC-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ADDR:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(3) @ReachableNonKernel, align 4
; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(3) @UnreachableNonKernel, align 4
; CGSCC-NEXT: [[TMP2:%.*]] = load i32, ptr [[ADDR]], align 4
; CGSCC-NEXT: call void @use(i32 noundef [[TMP0]], i32 noundef [[TMP1]], i32 [[TMP2]]) #[[ATTR4]]
; CGSCC-NEXT: ret void
;
entry:
%0 = load i32, ptr addrspacecast (ptr addrspace(3) @ReachableNonKernel to ptr), align 4
%1 = load i32, ptr addrspacecast (ptr addrspace(3) @UnreachableNonKernel to ptr), align 4
%2 = load i32, ptr %addr
call void @use(i32 %0, i32 %1, i32 %2)
ret void
}
define internal void @level2all_late(ptr %addr) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@level2all_late
; TUNIT-SAME: (ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[ADDR:%.*]]) #[[ATTR2]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: store i32 1, ptr addrspace(3) @UnreachableNonKernel, align 4
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; CGSCC-LABEL: define {{[^@]+}}@level2all_late
; CGSCC-SAME: (ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[ADDR:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: store i32 1, ptr addrspace(3) @UnreachableNonKernel, align 4
; CGSCC-NEXT: store i32 5, ptr [[ADDR]], align 4
; CGSCC-NEXT: ret void
;
entry:
store i32 1, ptr addrspacecast (ptr addrspace(3) @UnreachableNonKernel to ptr), align 4
store i32 5, ptr %addr, align 4
ret void
}
declare dso_local void @use(i32, i32, i32) nosync norecurse nounwind
;.
; TUNIT: attributes #[[ATTR0]] = { norecurse nosync nounwind "kernel" }
; TUNIT: attributes #[[ATTR1]] = { norecurse nosync nounwind }
; TUNIT: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
; TUNIT: attributes #[[ATTR3]] = { nofree nosync nounwind willreturn memory(write) }
; TUNIT: attributes #[[ATTR4]] = { nosync nounwind }
; TUNIT: attributes #[[ATTR5]] = { nosync nounwind memory(write) }
; TUNIT: attributes #[[ATTR6]] = { nounwind }
;.
; CGSCC: attributes #[[ATTR0]] = { norecurse nosync nounwind "kernel" }
; CGSCC: attributes #[[ATTR1]] = { norecurse nosync nounwind }
; CGSCC: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
; CGSCC: attributes #[[ATTR3]] = { nosync nounwind }
; CGSCC: attributes #[[ATTR4]] = { nounwind }
; CGSCC: attributes #[[ATTR5]] = { nofree nounwind willreturn memory(write) }
; CGSCC: attributes #[[ATTR6]] = { nounwind memory(write) }
;.