diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index 6d3e26aa36a3d..7a87e35c84603 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -610,161 +610,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __constexpr_isfinite(_A1 __lcpp_x)
   return __builtin_isfinite(__lcpp_x);
 }
 
-_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI float __constexpr_copysign(float __x, float __y) _NOEXCEPT {
-  return __builtin_copysignf(__x, __y);
-}
-
-_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI double __constexpr_copysign(double __x, double __y) _NOEXCEPT {
-  return __builtin_copysign(__x, __y);
-}
-
-_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI long double
-__constexpr_copysign(long double __x, long double __y) _NOEXCEPT {
-  return __builtin_copysignl(__x, __y);
-}
-
-template <class _A1,
-          class _A2,
-          __enable_if_t<std::is_arithmetic<_A1>::value && std::is_arithmetic<_A2>::value, int> = 0>
-_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type
-__constexpr_copysign(_A1 __x, _A2 __y) _NOEXCEPT {
-  typedef typename std::__promote<_A1, _A2>::type __result_type;
-  static_assert(!(std::_IsSame<_A1, __result_type>::value && std::_IsSame<_A2, __result_type>::value), "");
-  return __builtin_copysign((__result_type)__x, (__result_type)__y);
-}
-
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR float __constexpr_fabs(float __x) _NOEXCEPT {
-  return __builtin_fabsf(__x);
-}
-
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double __constexpr_fabs(double __x) _NOEXCEPT {
-  return __builtin_fabs(__x);
-}
-
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR long double __constexpr_fabs(long double __x) _NOEXCEPT {
-  return __builtin_fabsl(__x);
-}
-
-template <class _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double __constexpr_fabs(_Tp __x) _NOEXCEPT {
-  return __builtin_fabs(static_cast<double>(__x));
-}
-
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 float __constexpr_fmax(float __x, float __y) _NOEXCEPT {
-#if !__has_constexpr_builtin(__builtin_fmaxf)
-  if (__libcpp_is_constant_evaluated()) {
-    if (std::__constexpr_isnan(__x))
-      return __y;
-    if (std::__constexpr_isnan(__y))
-      return __x;
-    return __x < __y ? __y : __x;
-  }
-#endif
-  return __builtin_fmaxf(__x, __y);
-}
-
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 double __constexpr_fmax(double __x, double __y) _NOEXCEPT {
-#if !__has_constexpr_builtin(__builtin_fmax)
-  if (__libcpp_is_constant_evaluated()) {
-    if (std::__constexpr_isnan(__x))
-      return __y;
-    if (std::__constexpr_isnan(__y))
-      return __x;
-    return __x < __y ? __y : __x;
-  }
-#endif
-  return __builtin_fmax(__x, __y);
-}
-
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 long double
-__constexpr_fmax(long double __x, long double __y) _NOEXCEPT {
-#if !__has_constexpr_builtin(__builtin_fmaxl)
-  if (__libcpp_is_constant_evaluated()) {
-    if (std::__constexpr_isnan(__x))
-      return __y;
-    if (std::__constexpr_isnan(__y))
-      return __x;
-    return __x < __y ? __y : __x;
-  }
-#endif
-  return __builtin_fmaxl(__x, __y);
-}
-
-template <class _Tp, class _Up, __enable_if_t<is_arithmetic<_Tp>::value && is_arithmetic<_Up>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename __promote<_Tp, _Up>::type
-__constexpr_fmax(_Tp __x, _Up __y) _NOEXCEPT {
-  using __result_type = typename __promote<_Tp, _Up>::type;
-  return std::__constexpr_fmax(static_cast<__result_type>(__x), static_cast<__result_type>(__y));
-}
-
-template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __constexpr_logb(_Tp __x) {
-#if !__has_constexpr_builtin(__builtin_logb)
-  if (__libcpp_is_constant_evaluated()) {
-    if (__x == _Tp(0)) {
-      // raise FE_DIVBYZERO
-      return -numeric_limits<_Tp>::infinity();
-    }
-
-    if (std::__constexpr_isinf(__x))
-      return numeric_limits<_Tp>::infinity();
-
-    if (std::__constexpr_isnan(__x))
-      return numeric_limits<_Tp>::quiet_NaN();
-
-    __x                      = std::__constexpr_fabs(__x);
-    unsigned long long __exp = 0;
-    while (__x >= numeric_limits<_Tp>::radix) {
-      __x /= numeric_limits<_Tp>::radix;
-      __exp += 1;
-    }
-    return _Tp(__exp);
-  }
-#endif // !__has_constexpr_builtin(__builtin_logb)
-  return __builtin_logb(__x);
-}
-
-template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp __x, int __exp) {
-#if !__has_constexpr_builtin(__builtin_scalbln)
-  if (__libcpp_is_constant_evaluated()) {
-    if (__x == _Tp(0))
-      return __x;
-
-    if (std::__constexpr_isinf(__x))
-      return __x;
-
-    if (__exp == _Tp(0))
-      return __x;
-
-    if (std::__constexpr_isnan(__x))
-      return numeric_limits<_Tp>::quiet_NaN();
-
-    _Tp __mult(1);
-    if (__exp > 0) {
-      __mult = numeric_limits<_Tp>::radix;
-      --__exp;
-    } else {
-      ++__exp;
-      __exp = -__exp;
-      __mult /= numeric_limits<_Tp>::radix;
-    }
-
-    while (__exp > 0) {
-      if (!(__exp & 1)) {
-        __mult *= __mult;
-        __exp >>= 1;
-      } else {
-        __x *= __mult;
-        --__exp;
-      }
-    }
-    return __x;
-  }
-#endif // !__has_constexpr_builtin(__builtin_scalbln)
-  return __builtin_scalbn(__x, __exp);
-}
-
 #if _LIBCPP_STD_VER >= 20
 template <typename _Fp>
 _LIBCPP_HIDE_FROM_ABI constexpr _Fp __lerp(_Fp __a, _Fp __b, _Fp __t) noexcept {
diff --git a/libcxx/include/complex b/libcxx/include/complex
index a81f968143c4c..69a9fcce6f7ef 100644
--- a/libcxx/include/complex
+++ b/libcxx/include/complex
@@ -281,10 +281,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template <class _Tp>
 class _LIBCPP_TEMPLATE_VIS complex;
 
-template <class _Tp>
+template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> = 0>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator*(const complex<_Tp>& __z, const complex<_Tp>& __w);
-template <class _Tp>
+
+template <class _Tp, __enable_if_t<!is_floating_point<_Tp>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+operator*(const complex<_Tp>& __z, const complex<_Tp>& __w);
+
+template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+operator/(const complex<_Tp>& __x, const complex<_Tp>& __y);
+
+template <class _Tp, __enable_if_t<!is_floating_point<_Tp>::value, int> = 0>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator/(const complex<_Tp>& __x, const complex<_Tp>& __y);
 
@@ -384,6 +393,23 @@ class _LIBCPP_TEMPLATE_VIS complex<double>;
 template <>
 class _LIBCPP_TEMPLATE_VIS complex<long double>;
 
+struct __from_builtin_tag {};
+
+template <class _Tp>
+using __complex_t =
+    __conditional_t<is_same<_Tp, float>::value,
+                    _Complex float,
+                    __conditional_t<is_same<_Tp, double>::value, _Complex double, _Complex long double> >;
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __complex_t<_Tp> __make_complex(_Tp __re, _Tp __im) {
+#if __has_builtin(__builtin_complex)
+  return __builtin_complex(__re, __im);
+#else
+  return __complex_t<_Tp>{__re, __im};
+#endif
+}
+
 template <>
 class _LIBCPP_TEMPLATE_VIS complex<float> {
   float __re_;
@@ -393,6 +419,10 @@ public:
   typedef float value_type;
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(float __re = 0.0f, float __im = 0.0f) : __re_(__re), __im_(__im) {}
+
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(__from_builtin_tag, _Complex float __v)
+      : __re_(__real__ __v), __im_(__imag__ __v) {}
+
   _LIBCPP_HIDE_FROM_ABI explicit _LIBCPP_CONSTEXPR complex(const complex<double>& __c);
   _LIBCPP_HIDE_FROM_ABI explicit _LIBCPP_CONSTEXPR complex(const complex<long double>& __c);
 
@@ -402,6 +432,12 @@ public:
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) { __re_ = __re; }
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) { __im_ = __im; }
 
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Complex float __builtin() const { return std::__make_complex(__re_, __im_); }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __builtin(_Complex float __f) {
+    __re_ = __real__ __f;
+    __im_ = __imag__ __f;
+  }
+
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator=(float __re) {
     __re_ = __re;
     __im_ = value_type();
@@ -479,6 +515,10 @@ public:
   typedef double value_type;
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(double __re = 0.0, double __im = 0.0) : __re_(__re), __im_(__im) {}
+
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(__from_builtin_tag, _Complex double __v)
+      : __re_(__real__ __v), __im_(__imag__ __v) {}
+
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(const complex<float>& __c);
   _LIBCPP_HIDE_FROM_ABI explicit _LIBCPP_CONSTEXPR complex(const complex<long double>& __c);
 
@@ -488,6 +528,15 @@ public:
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) { __re_ = __re; }
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) { __im_ = __im; }
 
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Complex double __builtin() const {
+    return std::__make_complex(__re_, __im_);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __builtin(_Complex double __f) {
+    __re_ = __real__ __f;
+    __im_ = __imag__ __f;
+  }
+
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator=(double __re) {
     __re_ = __re;
     __im_ = value_type();
@@ -566,6 +615,10 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(long double __re = 0.0L, long double __im = 0.0L)
       : __re_(__re), __im_(__im) {}
+
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(__from_builtin_tag, _Complex long double __v)
+      : __re_(__real__ __v), __im_(__imag__ __v) {}
+
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(const complex<float>& __c);
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(const complex<double>& __c);
 
@@ -575,6 +628,15 @@ public:
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) { __re_ = __re; }
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) { __im_ = __im; }
 
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Complex long double __builtin() const {
+    return std::__make_complex(__re_, __im_);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __builtin(_Complex long double __f) {
+    __re_ = __real__ __f;
+    __im_ = __imag__ __f;
+  }
+
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex& operator=(long double __re) {
     __re_ = __re;
     __im_ = value_type();
@@ -709,7 +771,13 @@ operator-(const _Tp& __x, const complex<_Tp>& __y) {
   return __t;
 }
 
-template <class _Tp>
+template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> >
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+operator*(const complex<_Tp>& __lhs, const complex<_Tp>& __rhs) {
+  return complex<_Tp>(__from_builtin_tag(), __lhs.__builtin() * __rhs.__builtin());
+}
+
+template <class _Tp, __enable_if_t<!is_floating_point<_Tp>::value, int> >
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator*(const complex<_Tp>& __z, const complex<_Tp>& __w) {
   _Tp __a = __z.real();
@@ -717,78 +785,7 @@ operator*(const complex<_Tp>& __z, const complex<_Tp>& __w) {
   _Tp __c = __w.real();
   _Tp __d = __w.imag();
 
-  // Avoid floating point operations that are invalid during constant evaluation
-  if (__libcpp_is_constant_evaluated()) {
-    bool __z_zero = __a == _Tp(0) && __b == _Tp(0);
-    bool __w_zero = __c == _Tp(0) && __d == _Tp(0);
-    bool __z_inf  = std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b);
-    bool __w_inf  = std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d);
-    bool __z_nan =
-        !__z_inf && ((std::__constexpr_isnan(__a) && std::__constexpr_isnan(__b)) ||
-                     (std::__constexpr_isnan(__a) && __b == _Tp(0)) || (__a == _Tp(0) && std::__constexpr_isnan(__b)));
-    bool __w_nan =
-        !__w_inf && ((std::__constexpr_isnan(__c) && std::__constexpr_isnan(__d)) ||
-                     (std::__constexpr_isnan(__c) && __d == _Tp(0)) || (__c == _Tp(0) && std::__constexpr_isnan(__d)));
-    if (__z_nan || __w_nan) {
-      return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
-    }
-    if (__z_inf || __w_inf) {
-      if (__z_zero || __w_zero) {
-        return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
-      }
-      return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity()));
-    }
-    bool __z_nonzero_nan = !__z_inf && !__z_nan && (std::__constexpr_isnan(__a) || std::__constexpr_isnan(__b));
-    bool __w_nonzero_nan = !__w_inf && !__w_nan && (std::__constexpr_isnan(__c) || std::__constexpr_isnan(__d));
-    if (__z_nonzero_nan || __w_nonzero_nan) {
-      return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
-    }
-  }
-
-  _Tp __ac = __a * __c;
-  _Tp __bd = __b * __d;
-  _Tp __ad = __a * __d;
-  _Tp __bc = __b * __c;
-  _Tp __x  = __ac - __bd;
-  _Tp __y  = __ad + __bc;
-  if (std::__constexpr_isnan(__x) && std::__constexpr_isnan(__y)) {
-    bool __recalc = false;
-    if (std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b)) {
-      __a = std::__constexpr_copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a);
-      __b = std::__constexpr_copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b);
-      if (std::__constexpr_isnan(__c))
-        __c = std::__constexpr_copysign(_Tp(0), __c);
-      if (std::__constexpr_isnan(__d))
-        __d = std::__constexpr_copysign(_Tp(0), __d);
-      __recalc = true;
-    }
-    if (std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d)) {
-      __c = std::__constexpr_copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c);
-      __d = std::__constexpr_copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d);
-      if (std::__constexpr_isnan(__a))
-        __a = std::__constexpr_copysign(_Tp(0), __a);
-      if (std::__constexpr_isnan(__b))
-        __b = std::__constexpr_copysign(_Tp(0), __b);
-      __recalc = true;
-    }
-    if (!__recalc && (std::__constexpr_isinf(__ac) || std::__constexpr_isinf(__bd) || std::__constexpr_isinf(__ad) ||
-                      std::__constexpr_isinf(__bc))) {
-      if (std::__constexpr_isnan(__a))
-        __a = std::__constexpr_copysign(_Tp(0), __a);
-      if (std::__constexpr_isnan(__b))
-        __b = std::__constexpr_copysign(_Tp(0), __b);
-      if (std::__constexpr_isnan(__c))
-        __c = std::__constexpr_copysign(_Tp(0), __c);
-      if (std::__constexpr_isnan(__d))
-        __d = std::__constexpr_copysign(_Tp(0), __d);
-      __recalc = true;
-    }
-    if (__recalc) {
-      __x = _Tp(INFINITY) * (__a * __c - __b * __d);
-      __y = _Tp(INFINITY) * (__a * __d + __b * __c);
-    }
-  }
-  return complex<_Tp>(__x, __y);
+  return complex<_Tp>((__a * __c) - (__b * __d), (__a * __d) + (__b * __c));
 }
 
 template <class _Tp>
