[Openmp-commits] [clang] [openmp] [compiler-rt] [TSan][OpenMP][Archer] Treat all reduction operations as atomic (PR #74631)
via Openmp-commits
openmp-commits at lists.llvm.org
Wed Dec 6 11:22:08 PST 2023
https://github.com/felilxtomski updated https://github.com/llvm/llvm-project/pull/74631
>From 669ddace7494027779b2501805353577efa1ea18 Mon Sep 17 00:00:00 2001
From: Joachim Jenke <jenke at itc.rwth-aachen.de>
Date: Tue, 11 Jul 2023 14:40:17 +0200
Subject: [PATCH 1/2] Treat all reduction operations as atomic
---
clang/lib/CodeGen/CGOpenMPRuntime.cpp | 14 ++++--
.../lib/tsan/rtl/tsan_interface_ann.cpp | 10 +++++
compiler-rt/lib/tsan/rtl/tsan_rtl.cpp | 15 +++++++
compiler-rt/lib/tsan/rtl/tsan_rtl.h | 3 ++
compiler-rt/lib/tsan/rtl/tsan_shadow.h | 9 +++-
openmp/tools/archer/ompt-tsan.cpp | 31 +++++++++----
.../parallel-for-array-reduction-no-barrier.c | 42 +++++++++++++++++
.../parallel-for-array-reduction-nowait.c | 42 +++++++++++++++++
.../races/parallel-for-reduction-no-barrier.c | 42 +++++++++++++++++
.../races/parallel-for-reduction-nowait.c | 42 +++++++++++++++++
.../parallel-for-array-reduction-barrier.c | 45 +++++++++++++++++++
.../parallel-for-reduction-barrier.c | 45 +++++++++++++++++++
.../reduction/parallel-reduction-nowait.c | 1 +
.../tests/reduction/parallel-reduction.c | 14 +++---
14 files changed, 336 insertions(+), 19 deletions(-)
create mode 100644 openmp/tools/archer/tests/races/parallel-for-array-reduction-no-barrier.c
create mode 100644 openmp/tools/archer/tests/races/parallel-for-array-reduction-nowait.c
create mode 100644 openmp/tools/archer/tests/races/parallel-for-reduction-no-barrier.c
create mode 100644 openmp/tools/archer/tests/races/parallel-for-reduction-nowait.c
create mode 100644 openmp/tools/archer/tests/reduction/parallel-for-array-reduction-barrier.c
create mode 100644 openmp/tools/archer/tests/reduction/parallel-for-reduction-barrier.c
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 55648963df36a..a0381c315e5ec 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -4810,13 +4810,16 @@ llvm::Function *CGOpenMPRuntime::emitReductionFunction(
Args.push_back(&RHSArg);
const auto &CGFI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
+ CodeGenFunction CGF(CGM);
std::string Name = getReductionFuncName(ReducerName);
auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
llvm::GlobalValue::InternalLinkage, Name,
&CGM.getModule());
+ if (CGF.SanOpts.has(SanitizerKind::Thread)) {
+ return Fn;
+ }
CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Fn->setDoesNotRecurse();
- CodeGenFunction CGF(CGM);
CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
// Dst = (void*[n])(LHSArg);
@@ -5008,6 +5011,11 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
llvm::Function *ReductionFn = emitReductionFunction(
CGF.CurFn->getName(), Loc, CGF.ConvertTypeForMem(ReductionArrayTy),
Privates, LHSExprs, RHSExprs, ReductionOps);
+ llvm::Value *ReductionFnP = ReductionFn;
+ if (CGF.SanOpts.has(SanitizerKind::Thread)) {
+ ReductionFnP = llvm::ConstantPointerNull::get(
+ llvm::PointerType::get(ReductionFn->getFunctionType(), 0));
+ }
// 3. Create static kmp_critical_name lock = { 0 };
std::string Name = getName({"reduction"});
@@ -5026,8 +5034,8 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
ReductionArrayTySize, // size_type sizeof(RedList)
RL, // void *RedList
- ReductionFn, // void (*) (void *, void *) <reduce_func>
- Lock // kmp_critical_name *&<lock>
+ ReductionFnP, // void (*) (void *, void *) <reduce_func>
+ Lock // kmp_critical_name *&<lock>
};
llvm::Value *Res = CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp b/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp
index 5154662034c56..a79ed9b0983bd 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp
@@ -266,6 +266,16 @@ void INTERFACE_ATTRIBUTE AnnotateBenignRace(
BenignRaceImpl(f, l, mem, 1, desc);
}
+void INTERFACE_ATTRIBUTE AnnotateAllAtomicBegin(char *f, int l) {
+ SCOPED_ANNOTATION(AnnotateAllAtomicBegin);
+ ThreadAtomicBegin(thr, pc);
+}
+
+void INTERFACE_ATTRIBUTE AnnotateAllAtomicEnd(char *f, int l) {
+ SCOPED_ANNOTATION(AnnotateAllAtomicEnd);
+ ThreadAtomicEnd(thr);
+}
+
void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
ThreadIgnoreBegin(thr, pc);
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
index fd9441dfcb53c..c829247088f75 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
@@ -1053,6 +1053,21 @@ void ThreadIgnoreEnd(ThreadState *thr) {
}
}
+void ThreadAtomicBegin(ThreadState* thr, uptr pc) {
+ thr->all_atomic++;
+// CHECK_GT(thr->ignore_reads_and_writes, 0);
+ CHECK_EQ(thr->all_atomic, 1);
+ thr->fast_state.SetAtomicBit();
+}
+
+void ThreadAtomicEnd(ThreadState *thr) {
+ CHECK_GT(thr->all_atomic, 0);
+ thr->all_atomic--;
+ if (thr->all_atomic == 0) {
+ thr->fast_state.ClearAtomicBit();
+ }
+}
+
#if !SANITIZER_GO
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
uptr __tsan_testonly_shadow_stack_current_size() {
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
index de4ea0bb5f487..2a86007b47eef 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
@@ -182,6 +182,7 @@ struct ThreadState {
// for better performance.
int ignore_reads_and_writes;
int suppress_reports;
+ int all_atomic;
// Go does not support ignores.
#if !SANITIZER_GO
IgnoreSet mop_ignore_set;
@@ -550,6 +551,8 @@ void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size);
void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr,
uptr size);
+void ThreadAtomicBegin(ThreadState *thr, uptr pc);
+void ThreadAtomicEnd(ThreadState *thr);
void ThreadIgnoreBegin(ThreadState *thr, uptr pc);
void ThreadIgnoreEnd(ThreadState *thr);
void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc);
diff --git a/compiler-rt/lib/tsan/rtl/tsan_shadow.h b/compiler-rt/lib/tsan/rtl/tsan_shadow.h
index 6b8114ef51325..d22545d4fa2ee 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_shadow.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_shadow.h
@@ -9,6 +9,7 @@
#ifndef TSAN_SHADOW_H
#define TSAN_SHADOW_H
+#include "sanitizer_common/sanitizer_common.h"
#include "tsan_defs.h"
namespace __tsan {
@@ -21,8 +22,8 @@ class FastState {
part_.unused0_ = 0;
part_.sid_ = static_cast<u8>(kFreeSid);
part_.epoch_ = static_cast<u16>(kEpochLast);
- part_.unused1_ = 0;
part_.ignore_accesses_ = false;
+ part_.all_atomic_ = false;
}
void SetSid(Sid sid) { part_.sid_ = static_cast<u8>(sid); }
@@ -37,14 +38,18 @@ class FastState {
void ClearIgnoreBit() { part_.ignore_accesses_ = 0; }
bool GetIgnoreBit() const { return part_.ignore_accesses_; }
+ void SetAtomicBit() { part_.all_atomic_ = 1; }
+ void ClearAtomicBit() { part_.all_atomic_ = 0; }
+ bool GetAtomicBit() const { return part_.all_atomic_; }
+
private:
friend class Shadow;
struct Parts {
u32 unused0_ : 8;
u32 sid_ : 8;
u32 epoch_ : kEpochBits;
- u32 unused1_ : 1;
u32 ignore_accesses_ : 1;
+ u32 all_atomic_ : 1;
};
union {
Parts part_;
diff --git a/openmp/tools/archer/ompt-tsan.cpp b/openmp/tools/archer/ompt-tsan.cpp
index 8b338f6b18b6e..ece791683eedd 100644
--- a/openmp/tools/archer/ompt-tsan.cpp
+++ b/openmp/tools/archer/ompt-tsan.cpp
@@ -149,7 +149,7 @@ static ArcherFlags *archer_flags;
// Thread Sanitizer is a tool that finds races in code.
// See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations .
// tsan detects these exact functions by name.
-extern "C" {
+//extern "C" {
static void (*AnnotateHappensAfter)(const char *, int, const volatile void *);
static void (*AnnotateHappensBefore)(const char *, int, const volatile void *);
static void (*AnnotateIgnoreWritesBegin)(const char *, int);
@@ -159,7 +159,9 @@ static void (*AnnotateNewMemory)(const char *, int, const volatile void *,
static void (*__tsan_func_entry)(const void *);
static void (*__tsan_func_exit)(void);
static int (*RunningOnValgrind)(void);
-}
+static void (*AnnotateReductionBegin)(const char *, int);
+static void (*AnnotateReductionEnd)(const char *, int);
+//}
// This marker is used to define a happens-before arc. The race detector will
// infer an arc from the begin to the end when they share the same pointer
@@ -175,6 +177,10 @@ static int (*RunningOnValgrind)(void);
// Resume checking for racy writes.
#define TsanIgnoreWritesEnd() AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+// Maps to either AnnotateAllAtomics or AnnotateIgnoreWrites
+#define TsanReductionBegin() AnnotateReductionBegin(__FILE__, __LINE__)
+#define TsanReductionEnd() AnnotateReductionEnd(__FILE__, __LINE__)
+
// We don't really delete the clock for now
#define TsanDeleteClock(cv)
@@ -718,7 +724,7 @@ static void ompt_tsan_sync_region(ompt_sync_region_t kind,
// 2. execution of another task.
// For the latter case we will re-enable tracking in task_switch.
Data->InBarrier = true;
- TsanIgnoreWritesBegin();
+ TsanReductionBegin();
}
break;
@@ -751,7 +757,7 @@ static void ompt_tsan_sync_region(ompt_sync_region_t kind,
if (hasReductionCallback < ompt_set_always) {
// We want to track writes after the barrier again.
Data->InBarrier = false;
- TsanIgnoreWritesEnd();
+ TsanReductionEnd();
}
char BarrierIndex = Data->BarrierIndex;
@@ -806,7 +812,7 @@ static void ompt_tsan_reduction(ompt_sync_region_t kind,
case ompt_scope_begin:
switch (kind) {
case ompt_sync_region_reduction:
- TsanIgnoreWritesBegin();
+ TsanReductionBegin();
break;
default:
break;
@@ -815,7 +821,7 @@ static void ompt_tsan_reduction(ompt_sync_region_t kind,
case ompt_scope_end:
switch (kind) {
case ompt_sync_region_reduction:
- TsanIgnoreWritesEnd();
+ TsanReductionEnd();
break;
default:
break;
@@ -942,12 +948,12 @@ static void switchTasks(TaskData *FromTask, TaskData *ToTask) {
if (FromTask && FromTask->InBarrier) {
// We want to ignore writes in the runtime code during barriers,
// but not when executing tasks with user code!
- TsanIgnoreWritesEnd();
+ TsanReductionEnd();
}
if (ToTask && ToTask->InBarrier) {
// We want to ignore writes in the runtime code during barriers,
// but not when executing tasks with user code!
- TsanIgnoreWritesBegin();
+ TsanReductionBegin();
}
}
//// Not yet used
@@ -1147,6 +1153,7 @@ static void ompt_tsan_mutex_released(ompt_mutex_t kind, ompt_wait_id_t wait_id,
} while (0)
#define findTsanFunctionSilent(f, fSig) f = fSig dlsym(RTLD_DEFAULT, #f)
+#define findTsanFunctionName(f, name, fSig) f = fSig dlsym(RTLD_DEFAULT, #name)
static int ompt_tsan_initialize(ompt_function_lookup_t lookup, int device_num,
ompt_data_t *tool_data) {
@@ -1180,6 +1187,14 @@ static int ompt_tsan_initialize(ompt_function_lookup_t lookup, int device_num,
(void (*)(const char *, int, const volatile void *, size_t)));
findTsanFunction(__tsan_func_entry, (void (*)(const void *)));
findTsanFunction(__tsan_func_exit, (void (*)(void)));
+ findTsanFunctionName(AnnotateReductionBegin, AnnotateAllAtomicBegin, (void (*)(const char *, int)));
+ findTsanFunctionName(AnnotateReductionEnd, AnnotateAllAtomicEnd, (void (*)(const char *, int)));
+ if (!AnnotateReductionBegin) {
+ AnnotateReductionBegin = AnnotateIgnoreWritesBegin;
+ AnnotateReductionEnd = AnnotateIgnoreWritesEnd;
+ if (archer_flags->verbose)
+ std::cout << "Archer uses fallback solution for reductions: might miss some race" << std::endl;
+ }
SET_CALLBACK(thread_begin);
SET_CALLBACK(thread_end);
diff --git a/openmp/tools/archer/tests/races/parallel-for-array-reduction-no-barrier.c b/openmp/tools/archer/tests/races/parallel-for-array-reduction-no-barrier.c
new file mode 100644
index 0000000000000..2cdfb811fcbc5
--- /dev/null
+++ b/openmp/tools/archer/tests/races/parallel-for-array-reduction-no-barrier.c
@@ -0,0 +1,42 @@
+/*
+ * parallel-reduction.c -- Archer testcase
+ */
+
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+//
+// See tools/archer/LICENSE.txt for details.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Number of threads is empirical: We need enough (>4) threads so that
+// the reduction is really performed hierarchically in the barrier!
+
+// RUN: env OMP_NUM_THREADS=3 %libarcher-compile-and-run-race | FileCheck %s
+// RUN: env OMP_NUM_THREADS=7 %libarcher-compile-and-run-race | FileCheck %s
+
+// REQUIRES: tsan
+#include <omp.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+ int var[10]={0,1,2,3,4,5,6,7,8,9};
+
+#pragma omp parallel
+ {
+#pragma omp masked
+ var[5] = 23;
+#pragma omp for reduction(+ : var)
+ for (int i = 0; i < 1000; i++)
+ { var[i%10]++; }
+ }
+ fprintf(stderr, "DONE\n");
+ int error = (var[5] != 123);
+ return error;
+}
+
+// CHECK: ThreadSanitizer: data race
+// CHECK: DONE
+// CHECK: ThreadSanitizer: reported
diff --git a/openmp/tools/archer/tests/races/parallel-for-array-reduction-nowait.c b/openmp/tools/archer/tests/races/parallel-for-array-reduction-nowait.c
new file mode 100644
index 0000000000000..6ca17fcca6b54
--- /dev/null
+++ b/openmp/tools/archer/tests/races/parallel-for-array-reduction-nowait.c
@@ -0,0 +1,42 @@
+/*
+ * parallel-reduction.c -- Archer testcase
+ */
+
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+//
+// See tools/archer/LICENSE.txt for details.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Number of threads is empirical: We need enough (>4) threads so that
+// the reduction is really performed hierarchically in the barrier!
+
+// RUN: env OMP_NUM_THREADS=3 %libarcher-compile-and-run-race | FileCheck %s
+// RUN: env OMP_NUM_THREADS=7 %libarcher-compile-and-run-race | FileCheck %s
+
+// REQUIRES: tsan
+#include <omp.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+ int var[10]={0,1,2,3,4,5,6,7,8,9};
+
+#pragma omp parallel
+ {
+#pragma omp for reduction(+ : var) nowait
+ for (int i = 0; i < 1000; i++)
+ { var[i%10]++; }
+#pragma omp masked
+ var[5] += 23;
+ }
+ fprintf(stderr, "DONE\n");
+ int error = (var[5] != 123);
+ return error;
+}
+
+// CHECK: ThreadSanitizer: data race
+// CHECK: DONE
+// CHECK: ThreadSanitizer: reported
diff --git a/openmp/tools/archer/tests/races/parallel-for-reduction-no-barrier.c b/openmp/tools/archer/tests/races/parallel-for-reduction-no-barrier.c
new file mode 100644
index 0000000000000..3cc63cfab1996
--- /dev/null
+++ b/openmp/tools/archer/tests/races/parallel-for-reduction-no-barrier.c
@@ -0,0 +1,42 @@
+/*
+ * parallel-reduction.c -- Archer testcase
+ */
+
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+//
+// See tools/archer/LICENSE.txt for details.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Number of threads is empirical: We need enough (>4) threads so that
+// the reduction is really performed hierarchically in the barrier!
+
+// RUN: env OMP_NUM_THREADS=3 %libarcher-compile-and-run-race | FileCheck %s
+// RUN: env OMP_NUM_THREADS=7 %libarcher-compile-and-run-race | FileCheck %s
+
+// REQUIRES: tsan
+#include <omp.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+ int var = 0;
+
+#pragma omp parallel
+ {
+#pragma omp masked
+ var = 23;
+#pragma omp for reduction(+ : var)
+ for (int i = 0; i < 100; i++)
+ { var++; }
+ }
+ fprintf(stderr, "DONE\n");
+ int error = (var != 123);
+ return error;
+}
+
+// CHECK: ThreadSanitizer: data race
+// CHECK: DONE
+// CHECK: ThreadSanitizer: reported
diff --git a/openmp/tools/archer/tests/races/parallel-for-reduction-nowait.c b/openmp/tools/archer/tests/races/parallel-for-reduction-nowait.c
new file mode 100644
index 0000000000000..4c24e8a4f8285
--- /dev/null
+++ b/openmp/tools/archer/tests/races/parallel-for-reduction-nowait.c
@@ -0,0 +1,42 @@
+/*
+ * parallel-reduction.c -- Archer testcase
+ */
+
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+//
+// See tools/archer/LICENSE.txt for details.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Number of threads is empirical: We need enough (>4) threads so that
+// the reduction is really performed hierarchically in the barrier!
+
+// RUN: env OMP_NUM_THREADS=3 %libarcher-compile-and-run-race | FileCheck %s
+// RUN: env OMP_NUM_THREADS=7 %libarcher-compile-and-run-race | FileCheck %s
+
+// REQUIRES: tsan
+#include <omp.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+ int var = 0;
+
+#pragma omp parallel
+ {
+#pragma omp for reduction(+ : var) nowait
+ for (int i = 0; i < 100; i++)
+ { var++; }
+#pragma omp masked
+ var = 23;
+ }
+ fprintf(stderr, "DONE\n");
+ int error = (var != 123);
+ return error;
+}
+
+// CHECK: ThreadSanitizer: data race
+// CHECK: DONE
+// CHECK: ThreadSanitizer: reported
diff --git a/openmp/tools/archer/tests/reduction/parallel-for-array-reduction-barrier.c b/openmp/tools/archer/tests/reduction/parallel-for-array-reduction-barrier.c
new file mode 100644
index 0000000000000..2ac9ec449baa7
--- /dev/null
+++ b/openmp/tools/archer/tests/reduction/parallel-for-array-reduction-barrier.c
@@ -0,0 +1,45 @@
+/*
+ * parallel-reduction.c -- Archer testcase
+ */
+
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+//
+// See tools/archer/LICENSE.txt for details.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Number of threads is empirical: We need enough (>4) threads so that
+// the reduction is really performed hierarchically in the barrier!
+
+// RUN: env OMP_NUM_THREADS=3 %libarcher-compile-and-run| FileCheck %s
+// RUN: env OMP_NUM_THREADS=7 %libarcher-compile-and-run| FileCheck %s
+
+// REQUIRES: tsan
+#include <omp.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+ int var[10]={0,1,2,3,4,5,6,7,8,9};
+
+#pragma omp parallel
+ {
+#pragma omp masked
+ var[5] = 23;
+#pragma omp barrier
+#pragma omp for reduction(+ : var)
+ for (int i = 0; i < 1000; i++)
+ { var[i%10]++; }
+#pragma omp masked
+ var[4] += 42;
+ }
+ fprintf(stderr, "DONE\n");
+ int error = (var[5] != 23+100) || (var[4] != 4+100+42);
+ return error;
+}
+
+// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: reported
+// CHECK: DONE
diff --git a/openmp/tools/archer/tests/reduction/parallel-for-reduction-barrier.c b/openmp/tools/archer/tests/reduction/parallel-for-reduction-barrier.c
new file mode 100644
index 0000000000000..5050684ce2dda
--- /dev/null
+++ b/openmp/tools/archer/tests/reduction/parallel-for-reduction-barrier.c
@@ -0,0 +1,45 @@
+/*
+ * parallel-reduction.c -- Archer testcase
+ */
+
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+//
+// See tools/archer/LICENSE.txt for details.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Number of threads is empirical: We need enough (>4) threads so that
+// the reduction is really performed hierarchically in the barrier!
+
+// RUN: env OMP_NUM_THREADS=3 %libarcher-compile-and-run| FileCheck %s
+// RUN: env OMP_NUM_THREADS=7 %libarcher-compile-and-run| FileCheck %s
+
+// REQUIRES: tsan
+#include <omp.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+ int var = 0;
+
+#pragma omp parallel
+ {
+#pragma omp masked
+ var = 23;
+#pragma omp barrier
+#pragma omp for reduction(+ : var)
+ for (int i = 0; i < 100; i++)
+ { var++; }
+#pragma omp masked
+ var += 42;
+ }
+ fprintf(stderr, "DONE\n");
+ int error = (var != 23+100+42);
+ return error;
+}
+
+// CHECK-NOT: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer: reported
+// CHECK: DONE
diff --git a/openmp/tools/archer/tests/reduction/parallel-reduction-nowait.c b/openmp/tools/archer/tests/reduction/parallel-reduction-nowait.c
index b91579f0b00c2..0f6697f213e85 100644
--- a/openmp/tools/archer/tests/reduction/parallel-reduction-nowait.c
+++ b/openmp/tools/archer/tests/reduction/parallel-reduction-nowait.c
@@ -37,6 +37,7 @@ int main(int argc, char *argv[]) {
}
fprintf(stderr, "DONE\n");
+ printf("var = %i\n", var);
int error = (var != 100);
return error;
}
diff --git a/openmp/tools/archer/tests/reduction/parallel-reduction.c b/openmp/tools/archer/tests/reduction/parallel-reduction.c
index 6d1a556ac00ed..afb2863235d32 100644
--- a/openmp/tools/archer/tests/reduction/parallel-reduction.c
+++ b/openmp/tools/archer/tests/reduction/parallel-reduction.c
@@ -11,22 +11,24 @@
//
//===----------------------------------------------------------------------===//
+// Number of threads is empirical: We need enough (>4) threads so that
+// the reduction is really performed hierarchically in the barrier!
+
+// RUN: env OMP_NUM_THREADS=3 %libarcher-compile-and-run| FileCheck %s
+// RUN: env OMP_NUM_THREADS=7 %libarcher-compile-and-run| FileCheck %s
-// RUN: %libarcher-compile-and-run| FileCheck %s
// REQUIRES: tsan
#include <omp.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int var = 0;
-
-// Number of threads is empirical: We need enough threads so that
-// the reduction is really performed hierarchically in the barrier!
-#pragma omp parallel num_threads(5) reduction(+ : var)
+
+#pragma omp parallel reduction(+ : var)
{ var = 1; }
fprintf(stderr, "DONE\n");
- int error = (var != 5);
+ int error = (var != omp_get_max_threads());
return error;
}
>From e9ead10753caf0ac2e087466eccf58e91bec891a Mon Sep 17 00:00:00 2001
From: "felix.tomski" <tomski at itc.rwth-aachen.de>
Date: Wed, 6 Dec 2023 20:21:46 +0100
Subject: [PATCH 2/2] Fix format
---
compiler-rt/lib/tsan/rtl/tsan_rtl.cpp | 4 ++--
openmp/tools/archer/ompt-tsan.cpp | 14 +++++++++-----
.../parallel-for-array-reduction-no-barrier.c | 9 +++++----
.../races/parallel-for-array-reduction-nowait.c | 9 +++++----
.../races/parallel-for-reduction-no-barrier.c | 7 ++++---
.../tests/races/parallel-for-reduction-nowait.c | 7 ++++---
.../parallel-for-array-reduction-barrier.c | 11 ++++++-----
.../reduction/parallel-for-reduction-barrier.c | 9 +++++----
.../archer/tests/reduction/parallel-reduction.c | 2 +-
9 files changed, 41 insertions(+), 31 deletions(-)
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
index c829247088f75..cdbe4cb3442ac 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
@@ -1055,12 +1055,12 @@ void ThreadIgnoreEnd(ThreadState *thr) {
void ThreadAtomicBegin(ThreadState* thr, uptr pc) {
thr->all_atomic++;
-// CHECK_GT(thr->ignore_reads_and_writes, 0);
+ // CHECK_GT(thr->ignore_reads_and_writes, 0);
CHECK_EQ(thr->all_atomic, 1);
thr->fast_state.SetAtomicBit();
}
-void ThreadAtomicEnd(ThreadState *thr) {
+void ThreadAtomicEnd(ThreadState* thr) {
CHECK_GT(thr->all_atomic, 0);
thr->all_atomic--;
if (thr->all_atomic == 0) {
diff --git a/openmp/tools/archer/ompt-tsan.cpp b/openmp/tools/archer/ompt-tsan.cpp
index ece791683eedd..673b23aca8ab5 100644
--- a/openmp/tools/archer/ompt-tsan.cpp
+++ b/openmp/tools/archer/ompt-tsan.cpp
@@ -149,7 +149,7 @@ static ArcherFlags *archer_flags;
// Thread Sanitizer is a tool that finds races in code.
// See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations .
// tsan detects these exact functions by name.
-//extern "C" {
+// extern "C" {
static void (*AnnotateHappensAfter)(const char *, int, const volatile void *);
static void (*AnnotateHappensBefore)(const char *, int, const volatile void *);
static void (*AnnotateIgnoreWritesBegin)(const char *, int);
@@ -177,7 +177,7 @@ static void (*AnnotateReductionEnd)(const char *, int);
// Resume checking for racy writes.
#define TsanIgnoreWritesEnd() AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
-// Maps to either AnnotateAllAtomics or AnnotateIgnoreWrites
+// Maps to either AnnotateAllAtomics or AnnotateIgnoreWrites
#define TsanReductionBegin() AnnotateReductionBegin(__FILE__, __LINE__)
#define TsanReductionEnd() AnnotateReductionEnd(__FILE__, __LINE__)
@@ -1187,13 +1187,17 @@ static int ompt_tsan_initialize(ompt_function_lookup_t lookup, int device_num,
(void (*)(const char *, int, const volatile void *, size_t)));
findTsanFunction(__tsan_func_entry, (void (*)(const void *)));
findTsanFunction(__tsan_func_exit, (void (*)(void)));
- findTsanFunctionName(AnnotateReductionBegin, AnnotateAllAtomicBegin, (void (*)(const char *, int)));
- findTsanFunctionName(AnnotateReductionEnd, AnnotateAllAtomicEnd, (void (*)(const char *, int)));
+ findTsanFunctionName(AnnotateReductionBegin, AnnotateAllAtomicBegin,
+ (void (*)(const char *, int)));
+ findTsanFunctionName(AnnotateReductionEnd, AnnotateAllAtomicEnd,
+ (void (*)(const char *, int)));
if (!AnnotateReductionBegin) {
AnnotateReductionBegin = AnnotateIgnoreWritesBegin;
AnnotateReductionEnd = AnnotateIgnoreWritesEnd;
if (archer_flags->verbose)
- std::cout << "Archer uses fallback solution for reductions: might miss some race" << std::endl;
+ std::cout << "Archer uses fallback solution for reductions: might miss "
+ "some race"
+ << std::endl;
}
SET_CALLBACK(thread_begin);
diff --git a/openmp/tools/archer/tests/races/parallel-for-array-reduction-no-barrier.c b/openmp/tools/archer/tests/races/parallel-for-array-reduction-no-barrier.c
index 2cdfb811fcbc5..511a21013da4d 100644
--- a/openmp/tools/archer/tests/races/parallel-for-array-reduction-no-barrier.c
+++ b/openmp/tools/archer/tests/races/parallel-for-array-reduction-no-barrier.c
@@ -22,15 +22,16 @@
#include <stdio.h>
int main(int argc, char *argv[]) {
- int var[10]={0,1,2,3,4,5,6,7,8,9};
-
+ int var[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+
#pragma omp parallel
{
#pragma omp masked
var[5] = 23;
#pragma omp for reduction(+ : var)
- for (int i = 0; i < 1000; i++)
- { var[i%10]++; }
+ for (int i = 0; i < 1000; i++) {
+ var[i % 10]++;
+ }
}
fprintf(stderr, "DONE\n");
int error = (var[5] != 123);
diff --git a/openmp/tools/archer/tests/races/parallel-for-array-reduction-nowait.c b/openmp/tools/archer/tests/races/parallel-for-array-reduction-nowait.c
index 6ca17fcca6b54..bdac83d7ca6b2 100644
--- a/openmp/tools/archer/tests/races/parallel-for-array-reduction-nowait.c
+++ b/openmp/tools/archer/tests/races/parallel-for-array-reduction-nowait.c
@@ -22,13 +22,14 @@
#include <stdio.h>
int main(int argc, char *argv[]) {
- int var[10]={0,1,2,3,4,5,6,7,8,9};
-
+ int var[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+
#pragma omp parallel
{
#pragma omp for reduction(+ : var) nowait
- for (int i = 0; i < 1000; i++)
- { var[i%10]++; }
+ for (int i = 0; i < 1000; i++) {
+ var[i % 10]++;
+ }
#pragma omp masked
var[5] += 23;
}
diff --git a/openmp/tools/archer/tests/races/parallel-for-reduction-no-barrier.c b/openmp/tools/archer/tests/races/parallel-for-reduction-no-barrier.c
index 3cc63cfab1996..3ea874a0deb6f 100644
--- a/openmp/tools/archer/tests/races/parallel-for-reduction-no-barrier.c
+++ b/openmp/tools/archer/tests/races/parallel-for-reduction-no-barrier.c
@@ -23,14 +23,15 @@
int main(int argc, char *argv[]) {
int var = 0;
-
+
#pragma omp parallel
{
#pragma omp masked
var = 23;
#pragma omp for reduction(+ : var)
- for (int i = 0; i < 100; i++)
- { var++; }
+ for (int i = 0; i < 100; i++) {
+ var++;
+ }
}
fprintf(stderr, "DONE\n");
int error = (var != 123);
diff --git a/openmp/tools/archer/tests/races/parallel-for-reduction-nowait.c b/openmp/tools/archer/tests/races/parallel-for-reduction-nowait.c
index 4c24e8a4f8285..11afceb671a53 100644
--- a/openmp/tools/archer/tests/races/parallel-for-reduction-nowait.c
+++ b/openmp/tools/archer/tests/races/parallel-for-reduction-nowait.c
@@ -23,12 +23,13 @@
int main(int argc, char *argv[]) {
int var = 0;
-
+
#pragma omp parallel
{
#pragma omp for reduction(+ : var) nowait
- for (int i = 0; i < 100; i++)
- { var++; }
+ for (int i = 0; i < 100; i++) {
+ var++;
+ }
#pragma omp masked
var = 23;
}
diff --git a/openmp/tools/archer/tests/reduction/parallel-for-array-reduction-barrier.c b/openmp/tools/archer/tests/reduction/parallel-for-array-reduction-barrier.c
index 2ac9ec449baa7..d5d7ca525093c 100644
--- a/openmp/tools/archer/tests/reduction/parallel-for-array-reduction-barrier.c
+++ b/openmp/tools/archer/tests/reduction/parallel-for-array-reduction-barrier.c
@@ -22,21 +22,22 @@
#include <stdio.h>
int main(int argc, char *argv[]) {
- int var[10]={0,1,2,3,4,5,6,7,8,9};
-
+ int var[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+
#pragma omp parallel
{
#pragma omp masked
var[5] = 23;
#pragma omp barrier
#pragma omp for reduction(+ : var)
- for (int i = 0; i < 1000; i++)
- { var[i%10]++; }
+ for (int i = 0; i < 1000; i++) {
+ var[i % 10]++;
+ }
#pragma omp masked
var[4] += 42;
}
fprintf(stderr, "DONE\n");
- int error = (var[5] != 23+100) || (var[4] != 4+100+42);
+ int error = (var[5] != 23 + 100) || (var[4] != 4 + 100 + 42);
return error;
}
diff --git a/openmp/tools/archer/tests/reduction/parallel-for-reduction-barrier.c b/openmp/tools/archer/tests/reduction/parallel-for-reduction-barrier.c
index 5050684ce2dda..5ee6928161b5c 100644
--- a/openmp/tools/archer/tests/reduction/parallel-for-reduction-barrier.c
+++ b/openmp/tools/archer/tests/reduction/parallel-for-reduction-barrier.c
@@ -23,20 +23,21 @@
int main(int argc, char *argv[]) {
int var = 0;
-
+
#pragma omp parallel
{
#pragma omp masked
var = 23;
#pragma omp barrier
#pragma omp for reduction(+ : var)
- for (int i = 0; i < 100; i++)
- { var++; }
+ for (int i = 0; i < 100; i++) {
+ var++;
+ }
#pragma omp masked
var += 42;
}
fprintf(stderr, "DONE\n");
- int error = (var != 23+100+42);
+ int error = (var != 23 + 100 + 42);
return error;
}
diff --git a/openmp/tools/archer/tests/reduction/parallel-reduction.c b/openmp/tools/archer/tests/reduction/parallel-reduction.c
index afb2863235d32..887fe2e018281 100644
--- a/openmp/tools/archer/tests/reduction/parallel-reduction.c
+++ b/openmp/tools/archer/tests/reduction/parallel-reduction.c
@@ -23,7 +23,7 @@
int main(int argc, char *argv[]) {
int var = 0;
-
+
#pragma omp parallel reduction(+ : var)
{ var = 1; }
More information about the Openmp-commits
mailing list