[OpenMP] Add support for GOMP depobj

GOMP depobjs are represented as a two intptr_t array. The first
element is the base address of the dependency and the second element
is the flag indicating the type the depobj represents.

Differential Revision: https://reviews.llvm.org/D108790
This commit is contained in:
Peyton, Jonathan L 2021-08-26 14:10:15 -05:00
parent f68939d3d9
commit 258e27aae1
5 changed files with 143 additions and 13 deletions

View File

@ -23,18 +23,24 @@ enum {
KMP_GOMP_TASK_DEPENDS_FLAG = 8
};
enum {
KMP_GOMP_DEPOBJ_IN = 1,
KMP_GOMP_DEPOBJ_OUT = 2,
KMP_GOMP_DEPOBJ_INOUT = 3,
KMP_GOMP_DEPOBJ_MTXINOUTSET = 4
};
// This class helps convert gomp dependency info into
// kmp_depend_info_t structures
class kmp_gomp_depends_info_t {
void **depend;
kmp_int32 num_deps;
size_t num_out, num_mutexinout, num_in;
size_t num_out, num_mutexinout, num_in, num_depobj;
size_t offset;
public:
kmp_gomp_depends_info_t(void **depend) : depend(depend) {
size_t ndeps = (kmp_intptr_t)depend[0];
size_t num_doable;
// GOMP taskdep structure:
// if depend[0] != 0:
// depend = [ ndeps | nout | &out | ... | &out | &in | ... | &in ]
@ -45,21 +51,17 @@ public:
if (ndeps) {
num_out = (kmp_intptr_t)depend[1];
num_in = ndeps - num_out;
num_mutexinout = 0;
num_doable = ndeps;
num_mutexinout = num_depobj = 0;
offset = 2;
} else {
ndeps = (kmp_intptr_t)depend[1];
num_out = (kmp_intptr_t)depend[2];
num_mutexinout = (kmp_intptr_t)depend[3];
num_in = (kmp_intptr_t)depend[4];
num_doable = num_out + num_mutexinout + num_in;
num_depobj = ndeps - num_out - num_mutexinout - num_in;
KMP_ASSERT(num_depobj <= ndeps);
offset = 5;
}
// TODO: Support gomp depobj
if (ndeps != num_doable) {
KMP_FATAL(GompFeatureNotSupported, "depobj");
}
num_deps = static_cast<kmp_int32>(ndeps);
}
kmp_int32 get_num_deps() const { return num_deps; }
@ -67,7 +69,6 @@ public:
kmp_depend_info_t retval;
memset(&retval, '\0', sizeof(retval));
KMP_ASSERT(index < (size_t)num_deps);
retval.base_addr = (kmp_intptr_t)depend[offset + index];
retval.len = 0;
// Because inout and out are logically equivalent,
// use inout and in dependency flags. GOMP does not provide a
@ -75,10 +76,37 @@ public:
if (index < num_out) {
retval.flags.in = 1;
retval.flags.out = 1;
retval.base_addr = (kmp_intptr_t)depend[offset + index];
} else if (index >= num_out && index < (num_out + num_mutexinout)) {
retval.flags.mtx = 1;
} else {
retval.base_addr = (kmp_intptr_t)depend[offset + index];
} else if (index >= (num_out + num_mutexinout) &&
index < (num_out + num_mutexinout + num_in)) {
retval.flags.in = 1;
retval.base_addr = (kmp_intptr_t)depend[offset + index];
} else {
// depobj is a two element array (size of elements are size of pointer)
// depobj[0] = base_addr
// depobj[1] = type (in, out, inout, mutexinoutset, etc.)
kmp_intptr_t *depobj = (kmp_intptr_t *)depend[offset + index];
retval.base_addr = depobj[0];
switch (depobj[1]) {
case KMP_GOMP_DEPOBJ_IN:
retval.flags.in = 1;
break;
case KMP_GOMP_DEPOBJ_OUT:
retval.flags.out = 1;
break;
case KMP_GOMP_DEPOBJ_INOUT:
retval.flags.in = 1;
retval.flags.out = 1;
break;
case KMP_GOMP_DEPOBJ_MTXINOUTSET:
retval.flags.mtx = 1;
break;
default:
KMP_FATAL(GompFeatureNotSupported, "Unknown depobj type");
}
}
return retval;
}

View File

@ -29,6 +29,7 @@ pythonize_bool(LIBOMP_OMPT_SUPPORT)
pythonize_bool(LIBOMP_OMPT_OPTIONAL)
pythonize_bool(LIBOMP_HAVE_LIBM)
pythonize_bool(LIBOMP_HAVE_LIBATOMIC)
pythonize_bool(OPENMP_STANDALONE_BUILD)
add_library(ompt-print-callback INTERFACE)
target_include_directories(ompt-print-callback INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/ompt)

View File

@ -42,10 +42,11 @@ config.test_exec_root = config.libomp_obj_root
config.test_format = lit.formats.ShTest()
# compiler flags
config.test_flags = " -I " + config.test_source_root + \
" -I " + config.omp_header_directory + \
flags = " -I " + config.test_source_root + \
" -L " + config.library_dir + \
" " + config.test_extra_flags
config.test_flags = " -I " + config.omp_header_directory + flags
config.test_flags_use_compiler_omp_h = flags
# extra libraries
libs = ""
@ -126,6 +127,16 @@ config.substitutions.append(("%libomp-run", "%t"))
config.substitutions.append(("%clangXX", config.test_cxx_compiler))
config.substitutions.append(("%clang", config.test_c_compiler))
config.substitutions.append(("%openmp_flags", config.test_openmp_flags))
# %flags-use-compiler-omp-h allows us to use the test compiler's omp.h file which
# may have different definitions of structures than our omp.h file.
if config.is_standalone_build:
config.substitutions.append(("%flags-use-compiler-omp-h",
config.test_flags_use_compiler_omp_h))
else:
# If testing the runtime within an LLVM tree, then always include omp.h
# directory associated with the new clang compiler.
config.substitutions.append(("%flags-use-compiler-omp-h",
config.test_flags))
config.substitutions.append(("%flags", config.test_flags))
config.substitutions.append(("%python", '"%s"' % (sys.executable)))
config.substitutions.append(("%not", config.test_not))

View File

@ -16,6 +16,7 @@ config.using_hwloc = @LIBOMP_USE_HWLOC@
config.has_ompt = @LIBOMP_OMPT_SUPPORT@ and @LIBOMP_OMPT_OPTIONAL@
config.has_libm = @LIBOMP_HAVE_LIBM@
config.has_libatomic = @LIBOMP_HAVE_LIBATOMIC@
config.is_standalone_build = @OPENMP_STANDALONE_BUILD@
# Let the main config do the real work.
lit_config.load_config(config, "@LIBOMP_BASE_DIR@/test/lit.cfg")

View File

@ -0,0 +1,89 @@
// RUN: %clang %openmp_flags %flags-use-compiler-omp-h %s -o %t && %libomp-run
// UNSUPPORTED: gcc-5, gcc-6, gcc-7, gcc-8
// UNSUPPORTED: clang-5, clang-6, clang-7, clang-8, clang-9, clang-10
// UNSUPPORTED: icc
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#include "omp_my_sleep.h"
int a, b;
void mutexinoutset_task() {
if (b != 0) {
fprintf(stderr, "mutexinoutset_task: b != 0 at start of task\n");
exit(EXIT_FAILURE);
}
b++;
if (b != 1) {
fprintf(stderr, "mutexinoutset_task: b != 1\n");
exit(EXIT_FAILURE);
}
my_sleep(0.1);
b--;
if (b != 0) {
fprintf(stderr, "mutexinoutset_task: b != 0 at end of task\n");
exit(EXIT_FAILURE);
}
}
int main(int argc, char** argv) {
omp_depend_t dep_a_in;
omp_depend_t dep_a_out;
omp_depend_t dep_a_inout;
omp_depend_t dep_a_mutexinoutset;
a = 0;
b = 0;
#pragma omp depobj(dep_a_in) depend(in: a)
#pragma omp depobj(dep_a_out) depend(out: a)
#pragma omp depobj(dep_a_inout) depend(inout: a)
#pragma omp depobj(dep_a_mutexinoutset) depend(mutexinoutset: a)
#pragma omp parallel
{
#pragma omp single
{
#pragma omp task depend(depobj: dep_a_out)
{
my_sleep(0.1);
a = 10;
}
#pragma omp task depend(depobj: dep_a_inout)
{
my_sleep(0.1);
a++;
}
#pragma omp task depend(depobj: dep_a_mutexinoutset)
mutexinoutset_task();
#pragma omp task depend(depobj: dep_a_mutexinoutset)
mutexinoutset_task();
#pragma omp task depend(depobj: dep_a_mutexinoutset)
mutexinoutset_task();
#pragma omp task depend(depobj: dep_a_mutexinoutset)
mutexinoutset_task();
#pragma omp task depend(depobj: dep_a_mutexinoutset)
mutexinoutset_task();
#pragma omp task depend(depobj: dep_a_in)
{ a += 10; }
}
}
if (a != 21) {
fprintf(stderr, "a (%d) != 21\n", a);
exit(EXIT_FAILURE);
}
#pragma omp depobj(dep_a_in) destroy
#pragma omp depobj(dep_a_out) destroy
#pragma omp depobj(dep_a_inout) destroy
#pragma omp depobj(dep_a_mutexinoutset) destroy
return EXIT_SUCCESS;
}