diff options
Diffstat (limited to 'llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp')
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp index a963638be98..6c30057e5e2 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp @@ -304,6 +304,9 @@ class SystemZDAGToDAGISel : public SelectionDAGISel { void splitLargeImmediate(unsigned Opcode, SDNode *Node, SDValue Op0, uint64_t UpperVal, uint64_t LowerVal); + void loadVectorConstant(const SystemZVectorConstantInfo &VCI, + SDNode *Node); + // Try to use gather instruction Opcode to implement vector insertion N. bool tryGather(SDNode *N, unsigned Opcode); @@ -1132,6 +1135,35 @@ void SystemZDAGToDAGISel::splitLargeImmediate(unsigned Opcode, SDNode *Node, SelectCode(Or.getNode()); } +void SystemZDAGToDAGISel::loadVectorConstant( + const SystemZVectorConstantInfo &VCI, SDNode *Node) { + assert((VCI.Opcode == SystemZISD::BYTE_MASK || + VCI.Opcode == SystemZISD::REPLICATE || + VCI.Opcode == SystemZISD::ROTATE_MASK) && + "Bad opcode!"); + assert(VCI.VecVT.getSizeInBits() == 128 && "Expected a vector type"); + EVT VT = Node->getValueType(0); + SDLoc DL(Node); + SmallVector<SDValue, 2> Ops; + for (unsigned OpVal : VCI.OpVals) + Ops.push_back(CurDAG->getConstant(OpVal, DL, MVT::i32)); + SDValue Op = CurDAG->getNode(VCI.Opcode, DL, VCI.VecVT, Ops); + + if (VCI.VecVT == VT.getSimpleVT()) + ReplaceNode(Node, Op.getNode()); + else if (VT.getSizeInBits() == 128) { + SDValue BitCast = CurDAG->getNode(ISD::BITCAST, DL, VT, Op); + ReplaceNode(Node, BitCast.getNode()); + SelectCode(BitCast.getNode()); + } else { // float or double + unsigned SubRegIdx = + (VT.getSizeInBits() == 32 ? SystemZ::subreg_h32 : SystemZ::subreg_h64); + ReplaceNode( + Node, CurDAG->getTargetExtractSubreg(SubRegIdx, DL, VT, Op).getNode()); + } + SelectCode(Op.getNode()); +} + bool SystemZDAGToDAGISel::tryGather(SDNode *N, unsigned Opcode) { SDValue ElemV = N->getOperand(2); auto *ElemN = dyn_cast<ConstantSDNode>(ElemV); @@ -1529,13 +1561,9 @@ void SystemZDAGToDAGISel::Select(SDNode *Node) { case ISD::BUILD_VECTOR: { auto *BVN = cast<BuildVectorSDNode>(Node); - SDLoc DL(Node); - EVT VT = Node->getValueType(0); - uint64_t Mask = 0; - if (SystemZTargetLowering::tryBuildVectorByteMask(BVN, Mask)) { - SDNode *Res = CurDAG->getMachineNode(SystemZ::VGBM, DL, VT, - CurDAG->getTargetConstant(Mask, DL, MVT::i32)); - ReplaceNode(Node, Res); + SystemZVectorConstantInfo VCI(BVN); + if (VCI.isVectorConstantLegal(*Subtarget)) { + loadVectorConstant(VCI, Node); return; } break; @@ -1545,23 +1573,10 @@ void SystemZDAGToDAGISel::Select(SDNode *Node) { APFloat Imm = cast<ConstantFPSDNode>(Node)->getValueAPF(); if (Imm.isZero() || Imm.isNegZero()) break; - const SystemZInstrInfo *TII = getInstrInfo(); - EVT VT = Node->getValueType(0); - unsigned Start, End; - unsigned BitWidth = VT.getSizeInBits(); - bool Success = SystemZTargetLowering::analyzeFPImm(Imm, BitWidth, Start, - End, static_cast<const SystemZInstrInfo *>(TII)); (void)Success; + SystemZVectorConstantInfo VCI(Imm); + bool Success = VCI.isVectorConstantLegal(*Subtarget); (void)Success; assert(Success && "Expected legal FP immediate"); - SDLoc DL(Node); - unsigned Opcode = (BitWidth == 32 ? SystemZ::VGMF : SystemZ::VGMG); - SDNode *Res = CurDAG->getMachineNode(Opcode, DL, VT, - CurDAG->getTargetConstant(Start, DL, MVT::i32), - CurDAG->getTargetConstant(End, DL, MVT::i32)); - unsigned SubRegIdx = (BitWidth == 32 ? SystemZ::subreg_h32 - : SystemZ::subreg_h64); - Res = CurDAG->getTargetExtractSubreg(SubRegIdx, DL, VT, SDValue(Res, 0)) - .getNode(); - ReplaceNode(Node, Res); + loadVectorConstant(VCI, Node); return; } |