Merged in deven-amd/eigen-hip-fix-191018 (pull request PR-738)

Fix for the HIP build+test errors.
diff --git a/unsupported/Eigen/CXX11/Tensor b/unsupported/Eigen/CXX11/Tensor
index 04b20f4..a110b52 100644
--- a/unsupported/Eigen/CXX11/Tensor
+++ b/unsupported/Eigen/CXX11/Tensor
@@ -13,6 +13,8 @@
 
 #include "../../../Eigen/Core"
 
+#if EIGEN_HAS_CXX11
+
 #if defined(EIGEN_USE_SYCL)
 #undef min
 #undef max
@@ -47,6 +49,7 @@
 #include <cmath>
 #include <cstddef>
 #include <cstring>
+#include <random>
 
 #ifdef _WIN32
 typedef __int16 int16_t;
@@ -61,10 +64,6 @@
 #include <unistd.h>
 #endif
 
-#if __cplusplus > 199711 || EIGEN_COMP_MSVC >= 1900
-#include <random>
-#endif
-
 #ifdef _WIN32
 #include <windows.h>
 #elif defined(__APPLE__)
@@ -164,4 +163,5 @@
 
 #include "../../../Eigen/src/Core/util/ReenableStupidWarnings.h"
 
+#endif  // EIGEN_HAS_CXX11
 //#endif // EIGEN_CXX11_TENSOR_MODULE
diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorBase.h b/unsupported/Eigen/CXX11/src/Tensor/TensorBase.h
index a951bea..7aa98fa 100644
--- a/unsupported/Eigen/CXX11/src/Tensor/TensorBase.h
+++ b/unsupported/Eigen/CXX11/src/Tensor/TensorBase.h
@@ -1129,16 +1129,11 @@
       return TensorDevice<Derived, DeviceType>(dev, derived());
     }
 
-#ifdef EIGEN_USE_THREADS
     // Select the async device on which to evaluate the expression.
     template <typename DeviceType, typename DoneCallback>
-    typename internal::enable_if<
-        internal::is_same<DeviceType, ThreadPoolDevice>::value,
-        TensorAsyncDevice<Derived, DeviceType, DoneCallback>>::type
-    device(const DeviceType& dev, DoneCallback done) {
+    TensorAsyncDevice<Derived, DeviceType, DoneCallback> device(const DeviceType& dev, DoneCallback done) {
       return TensorAsyncDevice<Derived, DeviceType, DoneCallback>(dev, derived(), std::move(done));
     }
-#endif  // EIGEN_USE_THREADS
 
  protected:
     EIGEN_DEVICE_FUNC
diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorBlockV2.h b/unsupported/Eigen/CXX11/src/Tensor/TensorBlockV2.h
index 48417c1..221f8e8 100644
--- a/unsupported/Eigen/CXX11/src/Tensor/TensorBlockV2.h
+++ b/unsupported/Eigen/CXX11/src/Tensor/TensorBlockV2.h
@@ -51,13 +51,11 @@
   return strides<Layout>(DSizes<IndexType, NumDims>(dimensions));
 }
 
-#if EIGEN_HAS_CXX11
 template <int Layout, std::ptrdiff_t... Indices>
 EIGEN_STRONG_INLINE DSizes<std::ptrdiff_t, sizeof...(Indices)> strides(
     const Sizes<Indices...>& sizes) {
   return strides<Layout>(DSizes<std::ptrdiff_t, sizeof...(Indices)>(sizes));
 }
-#endif
 
 // -------------------------------------------------------------------------- //
 // TensorBlockDescriptor specifies a block offset within a tensor and the block