@@ -807,80 +804,22 @@ operator*(const _Tp& __x, const complex<_Tp>& __y) {
   return __t;
 }
 
-template <class _Tp>
+template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> >
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+operator/(const complex<_Tp>& __lhs, const complex<_Tp>& __rhs) {
+  return complex<_Tp>(__from_builtin_tag(), __lhs.__builtin() / __rhs.__builtin());
+}
+
+template <class _Tp, __enable_if_t<!is_floating_point<_Tp>::value, int> >
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator/(const complex<_Tp>& __z, const complex<_Tp>& __w) {
-  int __ilogbw = 0;
-  _Tp __a      = __z.real();
-  _Tp __b      = __z.imag();
-  _Tp __c      = __w.real();
-  _Tp __d      = __w.imag();
-  _Tp __logbw  = std::__constexpr_logb(std::__constexpr_fmax(std::__constexpr_fabs(__c), std::__constexpr_fabs(__d)));
-  if (std::__constexpr_isfinite(__logbw)) {
-    __ilogbw = static_cast<int>(__logbw);
-    __c      = std::__constexpr_scalbn(__c, -__ilogbw);
-    __d      = std::__constexpr_scalbn(__d, -__ilogbw);
-  }
-
-  // Avoid floating point operations that are invalid during constant evaluation
-  if (__libcpp_is_constant_evaluated()) {
-    bool __z_zero = __a == _Tp(0) && __b == _Tp(0);
-    bool __w_zero = __c == _Tp(0) && __d == _Tp(0);
-    bool __z_inf  = std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b);
-    bool __w_inf  = std::__constexpr_isinf(__c) || std::__constexpr_isinf(__d);
-    bool __z_nan =
-        !__z_inf && ((std::__constexpr_isnan(__a) && std::__constexpr_isnan(__b)) ||
-                     (std::__constexpr_isnan(__a) && __b == _Tp(0)) || (__a == _Tp(0) && std::__constexpr_isnan(__b)));
-    bool __w_nan =
-        !__w_inf && ((std::__constexpr_isnan(__c) && std::__constexpr_isnan(__d)) ||
-                     (std::__constexpr_isnan(__c) && __d == _Tp(0)) || (__c == _Tp(0) && std::__constexpr_isnan(__d)));
-    if ((__z_nan || __w_nan) || (__z_inf && __w_inf)) {
-      return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
-    }
-    bool __z_nonzero_nan = !__z_inf && !__z_nan && (std::__constexpr_isnan(__a) || std::__constexpr_isnan(__b));
-    bool __w_nonzero_nan = !__w_inf && !__w_nan && (std::__constexpr_isnan(__c) || std::__constexpr_isnan(__d));
-    if (__z_nonzero_nan || __w_nonzero_nan) {
-      if (__w_zero) {
-        return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity()));
-      }
-      return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
-    }
-    if (__w_inf) {
-      return complex<_Tp>(_Tp(0), _Tp(0));
-    }
-    if (__z_inf) {
-      return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity()));
-    }
-    if (__w_zero) {
-      if (__z_zero) {
-        return complex<_Tp>(_Tp(numeric_limits<_Tp>::quiet_NaN()), _Tp(0));
-      }
-      return complex<_Tp>(_Tp(numeric_limits<_Tp>::infinity()), _Tp(numeric_limits<_Tp>::infinity()));
-    }
-  }
+  _Tp __a = __z.real();
+  _Tp __b = __z.imag();
+  _Tp __c = __w.real();
+  _Tp __d = __w.imag();
 
   _Tp __denom = __c * __c + __d * __d;
