diff options
| author | Lei Huang <lei@ca.ibm.com> | 2018-05-08 17:36:40 +0000 |
|---|---|---|
| committer | Lei Huang <lei@ca.ibm.com> | 2018-05-08 17:36:40 +0000 |
| commit | c29229a6441b8818578247053af1686c72d46732 (patch) | |
| tree | 09fea204011962ea8124d9d54aed41928f5ff201 /llvm/lib | |
| parent | 2550ca1e93a6caae1a46f160087f06dea669d7d9 (diff) | |
| download | bcm5719-llvm-c29229a6441b8818578247053af1686c72d46732.tar.gz bcm5719-llvm-c29229a6441b8818578247053af1686c72d46732.zip | |
[PowerPC] Unify handling for conversion of FP_TO_INT feeding a store
Existing DAG combine only handles conversions for FP_TO_SINT:
"{f32, f64} x { i32, i16 }"
This patch simplifies the code to handle:
"{ FP_TO_SINT, FP_TO_UINT } x { f64, f32 } x { i64, i32, i16, i8 }"
Differential Revision: https://reviews.llvm.org/D46102
llvm-svn: 331778
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 129 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.h | 7 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCInstrInfo.td | 18 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCInstrVSX.td | 51 |
4 files changed, 149 insertions, 56 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index cfe77f4e3e3..bbf0caea10c 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1158,6 +1158,10 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { case PPCISD::FCTIWZ: return "PPCISD::FCTIWZ"; case PPCISD::FCTIDUZ: return "PPCISD::FCTIDUZ"; case PPCISD::FCTIWUZ: return "PPCISD::FCTIWUZ"; + case PPCISD::FP_TO_UINT_IN_VSR: + return "PPCISD::FP_TO_UINT_IN_VSR,"; + case PPCISD::FP_TO_SINT_IN_VSR: + return "PPCISD::FP_TO_SINT_IN_VSR"; case PPCISD::FRE: return "PPCISD::FRE"; case PPCISD::FRSQRTE: return "PPCISD::FRSQRTE"; case PPCISD::STFIWX: return "PPCISD::STFIWX"; @@ -1211,6 +1215,8 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { case PPCISD::SExtVElems: return "PPCISD::SExtVElems"; case PPCISD::LXVD2X: return "PPCISD::LXVD2X"; case PPCISD::STXVD2X: return "PPCISD::STXVD2X"; + case PPCISD::ST_VSR_SCAL_INT: + return "PPCISD::ST_VSR_SCAL_INT"; case PPCISD::COND_BRANCH: return "PPCISD::COND_BRANCH"; case PPCISD::BDNZ: return "PPCISD::BDNZ"; case PPCISD::BDZ: return "PPCISD::BDZ"; @@ -12224,6 +12230,64 @@ SDValue PPCTargetLowering::expandVSXStoreForLE(SDNode *N, return Store; } +// Handle DAG combine for STORE (FP_TO_INT F). +SDValue PPCTargetLowering::combineStoreFPToInt(SDNode *N, + DAGCombinerInfo &DCI) const { + + SelectionDAG &DAG = DCI.DAG; + SDLoc dl(N); + unsigned Opcode = N->getOperand(1).getOpcode(); + + assert((Opcode == ISD::FP_TO_SINT || Opcode == ISD::FP_TO_UINT) + && "Not a FP_TO_INT Instruction!"); + + SDValue Val = N->getOperand(1).getOperand(0); + EVT Op1VT = N->getOperand(1).getValueType(); + EVT ResVT = Val.getValueType(); + + // Floating point types smaller than 32 bits are not legal on Power. + if (ResVT.getScalarSizeInBits() < 32) + return SDValue(); + + // Only perform combine for conversion to i64/i32 or power9 i16/i8. + bool ValidTypeForStoreFltAsInt = + (Op1VT == MVT::i32 || Op1VT == MVT::i64 || + (Subtarget.hasP9Vector() && (Op1VT == MVT::i16 || Op1VT == MVT::i8))); + + if (ResVT == MVT::ppcf128 || !Subtarget.hasP8Altivec() || + cast<StoreSDNode>(N)->isTruncatingStore() || !ValidTypeForStoreFltAsInt) + return SDValue(); + + // Extend f32 values to f64 + if (ResVT.getScalarSizeInBits() == 32) { + Val = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Val); + DCI.AddToWorklist(Val.getNode()); + } + + // Set signed or unsigned conversion opcode. + unsigned ConvOpcode = (Opcode == ISD::FP_TO_SINT) ? + PPCISD::FP_TO_SINT_IN_VSR : + PPCISD::FP_TO_UINT_IN_VSR; + + Val = DAG.getNode(ConvOpcode, + dl, ResVT == MVT::f128 ? MVT::f128 : MVT::f64, Val); + DCI.AddToWorklist(Val.getNode()); + + // Set number of bytes being converted. + unsigned ByteSize = Op1VT.getScalarSizeInBits() / 8; + SDValue Ops[] = { N->getOperand(0), Val, N->getOperand(2), + DAG.getIntPtrConstant(ByteSize, dl, false), + DAG.getValueType(Op1VT) }; + + Val = DAG.getMemIntrinsicNode(PPCISD::ST_VSR_SCAL_INT, dl, + DAG.getVTList(MVT::Other), Ops, + cast<StoreSDNode>(N)->getMemoryVT(), + cast<StoreSDNode>(N)->getMemOperand()); + + DCI.AddToWorklist(Val.getNode()); + return Val; +} + SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -12263,60 +12327,22 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, case ISD::UINT_TO_FP: return combineFPToIntToFP(N, DCI); case ISD::STORE: { + EVT Op1VT = N->getOperand(1).getValueType(); - bool ValidTypeForStoreFltAsInt = (Op1VT == MVT::i32) || - (Subtarget.hasP9Vector() && (Op1VT == MVT::i8 || Op1VT == MVT::i16)); - - // Turn STORE (FP_TO_SINT F) -> STFIWX(FCTIWZ(F)). - if (Subtarget.hasSTFIWX() && !cast<StoreSDNode>(N)->isTruncatingStore() && - N->getOperand(1).getOpcode() == ISD::FP_TO_SINT && - ValidTypeForStoreFltAsInt && - N->getOperand(1).getOperand(0).getValueType() != MVT::ppcf128) { - SDValue Val = N->getOperand(1).getOperand(0); - if (Val.getValueType() == MVT::f32) { - Val = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Val); - DCI.AddToWorklist(Val.getNode()); - } - Val = DAG.getNode(PPCISD::FCTIWZ, dl, MVT::f64, Val); - DCI.AddToWorklist(Val.getNode()); - - if (Op1VT == MVT::i32) { - SDValue Ops[] = { - N->getOperand(0), Val, N->getOperand(2), - DAG.getValueType(N->getOperand(1).getValueType()) - }; - - Val = DAG.getMemIntrinsicNode(PPCISD::STFIWX, dl, - DAG.getVTList(MVT::Other), Ops, - cast<StoreSDNode>(N)->getMemoryVT(), - cast<StoreSDNode>(N)->getMemOperand()); - } else { - unsigned WidthInBytes = - N->getOperand(1).getValueType() == MVT::i8 ? 1 : 2; - SDValue WidthConst = DAG.getIntPtrConstant(WidthInBytes, dl, false); - - SDValue Ops[] = { - N->getOperand(0), Val, N->getOperand(2), WidthConst, - DAG.getValueType(N->getOperand(1).getValueType()) - }; - Val = DAG.getMemIntrinsicNode(PPCISD::STXSIX, dl, - DAG.getVTList(MVT::Other), Ops, - cast<StoreSDNode>(N)->getMemoryVT(), - cast<StoreSDNode>(N)->getMemOperand()); - } + unsigned Opcode = N->getOperand(1).getOpcode(); - DCI.AddToWorklist(Val.getNode()); - return Val; + if (Opcode == ISD::FP_TO_SINT || Opcode == ISD::FP_TO_UINT) { + SDValue Val= combineStoreFPToInt(N, DCI); + if (Val) + return Val; } // Turn STORE (BSWAP) -> sthbrx/stwbrx. - if (cast<StoreSDNode>(N)->isUnindexed() && - N->getOperand(1).getOpcode() == ISD::BSWAP && + if (cast<StoreSDNode>(N)->isUnindexed() && Opcode == ISD::BSWAP && N->getOperand(1).getNode()->hasOneUse() && - (N->getOperand(1).getValueType() == MVT::i32 || - N->getOperand(1).getValueType() == MVT::i16 || - (Subtarget.hasLDBRX() && Subtarget.isPPC64() && - N->getOperand(1).getValueType() == MVT::i64))) { + (Op1VT == MVT::i32 || Op1VT == MVT::i16 || + (Subtarget.hasLDBRX() && Subtarget.isPPC64() && Op1VT == MVT::i64))) { + // STBRX can only handle simple types. EVT mVT = cast<StoreSDNode>(N)->getMemoryVT(); if (mVT.isExtended()) @@ -12349,9 +12375,8 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, // STORE Constant:i32<0> -> STORE<trunc to i32> Constant:i64<0> // So it can increase the chance of CSE constant construction. - EVT VT = N->getOperand(1).getValueType(); if (Subtarget.isPPC64() && !DCI.isBeforeLegalize() && - isa<ConstantSDNode>(N->getOperand(1)) && VT == MVT::i32) { + isa<ConstantSDNode>(N->getOperand(1)) && Op1VT == MVT::i32) { // Need to sign-extended to 64-bits to handle negative values. EVT MemVT = cast<StoreSDNode>(N)->getMemoryVT(); uint64_t Val64 = SignExtend64(N->getConstantOperandVal(1), @@ -12369,8 +12394,8 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, // For little endian, VSX stores require generating xxswapd/lxvd2x. // Not needed on ISA 3.0 based CPUs since we have a non-permuting store. - if (VT.isSimple()) { - MVT StoreVT = VT.getSimpleVT(); + if (Op1VT.isSimple()) { + MVT StoreVT = Op1VT.getSimpleVT(); if (Subtarget.needsSwapsForVSXMemOps() && (StoreVT == MVT::v2f64 || StoreVT == MVT::v2i64 || StoreVT == MVT::v4f32 || StoreVT == MVT::v4i32)) diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h index f9d4c20bb2f..0c837730f00 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -71,6 +71,9 @@ namespace llvm { /// unsigned integers with round toward zero. FCTIDUZ, FCTIWUZ, + /// Floating-point-to-interger conversion instructions + FP_TO_UINT_IN_VSR, FP_TO_SINT_IN_VSR, + /// VEXTS, ByteWidth - takes an input in VSFRC and produces an output in /// VSFRC that is sign-extended from ByteWidth to a 64-byte integer. VEXTS, @@ -426,6 +429,9 @@ namespace llvm { /// an xxswapd. STXVD2X, + /// Store scalar integers from VSR. + ST_VSR_SCAL_INT, + /// QBRC, CHAIN = QVLFSb CHAIN, Ptr /// The 4xf32 load used for v4i1 constants. QVLFSb, @@ -1063,6 +1069,7 @@ namespace llvm { SDValue DAGCombineExtBoolTrunc(SDNode *N, DAGCombinerInfo &DCI) const; SDValue DAGCombineBuildVector(SDNode *N, DAGCombinerInfo &DCI) const; SDValue DAGCombineTruncBoolExt(SDNode *N, DAGCombinerInfo &DCI) const; + SDValue combineStoreFPToInt(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineFPToIntToFP(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineSHL(SDNode *N, DAGCombinerInfo &DCI) const; SDValue combineSRA(SDNode *N, DAGCombinerInfo &DCI) const; diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index cbe6a8cd094..ece17a77625 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -29,6 +29,12 @@ def SDT_PPCLxsizx : SDTypeProfile<1, 2, [ def SDT_PPCstxsix : SDTypeProfile<0, 3, [ SDTCisVT<0, f64>, SDTCisPtrTy<1>, SDTCisPtrTy<2> ]>; +def SDT_PPCcv_fp_to_int : SDTypeProfile<1, 1, [ + SDTCisFP<0>, SDTCisFP<1> + ]>; +def SDT_PPCstore_scal_int_from_vsr : SDTypeProfile<0, 3, [ + SDTCisVT<0, f64>, SDTCisPtrTy<1>, SDTCisPtrTy<2> +]>; def SDT_PPCVexts : SDTypeProfile<1, 2, [ SDTCisVT<0, f64>, SDTCisVT<1, f64>, SDTCisPtrTy<2> ]>; @@ -123,6 +129,14 @@ def PPCfctidz : SDNode<"PPCISD::FCTIDZ", SDTFPUnaryOp, []>; def PPCfctiwz : SDNode<"PPCISD::FCTIWZ", SDTFPUnaryOp, []>; def PPCfctiduz: SDNode<"PPCISD::FCTIDUZ",SDTFPUnaryOp, []>; def PPCfctiwuz: SDNode<"PPCISD::FCTIWUZ",SDTFPUnaryOp, []>; + +def PPCcv_fp_to_uint_in_vsr: + SDNode<"PPCISD::FP_TO_UINT_IN_VSR", SDT_PPCcv_fp_to_int, []>; +def PPCcv_fp_to_sint_in_vsr: + SDNode<"PPCISD::FP_TO_SINT_IN_VSR", SDT_PPCcv_fp_to_int, []>; +def PPCstore_scal_int_from_vsr: + SDNode<"PPCISD::ST_VSR_SCAL_INT", SDT_PPCstore_scal_int_from_vsr, + [SDNPHasChain, SDNPMayStore]>; def PPCstfiwx : SDNode<"PPCISD::STFIWX", SDT_PPCstfiwx, [SDNPHasChain, SDNPMayStore]>; def PPClfiwax : SDNode<"PPCISD::LFIWAX", SDT_PPClfiwx, @@ -1998,7 +2012,7 @@ def STWX : XForm_8_memOp<31, 151, (outs), (ins gprc:$rS, memrr:$dst), "stwx $rS, $dst", IIC_LdStStore, [(store i32:$rS, xaddr:$dst)]>, PPC970_DGroup_Cracked; - + def STHBRX: XForm_8_memOp<31, 918, (outs), (ins gprc:$rS, memrr:$dst), "sthbrx $rS, $dst", IIC_LdStStore, [(PPCstbrx i32:$rS, xoaddr:$dst, i16)]>, @@ -2011,7 +2025,7 @@ def STWBRX: XForm_8_memOp<31, 662, (outs), (ins gprc:$rS, memrr:$dst), def STFIWX: XForm_28_memOp<31, 983, (outs), (ins f8rc:$frS, memrr:$dst), "stfiwx $frS, $dst", IIC_LdStSTFD, [(PPCstfiwx f64:$frS, xoaddr:$dst)]>; - + def STFSX : XForm_28_memOp<31, 663, (outs), (ins f4rc:$frS, memrr:$dst), "stfsx $frS, $dst", IIC_LdStSTFD, [(store f32:$frS, xaddr:$dst)]>; diff --git a/llvm/lib/Target/PowerPC/PPCInstrVSX.td b/llvm/lib/Target/PowerPC/PPCInstrVSX.td index 1907b2766fb..99b3ea3a3db 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrVSX.td +++ b/llvm/lib/Target/PowerPC/PPCInstrVSX.td @@ -1200,6 +1200,7 @@ def ScalarLoads { */ def HasP8Vector : Predicate<"PPCSubTarget->hasP8Vector()">; def HasDirectMove : Predicate<"PPCSubTarget->hasDirectMove()">; +def NoP9Vector : Predicate<"!PPCSubTarget->hasP9Vector()">; let Predicates = [HasP8Vector] in { let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns. let isCommutable = 1, UseVSXReg = 1 in { @@ -1464,6 +1465,25 @@ let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns. } def : Pat<(v4i32 (scalar_to_vector ScalarLoads.Li32)), (v4i32 (XXSPLTWs (LIWAX xoaddr:$src), 1))>; + + // Instructions for converting float to i64 feeding a store. + let Predicates = [NoP9Vector] in { + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), xoaddr:$dst, 8), + (STXSDX (XSCVDPSXDS f64:$src), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), xoaddr:$dst, 8), + (STXSDX (XSCVDPUXDS f64:$src), xoaddr:$dst)>; + } + + // Instructions for converting float to i32 feeding a store. + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), xoaddr:$dst, 4), + (STIWX (XSCVDPSXWS f64:$src), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), xoaddr:$dst, 4), + (STIWX (XSCVDPUXWS f64:$src), xoaddr:$dst)>; + } // AddedComplexity = 400 } // HasP8Vector @@ -3150,8 +3170,36 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { def : Pat<(f128 (uint_to_fp ScalarLoads.ZELi8)), (f128 (XSCVUDQP (LXSIBZX xoaddr:$src)))>; -} // end HasP9Vector, AddedComplexity + // Instructions for fptosint (i64,i16,i8) feeding a store. + // The 8-byte version is repeated here due to availability of D-Form STXSD. + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), xaddr:$dst, 8), + (STXSDX (XSCVDPSXDS f64:$src), xaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), ixaddr:$dst, 8), + (STXSD (XSCVDPSXDS f64:$src), ixaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), xoaddr:$dst, 2), + (STXSIHX (XSCVDPSXWS f64:$src), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_sint_in_vsr f64:$src)), xoaddr:$dst, 1), + (STXSIBX (XSCVDPSXWS f64:$src), xoaddr:$dst)>; + + // Instructions for fptouint (i64,i16,i8) feeding a store. + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), xaddr:$dst, 8), + (STXSDX (XSCVDPUXDS f64:$src), xaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), ixaddr:$dst, 8), + (STXSD (XSCVDPUXDS f64:$src), ixaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), xoaddr:$dst, 2), + (STXSIHX (XSCVDPUXWS f64:$src), xoaddr:$dst)>; + def : Pat<(PPCstore_scal_int_from_vsr + (f64 (PPCcv_fp_to_uint_in_vsr f64:$src)), xoaddr:$dst, 1), + (STXSIBX (XSCVDPUXWS f64:$src), xoaddr:$dst)>; +} // end HasP9Vector, AddedComplexity let Predicates = [HasP9Vector] in { let isPseudo = 1 in { let mayStore = 1 in { @@ -3305,7 +3353,6 @@ def MrgFP { } // Patterns for BUILD_VECTOR nodes. -def NoP9Vector : Predicate<"!PPCSubTarget->hasP9Vector()">; let AddedComplexity = 400 in { let Predicates = [HasVSX] in { |

