[clang] [X86][Clang] Allow constexpr evaluation of F16C CVTPS2PH intrinsics (PR #162295)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 7 08:01:18 PDT 2025
================
@@ -3002,6 +3002,91 @@ static bool interp__builtin_vec_set(InterpState &S, CodePtr OpPC,
return true;
}
+static bool interp__builtin_ia32_vcvtps2ph(InterpState &S, CodePtr OpPC,
+ const CallExpr *Call) {
+ // Arguments are: vector of floats, rounding immediate
+ assert(Call->getNumArgs() == 2);
+
+ APSInt Imm = popToAPSInt(S, Call->getArg(1));
+ const Pointer &Src = S.Stk.pop<Pointer>();
+ const Pointer &Dst = S.Stk.peek<Pointer>();
+
+ assert(Src.getFieldDesc()->isPrimitiveArray());
+ assert(Dst.getFieldDesc()->isPrimitiveArray());
+
+ const auto *SrcVTy = Call->getArg(0)->getType()->castAs<VectorType>();
+ unsigned SrcNumElems = SrcVTy->getNumElements();
+ const auto *DstVTy = Call->getType()->castAs<VectorType>();
+ unsigned DstNumElems = DstVTy->getNumElements();
+
+ const llvm::fltSemantics &HalfSem =
+ S.getASTContext().getFloatTypeSemantics(S.getASTContext().HalfTy);
+
+ // imm[2] == 1 means use MXCSR rounding mode.
+ // In that case, we can only evaluate if the conversion is exact.
+ int ImmVal = Imm.getZExtValue();
+ bool UseMXCSR = (ImmVal & 4) != 0;
+
+ llvm::RoundingMode RM;
+ if (!UseMXCSR) {
+ switch (ImmVal & 3) {
+ case 0:
+ RM = llvm::RoundingMode::NearestTiesToEven;
+ break;
+ case 1:
+ RM = llvm::RoundingMode::TowardNegative;
+ break;
+ case 2:
+ RM = llvm::RoundingMode::TowardPositive;
+ break;
+ case 3:
+ RM = llvm::RoundingMode::TowardZero;
+ break;
+ default:
+ llvm_unreachable("Invalid immediate rounding mode");
+ }
+ } else {
+ // For MXCSR, we must check for exactness. We can use any rounding mode
+ // for the trial conversion since the result is the same if it's exact.
+ RM = llvm::RoundingMode::NearestTiesToEven;
+ }
+
+ QualType DstElemQT = Dst.getFieldDesc()->getElemQualType();
+ PrimType DstElemT = *S.getContext().classify(DstElemQT);
+ bool DstIsUnsigned = DstElemQT->isUnsignedIntegerOrEnumerationType();
+
+ for (unsigned I = 0; I < SrcNumElems; ++I) {
+ Floating SrcVal = Src.elem<Floating>(I);
+ APFloat DstVal = SrcVal.getAPFloat();
+
+ bool LostInfo;
+ APFloat::opStatus St = DstVal.convert(HalfSem, RM, &LostInfo);
+
+ if (UseMXCSR && St != APFloat::opOK) {
+ S.FFDiag(S.Current->getSource(OpPC),
+ diag::note_constexpr_dynamic_rounding);
+ return false;
+ }
+
+ INT_TYPE_SWITCH_NO_BOOL(DstElemT, {
+ // FIX: Extract the integer value before calling 'from'.
+ uint64_t RawBits = DstVal.bitcastToAPInt().getZExtValue();
+ Dst.elem<T>(I) = T::from(RawBits);
+ });
+ }
+
+ // Zero out remaining elements if the destination has more elements
+ // (e.g., vcvtps2ph converting 4 floats to 8 shorts).
+ if (DstNumElems > SrcNumElems) {
+ for (unsigned I = SrcNumElems; I < DstNumElems; ++I) {
----------------
tbaederr wrote:
```suggestion
for (unsigned I = SrcNumElems; I != DstNumElems; ++I) {
```
https://github.com/llvm/llvm-project/pull/162295
More information about the cfe-commits
mailing list