Skip to content

Commit 6de44cc

Browse files
committed
[Clang] Add -fdefault-generic-addrspace flag for targeting GPUs
Summary: GPU targets support several different address spaces which have differing semantics. When targeting C/C++ we have a very pessimistic view that these address spaces are completely incompatible. This has a lot of unfortable effects that limit using address spaces in C++ as well as making it more difficult to work with. Flat addressing is supported by the major GPU targets, so it's highly desierable to use. The C/C++ standard says nothing about address spaces, so we cannot make any assumptions. However, OpenCL has an option that causes all pointers to be seen as 'generic'. This patch adds support for making every address space as `__generic` by default, similar to the CL extensions. This allows us to use this behavior outside of OpenCL mode. I have re-used the language option as it seemed easier than creating a second one. This works in most cases, however it does cause some problems for cases like this, as the default pointer type is now `__generic T` so it fails to bind to `T`. But since this is an opt-in thing it seems fine to force the user to add an extra template, or remove the qualifiers. ```c template<typename T> void foo(T *, T); ```
1 parent b385c63 commit 6de44cc

File tree

7 files changed

+200
-6
lines changed

7 files changed

+200
-6
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3714,6 +3714,9 @@ def fopenmp_assume_no_nested_parallelism : Flag<["-"], "fopenmp-assume-no-nested
37143714
} // let Visibility = [ClangOption, CC1Option, FC1Option]
37153715
} // let Flags = [NoArgumentUnused, HelpHidden]
37163716

3717+
def fdefault_generic_addrspace : Flag<["-"], "fdefault-generic-addrspace">, Group<f_Group>,
3718+
Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option]>,
3719+
HelpText<"Allow pointers to be implicitly casted to other address spaces.">;
37173720
def fopenmp_offload_mandatory : Flag<["-"], "fopenmp-offload-mandatory">, Group<f_Group>,
37183721
Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option]>,
37193722
HelpText<"Do not create a host fallback if offloading to the device fails.">,

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7069,6 +7069,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
70697069
if (Args.hasArg(options::OPT_nogpulib))
70707070
CmdArgs.push_back("-nogpulib");
70717071

7072+
if (Args.hasArg(options::OPT_fdefault_generic_addrspace))
7073+
CmdArgs.push_back("-fdefault-generic-addrspace");
7074+
70727075
if (Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) {
70737076
CmdArgs.push_back(
70747077
Args.MakeArgString(Twine("-fcf-protection=") + A->getValue()));

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3670,6 +3670,9 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
36703670
if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200))
36713671
GenerateArg(Consumer, OPT_fblocks);
36723672

3673+
if (Opts.OpenCLGenericAddressSpace)
3674+
GenerateArg(Consumer, OPT_fdefault_generic_addrspace);
3675+
36733676
if (Opts.ConvergentFunctions)
36743677
GenerateArg(Consumer, OPT_fconvergent_functions);
36753678
else
@@ -3947,6 +3950,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
39473950
// These need to be parsed now. They are used to set OpenCL defaults.
39483951
Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header);
39493952
Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins);
3953+
Opts.OpenCLGenericAddressSpace = Args.hasArg(OPT_fdefault_generic_addrspace);
39503954

39513955
LangOptions::setLangDefaults(Opts, IK.getLanguage(), T, Includes, LangStd);
39523956

clang/lib/Sema/Sema.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1579,7 +1579,7 @@ NamedDecl *Sema::getCurFunctionOrMethodDecl() const {
15791579
}
15801580

15811581
LangAS Sema::getDefaultCXXMethodAddrSpace() const {
1582-
if (getLangOpts().OpenCL)
1582+
if (getLangOpts().OpenCL || getLangOpts().OpenCLGenericAddressSpace)
15831583
return getASTContext().getDefaultOpenCLPointeeAddrSpace();
15841584
return LangAS::Default;
15851585
}

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16178,7 +16178,8 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
1617816178
<< FnDecl->getDeclName();
1617916179

