[OpenMP] Ensure broken assumptions print once, not thousands of times.
If we have a broken assumption we want to print a message to the user. If the assumption is broken by many threads in many teams this can become a problem. To avoid it we use a hash that tracks if a broken assumption has (likely) been printed and avoid printing it again. This is not fool proof and has some caveats that might cause problems in the future (see comment) but it should improve the situation considerably for now. Reviewed By: JonChesterfield Differential Revision: https://reviews.llvm.org/D112156
This commit is contained in:
parent
2945f11c60
commit
27c799ecc9
|
@ -13,6 +13,7 @@
|
|||
#define OMPTARGET_DEVICERTL_DEBUG_H
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "Utils.h"
|
||||
|
||||
/// Assertion
|
||||
///
|
||||
|
@ -25,9 +26,10 @@ void __assert_fail(const char *assertion, const char *file, unsigned line,
|
|||
|
||||
#define ASSERT(expr) \
|
||||
{ \
|
||||
if (config::isDebugMode(config::DebugKind::Assertion) && !(expr)) \
|
||||
if (config::isDebugMode(config::DebugKind::Assertion) && !(expr) && \
|
||||
utils::SingletonFlag::testAndSet()) \
|
||||
__assert_fail(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
|
||||
else \
|
||||
else if (!config::isDebugMode(config::DebugKind::Assertion)) \
|
||||
__assert_assume(expr); \
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,10 @@ uint32_t add(uint32_t *Addr, uint32_t V, int Ordering);
|
|||
/// Atomically add \p V to \p *Addr with \p Ordering semantics.
|
||||
uint64_t add(uint64_t *Addr, uint64_t V, int Ordering);
|
||||
|
||||
/// Atomically write \p V to \p *Addr with \p Ordering semantics and return the
|
||||
/// old value of \p *Addr.
|
||||
uint32_t exchange(uint32_t *Addr, uint32_t V, int Ordering);
|
||||
|
||||
} // namespace atomic
|
||||
|
||||
} // namespace _OMP
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#ifndef OMPTARGET_DEVICERTL_UTILS_H
|
||||
#define OMPTARGET_DEVICERTL_UTILS_H
|
||||
|
||||
#include "Synchronization.h"
|
||||
#include "Types.h"
|
||||
|
||||
namespace _OMP {
|
||||
|
@ -72,6 +73,26 @@ template <typename Ty1, typename Ty2> inline Ty1 align_down(Ty1 V, Ty2 Align) {
|
|||
return V - V % Align;
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// Helper class to perform an action only once.
|
||||
///
|
||||
/// Using this is probably costly even if it is not executed. It should be
|
||||
/// guarded such that release mode execution will not be impacted.
|
||||
template <uint32_t ID> struct SingletonFlagImpl {
|
||||
|
||||
/// Each SingletonFlag instantiation with the same ID has an internal flag.
|
||||
/// This function will return true if the flag was not set before, otherwise
|
||||
/// it will return false. In either case the flag is set afterwards.
|
||||
static bool testAndSet() {
|
||||
static uint32_t DoOnceFlag = 0;
|
||||
return 1 != atomic::exchange(&DoOnceFlag, 1, __ATOMIC_ACQ_REL);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
/// Helper to hide the __COUNTER__ use away.
|
||||
#define SingletonFlag SingletonFlagImpl<__COUNTER__>
|
||||
|
||||
#define OMP_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true)
|
||||
#define OMP_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false)
|
||||
|
||||
|
|
|
@ -320,6 +320,10 @@ uint64_t atomic::add(uint64_t *Addr, uint64_t V, int Ordering) {
|
|||
return impl::atomicAdd(Addr, V, Ordering);
|
||||
}
|
||||
|
||||
uint32_t atomic::exchange(uint32_t *Addr, uint32_t V, int Ordering) {
|
||||
return impl::atomicExchange(Addr, V, Ordering);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void __kmpc_ordered(IdentTy *Loc, int32_t TId) { FunctionTracingRAII(); }
|
||||
|
||||
|
|
Loading…
Reference in New Issue