From 24087ff3cc08c9ef050165566d25257067744e10 Mon Sep 17 00:00:00 2001 From: Jean-Luc Duprat Date: Tue, 27 Nov 2012 13:38:28 -0800 Subject: [PATCH] Expose none() in the ISPC standard library. On KNC: all(), any() and none() do not generate a redundant movmsk instruction. --- docs/ispc.rst | 11 +++++++---- examples/intrinsics/knc.h | 2 +- stdlib.ispc | 23 +++++++++++++++++------ 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/docs/ispc.rst b/docs/ispc.rst index 609b7838..9412e649 100644 --- a/docs/ispc.rst +++ b/docs/ispc.rst @@ -3701,15 +3701,18 @@ where the ``i`` th element of ``x`` has been replaced with the value ``v`` Reductions ---------- -A number routines are available to evaluate conditions across the running -program instances. For example, ``any()`` returns ``true`` if the given -value ``v`` is ``true`` for any of the SPMD program instances currently -running, and ``all()`` returns ``true`` if it true for all of them. +A number routines are available to evaluate conditions across the +running program instances. For example, ``any()`` returns ``true`` if +the given value ``v`` is ``true`` for any of the SPMD program +instances currently running, ``all()`` returns ``true`` if it true +for all of them, and ``none()`` returns ``true`` if ``v`` is always +``false``. :: uniform bool any(bool v) uniform bool all(bool v) + uniform bool none(bool v) You can also compute a variety of reductions across the program instances. For example, the values of the given value in each of the active program diff --git a/examples/intrinsics/knc.h b/examples/intrinsics/knc.h index 08d2e8bf..dba551fe 100644 --- a/examples/intrinsics/knc.h +++ b/examples/intrinsics/knc.h @@ -482,7 +482,7 @@ static FORCEINLINE bool __all(__vec16_i1 mask) { } static FORCEINLINE bool __none(__vec16_i1 mask) { - return !__any(mask); + return _mm512_kortestz(mask, mask); } static FORCEINLINE __vec16_i1 __equal_i1(__vec16_i1 a, __vec16_i1 b) { diff --git a/stdlib.ispc b/stdlib.ispc index 80f44e91..81ebac70 100644 --- a/stdlib.ispc +++ b/stdlib.ispc @@ -340,9 +340,9 @@ static inline uniform bool any(bool v) { // We only care about whether "any" is true for the active program instances, // so we have to make v with the current program mask. #ifdef ISPC_TARGET_GENERIC - return __movmsk(v & __mask) != 0; + return __any(v | !__mask); #else - return __movmsk(__sext_varying_bool(v) & __mask) != 0; + return __any(__sext_varying_bool(v) | !__mask); #endif } @@ -350,13 +350,24 @@ __declspec(safe) static inline uniform bool all(bool v) { // As with any(), we need to explicitly mask v with the current program mask // so we're only looking at the current lanes + #ifdef ISPC_TARGET_GENERIC - bool match = ((v & __mask) == __mask); + return __all(v | !__mask); #else - int32 match = __sext_varying_bool((__sext_varying_bool(v) & __mask) == __mask); + return __all(__sext_varying_bool(v) | !__mask); +#endif +} + +__declspec(safe) +static inline uniform bool none(bool v) { + // As with any(), we need to explicitly mask v with the current program mask + // so we're only looking at the current lanes + +#ifdef ISPC_TARGET_GENERIC + return __none(v | !__mask); +#else + return __none(__sext_varying_bool(v) | !__mask); #endif - return __movmsk(match) == ((programCount == 64) ? ~0ull : - ((1ull << programCount) - 1)); } __declspec(safe)