Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 77805a3

Browse files
committed
[OpenMP] Show error if VLAs are not supported
Some target devices (e.g. Nvidia GPUs) don't support dynamic stack allocation and hence no VLAs. Print errors with description instead of failing in the backend or generating code that doesn't work. This patch handles explicit uses of VLAs (local variable in target or declare target region) or implicitly generated (private) VLAs for reductions on VLAs or on array sections with non-constant size. Differential Revision: https://reviews.llvm.org/D39505 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@318601 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent c7a8630 commit 77805a3

File tree

9 files changed

+248
-13
lines changed

9 files changed

+248
-13
lines changed

Diff for: include/clang/Basic/DiagnosticSemaKinds.td

+6
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ def err_vla_decl_has_extern_linkage : Error<
141141
"variable length array declaration cannot have 'extern' linkage">;
142142
def ext_vla_folded_to_constant : Extension<
143143
"variable length array folded to constant array as an extension">, InGroup<GNUFoldingConstant>;
144+
def err_vla_unsupported : Error<
145+
"variable length arrays are not supported for the current target">;
146+
def note_vla_unsupported : Note<
147+
"variable length arrays are not supported for the current target">;
144148

145149
// C99 variably modified types
146150
def err_variably_modified_template_arg : Error<
@@ -8985,6 +8989,8 @@ def err_omp_reduction_non_addressable_expression : Error<
89858989
"expected addressable reduction item for the task-based directives">;
89868990
def err_omp_reduction_with_nogroup : Error<
89878991
"'reduction' clause cannot be used with 'nogroup' clause">;
8992+
def err_omp_reduction_vla_unsupported : Error<
8993+
"cannot generate code for reduction on %select{|array section, which requires a }0variable length array">;
89888994
} // end of OpenMP category
89898995

89908996
let CategoryName = "Related Result Type Issue" in {

Diff for: include/clang/Basic/TargetInfo.h

+4
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
6060
// values are specified by the TargetInfo constructor.
6161
bool BigEndian;
6262
bool TLSSupported;
63+
bool VLASupported;
6364
bool NoAsmVariants; // True if {|} are normal characters.
6465
bool HasFloat128;
6566
unsigned char PointerWidth, PointerAlign;
@@ -939,6 +940,9 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
939940
return MaxTLSAlign;
940941
}
941942

943+
/// \brief Whether target supports variable-length arrays.
944+
bool isVLASupported() const { return VLASupported; }
945+
942946
/// \brief Whether the target supports SEH __try.
943947
bool isSEHTrySupported() const {
944948
return getTriple().isOSWindows() &&

Diff for: include/clang/Sema/Sema.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -8653,10 +8653,18 @@ class Sema {
86538653
NamedDeclSetType &SameDirectiveDecls);
86548654
/// Check declaration inside target region.
86558655
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D);
8656-
/// Return true inside OpenMP target region.
8656+
/// Return true inside OpenMP declare target region.
86578657
bool isInOpenMPDeclareTargetContext() const {
86588658
return IsInOpenMPDeclareTargetContext;
86598659
}
8660+
/// Return true inside OpenMP target region.
8661+
bool isInOpenMPTargetExecutionDirective() const;
8662+
/// Return true if (un)supported features for the current target should be
8663+
/// diagnosed if OpenMP (offloading) is enabled.
8664+
bool shouldDiagnoseTargetSupportFromOpenMP() const {
8665+
return !getLangOpts().OpenMPIsDevice || isInOpenMPDeclareTargetContext() ||
8666+
isInOpenMPTargetExecutionDirective();
8667+
}
86608668

86618669
/// Return the number of captured regions created for an OpenMP directive.
86628670
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind);

Diff for: lib/Basic/TargetInfo.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
3131
// SPARC. These should be overridden by concrete targets as needed.
3232
BigEndian = !T.isLittleEndian();
3333
TLSSupported = true;
34+
VLASupported = true;
3435
NoAsmVariants = false;
3536
HasFloat128 = false;
3637
PointerWidth = PointerAlign = 32;

