@@ -796,10 +796,134 @@ conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
796
796
{{MI.getOperand (1 ).getReg (), FromType, 0 }});
797
797
}
798
798
799
+ static RTLIB::Libcall
800
+ getStateLibraryFunctionFor (MachineInstr &MI, const TargetLowering &TLI) {
801
+ RTLIB::Libcall RTLibcall;
802
+ switch (MI.getOpcode ()) {
803
+ case TargetOpcode::G_GET_FPMODE:
804
+ RTLibcall = RTLIB::FEGETMODE;
805
+ break ;
806
+ case TargetOpcode::G_SET_FPMODE:
807
+ case TargetOpcode::G_RESET_FPMODE:
808
+ RTLibcall = RTLIB::FESETMODE;
809
+ break ;
810
+ default :
811
+ llvm_unreachable (" Unexpected opcode" );
812
+ }
813
+ return RTLibcall;
814
+ }
815
+
816
+ // Some library functions that read FP state (fegetmode, fegetenv) write the
817
+ // state into a region in memory. IR intrinsics that do the same operations
818
+ // (get_fpmode, get_fpenv) return the state as integer value. To implement these
819
+ // intrinsics via the library functions, we need to use temporary variable,
820
+ // for example:
821
+ //
822
+ // %0:_(s32) = G_GET_FPMODE
823
+ //
824
+ // is transformed to:
825
+ //
826
+ // %1:_(p0) = G_FRAME_INDEX %stack.0
827
+ // BL &fegetmode
828
+ // %0:_(s32) = G_LOAD % 1
829
+ //
830
+ LegalizerHelper::LegalizeResult
831
+ LegalizerHelper::createGetStateLibcall (MachineIRBuilder &MIRBuilder,
832
+ MachineInstr &MI) {
833
+ const DataLayout &DL = MIRBuilder.getDataLayout ();
834
+ auto &MF = MIRBuilder.getMF ();
835
+ auto &MRI = *MIRBuilder.getMRI ();
836
+ auto &Ctx = MF.getFunction ().getContext ();
837
+
838
+ // Create temporary, where library function will put the read state.
839
+ Register Dst = MI.getOperand (0 ).getReg ();
840
+ LLT StateTy = MRI.getType (Dst);
841
+ TypeSize StateSize = StateTy.getSizeInBytes ();
842
+ Align TempAlign = getStackTemporaryAlignment (StateTy);
843
+ MachinePointerInfo TempPtrInfo;
844
+ auto Temp = createStackTemporary (StateSize, TempAlign, TempPtrInfo);
845
+
846
+ // Create a call to library function, with the temporary as an argument.
847
+ unsigned TempAddrSpace = DL.getAllocaAddrSpace ();
848
+ Type *StatePtrTy = PointerType::get (Ctx, TempAddrSpace);
849
+ RTLIB::Libcall RTLibcall = getStateLibraryFunctionFor (MI, TLI);
850
+ auto Res =
851
+ createLibcall (MIRBuilder, RTLibcall,
852
+ CallLowering::ArgInfo ({0 }, Type::getVoidTy (Ctx), 0 ),
853
+ CallLowering::ArgInfo ({Temp.getReg (0 ), StatePtrTy, 0 }));
854
+ if (Res != LegalizerHelper::Legalized)
855
+ return Res;
856
+
857
+ // Create a load from the temporary.
858
+ MachineMemOperand *MMO = MF.getMachineMemOperand (
859
+ TempPtrInfo, MachineMemOperand::MOLoad, StateTy, TempAlign);
860
+ MIRBuilder.buildLoadInstr (TargetOpcode::G_LOAD, Dst, Temp, *MMO);
861
+
862
+ return LegalizerHelper::Legalized;
863
+ }
864
+
865
+ // Similar to `createGetStateLibcall` the function calls a library function
866
+ // using transient space in stack. In this case the library function reads
867
+ // content of memory region.
868
+ LegalizerHelper::LegalizeResult
869
+ LegalizerHelper::createSetStateLibcall (MachineIRBuilder &MIRBuilder,
870
+ MachineInstr &MI) {
871
+ const DataLayout &DL = MIRBuilder.getDataLayout ();
872
+ auto &MF = MIRBuilder.getMF ();
873
+ auto &MRI = *MIRBuilder.getMRI ();
874
+ auto &Ctx = MF.getFunction ().getContext ();
875
+
876
+ // Create temporary, where library function will get the new state.
877
+ Register Src = MI.getOperand (0 ).getReg ();
878
+ LLT StateTy = MRI.getType (Src);
879
+ TypeSize StateSize = StateTy.getSizeInBytes ();
880
+ Align TempAlign = getStackTemporaryAlignment (StateTy);
881
+ MachinePointerInfo TempPtrInfo;
882
+ auto Temp = createStackTemporary (StateSize, TempAlign, TempPtrInfo);
883
+
884
+ // Put the new state into the temporary.
885
+ MachineMemOperand *MMO = MF.getMachineMemOperand (
886
+ TempPtrInfo, MachineMemOperand::MOStore, StateTy, TempAlign);
887
+ MIRBuilder.buildStore (Src, Temp, *MMO);
888
+
889
+ // Create a call to library function, with the temporary as an argument.
890
+ unsigned TempAddrSpace = DL.getAllocaAddrSpace ();
891
+ Type *StatePtrTy = PointerType::get (Ctx, TempAddrSpace);
892
+ RTLIB::Libcall RTLibcall = getStateLibraryFunctionFor (MI, TLI);
893
+ return createLibcall (MIRBuilder, RTLibcall,
894
+ CallLowering::ArgInfo ({0 }, Type::getVoidTy (Ctx), 0 ),
895
+ CallLowering::ArgInfo ({Temp.getReg (0 ), StatePtrTy, 0 }));
896
+ }
897
+
898
+ // The function is used to legalize operations that set default environment
899
+ // state. In C library a call like `fesetmode(FE_DFL_MODE)` is used for that.
900
+ // On most targets supported in glibc FE_DFL_MODE is defined as
901
+ // `((const femode_t *) -1)`. Such assumption is used here. If for some target
902
+ // it is not true, the target must provide custom lowering.
903
+ LegalizerHelper::LegalizeResult
904
+ LegalizerHelper::createResetStateLibcall (MachineIRBuilder &MIRBuilder,
905
+ MachineInstr &MI) {
906
+ const DataLayout &DL = MIRBuilder.getDataLayout ();
907
+ auto &MF = MIRBuilder.getMF ();
908
+ auto &Ctx = MF.getFunction ().getContext ();
909
+
910
+ // Create an argument for the library function.
911
+ unsigned AddrSpace = DL.getDefaultGlobalsAddressSpace ();
912
+ Type *StatePtrTy = PointerType::get (Ctx, AddrSpace);
913
+ unsigned PtrSize = DL.getPointerSizeInBits (AddrSpace);
914
+ LLT MemTy = LLT::pointer (AddrSpace, PtrSize);
915
+ auto DefValue = MIRBuilder.buildConstant (LLT::scalar (PtrSize), -1LL );
916
+ DstOp Dest (MRI.createGenericVirtualRegister (MemTy));
917
+ MIRBuilder.buildIntToPtr (Dest, DefValue);
918
+
919
+ RTLIB::Libcall RTLibcall = getStateLibraryFunctionFor (MI, TLI);
920
+ return createLibcall (MIRBuilder, RTLibcall,
921
+ CallLowering::ArgInfo ({0 }, Type::getVoidTy (Ctx), 0 ),
922
+ CallLowering::ArgInfo ({ Dest.getReg (), StatePtrTy, 0 }));
923
+ }
924
+
799
925
LegalizerHelper::LegalizeResult
800
926
LegalizerHelper::libcall (MachineInstr &MI, LostDebugLocObserver &LocObserver) {
801
- LLT LLTy = MRI.getType (MI.getOperand (0 ).getReg ());
802
- unsigned Size = LLTy.getSizeInBits ();
803
927
auto &Ctx = MIRBuilder.getMF ().getFunction ().getContext ();
804
928
805
929
switch (MI.getOpcode ()) {
@@ -811,6 +935,8 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
811
935
case TargetOpcode::G_SREM:
812
936
case TargetOpcode::G_UREM:
813
937
case TargetOpcode::G_CTLZ_ZERO_UNDEF: {
938
+ LLT LLTy = MRI.getType (MI.getOperand (0 ).getReg ());
939
+ unsigned Size = LLTy.getSizeInBits ();
814
940
Type *HLTy = IntegerType::get (Ctx, Size );
815
941
auto Status = simpleLibcall (MI, MIRBuilder, Size , HLTy);
816
942
if (Status != Legalized)
@@ -841,6 +967,8 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
841
967
case TargetOpcode::G_FRINT:
842
968
case TargetOpcode::G_FNEARBYINT:
843
969
case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
970
+ LLT LLTy = MRI.getType (MI.getOperand (0 ).getReg ());
971
+ unsigned Size = LLTy.getSizeInBits ();
844
972
Type *HLTy = getFloatTypeForLLT (Ctx, LLTy);
845
973
if (!HLTy || (Size != 32 && Size != 64 && Size != 80 && Size != 128 )) {
846
974
LLVM_DEBUG (dbgs () << " No libcall available for type " << LLTy << " .\n " );
@@ -903,6 +1031,24 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
903
1031
MI.eraseFromParent ();
904
1032
return Result;
905
1033
}
1034
+ case TargetOpcode::G_GET_FPMODE: {
1035
+ LegalizeResult Result = createGetStateLibcall (MIRBuilder, MI);
1036
+ if (Result != Legalized)
1037
+ return Result;
1038
+ break ;
1039
+ }
1040
+ case TargetOpcode::G_SET_FPMODE: {
1041
+ LegalizeResult Result = createSetStateLibcall (MIRBuilder, MI);
1042
+ if (Result != Legalized)
1043
+ return Result;
1044
+ break ;
1045
+ }
1046
+ case TargetOpcode::G_RESET_FPMODE: {
1047
+ LegalizeResult Result = createResetStateLibcall (MIRBuilder, MI);
1048
+ if (Result != Legalized)
1049
+ return Result;
1050
+ break ;
1051
+ }
906
1052
}
907
1053
908
1054
MI.eraseFromParent ();
0 commit comments