@@ -192,7 +190,7 @@
       Scalar* dst_base,
       const DSizes<DstStridesIndexType, NumDims>& dst_strides) {
     // DSizes constructor will do index type promotion if it's safe.
-    AddDestinationBuffer<Layout>(*this, dst_base, Dimensions(dst_strides));
+    AddDestinationBuffer<Layout>(dst_base, Dimensions(dst_strides));
   }
 
   TensorBlockDescriptor& DropDestinationBuffer() {
@@ -292,11 +290,6 @@
 // -------------------------------------------------------------------------- //
 // TensorBlockKind represents all possible block kinds, that can be produced by
 // TensorEvaluator::evalBlock function.
-#if !EIGEN_HAS_CXX11
-// To be able to use `TensorBlockKind::kExpr` in C++03 we need a namespace.
-// (Use of enumeration in a nested name specifier is a c++11 extension).
-namespace TensorBlockKind {
-#endif
 enum TensorBlockKind {
   // Tensor block that is a lazy expression that must be assigned to a
   // destination using TensorBlockAssign.
@@ -320,9 +313,6 @@
   // TensorBlockAssign or for constructing another block expression.
   kMaterializedInOutput
 };
-#if !EIGEN_HAS_CXX11
-}  // namespace TensorBlockKind
-#endif
 
 // -------------------------------------------------------------------------- //
 // TensorBlockNotImplemented should be used to defined TensorBlock typedef in
@@ -368,9 +358,6 @@
 template <typename Scalar, int NumDims, int Layout,
           typename IndexType = Eigen::Index>
 class TensorMaterializedBlock {
-#if !EIGEN_HAS_CXX11
-  typedef internal::TensorBlockKind::TensorBlockKind TensorBlockKind;
-#endif
  public:
   typedef DSizes<IndexType, NumDims> Dimensions;
   typedef TensorMap<const Tensor<Scalar, NumDims, Layout> > XprType;
@@ -550,9 +537,6 @@
 
 template <typename UnaryOp, typename ArgTensorBlock>
 class TensorCwiseUnaryBlock {
-#if !EIGEN_HAS_CXX11
-  typedef internal::TensorBlockKind::TensorBlockKind TensorBlockKind;
-#endif
 
   static const bool NoArgBlockAccess =
       internal::is_void<typename ArgTensorBlock::XprType>::value;
@@ -585,9 +569,6 @@
 
 template <typename BinaryOp, typename LhsTensorBlock, typename RhsTensorBlock>
 class TensorCwiseBinaryBlock {
-#if !EIGEN_HAS_CXX11
-  typedef internal::TensorBlockKind::TensorBlockKind TensorBlockKind;
-#endif
 
   static const bool NoArgBlockAccess =
       internal::is_void<typename LhsTensorBlock::XprType>::value ||
@@ -635,9 +616,6 @@
 
 template <typename BlockFactory, typename ArgTensorBlock>
 class TensorUnaryExprBlock {
-#if !EIGEN_HAS_CXX11
-  typedef internal::TensorBlockKind::TensorBlockKind TensorBlockKind;
-#endif
 
   typedef typename ArgTensorBlock::XprType ArgXprType;
   static const bool NoArgBlockAccess = internal::is_void<ArgXprType>::value;
@@ -670,9 +648,6 @@
 template <typename BlockFactory, typename Arg1TensorBlock,
           typename Arg2TensorBlock, typename Arg3TensorBlock>
 class TensorTernaryExprBlock {
-#if !EIGEN_HAS_CXX11
-  typedef internal::TensorBlockKind::TensorBlockKind TensorBlockKind;
-#endif
 
   typedef typename Arg1TensorBlock::XprType Arg1XprType;
   typedef typename Arg2TensorBlock::XprType Arg2XprType;
diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorDevice.h b/unsupported/Eigen/CXX11/src/Tensor/TensorDevice.h
index cc9c657..804a16c 100644
--- a/unsupported/Eigen/CXX11/src/Tensor/TensorDevice.h
+++ b/unsupported/Eigen/CXX11/src/Tensor/TensorDevice.h
@@ -63,18 +63,18 @@
     ExpressionType& m_expression;
 };
 
-#ifdef EIGEN_USE_THREADS
-
 /** \class TensorAsyncDevice
-  * \ingroup CXX11_Tensor_Module
-  *
-  * \brief Pseudo expression providing an operator = that will evaluate its
-  * argument asynchronously on the specified device (currently supports only
-  * ThreadPoolDevice).
-  *
-  * Example:
-  *    auto done = []() { ... expression evaluation done ... };
-  *    C.device(EIGEN_THREAD_POOL, std::move(done)) = A + B;
+ * \ingroup CXX11_Tensor_Module
+ *
+ * \brief Pseudo expression providing an operator = that will evaluate its
+ * argument asynchronously on the specified device. Currently only
+ * ThreadPoolDevice implements proper asynchronous execution, while the default
+ * and GPU devices just run the expression synchronously and call m_done() on
+ * completion..
+ *
+ * Example:
+ *    auto done = []() { ... expression evaluation done ... };
+ *    C.device(thread_pool_device, std::move(done)) = A + B;
  */
 
 template <typename ExpressionType, typename DeviceType, typename DoneCallback>
@@ -87,11 +87,11 @@
   template <typename OtherDerived>
   EIGEN_STRONG_INLINE TensorAsyncDevice& operator=(const OtherDerived& other) {
     typedef TensorAssignOp<ExpressionType, const OtherDerived> Assign;
-    typedef internal::TensorAsyncExecutor<const Assign, DeviceType, DoneCallback> Executor;
+    typedef internal::TensorExecutor<const Assign, DeviceType> Executor;
 
-    // WARNING: After assignment 'm_done' callback will be in undefined state.
     Assign assign(m_expression, other);
-    Executor::runAsync(assign, m_device, std::move(m_done));
+    Executor::run(assign, m_device);
+    m_done();
 
     return *this;
   }
@@ -102,7 +102,33 @@
   DoneCallback m_done;
 };
 
-#endif  // EIGEN_USE_THREADS
+
+#ifdef EIGEN_USE_THREADS
+template <typename ExpressionType, typename DoneCallback>
+class TensorAsyncDevice<ExpressionType, ThreadPoolDevice, DoneCallback> {
+ public:
+  TensorAsyncDevice(const ThreadPoolDevice& device, ExpressionType& expression,
+                    DoneCallback done)
+      : m_device(device), m_expression(expression), m_done(std::move(done)) {}
+
+  template <typename OtherDerived>
+  EIGEN_STRONG_INLINE TensorAsyncDevice& operator=(const OtherDerived& other) {
+    typedef TensorAssignOp<ExpressionType, const OtherDerived> Assign;
+    typedef internal::TensorAsyncExecutor<const Assign, ThreadPoolDevice, DoneCallback> Executor;
+
+    // WARNING: After assignment 'm_done' callback will be in undefined state.
+    Assign assign(m_expression, other);
+    Executor::runAsync(assign, m_device, std::move(m_done));
+
+    return *this;
+  }
+
+ protected:
+  const ThreadPoolDevice& m_device;
+  ExpressionType& m_expression;
+  DoneCallback m_done;
+};
+#endif
 
 } // end namespace Eigen
 
diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorDeviceGpu.h b/unsupported/Eigen/CXX11/src/Tensor/TensorDeviceGpu.h
index 5b1abdc..7f33944 100644
--- a/unsupported/Eigen/CXX11/src/Tensor/TensorDeviceGpu.h
+++ b/unsupported/Eigen/CXX11/src/Tensor/TensorDeviceGpu.h
@@ -53,14 +53,8 @@
     // compile with nvcc, so we resort to atomics and thread fences instead.
     // Note that if the caller uses a compiler that doesn't support c++11 we
     // can't ensure that the initialization is thread safe.
-#if __cplusplus >= 201103L
     static std::atomic<bool> first(true);
     if (first.exchange(false)) {
-#else
-    static bool first = true;
-    if (first) {
-      first = false;
-#endif
       // We're the first thread to reach this point.
       int num_devices;
       gpuError_t status = gpuGetDeviceCount(&num_devices);
@@ -83,16 +77,12 @@
         }
       }
 
-#if __cplusplus >= 201103L
       std::atomic_thread_fence(std::memory_order_release);
-#endif
       m_devicePropInitialized = true;
     } else {
       // Wait for the other thread to inititialize the properties.
       while (!m_devicePropInitialized) {
-#if __cplusplus >= 201103L
         std::atomic_thread_fence(std::memory_order_acquire);
-#endif
         EIGEN_SLEEP(1000);
       }
     }
diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorEvalTo.h b/unsupported/Eigen/CXX11/src/Tensor/TensorEvalTo.h
index 22fc64c..cd1338c 100644
--- a/unsupported/Eigen/CXX11/src/Tensor/TensorEvalTo.h
+++ b/unsupported/Eigen/CXX11/src/Tensor/TensorEvalTo.h
@@ -151,6 +151,16 @@
     return m_impl.evalSubExprsIfNeeded(m_buffer);
   }
 
+#ifdef EIGEN_USE_THREADS
+  template <typename EvalSubExprsCallback>
+  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalSubExprsIfNeededAsync(
+      EvaluatorPointerType scalar, EvalSubExprsCallback done) {
+    EIGEN_UNUSED_VARIABLE(scalar);
+    eigen_assert(scalar == NULL);
+    m_impl.evalSubExprsIfNeededAsync(m_buffer, std::move(done));
+  }
+#endif
+
   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalScalar(Index i) {
     m_buffer[i] = m_impl.coeff(i);
   }
diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorExecutor.h b/unsupported/Eigen/CXX11/src/Tensor/TensorExecutor.h
index 97ac96d..f736c23 100644
--- a/unsupported/Eigen/CXX11/src/Tensor/TensorExecutor.h
+++ b/unsupported/Eigen/CXX11/src/Tensor/TensorExecutor.h
@@ -76,13 +76,8 @@
  * Default strategy: the expression is evaluated sequentially with a single cpu
  * thread, without vectorization and block evaluation.
  */
-#if EIGEN_HAS_CXX11
 template <typename Expression, typename Device, bool Vectorizable,
           TiledEvaluation Tiling>
-#else
- template <typename Expression, typename Device, bool Vectorizable,
-          TiledEvaluation::TiledEvaluation Tiling>
-#endif
 class TensorExecutor {
  public:
   typedef typename Expression::Index StorageIndex;
@@ -107,7 +102,7 @@
  * available for ThreadPoolDevice (see definition below).
  */
 template <typename Expression, typename Device, typename DoneCallback,
-          bool Vectorizable, bool Tileable>
+          bool Vectorizable, TiledEvaluation Tiling>
 class TensorAsyncExecutor {};
 
 /**
@@ -549,9 +544,9 @@
 };
 
 template <typename Expression, typename DoneCallback, bool Vectorizable,
-          bool Tileable>
+          TiledEvaluation Tiling>
 class TensorAsyncExecutor<Expression, ThreadPoolDevice, DoneCallback,
-                          Vectorizable, Tileable> {
+                          Vectorizable, Tiling> {
  public:
   typedef typename Expression::Index StorageIndex;
   typedef TensorEvaluator<Expression, ThreadPoolDevice> Evaluator;
@@ -603,7 +598,7 @@
 
 template <typename Expression, typename DoneCallback, bool Vectorizable>
 class TensorAsyncExecutor<Expression, ThreadPoolDevice, DoneCallback,
-                          Vectorizable, /*Tileable*/ true> {
+                          Vectorizable, /*Tileable*/ TiledEvaluation::Legacy> {
  public:
   typedef typename traits<Expression>::Index StorageIndex;
   typedef typename traits<Expression>::Scalar Scalar;
@@ -612,7 +607,9 @@
   static const int NumDims = traits<Expression>::NumDimensions;
 
   typedef TensorEvaluator<Expression, ThreadPoolDevice> Evaluator;
-  typedef TensorBlockMapper<ScalarNoConst, StorageIndex, NumDims, Evaluator::Layout> BlockMapper;
+  typedef TensorBlockMapper<ScalarNoConst, StorageIndex, NumDims,
+                            Evaluator::Layout>
+      BlockMapper;
   typedef TensorExecutorTilingContext<BlockMapper> TilingContext;
 
   static EIGEN_STRONG_INLINE void runAsync(const Expression& expr,
@@ -629,7 +626,7 @@
       auto delete_ctx = [ctx]() { delete ctx; };
       internal::TensorAsyncExecutor<
           Expression, ThreadPoolDevice, decltype(delete_ctx), Vectorizable,
-          /*Tileable*/ false>::runAsync(expr, device, std::move(delete_ctx));
+          /*Tileable*/ TiledEvaluation::Off>::runAsync(expr, device, std::move(delete_ctx));
       return;
     }
 
@@ -640,22 +637,102 @@
       }
 
       ctx->tiling =
-          GetTensorExecutorTilingContext<Evaluator, BlockMapper,
-                                         Vectorizable>(device, ctx->evaluator);
+          GetTensorExecutorTilingContext<Evaluator, BlockMapper, Vectorizable>(
+              device, ctx->evaluator);
 
-      device.parallelForAsync(
-          ctx->tiling.block_mapper.total_block_count(), ctx->tiling.cost,
-          [ctx](StorageIndex firstIdx, StorageIndex lastIdx) {
-            ScalarNoConst* thread_buf =
-                ctx->tiling.template GetCurrentThreadBuffer<ScalarNoConst>(
-                    ctx->device);
-            for (StorageIndex i = firstIdx; i < lastIdx; ++i) {
-              auto block =
-                  ctx->tiling.block_mapper.GetBlockForIndex(i, thread_buf);
-              ctx->evaluator.evalBlock(&block);
-            }
-          },
-          [ctx]() { delete ctx; });
+      auto eval_block = [ctx](StorageIndex firstIdx, StorageIndex lastIdx) {
+        ScalarNoConst* thread_buf =
+            ctx->tiling.template GetCurrentThreadBuffer<ScalarNoConst>(
+                ctx->device);
+        for (StorageIndex i = firstIdx; i < lastIdx; ++i) {
+          auto block = ctx->tiling.block_mapper.GetBlockForIndex(i, thread_buf);
+          ctx->evaluator.evalBlock(&block);
+        }
+      };
+      device.parallelForAsync(ctx->tiling.block_mapper.total_block_count(),
+                              ctx->tiling.cost, eval_block,
+                              [ctx]() { delete ctx; });
+    };
+
+    ctx->evaluator.evalSubExprsIfNeededAsync(nullptr, on_eval_subexprs);
+  }
+
+ private:
+  struct TensorAsyncExecutorContext {
+    TensorAsyncExecutorContext(const Expression& expr,
+                               const ThreadPoolDevice& thread_pool,
+                               DoneCallback done)
+        : device(thread_pool),
+          evaluator(expr, thread_pool),
+          on_done(std::move(done)) {}
+
+    ~TensorAsyncExecutorContext() {
+      on_done();
+      device.deallocate(tiling.buffer);
+      evaluator.cleanup();
+    }
+
+    const ThreadPoolDevice& device;
+    Evaluator evaluator;
+    TilingContext tiling;
+
+   private:
+    DoneCallback on_done;
+  };
+};
+
+template <typename Expression, typename DoneCallback, bool Vectorizable>
+class TensorAsyncExecutor<Expression, ThreadPoolDevice, DoneCallback,
+                          Vectorizable, /*Tileable*/ TiledEvaluation::On> {
+ public:
+  typedef typename traits<Expression>::Index IndexType;
+  typedef typename traits<Expression>::Scalar Scalar;
+  typedef typename remove_const<Scalar>::type ScalarNoConst;
+
+  static const int NumDims = traits<Expression>::NumDimensions;
+
+  typedef TensorEvaluator<Expression, ThreadPoolDevice> Evaluator;
+  typedef TensorBlockMapper<ScalarNoConst, IndexType, NumDims,
+                            Evaluator::Layout>
+      BlockMapper;
+  typedef TensorExecutorTilingContext<BlockMapper> TilingContext;
+
+  typedef internal::TensorBlockDescriptor<NumDims, IndexType> TensorBlockDesc;
+  typedef internal::TensorBlockScratchAllocator<ThreadPoolDevice>
+      TensorBlockScratch;
+
+  static EIGEN_STRONG_INLINE void runAsync(const Expression& expr,
+                                           const ThreadPoolDevice& device,
+                                           DoneCallback done) {
+
+    TensorAsyncExecutorContext* const ctx =
+        new TensorAsyncExecutorContext(expr, device, std::move(done));
+
+    const auto on_eval_subexprs = [ctx](bool need_assign) -> void {
+      if (!need_assign) {
+        delete ctx;
+        return;
+      }
+
+      ctx->tiling =
+          internal::GetTensorExecutorTilingContext<Evaluator, BlockMapper,
+                                                   Vectorizable>(
+              ctx->device, ctx->evaluator, /*allocate_buffer=*/false);
+
+      auto eval_block = [ctx](IndexType firstBlockIdx, IndexType lastBlockIdx) {
+        TensorBlockScratch scratch(ctx->device);
+
+        for (IndexType block_idx = firstBlockIdx; block_idx < lastBlockIdx;
+             ++block_idx) {
+          auto block =
+              ctx->tiling.block_mapper.GetBlockForIndex(block_idx, nullptr);
+          TensorBlockDesc desc(block.first_coeff_index(), block.block_sizes());
+          ctx->evaluator.evalBlockV2(desc, scratch);
+          scratch.reset();
+        }
+      };
+      ctx->device.parallelForAsync(ctx->tiling.block_mapper.total_block_count(),
+                                   ctx->tiling.cost, eval_block, [ctx]() { delete ctx; });
     };
 
     ctx->evaluator.evalSubExprsIfNeededAsync(nullptr, on_eval_subexprs);
@@ -687,7 +764,6 @@
 
 #endif  // EIGEN_USE_THREADS
 
-
 // GPU: the evaluation of the expression is offloaded to a GPU.
 #if defined(EIGEN_USE_GPU)
 
diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorFFT.h b/unsupported/Eigen/CXX11/src/Tensor/TensorFFT.h
index 7be007d..55c7d68 100644
--- a/unsupported/Eigen/CXX11/src/Tensor/TensorFFT.h
+++ b/unsupported/Eigen/CXX11/src/Tensor/TensorFFT.h
@@ -10,10 +10,6 @@
 #ifndef EIGEN_CXX11_TENSOR_TENSOR_FFT_H
 #define EIGEN_CXX11_TENSOR_TENSOR_FFT_H
 
-// This code requires the ability to initialize arrays of constant
-// values directly inside a class.
-#if __cplusplus >= 201103L || EIGEN_COMP_MSVC >= 1900
-
 namespace Eigen {
 
 /** \class TensorFFT
@@ -671,7 +667,4 @@
 
 }  // end namespace Eigen
 
-#endif  // EIGEN_HAS_CONSTEXPR
-
-
 #endif  // EIGEN_CXX11_TENSOR_TENSOR_FFT_H
diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorForcedEval.h b/unsupported/Eigen/CXX11/src/Tensor/TensorForcedEval.h
index 7d12e78..e5b67a1 100644
--- a/unsupported/Eigen/CXX11/src/Tensor/TensorForcedEval.h
+++ b/unsupported/Eigen/CXX11/src/Tensor/TensorForcedEval.h
@@ -132,14 +132,6 @@
   EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(EvaluatorPointerType) {
     const Index numValues =  internal::array_prod(m_impl.dimensions());
     m_buffer = m_device.get((CoeffReturnType*)m_device.allocate_temp(numValues * sizeof(CoeffReturnType)));
-    #ifndef EIGEN_USE_SYCL
-    // Should initialize the memory in case we're dealing with non POD types.
-    if (NumTraits<CoeffReturnType>::RequireInitialization) {
-      for (Index i = 0; i < numValues; ++i) {
-        new(m_buffer+i) CoeffReturnType();
-      }
-    }
-    #endif
     typedef TensorEvalToOp< const typename internal::remove_const<ArgType>::type > EvalTo;
     EvalTo evalToTmp(m_device.get(m_buffer), m_op);
 
@@ -151,6 +143,29 @@
 
     return true;
   }
+
+#ifdef EIGEN_USE_THREADS
+  template <typename EvalSubExprsCallback>
+  EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC void evalSubExprsIfNeededAsync(
+      EvaluatorPointerType, EvalSubExprsCallback done) {
+    const Index numValues = internal::array_prod(m_impl.dimensions());
+    m_buffer = m_device.get((CoeffReturnType*)m_device.allocate_temp(
+        numValues * sizeof(CoeffReturnType)));
+    typedef TensorEvalToOp<const typename internal::remove_const<ArgType>::type>
+        EvalTo;
+    EvalTo evalToTmp(m_device.get(m_buffer), m_op);
+
+    auto on_done = std::bind([](EvalSubExprsCallback done) { done(true); },
+                             std::move(done));
+    internal::TensorAsyncExecutor<
+        const EvalTo, typename internal::remove_const<Device>::type,
+        decltype(on_done),
+        /*Vectorizable=*/internal::IsVectorizable<Device, const ArgType>::value,
+        /*Tiling=*/internal::IsTileable<Device, const ArgType>::value>::
+        runAsync(evalToTmp, m_device, std::move(on_done));
+  }
+#endif
+
   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void cleanup() {
     m_device.deallocate_temp(m_buffer);
     m_buffer = NULL;
diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorForwardDeclarations.h b/unsupported/Eigen/CXX11/src/Tensor/TensorForwardDeclarations.h
index 802cf21..0da2d9e 100644
--- a/unsupported/Eigen/CXX11/src/Tensor/TensorForwardDeclarations.h
+++ b/unsupported/Eigen/CXX11/src/Tensor/TensorForwardDeclarations.h
@@ -155,19 +155,11 @@
 };
 
 // Tiled evaluation strategy.
-#if !EIGEN_HAS_CXX11
-// To be able to use `TiledEvaluation::Off` in C++03 we need a namespace.
-// (Use of enumeration in a nested name specifier is a c++11 extension).
-namespace TiledEvaluation {
-#endif
 enum TiledEvaluation {
   Off = 0,    // tiled evaluation is not supported
   On = 1,     // still work in progress (see TensorBlockV2.h)
   Legacy = 2  // soon to be deprecated (see TensorBock.h)
 };
-#if !EIGEN_HAS_CXX11
-}   // namespace TiledEvaluation
-#endif
 
 template <typename Device, typename Expression>
 struct IsTileable {
@@ -182,37 +174,23 @@
       TensorEvaluator<Expression, Device>::BlockAccessV2 &&
       TensorEvaluator<Expression, Device>::PreferBlockAccess;
 
-#if EIGEN_HAS_CXX11
   static const TiledEvaluation value =
       BlockAccessV2
           ? TiledEvaluation::On
           : (BlockAccess ? TiledEvaluation::Legacy : TiledEvaluation::Off);
-#else
-  static const TiledEvaluation::TiledEvaluation value =
-      BlockAccessV2
-          ? TiledEvaluation::On
-          : (BlockAccess ? TiledEvaluation::Legacy : TiledEvaluation::Off);
-#endif
 };
 
-#if EIGEN_HAS_CXX11
 template <typename Expression, typename Device,
           bool Vectorizable      = IsVectorizable<Device, Expression>::value,
           TiledEvaluation Tiling = IsTileable<Device, Expression>::value>
 class TensorExecutor;
-#else
-template <typename Expression, typename Device,
-          bool Vectorizable = IsVectorizable<Device, Expression>::value,
-          TiledEvaluation::TiledEvaluation Tiling = IsTileable<Device, Expression>::value>
-class TensorExecutor;
-#endif
 
-// TODO(ezhulenev): Add TiledEvaluation support to async executor.
 template <typename Expression, typename Device, typename DoneCallback,
           bool Vectorizable = IsVectorizable<Device, Expression>::value,
-          bool Tileable     = IsTileable<Device, Expression>::BlockAccess>
+          TiledEvaluation Tiling = IsTileable<Device, Expression>::value>
 class TensorAsyncExecutor;
 
+
 }  // end namespace internal
 
 }  // end namespace Eigen
diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorMorphing.h b/unsupported/Eigen/CXX11/src/Tensor/TensorMorphing.h
index 606d49a..781f1d7 100644
--- a/unsupported/Eigen/CXX11/src/Tensor/TensorMorphing.h
+++ b/unsupported/Eigen/CXX11/src/Tensor/TensorMorphing.h
@@ -205,6 +205,14 @@
 
   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_dimensions; }
 
+#ifdef EIGEN_USE_THREADS
+  template <typename EvalSubExprsCallback>
+  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalSubExprsIfNeededAsync(
+      EvaluatorPointerType data, EvalSubExprsCallback done) {
+    m_impl.evalSubExprsIfNeededAsync(data, std::move(done));
+  }
+#endif
+
   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(EvaluatorPointerType data) {
     return m_impl.evalSubExprsIfNeeded(data);
   }
diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorReduction.h b/unsupported/Eigen/CXX11/src/Tensor/TensorReduction.h
index cee7ae6..d826cfb 100644
--- a/unsupported/Eigen/CXX11/src/Tensor/TensorReduction.h
+++ b/unsupported/Eigen/CXX11/src/Tensor/TensorReduction.h
@@ -445,7 +445,7 @@
  */
 template <typename Op, typename CoeffReturnType>
 struct ReductionReturnType {
-#if EIGEN_HAS_CXX11 && defined(EIGEN_USE_SYCL)
+#if defined(EIGEN_USE_SYCL)
   typedef typename remove_const<decltype(std::declval<Op>().initialize())>::type type;
 #else
   typedef typename remove_const<CoeffReturnType>::type type;
@@ -689,15 +689,14 @@
   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_dimensions; }
 
   EIGEN_STRONG_INLINE
