@@ -167,14 +167,6 @@ class GenXEmulate : public ModulePass {
167167
168168 Value *buildRightShift (IVSplitter &SplitBuilder, BinaryOperator &Op);
169169
170- Value *visitFPToUI (FPToUIInst &);
171- Value *visitFPToSI (FPToSIInst &);
172- Value *visitUIToFP (UIToFPInst &);
173- Value *visitSIToFP (SIToFPInst &);
174- Value *buildUI64ToFloat (UIToFPInst &Op);
175- Value *buildSI64ToFloat (SIToFPInst &Op);
176- Value *buildI64ToHalf (CastInst &Op);
177-
178170 Value *visitZExtInst (ZExtInst &I);
179171 Value *visitSExtInst (SExtInst &I);
180172
@@ -737,191 +729,6 @@ Value *GenXEmulate::Emu64Expander::visitAShr(BinaryOperator &Op) {
737729 return buildRightShift (SplitBuilder, Op);
738730}
739731
740- Value *GenXEmulate::Emu64Expander::visitFPToUI (FPToUIInst &Op) {
741-
742- if (!(Op.getOperand (0 )->getType ()->getScalarType ()->isFloatTy () &&
743- Op.getType ()->getScalarType ()->isIntegerTy (64 )))
744- vc::diagnose (Op.getContext (), " GenXEmulate" , &Op,
745- " unsupported (floating point type) -> UI conversion. "
746- " Only float->i64 is supported" );
747-
748- // TODO: try to detect the case where operand is a constant expression
749- // and do the covertion manually
750- auto Builder = getIRBuilder ();
751- const bool IsSigned = false ;
752- auto *V = buildFPToI64 (*Op.getModule (), Builder, SplitBuilder,
753- Op.getOperand (0 ), IsSigned);
754- return Builder.CreateBitCast (V, Op.getType (),
755- Twine (Op.getOpcodeName ()) + " .emu" );
756- }
757- Value *GenXEmulate::Emu64Expander::visitFPToSI (FPToSIInst &Op) {
758-
759- if (!(Op.getOperand (0 )->getType ()->getScalarType ()->isFloatTy () &&
760- Op.getType ()->getScalarType ()->isIntegerTy (64 )))
761- vc::diagnose (Op.getContext (), " GenXEmulate" , &Op,
762- " unsupported (floating point type) -> UI conversion. "
763- " Only float->i64 is supported" );
764-
765- // TODO: try to detect the case where operand is a constant expression
766- // and do the covertion manually
767- auto Builder = getIRBuilder ();
768- const bool IsSigned = true ;
769- auto *V = buildFPToI64 (*Op.getModule (), Builder, SplitBuilder,
770- Op.getOperand (0 ), IsSigned);
771- return Builder.CreateBitCast (V, Op.getType (),
772- Twine (Op.getOpcodeName ()) + " .emu" );
773- }
774- Value *GenXEmulate::Emu64Expander::visitUIToFP (UIToFPInst &Op) {
775- auto *STy = Op.getType ()->getScalarType ();
776-
777- if (STy->isHalfTy ())
778- return buildI64ToHalf (Op);
779- if (STy->isFloatTy ())
780- return buildUI64ToFloat (Op);
781- vc::diagnose (Op.getContext (), " GenXEmulate" , &Op,
782- " unsupported UI64 -> (floating point type) conversion. "
783- " Only UI64->float and UI64->half are supported" );
784- return nullptr ; // to suppress warnings
785- }
786- Value *GenXEmulate::Emu64Expander::visitSIToFP (SIToFPInst &Op) {
787- auto *STy = Op.getType ()->getScalarType ();
788-
789- if (STy->isHalfTy ())
790- return buildI64ToHalf (Op);
791- if (STy->isFloatTy ())
792- return buildSI64ToFloat (Op);
793- vc::diagnose (Op.getContext (), " GenXEmulate" , &Op,
794- " unsupported SI64 -> (floating point type) conversion. "
795- " Only SI64->float and SI64->half are supported" );
796- return nullptr ; // to suppress warnings
797- }
798- Value *GenXEmulate::Emu64Expander::buildUI64ToFloat (UIToFPInst &Op) {
799- IGC_ASSERT_MESSAGE (Op.getType ()->getScalarType ()->isFloatTy (),
800- " UI64->fp32 conversion expected" );
801-
802- auto Builder = getIRBuilder ();
803- auto UI64 = SplitBuilder.splitOperandLoHi (0 );
804- ConstantEmitter K (UI64.Lo );
805-
806- Function *LzdF = GenXIntrinsic::getAnyDeclaration (
807- Op.getModule (), GenXIntrinsic::genx_lzd, {UI64.Hi ->getType ()});
808- Value *Lz = Builder.CreateCall (LzdF, UI64.Hi , " int_emu.ui2fp.lzd." );
809- // sp: 1|8|23
810- // we need to get that nice first set bit into bit position 23.
811- // thus we shift our nice pair of values by 63 - 23 - clz,
812- // some bits will be dropped by shift thus we'll add 1 bits as R bit.
813- // uint8_t shift = 39 - lz;
814- const unsigned kMaxDroppedMantBits = 39 ;
815- Value *DroppedBits = Builder.CreateSub (K.getSplat (kMaxDroppedMantBits ), Lz);
816- auto SI = constructShiftInfo (Builder, DroppedBits);
817- // mantissa = LoPartOf(shr64(data_h, data_l, shift))
818- Value *Mant = buildPartialRShift (Builder, UI64.Lo , UI64.Hi , SI);
819-
820- // bool sticky_h = (data_h & ~mask) & ((1 << (shift - 32)) - 1);
821- auto *TmpShA = Builder.CreateShl (K.getSplat (1 ), Builder.CreateNeg (SI.Sh32 ));
822- auto *TmpMask = Builder.CreateSub (TmpShA, K.getSplat (1 ));
823- auto *StickyH = Builder.CreateAnd (UI64.Hi , Builder.CreateNot (SI.Mask1 ));
824- StickyH = Builder.CreateAnd (StickyH, TmpMask);
825-
826- // bool sticky_l = (data_l & ~mask) || ((data_l & (mask >> shift));
827- auto *SL1 = Builder.CreateAnd (UI64.Lo , Builder.CreateNot (SI.Mask1 ));
828- auto *SL2 = Builder.CreateAnd (UI64.Lo , Builder.CreateLShr (SI.Mask1 , SI.Sh32 ));
829- auto *StickyL = Builder.CreateOr (SL1, SL2);
830-
831- // Calculate RS
832- // bool S = sticky_h | sticky_l;
833- auto *S = Builder.CreateOr (StickyH, StickyL);
834- S = Builder.CreateICmpEQ (S, K.getZero ());
835-
836- auto *notS = Builder.CreateSelect (S, K.getOnes (), K.getZero ());
837-
838- // R = Mant & 1
839- auto *R = Builder.CreateAnd (Mant, K.getSplat (1 ));
840- // mant = (mant + 0x1) >> 1;
841- Mant =
842- Builder.CreateLShr (Builder.CreateAdd (Mant, K.getSplat (1 )), K.getSplat (1 ));
843- // mant &= ~(!S & R); // R is set but no S, round to even.
844- auto *RoundMask = Builder.CreateNot (Builder.CreateAnd (notS, R));
845- Mant = Builder.CreateAnd (Mant, RoundMask);
846- // 0xbd - Lz
847- const unsigned kMaxValueExp = 0xbd ;
848- auto *Exp = Builder.CreateSub (K.getSplat (kMaxValueExp ), Lz);
849- auto *ResultLarge = Builder.CreateShl (Exp, K.getSplat (23 ));
850- ResultLarge = Builder.CreateAdd (ResultLarge, Mant);
851-
852- // NOTE: at this point ResultLarge is a integer vector
853- // Since we calculate "optimized" route through creating yes another
854- // UIToFP instrucion (on i32) and this shall be a vector operation,
855- // all further calculatoins assume that we always process vectors
856- // The cast to the final type (scalar or vector) shall be done at the end
857- auto *VFPTy = Op.getType ();
858- if (!VFPTy->isVectorTy ())
859- VFPTy = IGCLLVM::FixedVectorType::get (Builder.getFloatTy (), 1 );
860-
861- ResultLarge = Builder.CreateBitCast (
862- ResultLarge, VFPTy, Twine (" int_emu.ui2f.l." ) + Op.getOpcodeName ());
863- auto *ResultSmall = Builder.CreateUIToFP (
864- UI64.Lo , VFPTy, Twine (" int_emu.ui2f.s." ) + Op.getOpcodeName ());
865-
866- auto *IsSmallPred = Builder.CreateICmpEQ (UI64.Hi , K.getZero ());
867- auto *Result = Builder.CreateSelect (IsSmallPred, ResultSmall, ResultLarge);
868- // Final cast to the requested type (usually <1 x float> -> float)
869- if (Op.getType () != VFPTy)
870- Result = Builder.CreateBitCast (
871- Result, Op.getType (), Twine (" int_emu.ui2fp." ) + Op.getOpcodeName ());
872- return Result;
873- }
874- Value *GenXEmulate::Emu64Expander::buildSI64ToFloat (SIToFPInst &Op) {
875- IGC_ASSERT_MESSAGE (Op.getType ()->getScalarType ()->isFloatTy (),
876- " SI64->fp32 conversion expected" );
877-
878- // NOTE: SIToFP is special, since it does not do the convert by itself,
879- // Instead it just creates a sequence of 64.bit operations which
880- // are then expanded. As such some type convertion trickery is involved.
881- // Namely, we transform all operands to vector types type as early as possible
882- auto Builder = getIRBuilder ();
883- auto UI64 = SplitBuilder.splitOperandLoHi (0 );
884- ConstantEmitter K (UI64.Hi );
885-
886- auto *SignVal = Builder.CreateAnd (UI64.Hi , K.getSplat (1 << 31 ));
887- auto *PredSigned = Builder.CreateICmpNE (SignVal, K.getZero ());
888-
889- auto *VOprnd = toVector (Builder, Op.getOperand (0 )).V ;
890- // This would be a 64-bit operation on a vector types
891- auto *NegatedOpnd = Builder.CreateNeg (VOprnd);
892- NegatedOpnd = ensureEmulated (NegatedOpnd);
893-
894- auto *AbsVal = Builder.CreateSelect (PredSigned, NegatedOpnd, VOprnd);
895- AbsVal = ensureEmulated (AbsVal);
896-
897- Type *CnvType = Op.getType ();
898- if (!Op.getType ()->isVectorTy ()) {
899- CnvType = IGCLLVM::FixedVectorType::get (Builder.getFloatTy (), 1 );
900- }
901- auto *Cnv = Builder.CreateUIToFP (AbsVal, CnvType);
902- Cnv = ensureEmulated (Cnv);
903-
904- // we want to set a proper sign, so we cast it to <N x int>,
905- // set sign bit and cast-away to the final result
906- Value *AsInt = Builder.CreateBitCast (Cnv, K.getVTy ());
907- auto *Result = Builder.CreateOr (AsInt, SignVal);
908- return Builder.CreateBitCast (Result, Op.getType ());
909- }
910- // Expands both UI64->half and SI64->half
911- Value *GenXEmulate::Emu64Expander::buildI64ToHalf (CastInst &Op) {
912- IGC_ASSERT_MESSAGE (Op.getType ()->getScalarType ()->isHalfTy (),
913- " UI64->half or SI64->half conversion expected" );
914-
915- auto Builder = getIRBuilder ();
916- auto *FloatTy = Type::getFloatTy (Op.getContext ());
917- auto *Conv = cast<Instruction>(
918- Builder.CreateCast (Op.getOpcode (), Op.getOperand (0 ),
919- changeScalarType (Op.getType (), FloatTy)));
920- auto *EmulatedConv = Emu64Expander{ST, *Conv}.tryExpand ();
921- Conv->eraseFromParent ();
922- return Builder.CreateFPTrunc (EmulatedConv, Op.getType (), " int_emu.truncate" );
923- }
924-
925732Value *GenXEmulate::Emu64Expander::visitZExtInst (ZExtInst &I) {
926733 auto Builder = getIRBuilder ();
927734 auto VOp = toVector (Builder, I.getOperand (0 ));
0 commit comments