-  _Tp __x     = std::__constexpr_scalbn((__a * __c + __b * __d) / __denom, -__ilogbw);
-  _Tp __y     = std::__constexpr_scalbn((__b * __c - __a * __d) / __denom, -__ilogbw);
-  if (std::__constexpr_isnan(__x) && std::__constexpr_isnan(__y)) {
-    if ((__denom == _Tp(0)) && (!std::__constexpr_isnan(__a) || !std::__constexpr_isnan(__b))) {
-      __x = std::__constexpr_copysign(_Tp(INFINITY), __c) * __a;
-      __y = std::__constexpr_copysign(_Tp(INFINITY), __c) * __b;
-    } else if ((std::__constexpr_isinf(__a) || std::__constexpr_isinf(__b)) && std::__constexpr_isfinite(__c) &&
-               std::__constexpr_isfinite(__d)) {
-      __a = std::__constexpr_copysign(std::__constexpr_isinf(__a) ? _Tp(1) : _Tp(0), __a);
-      __b = std::__constexpr_copysign(std::__constexpr_isinf(__b) ? _Tp(1) : _Tp(0), __b);
-      __x = _Tp(INFINITY) * (__a * __c + __b * __d);
-      __y = _Tp(INFINITY) * (__b * __c - __a * __d);
-    } else if (std::__constexpr_isinf(__logbw) && __logbw > _Tp(0) && std::__constexpr_isfinite(__a) &&
-               std::__constexpr_isfinite(__b)) {
-      __c = std::__constexpr_copysign(std::__constexpr_isinf(__c) ? _Tp(1) : _Tp(0), __c);
-      __d = std::__constexpr_copysign(std::__constexpr_isinf(__d) ? _Tp(1) : _Tp(0), __d);
-      __x = _Tp(0) * (__a * __c + __b * __d);
-      __y = _Tp(0) * (__b * __c - __a * __d);
-    }
-  }
-  return complex<_Tp>(__x, __y);
+  return complex<_Tp>((__a * __c + __b * __d) / __denom, (__b * __c - __a * __d) / __denom);
 }
 
 template <class _Tp>
diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt
index 9e6c70335a794..16afce8680cd4 100644
--- a/libcxx/src/CMakeLists.txt
+++ b/libcxx/src/CMakeLists.txt
@@ -99,6 +99,7 @@ endif()
 
 if(WIN32)
   list(APPEND LIBCXX_SOURCES
+    support/win32/compiler_rt_shims.cpp
     support/win32/locale_win32.cpp
     support/win32/support.cpp
     )
diff --git a/libcxx/src/support/win32/compiler_rt_shims.cpp b/libcxx/src/support/win32/compiler_rt_shims.cpp
new file mode 100644
index 0000000000000..ab263224906ed
--- /dev/null
+++ b/libcxx/src/support/win32/compiler_rt_shims.cpp
@@ -0,0 +1,110 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+//
+// This file reimplements builtins that are normally provided by compiler-rt, which is
+// not provided on Windows. This should go away once compiler-rt is shipped on Windows.
+//
+
+#include <cmath>
+#include <complex>
+
+template <class T>
+static std::__complex_t<T> mul_impl(T a, T b, T c, T d) {
+  T __ac = a * c;
+  T __bd = b * d;
+  T __ad = a * d;
+  T __bc = b * c;
+  T __x  = __ac - __bd;
+  T __y  = __ad + __bc;
+  if (std::isnan(__x) && std::isnan(__y)) {
+    bool recalc = false;
+    if (std::isinf(a) || std::isinf(b)) {
+      a = std::copysign(std::isinf(a) ? T(1) : T(0), a);
+      b = std::copysign(std::isinf(b) ? T(1) : T(0), b);
+      if (std::isnan(c))
+        c = std::copysign(T(0), c);
+      if (std::isnan(d))
+        d = std::copysign(T(0), d);
+      recalc = true;
+    }
+    if (std::isinf(c) || std::isinf(d)) {
+      c = std::copysign(std::isinf(c) ? T(1) : T(0), c);
+      d = std::copysign(std::isinf(d) ? T(1) : T(0), d);
+      if (std::isnan(a))
+        a = std::copysign(T(0), a);
+      if (std::isnan(b))
+        b = std::copysign(T(0), b);
+      recalc = true;
+    }
+    if (!recalc && (std::isinf(__ac) || std::isinf(__bd) || std::isinf(__ad) || std::isinf(__bc))) {
+      if (std::isnan(a))
+        a = std::copysign(T(0), a);
+      if (std::isnan(b))
+        b = std::copysign(T(0), b);
+      if (std::isnan(c))
+        c = std::copysign(T(0), c);
+      if (std::isnan(d))
+        d = std::copysign(T(0), d);
+      recalc = true;
+    }
+    if (recalc) {
+      __x = T(INFINITY) * (a * c - b * d);
+      __y = T(INFINITY) * (a * d + b * c);
+    }
+  }
+  return {__x, __y};
+}
+
+extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex double __muldc3(double a, double b, double c, double d) {
+  return mul_impl(a, b, c, d);
+}
+
+extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex float __mulsc3(float a, float b, float c, float d) {
+  return mul_impl(a, b, c, d);
+}
+
+template <class T>
+std::__complex_t<T> div_impl(T a, T b, T c, T d) {
+  int ilogbw = 0;
+  T __logbw  = std::logb(std::fmax(std::fabs(c), std::fabs(d)));
+  if (std::isfinite(__logbw)) {
+    ilogbw = static_cast<int>(__logbw);
+    c      = std::scalbn(c, -ilogbw);
+    d      = std::scalbn(d, -ilogbw);
+  }
+
+  T denom = c * c + d * d;
+  T x     = std::scalbn((a * c + b * d) / denom, -ilogbw);
+  T y     = std::scalbn((b * c - a * d) / denom, -ilogbw);
+  if (std::isnan(x) && std::isnan(y)) {
+    if ((denom == T(0)) && (!std::isnan(a) || !std::isnan(b))) {
+      x = std::copysign(T(INFINITY), c) * a;
+      y = std::copysign(T(INFINITY), c) * b;
+    } else if ((std::isinf(a) || std::isinf(b)) && std::isfinite(c) && std::isfinite(d)) {
+      a = std::copysign(std::isinf(a) ? T(1) : T(0), a);
+      b = std::copysign(std::isinf(b) ? T(1) : T(0), b);
+      x = T(INFINITY) * (a * c + b * d);
+      y = T(INFINITY) * (b * c - a * d);
+    } else if (std::isinf(__logbw) && __logbw > T(0) && std::isfinite(a) && std::isfinite(b)) {
+      c = std::copysign(std::isinf(c) ? T(1) : T(0), c);
+      d = std::copysign(std::isinf(d) ? T(1) : T(0), d);
+      x = T(0) * (a * c + b * d);
+      y = T(0) * (b * c - a * d);
+    }
+  }
+  return {x, y};
+}
+
+extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex double __divdc3(double a, double b, double c, double d) {
+  return div_impl(a, b, c, d);
+}
+
+extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex float __divsc3(float a, float b, float c, float d) {
+  return div_impl(a, b, c, d);
+}
diff --git a/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp
index af2561e4cb9e9..61e0d01f2ae4d 100644
--- a/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.member.ops/divide_equal_complex.pass.cpp
@@ -10,9 +10,10 @@
 
 // complex& operator/=(const complex& rhs); // constexpr in C++20
 
