Skip to content

core: fix missing vec_cvfo on IBM POWER9 due to unavailable VSX float64 conversion #27633

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: 4.x
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions modules/core/include/opencv2/core/vsx_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
#ifndef OPENCV_HAL_VSX_UTILS_HPP
#define OPENCV_HAL_VSX_UTILS_HPP

#if (defined(__has_builtin) && __has_builtin(__builtin_vsx_xvcvdpsp) && __has_builtin(__builtin_vsx_xvcvspdp)) \
|| defined(__POWER10__)
#define CV_VSX_HAS_FLOAT64_CONVERT 1
#else
#define CV_VSX_HAS_FLOAT64_CONVERT 0
#endif

#include "opencv2/core/cvdef.h"

#ifndef SKIP_INCLUDES
Expand Down Expand Up @@ -257,8 +264,27 @@ VSX_IMPL_1VRG(vec_udword2, vec_udword2, vpopcntd, vec_popcntu)
VSX_IMPL_1VRG(vec_udword2, vec_dword2, vpopcntd, vec_popcntu)

// converts between single and double-precision
VSX_REDIRECT_1RG(vec_float4, vec_double2, vec_cvfo, vec_floate)
VSX_REDIRECT_1RG(vec_double2, vec_float4, vec_cvfo, vec_doubleo)

#if CV_VSX_HAS_FLOAT64_CONVERT
// Use VSX double<->float conversion instructions (if supported by the architecture)
VSX_REDIRECT_1RG(vec_float4, vec_double2, vec_cvfo, vec_floate)
VSX_REDIRECT_1RG(vec_double2, vec_float4, vec_cvfo, vec_doubleo)
#else
// Fallback: implement vec_cvfo using scalar operations (to ensure successful linking)
static inline vec_float4 vec_cvfo(const vec_double2& a)
{
float r0 = static_cast<float>(reinterpret_cast<const double*>(&a)[0]);
float r1 = static_cast<float>(reinterpret_cast<const double*>(&a)[1]);
return (vec_float4){r0, r1, 0.f, 0.f};
}

static inline vec_double2 vec_cvfo(const vec_float4& a)
{
double r0 = static_cast<double>(reinterpret_cast<const float*>(&a)[0]);
double r1 = static_cast<double>(reinterpret_cast<const float*>(&a)[2]);
return (vec_double2){r0, r1};
}
#endif

// converts word and doubleword to double-precision
#undef vec_ctd
Expand Down
Loading