@@ -498,6 +498,62 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
498498 .clampScalar (0 , s32, sMaxScalar )
499499 .widenScalarToNextPow2 (1 );
500500
501+ // For G_UITOFP and G_FPTOUI without AVX512, we have to custom legalize types
502+ // <= s32 manually. Otherwise, in custom handler there is no way to
503+ // understand whether s32 is an original type and we need to promote it to
504+ // s64 or s32 is obtained after widening and we shouldn't widen it to s64.
505+ //
506+ // For AVX512 we simply widen types as there is direct mapping from opcodes
507+ // to asm instructions.
508+ getActionDefinitionsBuilder (G_UITOFP)
509+ .legalIf ([=](const LegalityQuery &Query) {
510+ return HasAVX512 && typeInSet (0 , {s32, s64})(Query) &&
511+ typeInSet (1 , {s32, s64})(Query);
512+ })
513+ .customIf ([=](const LegalityQuery &Query) {
514+ return !HasAVX512 &&
515+ ((HasSSE1 && typeIs (0 , s32)(Query)) ||
516+ (HasSSE2 && typeIs (0 , s64)(Query))) &&
517+ scalarNarrowerThan (1 , Is64Bit ? 64 : 32 )(Query);
518+ })
519+ .lowerIf ([=](const LegalityQuery &Query) {
520+ // Lower conversions from s64
521+ return !HasAVX512 &&
522+ ((HasSSE1 && typeIs (0 , s32)(Query)) ||
523+ (HasSSE2 && typeIs (0 , s64)(Query))) &&
524+ (Is64Bit && typeIs (1 , s64)(Query));
525+ })
526+ .clampScalar (0 , s32, HasSSE2 ? s64 : s32)
527+ .widenScalarToNextPow2 (0 )
528+ .clampScalar (1 , s32, sMaxScalar )
529+ .widenScalarToNextPow2 (1 );
530+
531+ getActionDefinitionsBuilder (G_FPTOUI)
532+ .legalIf ([=](const LegalityQuery &Query) {
533+ return HasAVX512 && typeInSet (0 , {s32, s64})(Query) &&
534+ typeInSet (1 , {s32, s64})(Query);
535+ })
536+ .customIf ([=](const LegalityQuery &Query) {
537+ return !HasAVX512 &&
538+ ((HasSSE1 && typeIs (1 , s32)(Query)) ||
539+ (HasSSE2 && typeIs (1 , s64)(Query))) &&
540+ scalarNarrowerThan (0 , Is64Bit ? 64 : 32 )(Query);
541+ })
542+ // TODO: replace with customized legalization using
543+ // specifics of cvttsd2si. The selection of this node requires
544+ // a vector type. Either G_SCALAR_TO_VECTOR is needed or more advanced
545+ // support of G_BUILD_VECTOR/G_INSERT_VECTOR_ELT is required beforehand.
546+ .lowerIf ([=](const LegalityQuery &Query) {
547+ return !HasAVX512 &&
548+ ((HasSSE1 && typeIs (1 , s32)(Query)) ||
549+ (HasSSE2 && typeIs (1 , s64)(Query))) &&
550+ (Is64Bit && typeIs (0 , s64)(Query));
551+ })
552+ .clampScalar (0 , s32, sMaxScalar )
553+ .widenScalarToNextPow2 (0 )
554+ .clampScalar (1 , s32, HasSSE2 ? s64 : s32)
555+ .widenScalarToNextPow2 (1 );
556+
501557 // vector ops
502558 getActionDefinitionsBuilder (G_BUILD_VECTOR)
503559 .customIf ([=](const LegalityQuery &Query) {
@@ -590,6 +646,10 @@ bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
590646 return false ;
591647 case TargetOpcode::G_BUILD_VECTOR:
592648 return legalizeBuildVector (MI, MRI, Helper);
649+ case TargetOpcode::G_FPTOUI:
650+ return legalizeFPTOUI (MI, MRI, Helper);
651+ case TargetOpcode::G_UITOFP:
652+ return legalizeUITOFP (MI, MRI, Helper);
593653 }
594654 llvm_unreachable (" expected switch to return" );
595655}
@@ -645,6 +705,45 @@ bool X86LegalizerInfo::legalizeBuildVector(MachineInstr &MI,
645705 return true ;
646706}
647707
708+ bool X86LegalizerInfo::legalizeFPTOUI (MachineInstr &MI,
709+ MachineRegisterInfo &MRI,
710+ LegalizerHelper &Helper) const {
711+ MachineIRBuilder &MIRBuilder = Helper.MIRBuilder ;
712+ auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs ();
713+ unsigned DstSizeInBits = DstTy.getScalarSizeInBits ();
714+ const LLT s32 = LLT::scalar (32 );
715+ const LLT s64 = LLT::scalar (64 );
716+
717+ // Simply reuse FPTOSI when it is possible to widen the type
718+ if (DstSizeInBits <= 32 ) {
719+ auto Casted = MIRBuilder.buildFPTOSI (DstTy == s32 ? s64 : s32, Src);
720+ MIRBuilder.buildTrunc (Dst, Casted);
721+ MI.eraseFromParent ();
722+ return true ;
723+ }
724+
725+ return false ;
726+ }
727+
728+ bool X86LegalizerInfo::legalizeUITOFP (MachineInstr &MI,
729+ MachineRegisterInfo &MRI,
730+ LegalizerHelper &Helper) const {
731+ MachineIRBuilder &MIRBuilder = Helper.MIRBuilder ;
732+ auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs ();
733+ const LLT s32 = LLT::scalar (32 );
734+ const LLT s64 = LLT::scalar (64 );
735+
736+ // Simply reuse SITOFP when it is possible to widen the type
737+ if (SrcTy.getSizeInBits () <= 32 ) {
738+ auto Ext = MIRBuilder.buildZExt (SrcTy == s32 ? s64 : s32, Src);
739+ MIRBuilder.buildSITOFP (Dst, Ext);
740+ MI.eraseFromParent ();
741+ return true ;
742+ }
743+
744+ return false ;
745+ }
746+
648747bool X86LegalizerInfo::legalizeIntrinsic (LegalizerHelper &Helper,
649748 MachineInstr &MI) const {
650749 return true ;
0 commit comments