-    #if !defined(EIGEN_HIPCC)
-    // Marking this as EIGEN_DEVICE_FUNC for HIPCC requires also doing the same for all the functions
-    // being called within here, which then leads to proliferation of EIGEN_DEVICE_FUNC markings, one
-    // of which will eventually result in an NVCC error
-    EIGEN_DEVICE_FUNC
-    #endif
-    bool evalSubExprsIfNeeded(EvaluatorPointerType data) {
-    m_impl.evalSubExprsIfNeeded(NULL);
-
+#if !defined(EIGEN_HIPCC)
+  // Marking this as EIGEN_DEVICE_FUNC for HIPCC requires also doing the same
+  // for all the functions being called within here, which then leads to
+  // proliferation of EIGEN_DEVICE_FUNC markings, one of which will eventually
+  // result in an NVCC error
+  EIGEN_DEVICE_FUNC
+#endif
+  bool evalSubExprsIfNeededCommon(EvaluatorPointerType data) {
     // Use the FullReducer if possible.
     if ((RunningFullReduction && RunningOnSycl) ||(RunningFullReduction &&
         internal::FullReducer<Self, Op, Device>::HasOptimizedImplementation &&
@@ -802,6 +801,34 @@
     return true;
   }
 
+#ifdef EIGEN_USE_THREADS
+  template <typename EvalSubExprsCallback>
+  EIGEN_STRONG_INLINE
+#if !defined(EIGEN_HIPCC)
+      EIGEN_DEVICE_FUNC
+#endif
+      void
+      evalSubExprsIfNeededAsync(EvaluatorPointerType data,
+                                EvalSubExprsCallback done) {
+    m_impl.evalSubExprsIfNeededAsync(NULL, [this, data, done](bool) {
+      done(evalSubExprsIfNeededCommon(data));
+    });
+  }
+#endif
+
+  EIGEN_STRONG_INLINE
+#if !defined(EIGEN_HIPCC)
+  // Marking this as EIGEN_DEVICE_FUNC for HIPCC requires also doing the same
+  // for all the functions being called within here, which then leads to
+  // proliferation of EIGEN_DEVICE_FUNC markings, one of which will eventually
+  // result in an NVCC error
+  EIGEN_DEVICE_FUNC
+#endif
+  bool evalSubExprsIfNeeded(EvaluatorPointerType data) {
+    m_impl.evalSubExprsIfNeeded(NULL);
+    return evalSubExprsIfNeededCommon(data);
+  }
+
   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void cleanup() {
     m_impl.cleanup();
     if (m_result) {
diff --git a/unsupported/Eigen/CXX11/src/util/CXX11Meta.h b/unsupported/Eigen/CXX11/src/util/CXX11Meta.h
index 6c95d0a..86f56b9 100644
--- a/unsupported/Eigen/CXX11/src/util/CXX11Meta.h
+++ b/unsupported/Eigen/CXX11/src/util/CXX11Meta.h
@@ -11,19 +11,102 @@
 #define EIGEN_CXX11META_H
 
 #include <vector>
-#include "EmulateArray.h"
-
-// Emulate the cxx11 functionality that we need if the compiler doesn't support it.
-// Visual studio 2015 doesn't advertise itself as cxx11 compliant, although it
-// supports enough of the standard for our needs
-#if __cplusplus > 199711L || EIGEN_COMP_MSVC >= 1900
+#include <array>
 
 #include "CXX11Workarounds.h"
 
 namespace Eigen {
 
+// Workaround for constructors used by legacy code calling Eigen::array.
+template <typename T, size_t N>
+class array : public std::array<T, N> {
+ public:
+
+  typedef std::array<T, N> Base;
+
+  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
+  array() : Base() {}
+
+  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
+  array(const T& v) : Base{v} {
+    EIGEN_STATIC_ASSERT(N == 1, YOU_MADE_A_PROGRAMMING_MISTAKE);
+  }
+  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
+  array(const T& v1, const T& v2) : Base{v1, v2} {
+    EIGEN_STATIC_ASSERT(N == 2, YOU_MADE_A_PROGRAMMING_MISTAKE);
+  }
+
+  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
+  array(const T& v1, const T& v2, const T& v3) : Base{v1, v2, v3} {
+    EIGEN_STATIC_ASSERT(N == 3, YOU_MADE_A_PROGRAMMING_MISTAKE);
+  }
+  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
+  array(const T& v1, const T& v2, const T& v3, const T& v4)
+      : Base{v1, v2, v3, v4} {
+    EIGEN_STATIC_ASSERT(N == 4, YOU_MADE_A_PROGRAMMING_MISTAKE);
+  }
+  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
+  array(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
+      : Base{v1, v2, v3, v4, v5} {
+    EIGEN_STATIC_ASSERT(N == 5, YOU_MADE_A_PROGRAMMING_MISTAKE);
+  }
+  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
+  array(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5,
+       const T& v6) : Base{v1, v2, v3, v4, v5, v6} {
+    EIGEN_STATIC_ASSERT(N == 6, YOU_MADE_A_PROGRAMMING_MISTAKE);
+  }
+  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
+  array(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5,
+        const T& v6, const T& v7)
+      : Base{v1, v2, v3, v4, v5, v6, v7} {
+    EIGEN_STATIC_ASSERT(N == 7, YOU_MADE_A_PROGRAMMING_MISTAKE);
+  }
+  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
+  array(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5,
+        const T& v6, const T& v7, const T& v8)
+      : Base{v1, v2, v3, v4, v5, v6, v7, v8} {
+    EIGEN_STATIC_ASSERT(N == 8, YOU_MADE_A_PROGRAMMING_MISTAKE);
+  }
+#if EIGEN_HAS_VARIADIC_TEMPLATES
+  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
+  array(std::initializer_list<T> l) {
+    eigen_assert(l.size() == N);
+    internal::smart_copy(l.begin(), l.end(), this->begin());
+  }
+#endif
+};
+
+template<typename T, std::size_t N> struct internal::array_size<const array<T,N> > {
+  enum { value = N };
+};
+template<typename T, std::size_t N> struct internal::array_size<array<T,N> > {
+  enum { value = N };
+};
+
 namespace internal {
 
+/* std::get is only constexpr in C++14, not yet in C++11
+ *     - libstdc++ from version 4.7 onwards has it nevertheless,
+ *                                          so use that
+ *     - libstdc++ older versions: use _M_instance directly
+ *     - libc++ all versions so far: use __elems_ directly
+ *     - all other libs: use std::get to be portable, but
+ *                       this may not be constexpr
+ */
+#if defined(__GLIBCXX__) && __GLIBCXX__ < 20120322
+#define STD_GET_ARR_HACK             a._M_instance[I_]
+#elif defined(_LIBCPP_VERSION)
+#define STD_GET_ARR_HACK             a.__elems_[I_]
+#else
+#define STD_GET_ARR_HACK             std::template get<I_, T, N>(a)
+#endif
+
+template<std::size_t I_, class T, std::size_t N> constexpr inline T&       array_get(std::array<T,N>&       a) { return (T&)       STD_GET_ARR_HACK; }
+template<std::size_t I_, class T, std::size_t N> constexpr inline T&&      array_get(std::array<T,N>&&      a) { return (T&&)      STD_GET_ARR_HACK; }
+template<std::size_t I_, class T, std::size_t N> constexpr inline T const& array_get(std::array<T,N> const& a) { return (T const&) STD_GET_ARR_HACK; }
+
+#undef STD_GET_ARR_HACK
+
 /** \internal
   * \file CXX11/util/CXX11Meta.h
   * This file contains generic metaprogramming classes which are not specifically related to Eigen.
@@ -537,10 +620,4 @@
 
 } // end namespace Eigen
 
-#else // Non C++11, fallback to emulation mode
-
-#include "EmulateCXX11Meta.h"
-
-#endif
-
 #endif // EIGEN_CXX11META_H
diff --git a/unsupported/Eigen/CXX11/src/util/EmulateArray.h b/unsupported/Eigen/CXX11/src/util/EmulateArray.h
deleted file mode 100644
index 834b20b..0000000
--- a/unsupported/Eigen/CXX11/src/util/EmulateArray.h
+++ /dev/null
@@ -1,261 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
-//
-// This Source Code Form is subject to the terms of the Mozilla
-// Public License v. 2.0. If a copy of the MPL was not distributed
-// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef EIGEN_EMULATE_ARRAY_H
-#define EIGEN_EMULATE_ARRAY_H
-
-
-
-// The array class is only available starting with cxx11. Emulate our own here
-// if needed. Beware, msvc still doesn't advertise itself as a c++11 compiler!
-// Moreover, CUDA doesn't support the STL containers, so we use our own instead.
-#if (__cplusplus <= 199711L && EIGEN_COMP_MSVC < 1900) || defined(EIGEN_GPUCC) || defined(EIGEN_AVOID_STL_ARRAY)
-
-namespace Eigen {
-template <typename T, size_t n> class array {
- public:
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE T& operator[] (size_t index) { eigen_internal_assert(index < size()); return values[index]; }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE const T& operator[] (size_t index) const { eigen_internal_assert(index < size()); return values[index]; }
-
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE T& at(size_t index) { eigen_assert(index < size()); return values[index]; }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE const T& at(size_t index) const { eigen_assert(index < size()); return values[index]; }
-
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE T& front() { return values[0]; }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE const T& front() const { return values[0]; }
-
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE T& back() { return values[n-1]; }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE const T& back() const { return values[n-1]; }
-
-  EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
-  static std::size_t size() { return n; }
-
-  T values[n];
-
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE array() { }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE array(const T& v) {
-    EIGEN_STATIC_ASSERT(n==1, YOU_MADE_A_PROGRAMMING_MISTAKE)
-    values[0] = v;
-  }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE array(const T& v1, const T& v2) {
-    EIGEN_STATIC_ASSERT(n==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
-    values[0] = v1;
-    values[1] = v2;
-  }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3) {
-    EIGEN_STATIC_ASSERT(n==3, YOU_MADE_A_PROGRAMMING_MISTAKE)
-    values[0] = v1;
-    values[1] = v2;
-    values[2] = v3;
-  }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3,
-                            const T& v4) {
-    EIGEN_STATIC_ASSERT(n==4, YOU_MADE_A_PROGRAMMING_MISTAKE)
-    values[0] = v1;
-    values[1] = v2;
-    values[2] = v3;
-    values[3] = v4;
-  }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4,
-                            const T& v5) {
-    EIGEN_STATIC_ASSERT(n==5, YOU_MADE_A_PROGRAMMING_MISTAKE)
-    values[0] = v1;
-    values[1] = v2;
-    values[2] = v3;
-    values[3] = v4;
-    values[4] = v5;
-  }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4,
-                            const T& v5, const T& v6) {
-    EIGEN_STATIC_ASSERT(n==6, YOU_MADE_A_PROGRAMMING_MISTAKE)
-    values[0] = v1;
-    values[1] = v2;
-    values[2] = v3;
-    values[3] = v4;
-    values[4] = v5;
-    values[5] = v6;
-  }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE array(const T& v1, const T& v2, const T& v3, const T& v4,
-                            const T& v5, const T& v6, const T& v7) {
-    EIGEN_STATIC_ASSERT(n==7, YOU_MADE_A_PROGRAMMING_MISTAKE)
-    values[0] = v1;
-    values[1] = v2;
-    values[2] = v3;
-    values[3] = v4;
-    values[4] = v5;
-    values[5] = v6;
-    values[6] = v7;
-  }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE array(
-      const T& v1, const T& v2, const T& v3, const T& v4,
-      const T& v5, const T& v6, const T& v7, const T& v8) {
-    EIGEN_STATIC_ASSERT(n==8, YOU_MADE_A_PROGRAMMING_MISTAKE)
-    values[0] = v1;
-    values[1] = v2;
-    values[2] = v3;
-    values[3] = v4;
-    values[4] = v5;
-    values[5] = v6;
-    values[6] = v7;
-    values[7] = v8;
-  }
-
-#if EIGEN_HAS_VARIADIC_TEMPLATES
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE array(std::initializer_list<T> l) {
-    eigen_assert(l.size() == n);
-    internal::smart_copy(l.begin(), l.end(), values);
-  }
-#endif
-};
-
-
-// Specialize array for zero size
-template <typename T> class array<T, 0> {
- public:
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE T& operator[] (size_t) {
-    eigen_assert(false && "Can't index a zero size array");
-    return dummy;
-  }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE const T& operator[] (size_t) const {
-    eigen_assert(false && "Can't index a zero size array");
-    return dummy;
-  }
-
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE T& front() {
-    eigen_assert(false && "Can't index a zero size array");
-    return dummy;
-  }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE const T& front() const {
-    eigen_assert(false && "Can't index a zero size array");
-    return dummy;
-  }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE T& back() {
-    eigen_assert(false && "Can't index a zero size array");
-    return dummy;
-  }
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE const T& back() const {
-    eigen_assert(false && "Can't index a zero size array");
-    return dummy;
-  }
-
-  static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE std::size_t size() { return 0; }
-
-  EIGEN_DEVICE_FUNC
-  EIGEN_STRONG_INLINE array() : dummy() { }
-
-#if EIGEN_HAS_VARIADIC_TEMPLATES
-  EIGEN_DEVICE_FUNC array(std::initializer_list<T> l) : dummy() {
-    EIGEN_UNUSED_VARIABLE(l);
-    eigen_assert(l.size() == 0);
-  }
-#endif
-
- private:
-  T dummy;
-};
-
-// Comparison operator
-// Todo: implement !=, <, <=, >,  and >=
-template<class T, std::size_t N>
-EIGEN_DEVICE_FUNC bool operator==(const array<T,N>& lhs, const array<T,N>& rhs) {
-  for (std::size_t i = 0; i < N; ++i) {
-    if (lhs[i] != rhs[i]) {
-      return false;
-    }
-  }
-  return true;
-}
-
-
-namespace internal {
-template<std::size_t I_, class T, std::size_t N>
-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& array_get(array<T,N>& a) {
-  return a[I_];
-}
-template<std::size_t I_, class T, std::size_t N>
-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& array_get(const array<T,N>& a) {
-  return a[I_];
-}
-
-template<class T, std::size_t N> struct array_size<array<T,N> > {
-  enum { value = N };
-};
-template<class T, std::size_t N> struct array_size<array<T,N>& > {
-  enum { value = N };
-};
-template<class T, std::size_t N> struct array_size<const array<T,N> > {
-  enum { value = N };
-};
-template<class T, std::size_t N> struct array_size<const array<T,N>& > {
-  enum { value = N };
-};
-
-}  // end namespace internal
-}  // end namespace Eigen
-
-#else
-
-// The compiler supports c++11, and we're not targeting cuda: use std::array as Eigen::array
-#include <array>
-namespace Eigen {
-
-template <typename T, std::size_t N> using array = std::array<T, N>;
-
-namespace internal {
-/* std::get is only constexpr in C++14, not yet in C++11
- *     - libstdc++ from version 4.7 onwards has it nevertheless,
- *                                          so use that
- *     - libstdc++ older versions: use _M_instance directly
- *     - libc++ all versions so far: use __elems_ directly
- *     - all other libs: use std::get to be portable, but
- *                       this may not be constexpr
- */
-#if defined(__GLIBCXX__) && __GLIBCXX__ < 20120322
-#define STD_GET_ARR_HACK             a._M_instance[I_]
-#elif defined(_LIBCPP_VERSION)
-#define STD_GET_ARR_HACK             a.__elems_[I_]
-#else
-#define STD_GET_ARR_HACK             std::template get<I_, T, N>(a)
-#endif
-
-template<std::size_t I_, class T, std::size_t N> constexpr inline T&       array_get(std::array<T,N>&       a) { return (T&)       STD_GET_ARR_HACK; }
-template<std::size_t I_, class T, std::size_t N> constexpr inline T&&      array_get(std::array<T,N>&&      a) { return (T&&)      STD_GET_ARR_HACK; }
-template<std::size_t I_, class T, std::size_t N> constexpr inline T const& array_get(std::array<T,N> const& a) { return (T const&) STD_GET_ARR_HACK; }
-
-#undef STD_GET_ARR_HACK
-
-}  // end namespace internal
-}  // end namespace Eigen
-
-#endif
-
-#endif  // EIGEN_EMULATE_ARRAY_H
diff --git a/unsupported/Eigen/CXX11/src/util/EmulateCXX11Meta.h b/unsupported/Eigen/CXX11/src/util/EmulateCXX11Meta.h
deleted file mode 100644
index d02d86f..0000000
--- a/unsupported/Eigen/CXX11/src/util/EmulateCXX11Meta.h
+++ /dev/null
@@ -1,311 +0,0 @@
-// This file is part of Eigen, a lightweight C++ template library
-// for linear algebra.
-//
-// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
-//
-// This Source Code Form is subject to the terms of the Mozilla
-// Public License v. 2.0. If a copy of the MPL was not distributed
-// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef EIGEN_EMULATE_CXX11_META_H
-#define EIGEN_EMULATE_CXX11_META_H
-
-
-
-namespace Eigen {
-
-namespace internal {
-
-/** \internal
-  * \file CXX11/util/EmulateCXX11Meta.h
-  * This file emulates a subset of the functionality provided by CXXMeta.h for
-  * compilers that don't yet support cxx11 such as nvcc.
-  */
-
-struct empty_list { static const std::size_t count = 0; };
-
-template<typename T, typename Tail=empty_list> struct type_list {
-  typedef T HeadType;
-  typedef Tail TailType;
-  static const T head;
-  static const Tail tail;
-  static const std::size_t count = 1 + Tail::count;
-};
-
-struct null_type { };
-
-template<typename T1 = null_type, typename T2 = null_type, typename T3 = null_type,
-         typename T4 = null_type, typename T5 = null_type, typename T6 = null_type,
-         typename T7 = null_type, typename T8 = null_type>
-struct make_type_list {
-  typedef typename make_type_list<T2, T3, T4, T5, T6, T7, T8>::type tailresult;
-
-  typedef type_list<T1, tailresult> type;
-};
-
-template<> struct make_type_list<> {
-  typedef empty_list type;
-};
-
-
-template <std::size_t index, class TList> struct get_type;
-
-template <class Head, class Tail>
-struct get_type<0, type_list<Head, Tail> >
-{
-  typedef Head type;
-};
-
-template <std::size_t i, class Head, class Tail>
-struct get_type<i, type_list<Head, Tail> >
-{
-  typedef typename get_type<i-1, Tail>::type type;
-};
-
-
-/* numeric list */
-template <typename T, T n>
-struct type2val {
-  typedef T type;
-  static const T value = n;
-};
-
-
-template<typename T, size_t n, T V> struct gen_numeric_list_repeated;
-
-template<typename T, T V> struct gen_numeric_list_repeated<T, 1, V> {
-  typedef typename make_type_list<type2val<T, V> >::type type;
-};
-
-template<typename T, T V> struct gen_numeric_list_repeated<T, 2, V> {
-  typedef typename make_type_list<type2val<T, V>, type2val<T, V> >::type type;
-};
-
-template<typename T, T V> struct gen_numeric_list_repeated<T, 3, V> {
-  typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V> >::type type;
-};
-
-template<typename T, T V> struct gen_numeric_list_repeated<T, 4, V> {
-  typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>, type2val<T, V> >::type type;
-};
-
-template<typename T, T V> struct gen_numeric_list_repeated<T, 5, V> {
-  typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>, type2val<T, V>, type2val<T, V> >::type type;
-};
-
-template<typename T, T V> struct gen_numeric_list_repeated<T, 6, V> {
-  typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>,
-                                  type2val<T, V>, type2val<T, V>, type2val<T, V> >::type type;
-};
-
-template<typename T, T V> struct gen_numeric_list_repeated<T, 7, V> {
-  typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>,
-                                  type2val<T, V>, type2val<T, V>, type2val<T, V>,
-                                  type2val<T, V> >::type type;
-};
-
-template<typename T, T V> struct gen_numeric_list_repeated<T, 8, V> {
-  typedef typename make_type_list<type2val<T, V>, type2val<T, V>, type2val<T, V>,
-                                  type2val<T, V>, type2val<T, V>, type2val<T, V>,
-                                  type2val<T, V>, type2val<T, V> >::type type;
-};
-
-
-template <std::size_t index, class NList> struct get;
-
-template <std::size_t i>
-struct get<i, empty_list>
-{
-  get() { eigen_assert(false && "index overflow"); }
-  typedef void type;
-  static const char value = '\0';
-};
-
-template <std::size_t i, class Head>
-struct get<i, type_list<Head, empty_list> >
-{
-  get() { eigen_assert(false && "index overflow"); }
-  typedef void type;
-  static const char value = '\0';
-};
-
-template <class Head>
-struct get<0, type_list<Head, empty_list> >
-{
-  typedef typename Head::type type;
-  static const type value = Head::value;
-};
-
-template <class Head, class Tail>
-struct get<0, type_list<Head, Tail> >
-{
-  typedef typename Head::type type;
-  static const type value = Head::value;
-};
-
-template <std::size_t i, class Head, class Tail>
-struct get<i, type_list<Head, Tail> >
-{
-  typedef typename Tail::HeadType::type type;
-  static const type value = get<i-1, Tail>::value;
-};
-
-
-template <class NList> struct arg_prod {
-  static const typename NList::HeadType::type value = get<0, NList>::value * arg_prod<typename NList::TailType>::value;
-};
-template <> struct arg_prod<empty_list> {
-  static const int value = 1;
-};
-
-
-template<int n, typename t>
-array<t, n> repeat(t v) {
-  array<t, n> array;
-  array.fill(v);
-  return array;
-}
-
-template<std::size_t I_, class Head, class Tail>
-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename Head::type array_get(type_list<Head, Tail>&) {
-  return get<I_, type_list<Head, Tail> >::value;
-}
-template<std::size_t I_, class Head, class Tail>
-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename Head::type array_get(const type_list<Head, Tail>&) {
-  return get<I_, type_list<Head, Tail> >::value;
-}
-
-template <class NList>
-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename NList::HeadType::type array_prod(const NList&) {
-  return arg_prod<NList>::value;
-}
-
-template<typename t, std::size_t n>
-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE t array_prod(const array<t, n>& a) {
-  t prod = 1;
-  for (size_t i = 0; i < n; ++i) { prod *= a[i]; }
-  return prod;
-}
-template<typename t>
-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE t array_prod(const array<t, 0>& /*a*/) {
-  return 1;
-}
-
-template<typename t>
-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE t array_prod(const std::vector<t>& a) {
-  eigen_assert(a.size() > 0);
-  t prod = 1;
-  for (size_t i = 0; i < a.size(); ++i) { prod *= a[i]; }
-  return prod;
-}
-
-
-template<std::size_t I_, class T>
-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T& array_get(std::vector<T>& a) {
-  return a[I_];
-}
-template<std::size_t I_, class T>
-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T& array_get(const std::vector<T>& a) {
-  return a[I_];
-}
-
-struct sum_op {
-  template<typename A, typename B> static inline bool run(A a, B b) { return a + b; }
-};
-struct product_op {
-  template<typename A, typename B> static inline bool run(A a, B b) { return a * b; }
-};
-
-struct logical_and_op {
-  template<typename A, typename B> static inline bool run(A a, B b) { return a && b; }
-};
-struct logical_or_op {
-  template<typename A, typename B> static inline bool run(A a, B b) { return a || b; }
-};
-
-struct equal_op {
-  template<typename A, typename B> static inline bool run(A a, B b) { return a == b; }
-};
-struct not_equal_op {
-  template<typename A, typename B> static inline bool run(A a, B b) { return a != b; }
-};
-struct lesser_op {
-  template<typename A, typename B> static inline bool run(A a, B b) { return a < b; }
-};
-struct lesser_equal_op {
-  template<typename A, typename B> static inline bool run(A a, B b) { return a <= b; }
-};
-
-struct greater_op {
-  template<typename A, typename B> static inline bool run(A a, B b) { return a > b; }
-};
-struct greater_equal_op {
-  template<typename A, typename B> static inline bool run(A a, B b) { return a >= b; }
-};
-
-struct not_op {
-  template<typename A> static inline bool run(A a) { return !a; }
-};
-struct negation_op {
-  template<typename A> static inline bool run(A a) { return -a; }
-};
-struct greater_equal_zero_op {
-  template<typename A> static inline bool run(A a) { return a >= 0; }
-};
-
-
-template<typename Reducer, typename Op, typename A, std::size_t N>
-struct ArrayApplyAndReduce {
-  static inline bool run(const array<A, N>& a) {
-    EIGEN_STATIC_ASSERT(N >= 2, YOU_MADE_A_PROGRAMMING_MISTAKE);
-    bool result = Reducer::run(Op::run(a[0]), Op::run(a[1]));
-    for (size_t i = 2; i < N; ++i) {
-      result = Reducer::run(result, Op::run(a[i]));
-    }
-    return result;
-  }
-};
-
-template<typename Reducer, typename Op, typename A>
-struct ArrayApplyAndReduce<Reducer, Op, A, 1>  {
-  static inline bool run(const array<A, 1>& a) {
-    return Op::run(a[0]);
-  }
-};
-
-template<typename Reducer, typename Op, typename A, std::size_t N>
-inline bool array_apply_and_reduce(const array<A, N>& a) {
-  return ArrayApplyAndReduce<Reducer, Op, A, N>::run(a);
-}
-
-template<typename Reducer, typename Op, typename A, typename B, std::size_t N>
-struct ArrayZipAndReduce {
-  static inline bool run(const array<A, N>& a, const array<B, N>& b) {
-    EIGEN_STATIC_ASSERT(N >= 2, YOU_MADE_A_PROGRAMMING_MISTAKE);
-    bool result = Reducer::run(Op::run(a[0], b[0]), Op::run(a[1], b[1]));
-    for (size_t i = 2; i < N; ++i) {
-      result = Reducer::run(result, Op::run(a[i], b[i]));
-    }
-    return result;
-  }
-};
-
-template<typename Reducer, typename Op, typename A, typename B>
-struct ArrayZipAndReduce<Reducer, Op, A, B, 1> {
-  static inline bool run(const array<A, 1>& a, const array<B, 1>& b) {
-    return Op::run(a[0], b[0]);
-  }
-};
-
-template<typename Reducer, typename Op, typename A, typename B, std::size_t N>
-inline bool array_zip_and_reduce(const array<A, N>& a, const array<B, N>& b) {
-  return ArrayZipAndReduce<Reducer, Op, A, B, N>::run(a, b);
-}
-
-}  // end namespace internal
-
-}  // end namespace Eigen
-
-
-
-#endif  // EIGEN_EMULATE_CXX11_META_H
diff --git a/unsupported/test/CMakeLists.txt b/unsupported/test/CMakeLists.txt
index ffc8af4..4017476 100644
--- a/unsupported/test/CMakeLists.txt
+++ b/unsupported/test/CMakeLists.txt
@@ -109,31 +109,6 @@
 ei_add_test(bessel_functions)
 ei_add_test(special_functions)
 
-# TODO: The following test names are prefixed with the cxx11 string, since historically
-# the tests depended on c++11. This isn't the case anymore so we ought to rename them.
-# FIXME: Old versions of MSVC fail to compile this code, so we just disable these tests
-# when using visual studio. We should make the check more strict to enable the tests for
-# newer versions of MSVC.
-if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
-ei_add_test(cxx11_tensor_dimension)
-ei_add_test(cxx11_tensor_map)
-ei_add_test(cxx11_tensor_assign)
-ei_add_test(cxx11_tensor_block_access)
-ei_add_test(cxx11_tensor_broadcasting)
-ei_add_test(cxx11_tensor_comparisons)
-ei_add_test(cxx11_tensor_forced_eval)
-ei_add_test(cxx11_tensor_math)
-ei_add_test(cxx11_tensor_const)
-ei_add_test(cxx11_tensor_intdiv)
-ei_add_test(cxx11_tensor_casts)
-ei_add_test(cxx11_tensor_empty)
-ei_add_test(cxx11_tensor_sugar)
-ei_add_test(cxx11_tensor_roundings)
-ei_add_test(cxx11_tensor_layout_swap)
-ei_add_test(cxx11_tensor_io)
-ei_add_test(cxx11_maxsizevector)
-endif()
-
 if(EIGEN_TEST_CXX11)
   if(EIGEN_TEST_SYCL)
     if(EIGEN_SYCL_TRISYCL)
@@ -177,46 +152,63 @@
   ei_add_test(cxx11_non_blocking_thread_pool "-pthread" "${CMAKE_THREAD_LIBS_INIT}")
 
   ei_add_test(cxx11_meta)
-  ei_add_test(cxx11_tensor_simple)
-#  ei_add_test(cxx11_tensor_symmetry)
-  ei_add_test(cxx11_tensor_index_list)
-  ei_add_test(cxx11_tensor_mixed_indices)
-  ei_add_test(cxx11_tensor_contraction)
-  ei_add_test(cxx11_tensor_convolution)
-  ei_add_test(cxx11_tensor_expr)
-  ei_add_test(cxx11_tensor_fixed_size)
-  ei_add_test(cxx11_tensor_of_const_values)
-  ei_add_test(cxx11_tensor_of_complex)
-  ei_add_test(cxx11_tensor_of_strings)
-  ei_add_test(cxx11_tensor_lvalue)
-  ei_add_test(cxx11_tensor_chipping)
+  ei_add_test(cxx11_maxsizevector)
+  ei_add_test(cxx11_tensor_argmax)
+  ei_add_test(cxx11_tensor_assign)
+  ei_add_test(cxx11_tensor_block_access)
   ei_add_test(cxx11_tensor_block_eval)
   ei_add_test(cxx11_tensor_block_io)
+  ei_add_test(cxx11_tensor_broadcasting)
+  ei_add_test(cxx11_tensor_casts)
+  ei_add_test(cxx11_tensor_chipping)
+  ei_add_test(cxx11_tensor_comparisons)
   ei_add_test(cxx11_tensor_concatenation)
+  ei_add_test(cxx11_tensor_const)
+  ei_add_test(cxx11_tensor_contraction)
+  ei_add_test(cxx11_tensor_convolution)
+  ei_add_test(cxx11_tensor_custom_index)
+  ei_add_test(cxx11_tensor_custom_op)
+  ei_add_test(cxx11_tensor_dimension)
+  ei_add_test(cxx11_tensor_empty)
+  ei_add_test(cxx11_tensor_executor "-pthread" "${CMAKE_THREAD_LIBS_INIT}")
+  ei_add_test(cxx11_tensor_expr)
+  ei_add_test(cxx11_tensor_fft)
+  ei_add_test(cxx11_tensor_fixed_size)
+  ei_add_test(cxx11_tensor_forced_eval)
+  ei_add_test(cxx11_tensor_generator)
+  ei_add_test(cxx11_tensor_ifft)
+  ei_add_test(cxx11_tensor_image_patch)
+  ei_add_test(cxx11_tensor_index_list)
   ei_add_test(cxx11_tensor_inflation)
+  ei_add_test(cxx11_tensor_intdiv)
+  ei_add_test(cxx11_tensor_io)
+  ei_add_test(cxx11_tensor_layout_swap)
+  ei_add_test(cxx11_tensor_lvalue)
+  ei_add_test(cxx11_tensor_map)
+  ei_add_test(cxx11_tensor_math)
+  ei_add_test(cxx11_tensor_mixed_indices)
   ei_add_test(cxx11_tensor_morphing)
+  ei_add_test(cxx11_tensor_move)
+  ei_add_test(cxx11_tensor_notification "-pthread" "${CMAKE_THREAD_LIBS_INIT}")
+  ei_add_test(cxx11_tensor_of_complex)
+  ei_add_test(cxx11_tensor_of_const_values)
+  ei_add_test(cxx11_tensor_of_strings)
   ei_add_test(cxx11_tensor_padding)
   ei_add_test(cxx11_tensor_patch)
-  ei_add_test(cxx11_tensor_image_patch)
-  ei_add_test(cxx11_tensor_volume_patch)
+  ei_add_test(cxx11_tensor_random)
   ei_add_test(cxx11_tensor_reduction)
-  ei_add_test(cxx11_tensor_argmax)
+  ei_add_test(cxx11_tensor_ref)
+  ei_add_test(cxx11_tensor_roundings)
+  ei_add_test(cxx11_tensor_scan)
   ei_add_test(cxx11_tensor_shuffling)
+  ei_add_test(cxx11_tensor_simple)
   ei_add_test(cxx11_tensor_striding)
-  ei_add_test(cxx11_tensor_notification "-pthread" "${CMAKE_THREAD_LIBS_INIT}")
+  ei_add_test(cxx11_tensor_sugar)
   ei_add_test(cxx11_tensor_thread_local "-pthread" "${CMAKE_THREAD_LIBS_INIT}")
   ei_add_test(cxx11_tensor_thread_pool "-pthread" "${CMAKE_THREAD_LIBS_INIT}")
-  ei_add_test(cxx11_tensor_executor "-pthread" "${CMAKE_THREAD_LIBS_INIT}")
-  ei_add_test(cxx11_tensor_ref)
-  ei_add_test(cxx11_tensor_random)
-  ei_add_test(cxx11_tensor_generator)
-  ei_add_test(cxx11_tensor_custom_op)
-  ei_add_test(cxx11_tensor_custom_index)
-  ei_add_test(cxx11_tensor_fft)
-  ei_add_test(cxx11_tensor_ifft)
-  ei_add_test(cxx11_tensor_scan)
   ei_add_test(cxx11_tensor_trace)
-  ei_add_test(cxx11_tensor_move)
+  ei_add_test(cxx11_tensor_volume_patch)
+#  ei_add_test(cxx11_tensor_symmetry)
 if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8" AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
   # This test requires __uint128_t which is only available on 64bit systems
   ei_add_test(cxx11_tensor_uint128)
diff --git a/unsupported/test/cxx11_tensor_executor.cpp b/unsupported/test/cxx11_tensor_executor.cpp
index dd68ddf..0e70e17 100644
--- a/unsupported/test/cxx11_tensor_executor.cpp
+++ b/unsupported/test/cxx11_tensor_executor.cpp
@@ -604,11 +604,10 @@
   Eigen::Barrier done(1);
   auto on_done = [&done]() { done.Notify(); };
 
-  static const bool TilingOn = Tiling == TiledEvaluation::Off ? false : true;
   using Assign = TensorAssignOp<decltype(dst), const decltype(expr)>;
   using DoneCallback = decltype(on_done);
   using Executor = internal::TensorAsyncExecutor<const Assign, Device, DoneCallback,
-                                                 Vectorizable, TilingOn>;
+                                                 Vectorizable, Tiling>;
 
   Executor::runAsync(Assign(dst, expr), d, on_done);
   done.Wait();
@@ -641,11 +640,10 @@
   Eigen::Barrier done(1);
   auto on_done = [&done]() { done.Notify(); };
 
-  static const bool TilingOn = Tiling == TiledEvaluation::Off ? false : true;
   using Assign = TensorAssignOp<decltype(dst), const decltype(expr)>;
   using DoneCallback = decltype(on_done);
   using Executor = internal::TensorAsyncExecutor<const Assign, Device, DoneCallback,
-                                                 Vectorizable, TilingOn>;
+                                                 Vectorizable, Tiling>;
 
   Executor::runAsync(Assign(dst, expr), d, on_done);
   done.Wait();