diff --git a/gnu/local.mk b/gnu/local.mk
index 060470cfea..1f8f936917 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1015,8 +1015,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/ecl-16-libffi.patch			\
   %D%/packages/patches/efibootmgr-remove-extra-decl.patch	\
   %D%/packages/patches/efivar-211.patch			\
-  %D%/packages/patches/eigen-remove-openmp-error-counting.patch	\
-  %D%/packages/patches/eigen-stabilise-sparseqr-test.patch	\
+  %D%/packages/patches/eigen-fix-strict-aliasing-bug.patch	\
   %D%/packages/patches/einstein-build.patch			\
   %D%/packages/patches/elfutils-tests-ptrace.patch		\
   %D%/packages/patches/elixir-path-length.patch			\
diff --git a/gnu/packages/algebra.scm b/gnu/packages/algebra.scm
index 6823531cc0..fa0e09276d 100644
--- a/gnu/packages/algebra.scm
+++ b/gnu/packages/algebra.scm
@@ -986,20 +986,17 @@ (define-public ginac
 (define-public eigen
   (package
     (name "eigen")
-    (version "3.3.8")
+    (version "3.4.0")
     (source (origin
-              (method url-fetch)
-              (uri (list
-                     (string-append "https://bitbucket.org/eigen/eigen/get/"
-                                    version ".tar.bz2")
-                     (string-append "mirror://debian/pool/main/e/eigen3/eigen3_"
-                                    version ".orig.tar.bz2")))
+              (method git-fetch)
+              (uri (git-reference
+                    (url "https://gitlab.com/libeigen/eigen.git")
+                    (commit version)))
               (sha256
                (base32
-                "1vxrsncfnkyq6gwxpsannpryp12mk7lc8f42ybvz3saf7icwc582"))
-              (file-name (string-append name "-" version ".tar.bz2"))
-              (patches (search-patches "eigen-remove-openmp-error-counting.patch"
-                                       "eigen-stabilise-sparseqr-test.patch"))
+                "0k1c4qnymwwvm68rv6s0cyk08xbw65ixvwqccsh36c2axcqk3znp"))
+              (file-name (git-file-name name version))
+              (patches (search-patches "eigen-fix-strict-aliasing-bug.patch"))
               (modules '((guix build utils)))
               (snippet
                ;; There are 3 test failures in the "unsupported" directory,
diff --git a/gnu/packages/patches/eigen-fix-strict-aliasing-bug.patch b/gnu/packages/patches/eigen-fix-strict-aliasing-bug.patch
new file mode 100644
index 0000000000..139d633c44
--- /dev/null
+++ b/gnu/packages/patches/eigen-fix-strict-aliasing-bug.patch
@@ -0,0 +1,73 @@
+From f046e326d9e30772725d8fb26dc33328e418d9d3 Mon Sep 17 00:00:00 2001
+From: Antonio Sanchez <cantonios@google.com>
+Date: Fri, 17 Sep 2021 12:49:01 -0700
+Subject: [PATCH] Fix strict aliasing bug causing product_small failure.
+
+Packet loading is skipped due to aliasing violation, leading to nullopt matrix
+multiplication.
+
+Fixes #2327.
+
+
+(cherry picked from commit 3c724c44cff3f9e2e9e35351abff0b5c022b320d)
+---
+ Eigen/src/Core/arch/AVX/Complex.h    |  4 +++-
+ Eigen/src/Core/arch/AVX512/Complex.h |  4 +++-
+ Eigen/src/Core/arch/SSE/Complex.h    | 11 +++--------
+ 3 files changed, 9 insertions(+), 10 deletions(-)
+
+diff --git a/Eigen/src/Core/arch/AVX/Complex.h b/Eigen/src/Core/arch/AVX/Complex.h
+index ab7bd6c65..e9096c0a1 100644
+--- a/Eigen/src/Core/arch/AVX/Complex.h
++++ b/Eigen/src/Core/arch/AVX/Complex.h
+@@ -99,7 +99,9 @@ template<> EIGEN_STRONG_INLINE Packet4cf ploadu<Packet4cf>(const std::complex<fl
+ 
+ template<> EIGEN_STRONG_INLINE Packet4cf pset1<Packet4cf>(const std::complex<float>& from)
+ {
+-  return Packet4cf(_mm256_castpd_ps(_mm256_broadcast_sd((const double*)(const void*)&from)));
++  const float re = std::real(from);
++  const float im = std::imag(from);
++  return Packet4cf(_mm256_set_ps(im, re, im, re, im, re, im, re));
+ }
+ 
+ template<> EIGEN_STRONG_INLINE Packet4cf ploaddup<Packet4cf>(const std::complex<float>* from)
+diff --git a/Eigen/src/Core/arch/AVX512/Complex.h b/Eigen/src/Core/arch/AVX512/Complex.h
+index 49c72b3f1..074253859 100644
+--- a/Eigen/src/Core/arch/AVX512/Complex.h
++++ b/Eigen/src/Core/arch/AVX512/Complex.h
+@@ -97,7 +97,9 @@ template<> EIGEN_STRONG_INLINE Packet8cf ploadu<Packet8cf>(const std::complex<fl
+ 
+ template<> EIGEN_STRONG_INLINE Packet8cf pset1<Packet8cf>(const std::complex<float>& from)
+ {
+-  return Packet8cf(_mm512_castpd_ps(pload1<Packet8d>((const double*)(const void*)&from)));
++  const float re = std::real(from);
++  const float im = std::imag(from);
++  return Packet8cf(_mm512_set_ps(im, re, im, re, im, re, im, re, im, re, im, re, im, re, im, re));
+ }
+ 
+ template<> EIGEN_STRONG_INLINE Packet8cf ploaddup<Packet8cf>(const std::complex<float>* from)
+diff --git a/Eigen/src/Core/arch/SSE/Complex.h b/Eigen/src/Core/arch/SSE/Complex.h
+index 8fe22da46..215bfd7bb 100644
+--- a/Eigen/src/Core/arch/SSE/Complex.h
++++ b/Eigen/src/Core/arch/SSE/Complex.h
+@@ -106,14 +106,9 @@ template<> EIGEN_STRONG_INLINE Packet2cf ploadu<Packet2cf>(const std::complex<fl
+ 
+ template<> EIGEN_STRONG_INLINE Packet2cf pset1<Packet2cf>(const std::complex<float>&  from)
+ {
+-  Packet2cf res;
+-#ifdef EIGEN_VECTORIZE_SSE3
+-  res.v = _mm_castpd_ps(_mm_loaddup_pd(reinterpret_cast<double const*>(&from)));
+-#else
+-  res.v = _mm_castpd_ps(_mm_load_sd(reinterpret_cast<double const*>(&from)));
+-  res.v = _mm_movelh_ps(res.v, res.v);
+-#endif
+-  return res;
++  const float re = std::real(from);
++  const float im = std::imag(from);
++  return Packet2cf(_mm_set_ps(im, re, im, re));
+ }
+ 
+ template<> EIGEN_STRONG_INLINE Packet2cf ploaddup<Packet2cf>(const std::complex<float>* from) { return pset1<Packet2cf>(*from); }
+-- 
+2.37.0
+
diff --git a/gnu/packages/patches/eigen-remove-openmp-error-counting.patch b/gnu/packages/patches/eigen-remove-openmp-error-counting.patch
deleted file mode 100644
index 556474e8b3..0000000000
--- a/gnu/packages/patches/eigen-remove-openmp-error-counting.patch
+++ /dev/null
@@ -1,64 +0,0 @@
-From ef3cc72cb65e2d500459c178c63e349bacfa834f Mon Sep 17 00:00:00 2001
-From: Luke Peterson <hazelnusse@gmail.com>
-Date: Thu, 8 Oct 2020 12:16:53 -0700
-Subject: [PATCH] Remove error counting in OpenMP parallelize_gemm
-
-This resolves a compilation error associated with
-Eigen::eigen_assert_exception. It also eliminates the counting of
-exceptions that may occur in the OpenMP parallel section. If an
-unhandled exception occurs in this section, the behavior is non-conforming
-according to the OpenMP specification.
----
- Eigen/src/Core/products/Parallelizer.h | 14 +++++---------
- test/CMakeLists.txt                    |  2 +-
- 2 files changed, 6 insertions(+), 10 deletions(-)
-
-diff --git a/Eigen/src/Core/products/Parallelizer.h b/Eigen/src/Core/products/Parallelizer.h
-index 67b2442b5..a3cc05b77 100644
---- a/Eigen/src/Core/products/Parallelizer.h
-+++ b/Eigen/src/Core/products/Parallelizer.h
-@@ -132,8 +132,7 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, Index depth,
- 
-   ei_declare_aligned_stack_constructed_variable(GemmParallelInfo<Index>,info,threads,0);
- 
--  int errorCount = 0;
--  #pragma omp parallel num_threads(threads) reduction(+: errorCount)
-+  #pragma omp parallel num_threads(threads)
-   {
-     Index i = omp_get_thread_num();
-     // Note that the actual number of threads might be lower than the number of request ones.
-@@ -152,14 +151,11 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, Index depth,
-     info[i].lhs_start = r0;
-     info[i].lhs_length = actualBlockRows;
- 
--    EIGEN_TRY {
--      if(transpose) func(c0, actualBlockCols, 0, rows, info);
--      else          func(0, rows, c0, actualBlockCols, info);
--    } EIGEN_CATCH(...) {
--      ++errorCount;
--    }
-+    if(transpose)
-+      func(c0, actualBlockCols, 0, rows, info);
-+    else
-+      func(0, rows, c0, actualBlockCols, info);
-   }
--  if (errorCount) EIGEN_THROW_X(Eigen::eigen_assert_exception());
- #endif
- }
- 
-diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
-index 0747aa6cb..b02577780 100644
---- a/test/CMakeLists.txt
-+++ b/test/CMakeLists.txt
-@@ -163,7 +163,7 @@ ei_add_test(constructor)
- ei_add_test(linearstructure)
- ei_add_test(integer_types)
- ei_add_test(unalignedcount)
--if(NOT EIGEN_TEST_NO_EXCEPTIONS)
-+if(NOT EIGEN_TEST_NO_EXCEPTIONS AND NOT EIGEN_TEST_OPENMP)
-   ei_add_test(exceptions)
- endif()
- ei_add_test(redux)
--- 
-GitLab
-
diff --git a/gnu/packages/patches/eigen-stabilise-sparseqr-test.patch b/gnu/packages/patches/eigen-stabilise-sparseqr-test.patch
deleted file mode 100644
index b95b46077a..0000000000
--- a/gnu/packages/patches/eigen-stabilise-sparseqr-test.patch
+++ /dev/null
@@ -1,74 +0,0 @@
-From: Tobias Geerinckx-Rice <me@tobias.gr>
-Date: Mon, 16 Mar 2020 22:51:37 +0000
-Subject: gnu: eigen: Stabilise sparseqr test.
-
-Taken verbatim from this[0] upstream commit.
-
-[0]: https://gitlab.com/libeigen/eigen/-/commit/3b5deeb546d4017b24846f5b0dc3296a50a039fe
-
-From 3b5deeb546d4017b24846f5b0dc3296a50a039fe Mon Sep 17 00:00:00 2001
-From: Gael Guennebaud <g.gael@free.fr>
-Date: Tue, 19 Feb 2019 22:57:51 +0100
-Subject: [PATCH] bug #899: make sparseqr unit test more stable by 1) trying
- with larger threshold and 2) relax rank computation for rank-deficient
- problems.
-
----
- test/sparseqr.cpp | 31 ++++++++++++++++++++++++++-----
- 1 file changed, 26 insertions(+), 5 deletions(-)
-
-diff --git a/test/sparseqr.cpp b/test/sparseqr.cpp
-index 3ffe62314..3576cc626 100644
---- a/test/sparseqr.cpp
-+++ b/test/sparseqr.cpp
-@@ -43,6 +43,7 @@ int generate_sparse_rectangular_problem(MatrixType& A, DenseMat& dA, int maxRows
- 
- template<typename Scalar> void test_sparseqr_scalar()
- {
-+  typedef typename NumTraits<Scalar>::Real RealScalar;
-   typedef SparseMatrix<Scalar,ColMajor> MatrixType; 
-   typedef Matrix<Scalar,Dynamic,Dynamic> DenseMat;
-   typedef Matrix<Scalar,Dynamic,1> DenseVector;
-@@ -91,14 +92,34 @@ template<typename Scalar> void test_sparseqr_scalar()
-     exit(0);
-     return;
-   }
--  
--  VERIFY_IS_APPROX(A * x, b);
--  
--  //Compare with a dense QR solver
-+
-+  // Compare with a dense QR solver
-   ColPivHouseholderQR<DenseMat> dqr(dA);
-   refX = dqr.solve(b);
-   
--  VERIFY_IS_EQUAL(dqr.rank(), solver.rank());
-+  bool rank_deficient = A.cols()>A.rows() || dqr.rank()<A.cols();
-+  if(rank_deficient)
-+  {
-+    // rank deficient problem -> we might have to increase the threshold
-+    // to get a correct solution.
-+    RealScalar th = RealScalar(20)*dA.colwise().norm().maxCoeff()*(A.rows()+A.cols()) * NumTraits<RealScalar>::epsilon();
-+    for(Index k=0; (k<16) && !test_isApprox(A*x,b); ++k)
-+    {
-+      th *= RealScalar(10);
-+      solver.setPivotThreshold(th);
-+      solver.compute(A);
-+      x = solver.solve(b);
-+    }
-+  }
-+
-+  VERIFY_IS_APPROX(A * x, b);
-+  
-+  // For rank deficient problem, the estimated rank might
-+  // be slightly off, so let's only raise a warning in such cases.
-+  if(rank_deficient) ++g_test_level;
-+  VERIFY_IS_EQUAL(solver.rank(), dqr.rank());
-+  if(rank_deficient) --g_test_level;
-+
-   if(solver.rank()==A.cols()) // full rank
-     VERIFY_IS_APPROX(x, refX);
- //   else
--- 
-2.24.1
-
