summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelLowering.cpp59
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelLowering.h5
-rw-r--r--llvm/lib/Target/PowerPC/PPCInstrVSX.td9
3 files changed, 49 insertions, 24 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 41a223bd5dd..9655c212d4c 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -1405,7 +1405,7 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
case PPCISD::EXTRACT_SPE: return "PPCISD::EXTRACT_SPE";
case PPCISD::EXTSWSLI: return "PPCISD::EXTSWSLI";
case PPCISD::LD_VSX_LH: return "PPCISD::LD_VSX_LH";
- case PPCISD::FP_EXTEND_LH: return "PPCISD::FP_EXTEND_LH";
+ case PPCISD::FP_EXTEND_HALF: return "PPCISD::FP_EXTEND_HALF";
}
return nullptr;
}
@@ -9913,6 +9913,30 @@ SDValue PPCTargetLowering::LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const {
switch (Op0.getOpcode()) {
default:
return SDValue();
+ case ISD::EXTRACT_SUBVECTOR: {
+ assert(Op0.getNumOperands() == 2 &&
+ isa<ConstantSDNode>(Op0->getOperand(1)) &&
+ "Node should have 2 operands with second one being a constant!");
+
+ if (Op0.getOperand(0).getValueType() != MVT::v4f32)
+ return SDValue();
+
+ // Custom lower is only done for high or low doubleword.
+ int Idx = cast<ConstantSDNode>(Op0.getOperand(1))->getZExtValue();
+ if (Idx % 2 != 0)
+ return SDValue();
+
+ // Since input is v4f32, at this point Idx is either 0 or 2.
+ // Shift to get the doubleword position we want.
+ int DWord = Idx >> 1;
+
+ // High and low word positions are different on little endian.
+ if (Subtarget.isLittleEndian())
+ DWord ^= 0x1;
+
+ return DAG.getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64,
+ Op0.getOperand(0), DAG.getConstant(DWord, dl, MVT::i32));
+ }
case ISD::FADD:
case ISD::FMUL:
case ISD::FSUB: {
@@ -9924,26 +9948,25 @@ SDValue PPCTargetLowering::LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const {
return SDValue();
// Generate new load node.
LoadSDNode *LD = cast<LoadSDNode>(LdOp);
- SDValue LoadOps[] = { LD->getChain(), LD->getBasePtr() };
- NewLoad[i] =
- DAG.getMemIntrinsicNode(PPCISD::LD_VSX_LH, dl,
- DAG.getVTList(MVT::v4f32, MVT::Other),
- LoadOps, LD->getMemoryVT(),
- LD->getMemOperand());
- }
- SDValue NewOp = DAG.getNode(Op0.getOpcode(), SDLoc(Op0), MVT::v4f32,
- NewLoad[0], NewLoad[1],
- Op0.getNode()->getFlags());
- return DAG.getNode(PPCISD::FP_EXTEND_LH, dl, MVT::v2f64, NewOp);
+ SDValue LoadOps[] = {LD->getChain(), LD->getBasePtr()};
+ NewLoad[i] = DAG.getMemIntrinsicNode(
+ PPCISD::LD_VSX_LH, dl, DAG.getVTList(MVT::v4f32, MVT::Other), LoadOps,
+ LD->getMemoryVT(), LD->getMemOperand());
+ }
+ SDValue NewOp =
+ DAG.getNode(Op0.getOpcode(), SDLoc(Op0), MVT::v4f32, NewLoad[0],
+ NewLoad[1], Op0.getNode()->getFlags());
+ return DAG.getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewOp,
+ DAG.getConstant(0, dl, MVT::i32));
}
case ISD::LOAD: {
LoadSDNode *LD = cast<LoadSDNode>(Op0);
- SDValue LoadOps[] = { LD->getChain(), LD->getBasePtr() };
- SDValue NewLd =
- DAG.getMemIntrinsicNode(PPCISD::LD_VSX_LH, dl,
- DAG.getVTList(MVT::v4f32, MVT::Other),
- LoadOps, LD->getMemoryVT(), LD->getMemOperand());
- return DAG.getNode(PPCISD::FP_EXTEND_LH, dl, MVT::v2f64, NewLd);
+ SDValue LoadOps[] = {LD->getChain(), LD->getBasePtr()};
+ SDValue NewLd = DAG.getMemIntrinsicNode(
+ PPCISD::LD_VSX_LH, dl, DAG.getVTList(MVT::v4f32, MVT::Other), LoadOps,
+ LD->getMemoryVT(), LD->getMemOperand());
+ return DAG.getNode(PPCISD::FP_EXTEND_HALF, dl, MVT::v2f64, NewLd,
+ DAG.getConstant(0, dl, MVT::i32));
}
}
llvm_unreachable("ERROR:Should return for all cases within swtich.");
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h
index dda9df97158..f143d52870b 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h
@@ -412,8 +412,9 @@ namespace llvm {
/// representation.
QBFLT,
- /// Custom extend v4f32 to v2f64.
- FP_EXTEND_LH,
+ /// FP_EXTEND_HALF(VECTOR, IDX) - Custom extend upper (IDX=0) half or
+ /// lower (IDX=1) half of v4f32 to v2f64.
+ FP_EXTEND_HALF,
/// CHAIN = STBRX CHAIN, GPRC, Ptr, Type - This is a
/// byte-swapping store instruction. It byte-swaps the low "Type" bits of
diff --git a/llvm/lib/Target/PowerPC/PPCInstrVSX.td b/llvm/lib/Target/PowerPC/PPCInstrVSX.td
index fbae8de4081..f6e2a3259a2 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrVSX.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrVSX.td
@@ -58,8 +58,8 @@ def SDT_PPCldvsxlh : SDTypeProfile<1, 1, [
SDTCisVT<0, v4f32>, SDTCisPtrTy<1>
]>;
-def SDT_PPCfpextlh : SDTypeProfile<1, 1, [
- SDTCisVT<0, v2f64>, SDTCisVT<1, v4f32>
+def SDT_PPCfpexth : SDTypeProfile<1, 2, [
+ SDTCisVT<0, v2f64>, SDTCisVT<1, v4f32>, SDTCisPtrTy<2>
]>;
// Little-endian-specific nodes.
@@ -102,7 +102,7 @@ def PPCuvec2fp: SDNode<"PPCISD::UINT_VEC_TO_FP", SDTVecConv, []>;
def PPCswapNoChain : SDNode<"PPCISD::SWAP_NO_CHAIN", SDT_PPCxxswapd>;
def PPCvabsd : SDNode<"PPCISD::VABSD", SDTVabsd, []>;
-def PPCfpextlh : SDNode<"PPCISD::FP_EXTEND_LH", SDT_PPCfpextlh, []>;
+def PPCfpexth : SDNode<"PPCISD::FP_EXTEND_HALF", SDT_PPCfpexth, []>;
def PPCldvsxlh : SDNode<"PPCISD::LD_VSX_LH", SDT_PPCldvsxlh,
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
@@ -1086,7 +1086,8 @@ def : Pat<(v2f64 (PPCuvec2fp v4i32:$C, 0)),
def : Pat<(v2f64 (PPCuvec2fp v4i32:$C, 1)),
(v2f64 (XVCVUXWDP (v2i64 (XXMRGLW $C, $C))))>;
-def : Pat<(v2f64 (PPCfpextlh v4f32:$C)), (XVCVSPDP (XXMRGHW $C, $C))>;
+def : Pat<(v2f64 (PPCfpexth v4f32:$C, 0)), (XVCVSPDP (XXMRGHW $C, $C))>;
+def : Pat<(v2f64 (PPCfpexth v4f32:$C, 1)), (XVCVSPDP (XXMRGLW $C, $C))>;
// Loads.
let Predicates = [HasVSX, HasOnlySwappingMemOps] in {
OpenPOWER on IntegriCloud