forked from OSchip/llvm-project
[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:
parent
786a140650
commit
49476a4d66
|
@ -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);
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue