Skip to content

Commit eaab947

Browse files
authored
[OpenMP] Use simple VLA implementation to replace uses of actual VLA (#71412)
Use of VLA can cause compile warning that was introduced in D156565. This patch implements a simple stack/heap-based VLA that can miminc the behavior of an actual VLA and prevent the warning. By default the stack accomodates the elements. If the number of emelements is greater than N, which by default is 8, a heap buffer will be allocated and used to acccomodate the elements.
1 parent ab56268 commit eaab947

File tree

3 files changed

+58
-4
lines changed

3 files changed

+58
-4
lines changed

openmp/runtime/src/kmp_gsupport.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "kmp.h"
1414
#include "kmp_atomic.h"
15+
#include "kmp_utils.h"
1516

1617
#if OMPT_SUPPORT
1718
#include "ompt-specific.h"
@@ -1280,7 +1281,7 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASK)(void (*func)(void *), void *data,
12801281
KMP_ASSERT(depend);
12811282
kmp_gomp_depends_info_t gomp_depends(depend);
12821283
kmp_int32 ndeps = gomp_depends.get_num_deps();
1283-
kmp_depend_info_t dep_list[ndeps];
1284+
SimpleVLA<kmp_depend_info_t> dep_list(ndeps);
12841285
for (kmp_int32 i = 0; i < ndeps; i++)
12851286
dep_list[i] = gomp_depends.get_kmp_depend(i);
12861287
kmp_int32 ndeps_cnv;
@@ -1309,7 +1310,7 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASK)(void (*func)(void *), void *data,
13091310
KMP_ASSERT(depend);
13101311
kmp_gomp_depends_info_t gomp_depends(depend);
13111312
kmp_int32 ndeps = gomp_depends.get_num_deps();
1312-
kmp_depend_info_t dep_list[ndeps];
1313+
SimpleVLA<kmp_depend_info_t> dep_list(ndeps);
13131314
for (kmp_int32 i = 0; i < ndeps; i++)
13141315
dep_list[i] = gomp_depends.get_kmp_depend(i);
13151316
__kmpc_omp_wait_deps(&loc, gtid, ndeps, dep_list, 0, NULL);
@@ -1993,7 +1994,7 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASKWAIT_DEPEND)(void **depend) {
19931994
KA_TRACE(20, ("GOMP_taskwait_depend: T#%d\n", gtid));
19941995
kmp_gomp_depends_info_t gomp_depends(depend);
19951996
kmp_int32 ndeps = gomp_depends.get_num_deps();
1996-
kmp_depend_info_t dep_list[ndeps];
1997+
SimpleVLA<kmp_depend_info_t> dep_list(ndeps);
19971998
for (kmp_int32 i = 0; i < ndeps; i++)
19981999
dep_list[i] = gomp_depends.get_kmp_depend(i);
19992000
#if OMPT_SUPPORT

openmp/runtime/src/kmp_runtime.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "kmp_wait_release.h"
2525
#include "kmp_wrapper_getpid.h"
2626
#include "kmp_dispatch.h"
27+
#include "kmp_utils.h"
2728
#if KMP_USE_HIER_SCHED
2829
#include "kmp_dispatch_hier.h"
2930
#endif
@@ -1652,7 +1653,7 @@ __kmp_serial_fork_call(ident_t *loc, int gtid, enum fork_context_e call_context,
16521653
/* josh todo: hypothetical question: what do we do for OS X*? */
16531654
#if KMP_OS_LINUX && \
16541655
(KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_ARM || KMP_ARCH_AARCH64)
1655-
void *args[argc];
1656+
SimpleVLA<void *> args(argc);
16561657
#else
16571658
void **args = (void **)KMP_ALLOCA(argc * sizeof(void *));
16581659
#endif /* KMP_OS_LINUX && ( KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_ARCH_ARM || \

openmp/runtime/src/kmp_utils.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* kmp_utils.h -- Utilities that used internally
3+
*/
4+
5+
//===----------------------------------------------------------------------===//
6+
//
7+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8+
// See https://llvm.org/LICENSE.txt for license information.
9+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10+
//
11+
//===----------------------------------------------------------------------===//
12+
#ifndef __KMP_UTILS_H__
13+
#define __KMP_UTILS_H__
14+
15+
#include <cstddef>
16+
17+
/// A simple pure header implementation of VLA that aims to replace uses of
18+
/// actual VLA, which can cause compile warning. This class by default creates a
19+
/// stack buffer that can accomodate \p N elements. If the number of elements is
20+
/// greater than \p N, then a heap buffer will be allocated and used to
21+
/// accomodate the elements. Similar to the actual VLA, we don't check boundary
22+
/// (for now), so we will not store the number of elements. We can always revise
23+
/// it later.
24+
template <typename T, unsigned N = 8> class SimpleVLA final {
25+
T StackBuffer[N];
26+
T *HeapBuffer = nullptr;
27+
T *Ptr = StackBuffer;
28+
29+
public:
30+
SimpleVLA() = delete;
31+
SimpleVLA(const SimpleVLA &) = delete;
32+
SimpleVLA(SimpleVLA &&) = delete;
33+
SimpleVLA &operator=(const SimpleVLA &) = delete;
34+
SimpleVLA &operator=(SimpleVLA &&) = delete;
35+
36+
explicit SimpleVLA(unsigned NumOfElements) noexcept {
37+
if (NumOfElements > N) {
38+
HeapBuffer = new T[NumOfElements];
39+
Ptr = HeapBuffer;
40+
}
41+
}
42+
43+
~SimpleVLA() { delete[] HeapBuffer; }
44+
45+
const T &operator[](std::size_t Idx) const noexcept { return Ptr[Idx]; }
46+
T &operator[](std::size_t Idx) noexcept { return Ptr[Idx]; }
47+
48+
operator T *() noexcept { return Ptr; }
49+
operator const T *() const noexcept { return Ptr; }
50+
};
51+
52+
#endif

0 commit comments

Comments
 (0)