1618016180
QualType FirstParamType = FnDecl->getParamDecl(0)->getType();
16181-
if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
16181+
if (SemaRef.getLangOpts().OpenCLCPlusPlus ||
16182+
SemaRef.getLangOpts().OpenCLGenericAddressSpace) {
1618216183
// The operator is valid on any address space for OpenCL.
1618316184
// Drop address space from actual and expected first parameter types.
1618416185
if (const auto *PtrTy =

clang/lib/Sema/SemaType.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,7 +1836,7 @@ QualType Sema::BuildPointerType(QualType T,
18361836
if (getLangOpts().ObjCAutoRefCount)
18371837
T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ false);
18381838

1839-
if (getLangOpts().OpenCL)
1839+
if (getLangOpts().OpenCL || getLangOpts().OpenCLGenericAddressSpace)
18401840
T = deduceOpenCLPointeeAddrSpace(*this, T);
18411841

18421842
// In WebAssembly, pointers to reference types and pointers to tables are
@@ -1913,7 +1913,7 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
19131913
if (getLangOpts().ObjCAutoRefCount)
19141914
T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true);
19151915

1916-
if (getLangOpts().OpenCL)
1916+
if (getLangOpts().OpenCL || getLangOpts().OpenCLGenericAddressSpace)
19171917
T = deduceOpenCLPointeeAddrSpace(*this, T);
19181918

19191919
// In WebAssembly, references to reference types and tables are illegal.
@@ -2741,7 +2741,7 @@ QualType Sema::BuildBlockPointerType(QualType T,
27412741
if (checkQualifiedFunction(*this, T, Loc, QFK_BlockPointer))
27422742
return QualType();
27432743

2744-
if (getLangOpts().OpenCL)
2744+
if (getLangOpts().OpenCL || getLangOpts().OpenCLGenericAddressSpace)
27452745
T = deduceOpenCLPointeeAddrSpace(*this, T);
27462746

27472747
return Context.getBlockPointerType(T);
@@ -5289,7 +5289,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
52895289
DeclaratorContext::LambdaExpr;
52905290
};
52915291

5292-
if (state.getSema().getLangOpts().OpenCLCPlusPlus && IsClassMember()) {
5292+
if ((state.getSema().getLangOpts().OpenCLCPlusPlus ||
5293+
(!state.getSema().getLangOpts().OpenCL &&
5294+
state.getSema().getLangOpts().OpenCLGenericAddressSpace)) &&
5295+
IsClassMember()) {
52935296
LangAS ASIdx = LangAS::Default;
52945297
// Take address space attr if any and mark as invalid to avoid adding
52955298
// them later while creating QualType.
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
2+
// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fdefault-generic-addrspace -emit-llvm \
3+
// RUN: -fvisibility=hidden -o - %s | FileCheck %s --check-prefix=NVPTX
4+
// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fdefault-generic-addrspace -emit-llvm \
5+
// RUN: -fvisibility=hidden -o - %s | FileCheck %s --check-prefix=AMDGPU
6+
7+
// NVPTX-LABEL: define hidden void @_Z1fPv(
8+
// NVPTX-SAME: ptr noundef [[P:%.*]]) #[[ATTR0:[0-9]+]] {
9+
// NVPTX-NEXT: [[ENTRY:.*:]]
10+
// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8
11+
// NVPTX-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8
12+
// NVPTX-NEXT: ret void
13+
//
14+
// AMDGPU-LABEL: define hidden void @_Z1fPv(
15+
// AMDGPU-SAME: ptr noundef [[P:%.*]]) #[[ATTR0:[0-9]+]] {
16+
// AMDGPU-NEXT: [[ENTRY:.*:]]
17+
// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
18+
// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr
19+
// AMDGPU-NEXT: store ptr [[P]], ptr [[P_ADDR_ASCAST]], align 8
20+
// AMDGPU-NEXT: ret void
21+
//
22+
void f(void *p) {}
23+
24+
// NVPTX-LABEL: define hidden void @_Z2p1Pv(
25+
// NVPTX-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] {
26+
// NVPTX-NEXT: [[ENTRY:.*:]]
27+
// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8
28+
// NVPTX-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8
29+
// NVPTX-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8
30+
// NVPTX-NEXT: call void @_Z1fPv(ptr noundef [[TMP0]]) #[[ATTR1:[0-9]+]]
31+
// NVPTX-NEXT: ret void
32+
//
33+
// AMDGPU-LABEL: define hidden void @_Z2p1Pv(
34+
// AMDGPU-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] {
35+
// AMDGPU-NEXT: [[ENTRY:.*:]]
36+
// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
37+
// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr
38+
// AMDGPU-NEXT: store ptr [[P]], ptr [[P_ADDR_ASCAST]], align 8
39+
// AMDGPU-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR_ASCAST]], align 8
40+
// AMDGPU-NEXT: call void @_Z1fPv(ptr noundef [[TMP0]]) #[[ATTR1:[0-9]+]]
41+
// AMDGPU-NEXT: ret void
42+
//
43+
void p1(void [[clang::opencl_generic]] * p) { f(p); }
44+
// NVPTX-LABEL: define hidden noundef ptr @_Z2p2PU3AS3v(
45+
// NVPTX-SAME: ptr addrspace(3) noundef [[P:%.*]]) #[[ATTR0]] {
46+
// NVPTX-NEXT: [[ENTRY:.*:]]
47+
// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(3), align 8
48+
// NVPTX-NEXT: store ptr addrspace(3) [[P]], ptr [[P_ADDR]], align 8
49+
// NVPTX-NEXT: [[TMP0:%.*]] = load ptr addrspace(3), ptr [[P_ADDR]], align 8
50+
// NVPTX-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(3) [[TMP0]] to ptr
51+
// NVPTX-NEXT: ret ptr [[TMP1]]
52+
//
53+
// AMDGPU-LABEL: define hidden noundef ptr @_Z2p2PU3AS3v(
54+
// AMDGPU-SAME: ptr addrspace(3) noundef [[P:%.*]]) #[[ATTR0]] {
55+
// AMDGPU-NEXT: [[ENTRY:.*:]]
56+
// AMDGPU-NEXT: [[RETVAL:%.*]] = alloca ptr, align 8, addrspace(5)
57+
// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5)
58+
// AMDGPU-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL]] to ptr
59+
// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr
60+
// AMDGPU-NEXT: store ptr addrspace(3) [[P]], ptr [[P_ADDR_ASCAST]], align 4
61+
// AMDGPU-NEXT: [[TMP0:%.*]] = load ptr addrspace(3), ptr [[P_ADDR_ASCAST]], align 4
62+
// AMDGPU-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(3) [[TMP0]] to ptr
63+
// AMDGPU-NEXT: ret ptr [[TMP1]]
64+
//
65+
void *p2(void [[clang::opencl_local]] * p) { return p; }
66+
// NVPTX-LABEL: define hidden noundef ptr @_Z2p3PU3AS3v(
67+
// NVPTX-SAME: ptr addrspace(3) noundef [[P:%.*]]) #[[ATTR0]] {
68+
// NVPTX-NEXT: [[ENTRY:.*:]]
69+
// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(3), align 8
70+
// NVPTX-NEXT: store ptr addrspace(3) [[P]], ptr [[P_ADDR]], align 8
71+
// NVPTX-NEXT: [[TMP0:%.*]] = load ptr addrspace(3), ptr [[P_ADDR]], align 8
72+
// NVPTX-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(3) [[TMP0]] to ptr
73+
// NVPTX-NEXT: ret ptr [[TMP1]]
74+
//
75+
// AMDGPU-LABEL: define hidden noundef ptr @_Z2p3PU3AS3v(
76+
// AMDGPU-SAME: ptr addrspace(3) noundef [[P:%.*]]) #[[ATTR0]] {
77+
// AMDGPU-NEXT: [[ENTRY:.*:]]
78+
// AMDGPU-NEXT: [[RETVAL:%.*]] = alloca ptr, align 8, addrspace(5)
79+
// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5)
80+
// AMDGPU-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL]] to ptr
81+
// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr
82+
// AMDGPU-NEXT: store ptr addrspace(3) [[P]], ptr [[P_ADDR_ASCAST]], align 4
83+
// AMDGPU-NEXT: [[TMP0:%.*]] = load ptr addrspace(3), ptr [[P_ADDR_ASCAST]], align 4
84+
// AMDGPU-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(3) [[TMP0]] to ptr
85+
// AMDGPU-NEXT: ret ptr [[TMP1]]
86+
//
87+
void *p3(void [[clang::address_space(3)]] * p) { return p; }
88+
89+
struct S {
90+
S() = default;
91+
~S() = default;
92+
void foo() {}
93+
};
94+
95+
S s1;
96+
S [[clang::opencl_global]] s2;
97+
S [[clang::opencl_local]] s3;
98+
99+
template <typename Ty> void foo(Ty *) {}
100+
101+
// NVPTX-LABEL: define hidden void @_Z2t1Pv(
102+
// NVPTX-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] {
103+
// NVPTX-NEXT: [[ENTRY:.*:]]
104+
// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8
105+
// NVPTX-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8
106+
// NVPTX-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8
107+
// NVPTX-NEXT: call void @_Z3fooIvEvPT_(ptr noundef [[TMP0]]) #[[ATTR1]]
108+
// NVPTX-NEXT: ret void
109+
//
110+
// AMDGPU-LABEL: define hidden void @_Z2t1Pv(
111+
// AMDGPU-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] {
112+
// AMDGPU-NEXT: [[ENTRY:.*:]]
113+
// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
114+
// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr
115+
// AMDGPU-NEXT: store ptr [[P]], ptr [[P_ADDR_ASCAST]], align 8
116+
// AMDGPU-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR_ASCAST]], align 8
117+
// AMDGPU-NEXT: call void @_Z3fooIvEvPT_(ptr noundef [[TMP0]]) #[[ATTR1]]
118+
// AMDGPU-NEXT: ret void
119+
//
120+
void t1(void *p) { foo(p); }
121+
// NVPTX-LABEL: define hidden void @_Z2t2Pv(
122+
// NVPTX-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] {
123+
// NVPTX-NEXT: [[ENTRY:.*:]]
124+
// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8
125+
// NVPTX-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8
126+
// NVPTX-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8
127+
// NVPTX-NEXT: call void @_Z3fooIvEvPT_(ptr noundef [[TMP0]]) #[[ATTR1]]
128+
// NVPTX-NEXT: ret void
129+
//
130+
// AMDGPU-LABEL: define hidden void @_Z2t2Pv(
131+
// AMDGPU-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] {
132+
// AMDGPU-NEXT: [[ENTRY:.*:]]
133+
// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
134+
// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr
135+
// AMDGPU-NEXT: store ptr [[P]], ptr [[P_ADDR_ASCAST]], align 8
136+
// AMDGPU-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR_ASCAST]], align 8
137+
// AMDGPU-NEXT: call void @_Z3fooIvEvPT_(ptr noundef [[TMP0]]) #[[ATTR1]]
138+
// AMDGPU-NEXT: ret void
139+
//
140+
void t2(void [[clang::opencl_generic]] *p) { foo(p); }
141+
// NVPTX-LABEL: define hidden void @_Z2t3PU3AS3v(
142+
// NVPTX-SAME: ptr addrspace(3) noundef [[P:%.*]]) #[[ATTR0]] {
143+
// NVPTX-NEXT: [[ENTRY:.*:]]
144+
// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(3), align 8
145+
// NVPTX-NEXT: store ptr addrspace(3) [[P]], ptr [[P_ADDR]], align 8
146+
// NVPTX-NEXT: [[TMP0:%.*]] = load ptr addrspace(3), ptr [[P_ADDR]], align 8
147+
// NVPTX-NEXT: call void @_Z3fooIU3AS3vEvPT_(ptr addrspace(3) noundef [[TMP0]]) #[[ATTR1]]
148+
// NVPTX-NEXT: ret void
149+
//
150+
// AMDGPU-LABEL: define hidden void @_Z2t3PU3AS3v(
151+
// AMDGPU-SAME: ptr addrspace(3) noundef [[P:%.*]]) #[[ATTR0]] {
152+
// AMDGPU-NEXT: [[ENTRY:.*:]]
153+
// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5)
154+
// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr
155+
// AMDGPU-NEXT: store ptr addrspace(3) [[P]], ptr [[P_ADDR_ASCAST]], align 4
156+
// AMDGPU-NEXT: [[TMP0:%.*]] = load ptr addrspace(3), ptr [[P_ADDR_ASCAST]], align 4
157+
// AMDGPU-NEXT: call void @_Z3fooIU3AS3vEvPT_(ptr addrspace(3) noundef [[TMP0]]) #[[ATTR1]]
158+
// AMDGPU-NEXT: ret void
159+
//
160+
void t3(void [[clang::opencl_local]] *p) { foo(p); }
161+
// NVPTX-LABEL: define hidden void @_Z2t4PU5AS999v(
162+
// NVPTX-SAME: ptr addrspace(999) noundef [[P:%.*]]) #[[ATTR0]] {
163+
// NVPTX-NEXT: [[ENTRY:.*:]]
164+
// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(999), align 8
165+
// NVPTX-NEXT: store ptr addrspace(999) [[P]], ptr [[P_ADDR]], align 8
166+
// NVPTX-NEXT: [[TMP0:%.*]] = load ptr addrspace(999), ptr [[P_ADDR]], align 8
167+
// NVPTX-NEXT: call void @_Z3fooIU5AS999vEvPT_(ptr addrspace(999) noundef [[TMP0]]) #[[ATTR1]]
168+
// NVPTX-NEXT: ret void
169+
//
170+
// AMDGPU-LABEL: define hidden void @_Z2t4PU5AS999v(
171+
// AMDGPU-SAME: ptr addrspace(999) noundef [[P:%.*]]) #[[ATTR0]] {
172+
// AMDGPU-NEXT: [[ENTRY:.*:]]
173+
// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(999), align 8, addrspace(5)
174+
// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr
175+
// AMDGPU-NEXT: store ptr addrspace(999) [[P]], ptr [[P_ADDR_ASCAST]], align 8
176+
// AMDGPU-NEXT: [[TMP0:%.*]] = load ptr addrspace(999), ptr [[P_ADDR_ASCAST]], align 8
177+
// AMDGPU-NEXT: call void @_Z3fooIU5AS999vEvPT_(ptr addrspace(999) noundef [[TMP0]]) #[[ATTR1]]
178+
// AMDGPU-NEXT: ret void
179+
//
180+
void t4(void [[clang::address_space(999)]] *p) { foo(p); }

0 commit comments

Comments
 (0)