[ARM] Add MVE lowering for fptosi.sat

This adds lowering of the llvm.fptosi.sat and llvm.fptoui.sat intinsics,
selecting a VCVT instruction which under MVE will inherently perform the
saturate.

Differential Revision: https://reviews.llvm.org/D107865
This commit is contained in:
David Green 2021-09-01 22:38:47 +01:00
parent 786a140650
commit 49476a4d66
4 changed files with 2123 additions and 1869 deletions

View File

@ -301,6 +301,9 @@ void ARMTargetLowering::addMVEVectorTypes(bool HasMVEFP) {
setOperationAction(ISD::UINT_TO_FP, VT, Expand); setOperationAction(ISD::UINT_TO_FP, VT, Expand);
setOperationAction(ISD::FP_TO_SINT, VT, Expand); setOperationAction(ISD::FP_TO_SINT, VT, Expand);
setOperationAction(ISD::FP_TO_UINT, VT, Expand); setOperationAction(ISD::FP_TO_UINT, VT, Expand);
} else {
setOperationAction(ISD::FP_TO_SINT_SAT, VT, Custom);
setOperationAction(ISD::FP_TO_UINT_SAT, VT, Custom);
} }
// Pre and Post inc are supported on loads and stores // Pre and Post inc are supported on loads and stores
@ -5821,6 +5824,32 @@ SDValue ARMTargetLowering::LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const {
return Op; return Op;
} }
static SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) {
EVT VT = Op.getValueType();
EVT ToVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
EVT FromVT = Op.getOperand(0).getValueType();
if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32)
return Op;
if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16)
return Op;
if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
return SDValue();
SDLoc DL(Op);
bool IsSigned = Op.getOpcode() == ISD::FP_TO_SINT_SAT;
unsigned BW = ToVT.getScalarSizeInBits() - IsSigned;
SDValue CVT = DAG.getNode(Op.getOpcode(), DL, VT, Op.getOperand(0),
DAG.getValueType(VT.getScalarType()));
SDValue Max = DAG.getNode(IsSigned ? ISD::SMIN : ISD::UMIN, DL, VT, CVT,
DAG.getConstant((1 << BW) - 1, DL, VT));
if (IsSigned)
Max = DAG.getNode(ISD::SMAX, DL, VT, Max,
DAG.getConstant(-(1 << BW), DL, VT));
return Max;
}
static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG) { static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG) {
EVT VT = Op.getValueType(); EVT VT = Op.getValueType();
SDLoc dl(Op); SDLoc dl(Op);
@ -10164,6 +10193,8 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::STRICT_FP_TO_UINT: case ISD::STRICT_FP_TO_UINT:
case ISD::FP_TO_SINT: case ISD::FP_TO_SINT:
case ISD::FP_TO_UINT: return LowerFP_TO_INT(Op, DAG); case ISD::FP_TO_UINT: return LowerFP_TO_INT(Op, DAG);
case ISD::FP_TO_SINT_SAT:
case ISD::FP_TO_UINT_SAT: return LowerFP_TO_INT_SAT(Op, DAG);
case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG); case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG);
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);

View File

@ -4049,6 +4049,17 @@ defm MVE_VCVTf16u16n : MVE_VCVT_fp_int_m<MVE_v8f16, MVE_v8u16, uint_to_fp>;
defm MVE_VCVTf32s32n : MVE_VCVT_fp_int_m<MVE_v4f32, MVE_v4s32, sint_to_fp>; defm MVE_VCVTf32s32n : MVE_VCVT_fp_int_m<MVE_v4f32, MVE_v4s32, sint_to_fp>;
defm MVE_VCVTf32u32n : MVE_VCVT_fp_int_m<MVE_v4f32, MVE_v4u32, uint_to_fp>; defm MVE_VCVTf32u32n : MVE_VCVT_fp_int_m<MVE_v4f32, MVE_v4u32, uint_to_fp>;
let Predicates = [HasMVEFloat] in {
def : Pat<(v4i32 (fp_to_sint_sat v4f32:$src, i32)),
(MVE_VCVTs32f32z v4f32:$src)>;
def : Pat<(v4i32 (fp_to_uint_sat v4f32:$src, i32)),
(MVE_VCVTu32f32z v4f32:$src)>;
def : Pat<(v8i16 (fp_to_sint_sat v8f16:$src, i16)),
(MVE_VCVTs16f16z v8f16:$src)>;
def : Pat<(v8i16 (fp_to_uint_sat v8f16:$src, i16)),
(MVE_VCVTu16f16z v8f16:$src)>;
}
class MVE_VABSNEG_fp<string iname, string suffix, bits<2> size, bit negate, class MVE_VABSNEG_fp<string iname, string suffix, bits<2> size, bit negate,
list<dag> pattern=[]> list<dag> pattern=[]>
: MVE_float<iname, suffix, (outs MQPR:$Qd), : MVE_float<iname, suffix, (outs MQPR:$Qd),

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff