One more hack to work around compiler quirks

Submitted by Matthias on Tue, 02/16/2016 - 17:04

The Intel C++ compiler can be rather annoying for my work on Vc. I encountered many subtle issues with C++ that are hard to debug and reduce to a minimal test case. My latest hack:

 template <typename Op, typename R, typename... Args>
 Vc_INTRINSIC void unpackArgumentsAuto(Op op, R &&r, Args &&... args)
 {
-    unpackArgumentsAutoImpl<0>(
+#ifdef Vc_ICC
+    // ugly hacky workaround for ICC:
+    // The compiler fails to do SFINAE right on recursion. We have to hit the right
+    // recursionStart number from the start.
+    const int recursionStart =
+        Traits::isSimdArray<
+            typename IccWorkaround<sizeof...(Args), Args...>::type>::value &&
+                (std::is_same<Op, Common::Operations::Forward_frexp>::value ||
+                 std::is_same<Op, Common::Operations::Forward_ldexp>::value)
+            ? 2
+            : 0;
+#else
+    const int recursionStart = 0;
+#endif
+    unpackArgumentsAutoImpl<recursionStart>(
         int(), make_index_sequence<sizeof...(Args)>(), op, std::forward<R>(r),
         std::forward<Args>(args)...);
 }

This function implements a beautiful feature: A function to be called is identified via the Op type. The return value goes into r and the arguments to the function are in the parameter pack args. Now the unpackArgumentsAuto function determines which function arguments need to be adapted (unpacked) in some pre-defined way (depending on their type) so that the identified function can be called. This allows a very generic interface in this case for adding more operations.

The problem: The code needs to try what works via SFINAE. It does so via recursion. The recursionStart template argument determines the function arguments to be unpacked. In the recursion this number is incremented until it reaches a maximum where the machinery fails in a static_assert. This works as expected with GCC and Clang. However, the Intel compiler always reaches the static_assert unless the recursionStart value is the right number. I.e. something goes wrong with SFINAE when it recurses the function. Therefore, the fix for ICC is to spell out the correct magic number depending on the input types. This is exactly the kind of thing the whole construction was supposed to automate. :'(

Add new comment

By submitting this form, you accept the Mollom privacy policy.