-#include <complex>
 #include <cassert>
+#include <complex>
 
+#include "floating_pointer_helpers.h"
 #include "test_macros.h"
 
 template <class T>
@@ -22,28 +23,28 @@ test()
 {
     std::complex<T> c(-4, 7.5);
     const std::complex<T> c2(1.5, 2.5);
-    assert(c.real() == -4);
-    assert(c.imag() == 7.5);
+    assert(is_close(c.real(), T(-4)));
+    assert(is_close(c.imag(), T(7.5)));
     c /= c2;
-    assert(c.real() == 1.5);
-    assert(c.imag() == 2.5);
+    assert(is_close(c.real(), T(1.5)));
+    assert(is_close(c.imag(), T(2.5)));
     c /= c2;
-    assert(c.real() == 1);
-    assert(c.imag() == 0);
+    assert(is_close(c.real(), T(1)));
+    assert(is_close(c.imag(), T(0)));
 
     std::complex<T> c3;
 
     c3 = c;
     std::complex<int> ic (1,1);
     c3 /= ic;
-    assert(c3.real() == 0.5);
-    assert(c3.imag() == -0.5);
+    assert(is_close(c3.real(), T(0.5)));
+    assert(is_close(c3.imag(), T(-0.5)));
 
     c3 = c;
     std::complex<float> fc (1,1);
     c3 /= fc;
-    assert(c3.real() == 0.5);
-    assert(c3.imag() == -0.5);
+    assert(is_close(c3.real(), T(0.5)));
+    assert(is_close(c3.imag(), T(-0.5)));
     return true;
 }
 
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp
index 7119710a95557..d12dfd994b0ae 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp
@@ -12,11 +12,12 @@
 //   complex<T>
 //   operator/(const complex<T>& lhs, const complex<T>& rhs); // constexpr in C++20
 
-// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=5000000
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
 
-#include <complex>
 #include <cassert>
+#include <complex>
 
+#include "floating_pointer_helpers.h"
 #include "test_macros.h"
 #include "../cases.h"
 
@@ -27,7 +28,9 @@ test()
 {
     const std::complex<T> lhs(-4.0, 7.5);
     const std::complex<T> rhs(1.5, 2.5);
-    assert(lhs / rhs == std::complex<T>(1.5, 2.5));
+    const std::complex<T> c = lhs / rhs;
+    assert(is_close(c.real(), T(1.5)));
+    assert(is_close(c.imag(), T(2.5)));
     return true;
 }
 
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp
index 38ec71e3a00a5..817d6cdf492d3 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp
@@ -12,7 +12,7 @@
 //   complex<T>
 //   operator*(const complex<T>& lhs, const complex<T>& rhs); // constexpr in C++20
 
-// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=5000000
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
 
 #include <complex>
 #include <cassert>
diff --git a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp
index 50981216cc5f0..f32b560c1e864 100644
--- a/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp
@@ -24,7 +24,11 @@ test()
 {
     const T lhs(-8.5);
     const std::complex<T> rhs(1.5, 2.5);
-    assert(lhs / rhs == std::complex<T>(-1.5, 2.5));
+    const std::complex<T> c = lhs / rhs;
+    assert(c.real() >= T(-1.500000000000001));
+    assert(c.real() <= T(-1.499999999999999));
+    assert(c.imag() >= T(2.499999999999999));
+    assert(c.imag() <= T(2.500000000000001));
     return true;
 }
 
diff --git a/libcxx/test/support/floating_pointer_helpers.h b/libcxx/test/support/floating_pointer_helpers.h
new file mode 100644
index 0000000000000..5943425bab018
--- /dev/null
+++ b/libcxx/test/support/floating_pointer_helpers.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_SUPPORT_FLOATING_POINT_HELPERS_H
+#define TEST_SUPPORT_FLOATING_POINT_HELPERS_H
+
+#include <limits>
+
+#include "test_macros.h"
+
+template <class T>
+TEST_CONSTEXPR_CXX20 bool is_close(T v, T comp) {
+  return v <= comp + std::numeric_limits<T>::epsilon() && v >= comp - std::numeric_limits<T>::epsilon();
+}
+
+#endif // TEST_SUPPORT_FLOATING_POINT_HELPERS_H