@@ -2405,6 +2405,15 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
24052405 setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i128, Custom);
24062406 }
24072407
2408+ if (Subtarget.hasAVX512()) {
2409+ for (MVT VT : { MVT::f16, MVT::f32, MVT::f64, MVT::v4f32, MVT::v2f64 })
2410+ setOperationAction(ISD::FLDEXP, VT, Custom);
2411+
2412+ if (Subtarget.hasVLX())
2413+ for (MVT VT : { MVT::v8f32, MVT::v4f64, MVT::v16f32, MVT::v8f64 })
2414+ setOperationAction(ISD::FLDEXP, VT, Custom);
2415+ }
2416+
24082417 // On 32 bit MSVC, `fmodf(f32)` is not defined - only `fmod(f64)`
24092418 // is. We should promote the value to 64-bits to solve this.
24102419 // This is what the CRT headers do - `fmodf` is an inline header
@@ -31814,6 +31823,57 @@ static StringRef getInstrStrFromOpNo(const SmallVectorImpl<StringRef> &AsmStrs,
3181431823 return StringRef();
3181531824}
3181631825
31826+ static SDValue LowerFLDEXP(SDValue Op, const X86Subtarget &Subtarget,
31827+ SelectionDAG &DAG) {
31828+ SDValue X = Op.getOperand(0);
31829+ EVT XTy = X.getValueType();
31830+ SDValue Exp = Op.getOperand(1);
31831+ SDLoc DL(Op);
31832+ EVT XVT, ExpVT;
31833+ switch (Op.getSimpleValueType().SimpleTy) {
31834+ default:
31835+ return SDValue();
31836+ case MVT::f16:
31837+ // TODO: Choose vscalefph when fp16 for ISD::FLDEXP is fully supported.
31838+ X = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, X);
31839+ [[fallthrough]];
31840+ case MVT::f32:
31841+ XVT = MVT::v4f32;
31842+ ExpVT = MVT::v4f32;
31843+ break;
31844+ case MVT::f64:
31845+ XVT = MVT::v2f64;
31846+ ExpVT = MVT::v2f64;
31847+ break;
31848+ case MVT::v4f32:
31849+ case MVT::v2f64:
31850+ if (!Subtarget.hasVLX()) {
31851+ Exp = DAG.getNode(ISD::SINT_TO_FP, DL, XTy, Exp);
31852+ return DAG.getNode(X86ISD::SCALEFS, DL, XTy, X, Exp, X);
31853+ }
31854+ case MVT::v8f32:
31855+ case MVT::v4f64:
31856+ case MVT::v16f32:
31857+ case MVT::v8f64:
31858+ Exp = DAG.getNode(ISD::SINT_TO_FP, DL, XTy, Exp);
31859+ return DAG.getNode(X86ISD::SCALEF, DL, XTy, X, Exp, X);
31860+ }
31861+
31862+ SDValue Zero = DAG.getConstant(0, DL, MVT::i64);
31863+ Exp = DAG.getNode(ISD::SINT_TO_FP, DL, X.getValueType(), Exp);
31864+ SDValue VX =
31865+ DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, XVT, DAG.getUNDEF(XVT), X, Zero);
31866+ SDValue VExp = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, ExpVT,
31867+ DAG.getUNDEF(ExpVT), Exp, Zero);
31868+ SDValue Scalef = DAG.getNode(X86ISD::SCALEFS, DL, XVT, VX, VExp, VX);
31869+ SDValue Final =
31870+ DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, X.getValueType(), Scalef, Zero);
31871+ if (X.getValueType() != XTy)
31872+ Final = DAG.getNode(ISD::FP_ROUND, DL, XTy, Final,
31873+ DAG.getIntPtrConstant(1, SDLoc(Op)));
31874+ return Final;
31875+ }
31876+
3181731877bool X86TargetLowering::isInlineAsmTargetBranch(
3181831878 const SmallVectorImpl<StringRef> &AsmStrs, unsigned OpNo) const {
3181931879 // In a __asm block, __asm inst foo where inst is CALL or JMP should be
@@ -31979,6 +32039,7 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
3197932039 case ISD::ADDRSPACECAST: return LowerADDRSPACECAST(Op, DAG);
3198032040 case X86ISD::CVTPS2PH: return LowerCVTPS2PH(Op, DAG);
3198132041 case ISD::PREFETCH: return LowerPREFETCH(Op, Subtarget, DAG);
32042+ case ISD::FLDEXP: return LowerFLDEXP(Op, Subtarget, DAG);
3198232043 }
3198332044}
3198432045
0 commit comments