summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
diff options
context:
space:
mode:
authorLei Huang <lei@ca.ibm.com>2018-05-08 17:36:40 +0000
committerLei Huang <lei@ca.ibm.com>2018-05-08 17:36:40 +0000
commitc29229a6441b8818578247053af1686c72d46732 (patch)
tree09fea204011962ea8124d9d54aed41928f5ff201 /llvm/lib/Target/PowerPC/PPCISelLowering.cpp
parent2550ca1e93a6caae1a46f160087f06dea669d7d9 (diff)
downloadbcm5719-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/Target/PowerPC/PPCISelLowering.cpp')
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelLowering.cpp129
1 files changed, 77 insertions, 52 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))
OpenPOWER on IntegriCloud