summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCISelLowering.cpp')
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelLowering.cpp59
1 files changed, 41 insertions, 18 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.");
OpenPOWER on IntegriCloud