Diff for: lib/Basic/Targets/NVPTX.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,
4141
"NVPTX only supports 32- and 64-bit modes.");
4242

4343
TLSSupported = false;
44+
VLASupported = false;
4445
AddrSpaceMap = &NVPTXAddrSpaceMap;
4546
UseAddrSpaceMapMangling = true;
4647

Diff for: lib/Basic/Targets/SPIR.h

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public TargetInfo {
4343
assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
4444
"SPIR target must use unknown environment type");
4545
TLSSupported = false;
46+
VLASupported = false;
4647
LongWidth = LongAlign = 64;
4748
AddrSpaceMap = &SPIRAddrSpaceMap;
4849
UseAddrSpaceMapMangling = true;

Diff for: lib/Sema/SemaOpenMP.cpp

+19-12
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,17 @@ unsigned Sema::getOpenMPNestingLevel() const {
13031303
return DSAStack->getNestingLevel();
13041304
}
13051305

1306+
bool Sema::isInOpenMPTargetExecutionDirective() const {
1307+
return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
1308+
!DSAStack->isClauseParsingMode()) ||
1309+
DSAStack->hasDirective(
1310+
[](OpenMPDirectiveKind K, const DeclarationNameInfo &,
1311+
SourceLocation) -> bool {
1312+
return isOpenMPTargetExecutionDirective(K);
1313+
},
1314+
false);
1315+
}
1316+
13061317
VarDecl *Sema::IsOpenMPCapturedDecl(ValueDecl *D) {
13071318
assert(LangOpts.OpenMP && "OpenMP is not allowed");
13081319
D = getCanonicalDecl(D);
@@ -1315,18 +1326,8 @@ VarDecl *Sema::IsOpenMPCapturedDecl(ValueDecl *D) {
13151326
// inserted here once support for 'declare target' is added.
13161327
//
13171328
auto *VD = dyn_cast<VarDecl>(D);
1318-
if (VD && !VD->hasLocalStorage()) {
1319-
if (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
1320-
!DSAStack->isClauseParsingMode())
1321-
return VD;
1322-
if (DSAStack->hasDirective(
1323-
[](OpenMPDirectiveKind K, const DeclarationNameInfo &,
1324-
SourceLocation) -> bool {
1325-
return isOpenMPTargetExecutionDirective(K);
1326-
},
1327-
false))
1328-
return VD;
1329-
}
1329+
if (VD && !VD->hasLocalStorage() && isInOpenMPTargetExecutionDirective())
1330+
return VD;
13301331

13311332
if (DSAStack->getCurrentDirective() != OMPD_unknown &&
13321333
(!DSAStack->isClauseParsingMode() ||
@@ -9812,6 +9813,12 @@ static bool ActOnOMPReductionKindClause(
98129813
if ((OASE && !ConstantLengthOASE) ||
98139814
(!OASE && !ASE &&
98149815
D->getType().getNonReferenceType()->isVariablyModifiedType())) {
9816+
if (!Context.getTargetInfo().isVLASupported() &&
9817+
S.shouldDiagnoseTargetSupportFromOpenMP()) {
9818+
S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
9819+
S.Diag(ELoc, diag::note_vla_unsupported);
9820+
continue;
9821+
}
98159822
// For arrays/array sections only:
98169823
// Create pseudo array type for private copy. The size for this array will
98179824
// be generated during codegen.

Diff for: lib/Sema/SemaType.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -2183,6 +2183,12 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
21832183
// CUDA device code doesn't support VLAs.
21842184
if (getLangOpts().CUDA && T->isVariableArrayType())
21852185
CUDADiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentCUDATarget();
2186+
// Some targets don't support VLAs.
2187+
if (T->isVariableArrayType() && !Context.getTargetInfo().isVLASupported() &&
2188+
shouldDiagnoseTargetSupportFromOpenMP()) {
2189+
Diag(Loc, diag::err_vla_unsupported);
2190+
return QualType();
2191+
}
21862192

21872193
// If this is not C99, extwarn about VLA's and C99 array size modifiers.
21882194
if (!getLangOpts().C99) {

Diff for: test/OpenMP/target_vla_messages.cpp

+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
// PowerPC supports VLAs.
2+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-unknown-unknown -emit-llvm-bc %s -o %t-ppc-host-ppc.bc
3+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host-ppc.bc -o %t-ppc-device.ll
4+
5+
// Nvidia GPUs don't support VLAs.
6+
// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host-nvptx.bc
7+
// RUN: %clang_cc1 -verify -DNO_VLA -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host-nvptx.bc -o %t-nvptx-device.ll
8+
9+
#ifndef NO_VLA
10+
// expected-no-diagnostics
11+
#endif
12+
13+
#pragma omp declare target
14+
void declare(int arg) {
15+
int a[2];
16+
#ifdef NO_VLA
17+
// expected-error@+2 {{variable length arrays are not supported for the current target}}
18+
#endif
19+
int vla[arg];
20+
}
21+
22+
void declare_parallel_reduction(int arg) {
23+
int a[2];
24+
25+
#pragma omp parallel reduction(+: a)
26+
{ }
27+
28+
#pragma omp parallel reduction(+: a[0:2])
29+
{ }
30+
31+
#ifdef NO_VLA
32+
// expected-error@+3 {{cannot generate code for reduction on array section, which requires a variable length array}}
33+
// expected-note@+2 {{variable length arrays are not supported for the current target}}
34+
#endif
35+
#pragma omp parallel reduction(+: a[0:arg])
36+
{ }
37+
}
38+
#pragma omp end declare target
39+
40+
template <typename T>
41+
void target_template(int arg) {
42+
#pragma omp target
43+
{
44+
#ifdef NO_VLA
45+
// expected-error@+2 {{variable length arrays are not supported for the current target}}
46+
#endif
47+
T vla[arg];
48+
}
49+
}
50+
51+
void target(int arg) {
52+
#pragma omp target
53+
{
54+
#ifdef NO_VLA
55+
// expected-error@+2 {{variable length arrays are not supported for the current target}}
56+
#endif
57+
int vla[arg];
58+
}
59+
60+
#pragma omp target
61+
{
62+
#pragma omp parallel
63+
{
64+
#ifdef NO_VLA
65+
// expected-error@+2 {{variable length arrays are not supported for the current target}}
66+
#endif
67+
int vla[arg];
68+
}
69+
}
70+
71+
target_template<long>(arg);
72+
}
73+
74+
void teams_reduction(int arg) {
75+
int a[2];
76+
int vla[arg];
77+
78+
#pragma omp target map(a)
79+
#pragma omp teams reduction(+: a)
80+
{ }
81+
82+
#ifdef NO_VLA
83+
// expected-error@+4 {{cannot generate code for reduction on variable length array}}
84+
// expected-note@+3 {{variable length arrays are not supported for the current target}}
85+
#endif
86+
#pragma omp target map(vla)
87+
#pragma omp teams reduction(+: vla)
88+
{ }
89+
90+
#pragma omp target map(a[0:2])
91+
#pragma omp teams reduction(+: a[0:2])
92+
{ }
93+
94+
#pragma omp target map(vla[0:2])
95+
#pragma omp teams reduction(+: vla[0:2])
96+
{ }
97+
98+
#ifdef NO_VLA
99+
// expected-error@+4 {{cannot generate code for reduction on array section, which requires a variable length array}}
100+
// expected-note@+3 {{variable length arrays are not supported for the current target}}
101+
#endif
102+
#pragma omp target map(a[0:arg])
103+
#pragma omp teams reduction(+: a[0:arg])
104+
{ }
105+
106+
#ifdef NO_VLA
107+
// expected-error@+4 {{cannot generate code for reduction on array section, which requires a variable length array}}
108+
// expected-note@+3 {{variable length arrays are not supported for the current target}}
109+
#endif
110+
#pragma omp target map(vla[0:arg])
111+
#pragma omp teams reduction(+: vla[0:arg])
112+
{ }
113+
}
114+
115+
void parallel_reduction(int arg) {
116+
int a[2];
117+
int vla[arg];
118+
119+
#pragma omp target map(a)
120+
#pragma omp parallel reduction(+: a)
121+
{ }
122+
123+
#ifdef NO_VLA
124+
// expected-error@+4 {{cannot generate code for reduction on variable length array}}
125+
// expected-note@+3 {{variable length arrays are not supported for the current target}}
126+
#endif
127+
#pragma omp target map(vla)
128+
#pragma omp parallel reduction(+: vla)
129+
{ }
130+
131+
#pragma omp target map(a[0:2])
132+
#pragma omp parallel reduction(+: a[0:2])
133+
{ }
134+
135+
#pragma omp target map(vla[0:2])
136+
#pragma omp parallel reduction(+: vla[0:2])
137+
{ }
138+
139+
#ifdef NO_VLA
140+
// expected-error@+4 {{cannot generate code for reduction on array section, which requires a variable length array}}
141+
// expected-note@+3 {{variable length arrays are not supported for the current target}}
142+
#endif
143+
#pragma omp target map(a[0:arg])
144+
#pragma omp parallel reduction(+: a[0:arg])
145+
{ }
146+
147+
#ifdef NO_VLA
148+
// expected-error@+4 {{cannot generate code for reduction on array section, which requires a variable length array}}
149+
// expected-note@+3 {{variable length arrays are not supported for the current target}}
150+
#endif
151+
#pragma omp target map(vla[0:arg])
152+
#pragma omp parallel reduction(+: vla[0:arg])
153+
{ }
154+
}
155+
156+
void for_reduction(int arg) {
157+
int a[2];
158+
int vla[arg];
159+
160+
#pragma omp target map(a)
161+
#pragma omp parallel
162+
#pragma omp for reduction(+: a)
163+
for (int i = 0; i < arg; i++) ;
164+
165+
#ifdef NO_VLA
166+
// expected-error@+5 {{cannot generate code for reduction on variable length array}}
167+
// expected-note@+4 {{variable length arrays are not supported for the current target}}
168+
#endif
169+
#pragma omp target map(vla)
170+
#pragma omp parallel
171+
#pragma omp for reduction(+: vla)
172+
for (int i = 0; i < arg; i++) ;
173+
174+
#pragma omp target map(a[0:2])
175+
#pragma omp parallel
176+
#pragma omp for reduction(+: a[0:2])
177+
for (int i = 0; i < arg; i++) ;
178+
179+
#pragma omp target map(vla[0:2])
180+
#pragma omp parallel
181+
#pragma omp for reduction(+: vla[0:2])
182+
for (int i = 0; i < arg; i++) ;
183+
184+
#ifdef NO_VLA
185+
// expected-error@+5 {{cannot generate code for reduction on array section, which requires a variable length array}}
186+
// expected-note@+4 {{variable length arrays are not supported for the current target}}
187+
#endif
188+
#pragma omp target map(a[0:arg])
189+
#pragma omp parallel
190+
#pragma omp for reduction(+: a[0:arg])
191+
for (int i = 0; i < arg; i++) ;
192+
193+
#ifdef NO_VLA
194+
// expected-error@+5 {{cannot generate code for reduction on array section, which requires a variable length array}}
195+
// expected-note@+4 {{variable length arrays are not supported for the current target}}
196+
#endif
197+
#pragma omp target map(vla[0:arg])
198+
#pragma omp parallel
199+
#pragma omp for reduction(+: vla[0:arg])
200+
for (int i = 0; i < arg; i++) ;
201+
}

0 commit comments

Comments
 (0)