@@ -167,14 +167,6 @@ class GenXEmulate : public ModulePass {
167
167
168
168
Value *buildRightShift (IVSplitter &SplitBuilder, BinaryOperator &Op);
169
169
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
-
178
170
Value *visitZExtInst (ZExtInst &I);
179
171
Value *visitSExtInst (SExtInst &I);
180
172
@@ -737,191 +729,6 @@ Value *GenXEmulate::Emu64Expander::visitAShr(BinaryOperator &Op) {
737
729
return buildRightShift (SplitBuilder, Op);
738
730
}
739
731
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
-
925
732
Value *GenXEmulate::Emu64Expander::visitZExtInst (ZExtInst &I) {
926
733
auto Builder = getIRBuilder ();
927
734
auto VOp = toVector (Builder, I.getOperand (0 ));
0 commit comments