From 208ca28eba23da3a1ad49c9b78a2c4bd739c9da4 Mon Sep 17 00:00:00 2001 From: Sam Yates <yates@cscs.ch> Date: Wed, 3 May 2017 14:15:56 +0200 Subject: [PATCH] Work-around for inlining bug in icc 16.0.3 (#248) Fixes #247. Forces evaluation of partition bounds call within the `div_component_sampler` constructor, which for subtle and obscure reasons is mis- or un-computed with icpc and the `-xMIC-AVX512` target option. * Add `compat::sink()` function that forces evaluation of the argument. * Add `compat::sink_if_icc_leq(version, const X&)` function that performs this only when run with the Intel compiler subject to version bound. * Use the `compat::sink_if_icc_leq` function in the `div_component_sampler` constructor. --- src/compartment.hpp | 5 ++++- src/util/compat.hpp | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/compartment.hpp b/src/compartment.hpp index db548fa3..10c26fd1 100644 --- a/src/compartment.hpp +++ b/src/compartment.hpp @@ -5,11 +5,12 @@ #include <common_types.hpp> #include <math.hpp> +#include <util/compat.hpp> #include <util/counter.hpp> #include <util/iterutil.hpp> #include <util/partition.hpp> #include <util/span.hpp> -#include "util/rangeutil.hpp" +#include <util/rangeutil.hpp> #include <util/transform.hpp> namespace nest { @@ -184,6 +185,8 @@ public: using namespace util; segs_ = make_partition(offsets_, lengths); + compat::sink_if_icc_leq(20160415u, segs_.bounds()); + nseg_ = size(segs_); scale_ = segs_.bounds().second/n; assign(radii_, radii); diff --git a/src/util/compat.hpp b/src/util/compat.hpp index c288effe..a10e8cc1 100644 --- a/src/util/compat.hpp +++ b/src/util/compat.hpp @@ -34,4 +34,27 @@ inline void compiler_barrier_if_xlc_leq(unsigned ver) { template <typename X> inline constexpr bool isinf(X x) { return std::isinf(x); } +// Work around a bad inlining-related optimization with icpc 16.0.3 and -xMIC-AVX512, +// by forcing a computation. + +template <typename X> +inline void sink(const X& x) { + char buf[sizeof x]; + volatile char* bufptr = buf; + const char* xptr = reinterpret_cast<const char*>(&x); + + for (std::size_t i = 0; i<sizeof buf; ++i) { + *bufptr++ = *xptr++; + } +} + +template <typename X> +inline void sink_if_icc_leq(unsigned ver, const X& x) { +#if defined(__INTEL_COMPILER_BUILD_DATE) + if (__INTEL_COMPILER_BUILD_DATE<=ver) { + sink(x); + } +#endif } + +} // namespace compat -- GitLab