diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp | 508 |
1 files changed, 308 insertions, 200 deletions
diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index a6ac4e3df745..efb4c2eb0fc3 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -64,51 +64,6 @@ FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM, } } -// Intrinsics that return a a predicate. -static bool doesIntrinsicReturnPredicate(unsigned ID) { - switch (ID) { - default: - return false; - case Intrinsic::hexagon_C2_cmpeq: - case Intrinsic::hexagon_C2_cmpgt: - case Intrinsic::hexagon_C2_cmpgtu: - case Intrinsic::hexagon_C2_cmpgtup: - case Intrinsic::hexagon_C2_cmpgtp: - case Intrinsic::hexagon_C2_cmpeqp: - case Intrinsic::hexagon_C2_bitsset: - case Intrinsic::hexagon_C2_bitsclr: - case Intrinsic::hexagon_C2_cmpeqi: - case Intrinsic::hexagon_C2_cmpgti: - case Intrinsic::hexagon_C2_cmpgtui: - case Intrinsic::hexagon_C2_cmpgei: - case Intrinsic::hexagon_C2_cmpgeui: - case Intrinsic::hexagon_C2_cmplt: - case Intrinsic::hexagon_C2_cmpltu: - case Intrinsic::hexagon_C2_bitsclri: - case Intrinsic::hexagon_C2_and: - case Intrinsic::hexagon_C2_or: - case Intrinsic::hexagon_C2_xor: - case Intrinsic::hexagon_C2_andn: - case Intrinsic::hexagon_C2_not: - case Intrinsic::hexagon_C2_orn: - case Intrinsic::hexagon_C2_pxfer_map: - case Intrinsic::hexagon_C2_any8: - case Intrinsic::hexagon_C2_all8: - case Intrinsic::hexagon_A2_vcmpbeq: - case Intrinsic::hexagon_A2_vcmpbgtu: - case Intrinsic::hexagon_A2_vcmpheq: - case Intrinsic::hexagon_A2_vcmphgt: - case Intrinsic::hexagon_A2_vcmphgtu: - case Intrinsic::hexagon_A2_vcmpweq: - case Intrinsic::hexagon_A2_vcmpwgt: - case Intrinsic::hexagon_A2_vcmpwgtu: - case Intrinsic::hexagon_C2_tfrrp: - case Intrinsic::hexagon_S2_tstbit_i: - case Intrinsic::hexagon_S2_tstbit_r: - return true; - } -} - void HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl) { SDValue Chain = LD->getChain(); SDValue Base = LD->getBasePtr(); @@ -138,12 +93,18 @@ void HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl) { Opcode = IsValidInc ? Hexagon::L2_loadrh_pi : Hexagon::L2_loadrh_io; break; case MVT::i32: + case MVT::f32: + case MVT::v2i16: + case MVT::v4i8: Opcode = IsValidInc ? Hexagon::L2_loadri_pi : Hexagon::L2_loadri_io; break; case MVT::i64: + case MVT::f64: + case MVT::v2i32: + case MVT::v4i16: + case MVT::v8i8: Opcode = IsValidInc ? Hexagon::L2_loadrd_pi : Hexagon::L2_loadrd_io; break; - // 64B case MVT::v64i8: case MVT::v32i16: case MVT::v16i32: @@ -223,7 +184,6 @@ void HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl) { CurDAG->RemoveDeadNode(LD); } - MachineSDNode *HexagonDAGToDAGISel::LoadInstrForLoadIntrinsic(SDNode *IntN) { if (IntN->getOpcode() != ISD::INTRINSIC_W_CHAIN) return nullptr; @@ -241,35 +201,14 @@ MachineSDNode *HexagonDAGToDAGISel::LoadInstrForLoadIntrinsic(SDNode *IntN) { }; auto FLC = LoadPciMap.find(IntNo); if (FLC != LoadPciMap.end()) { - SDNode *Mod = CurDAG->getMachineNode(Hexagon::A2_tfrrcr, dl, MVT::i32, - IntN->getOperand(4)); EVT ValTy = (IntNo == Intrinsic::hexagon_circ_ldd) ? MVT::i64 : MVT::i32; EVT RTys[] = { ValTy, MVT::i32, MVT::Other }; // Operands: { Base, Increment, Modifier, Chain } auto Inc = cast<ConstantSDNode>(IntN->getOperand(5)); SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), dl, MVT::i32); MachineSDNode *Res = CurDAG->getMachineNode(FLC->second, dl, RTys, - { IntN->getOperand(2), I, SDValue(Mod,0), IntN->getOperand(0) }); - return Res; - } - - static std::map<unsigned,unsigned> LoadPbrMap = { - { Intrinsic::hexagon_brev_ldb, Hexagon::L2_loadrb_pbr }, - { Intrinsic::hexagon_brev_ldub, Hexagon::L2_loadrub_pbr }, - { Intrinsic::hexagon_brev_ldh, Hexagon::L2_loadrh_pbr }, - { Intrinsic::hexagon_brev_lduh, Hexagon::L2_loadruh_pbr }, - { Intrinsic::hexagon_brev_ldw, Hexagon::L2_loadri_pbr }, - { Intrinsic::hexagon_brev_ldd, Hexagon::L2_loadrd_pbr }, - }; - auto FLB = LoadPbrMap.find(IntNo); - if (FLB != LoadPbrMap.end()) { - SDNode *Mod = CurDAG->getMachineNode(Hexagon::A2_tfrrcr, dl, MVT::i32, - IntN->getOperand(4)); - EVT ValTy = (IntNo == Intrinsic::hexagon_brev_ldd) ? MVT::i64 : MVT::i32; - EVT RTys[] = { ValTy, MVT::i32, MVT::Other }; - // Operands: { Base, Modifier, Chain } - MachineSDNode *Res = CurDAG->getMachineNode(FLB->second, dl, RTys, - { IntN->getOperand(2), SDValue(Mod,0), IntN->getOperand(0) }); + { IntN->getOperand(2), I, IntN->getOperand(4), + IntN->getOperand(0) }); return Res; } @@ -343,14 +282,10 @@ bool HexagonDAGToDAGISel::tryLoadOfLoadIntrinsic(LoadSDNode *N) { // a sign-extending intrinsic into (or the other way around). ISD::LoadExtType IntExt; switch (cast<ConstantSDNode>(C->getOperand(1))->getZExtValue()) { - case Intrinsic::hexagon_brev_ldub: - case Intrinsic::hexagon_brev_lduh: case Intrinsic::hexagon_circ_ldub: case Intrinsic::hexagon_circ_lduh: IntExt = ISD::ZEXTLOAD; break; - case Intrinsic::hexagon_brev_ldw: - case Intrinsic::hexagon_brev_ldd: case Intrinsic::hexagon_circ_ldw: case Intrinsic::hexagon_circ_ldd: IntExt = ISD::NON_EXTLOAD; @@ -378,6 +313,134 @@ bool HexagonDAGToDAGISel::tryLoadOfLoadIntrinsic(LoadSDNode *N) { CurDAG->RemoveDeadNode(C); return true; } + return false; +} + +// Convert the bit-reverse load intrinsic to appropriate target instruction. +bool HexagonDAGToDAGISel::SelectBrevLdIntrinsic(SDNode *IntN) { + if (IntN->getOpcode() != ISD::INTRINSIC_W_CHAIN) + return false; + + const SDLoc &dl(IntN); + unsigned IntNo = cast<ConstantSDNode>(IntN->getOperand(1))->getZExtValue(); + + static const std::map<unsigned, unsigned> LoadBrevMap = { + { Intrinsic::hexagon_L2_loadrb_pbr, Hexagon::L2_loadrb_pbr }, + { Intrinsic::hexagon_L2_loadrub_pbr, Hexagon::L2_loadrub_pbr }, + { Intrinsic::hexagon_L2_loadrh_pbr, Hexagon::L2_loadrh_pbr }, + { Intrinsic::hexagon_L2_loadruh_pbr, Hexagon::L2_loadruh_pbr }, + { Intrinsic::hexagon_L2_loadri_pbr, Hexagon::L2_loadri_pbr }, + { Intrinsic::hexagon_L2_loadrd_pbr, Hexagon::L2_loadrd_pbr } + }; + auto FLI = LoadBrevMap.find(IntNo); + if (FLI != LoadBrevMap.end()) { + EVT ValTy = + (IntNo == Intrinsic::hexagon_L2_loadrd_pbr) ? MVT::i64 : MVT::i32; + EVT RTys[] = { ValTy, MVT::i32, MVT::Other }; + // Operands of Intrinsic: {chain, enum ID of intrinsic, baseptr, + // modifier}. + // Operands of target instruction: { Base, Modifier, Chain }. + MachineSDNode *Res = CurDAG->getMachineNode( + FLI->second, dl, RTys, + {IntN->getOperand(2), IntN->getOperand(3), IntN->getOperand(0)}); + + MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); + MemOp[0] = cast<MemIntrinsicSDNode>(IntN)->getMemOperand(); + Res->setMemRefs(MemOp, MemOp + 1); + + ReplaceUses(SDValue(IntN, 0), SDValue(Res, 0)); + ReplaceUses(SDValue(IntN, 1), SDValue(Res, 1)); + ReplaceUses(SDValue(IntN, 2), SDValue(Res, 2)); + CurDAG->RemoveDeadNode(IntN); + return true; + } + return false; +} + +/// Generate a machine instruction node for the new circlar buffer intrinsics. +/// The new versions use a CSx register instead of the K field. +bool HexagonDAGToDAGISel::SelectNewCircIntrinsic(SDNode *IntN) { + if (IntN->getOpcode() != ISD::INTRINSIC_W_CHAIN) + return false; + + SDLoc DL(IntN); + unsigned IntNo = cast<ConstantSDNode>(IntN->getOperand(1))->getZExtValue(); + SmallVector<SDValue, 7> Ops; + + static std::map<unsigned,unsigned> LoadNPcMap = { + { Intrinsic::hexagon_L2_loadrub_pci, Hexagon::PS_loadrub_pci }, + { Intrinsic::hexagon_L2_loadrb_pci, Hexagon::PS_loadrb_pci }, + { Intrinsic::hexagon_L2_loadruh_pci, Hexagon::PS_loadruh_pci }, + { Intrinsic::hexagon_L2_loadrh_pci, Hexagon::PS_loadrh_pci }, + { Intrinsic::hexagon_L2_loadri_pci, Hexagon::PS_loadri_pci }, + { Intrinsic::hexagon_L2_loadrd_pci, Hexagon::PS_loadrd_pci }, + { Intrinsic::hexagon_L2_loadrub_pcr, Hexagon::PS_loadrub_pcr }, + { Intrinsic::hexagon_L2_loadrb_pcr, Hexagon::PS_loadrb_pcr }, + { Intrinsic::hexagon_L2_loadruh_pcr, Hexagon::PS_loadruh_pcr }, + { Intrinsic::hexagon_L2_loadrh_pcr, Hexagon::PS_loadrh_pcr }, + { Intrinsic::hexagon_L2_loadri_pcr, Hexagon::PS_loadri_pcr }, + { Intrinsic::hexagon_L2_loadrd_pcr, Hexagon::PS_loadrd_pcr } + }; + auto FLI = LoadNPcMap.find (IntNo); + if (FLI != LoadNPcMap.end()) { + EVT ValTy = MVT::i32; + if (IntNo == Intrinsic::hexagon_L2_loadrd_pci || + IntNo == Intrinsic::hexagon_L2_loadrd_pcr) + ValTy = MVT::i64; + EVT RTys[] = { ValTy, MVT::i32, MVT::Other }; + // Handle load.*_pci case which has 6 operands. + if (IntN->getNumOperands() == 6) { + auto Inc = cast<ConstantSDNode>(IntN->getOperand(3)); + SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), DL, MVT::i32); + // Operands: { Base, Increment, Modifier, Start, Chain }. + Ops = { IntN->getOperand(2), I, IntN->getOperand(4), IntN->getOperand(5), + IntN->getOperand(0) }; + } else + // Handle load.*_pcr case which has 5 operands. + // Operands: { Base, Modifier, Start, Chain }. + Ops = { IntN->getOperand(2), IntN->getOperand(3), IntN->getOperand(4), + IntN->getOperand(0) }; + MachineSDNode *Res = CurDAG->getMachineNode(FLI->second, DL, RTys, Ops); + ReplaceUses(SDValue(IntN, 0), SDValue(Res, 0)); + ReplaceUses(SDValue(IntN, 1), SDValue(Res, 1)); + ReplaceUses(SDValue(IntN, 2), SDValue(Res, 2)); + CurDAG->RemoveDeadNode(IntN); + return true; + } + + static std::map<unsigned,unsigned> StoreNPcMap = { + { Intrinsic::hexagon_S2_storerb_pci, Hexagon::PS_storerb_pci }, + { Intrinsic::hexagon_S2_storerh_pci, Hexagon::PS_storerh_pci }, + { Intrinsic::hexagon_S2_storerf_pci, Hexagon::PS_storerf_pci }, + { Intrinsic::hexagon_S2_storeri_pci, Hexagon::PS_storeri_pci }, + { Intrinsic::hexagon_S2_storerd_pci, Hexagon::PS_storerd_pci }, + { Intrinsic::hexagon_S2_storerb_pcr, Hexagon::PS_storerb_pcr }, + { Intrinsic::hexagon_S2_storerh_pcr, Hexagon::PS_storerh_pcr }, + { Intrinsic::hexagon_S2_storerf_pcr, Hexagon::PS_storerf_pcr }, + { Intrinsic::hexagon_S2_storeri_pcr, Hexagon::PS_storeri_pcr }, + { Intrinsic::hexagon_S2_storerd_pcr, Hexagon::PS_storerd_pcr } + }; + auto FSI = StoreNPcMap.find (IntNo); + if (FSI != StoreNPcMap.end()) { + EVT RTys[] = { MVT::i32, MVT::Other }; + // Handle store.*_pci case which has 7 operands. + if (IntN->getNumOperands() == 7) { + auto Inc = cast<ConstantSDNode>(IntN->getOperand(3)); + SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), DL, MVT::i32); + // Operands: { Base, Increment, Modifier, Value, Start, Chain }. + Ops = { IntN->getOperand(2), I, IntN->getOperand(4), IntN->getOperand(5), + IntN->getOperand(6), IntN->getOperand(0) }; + } else + // Handle store.*_pcr case which has 6 operands. + // Operands: { Base, Modifier, Value, Start, Chain }. + Ops = { IntN->getOperand(2), IntN->getOperand(3), IntN->getOperand(4), + IntN->getOperand(5), IntN->getOperand(0) }; + MachineSDNode *Res = CurDAG->getMachineNode(FSI->second, DL, RTys, Ops); + ReplaceUses(SDValue(IntN, 0), SDValue(Res, 0)); + ReplaceUses(SDValue(IntN, 1), SDValue(Res, 1)); + CurDAG->RemoveDeadNode(IntN); + return true; + } return false; } @@ -385,9 +448,9 @@ bool HexagonDAGToDAGISel::tryLoadOfLoadIntrinsic(LoadSDNode *N) { void HexagonDAGToDAGISel::SelectLoad(SDNode *N) { SDLoc dl(N); LoadSDNode *LD = cast<LoadSDNode>(N); - ISD::MemIndexedMode AM = LD->getAddressingMode(); // Handle indexed loads. + ISD::MemIndexedMode AM = LD->getAddressingMode(); if (AM != ISD::UNINDEXED) { SelectIndexedLoad(LD, dl); return; @@ -422,9 +485,16 @@ void HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl) { Opcode = IsValidInc ? Hexagon::S2_storerh_pi : Hexagon::S2_storerh_io; break; case MVT::i32: + case MVT::f32: + case MVT::v2i16: + case MVT::v4i8: Opcode = IsValidInc ? Hexagon::S2_storeri_pi : Hexagon::S2_storeri_io; break; case MVT::i64: + case MVT::f64: + case MVT::v2i32: + case MVT::v4i16: + case MVT::v8i8: Opcode = IsValidInc ? Hexagon::S2_storerd_pi : Hexagon::S2_storerd_io; break; case MVT::v64i8: @@ -488,9 +558,9 @@ void HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl) { void HexagonDAGToDAGISel::SelectStore(SDNode *N) { SDLoc dl(N); StoreSDNode *ST = cast<StoreSDNode>(N); - ISD::MemIndexedMode AM = ST->getAddressingMode(); // Handle indexed stores. + ISD::MemIndexedMode AM = ST->getAddressingMode(); if (AM != ISD::UNINDEXED) { SelectIndexedStore(ST, dl); return; @@ -553,85 +623,6 @@ void HexagonDAGToDAGISel::SelectSHL(SDNode *N) { return Default(); } - -// -// If there is an zero_extend followed an intrinsic in DAG (this means - the -// result of the intrinsic is predicate); convert the zero_extend to -// transfer instruction. -// -// Zero extend -> transfer is lowered here. Otherwise, zero_extend will be -// converted into a MUX as predicate registers defined as 1 bit in the -// compiler. Architecture defines them as 8-bit registers. -// We want to preserve all the lower 8-bits and, not just 1 LSB bit. -// -void HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) { - SDLoc dl(N); - - SDValue Op0 = N->getOperand(0); - EVT OpVT = Op0.getValueType(); - unsigned OpBW = OpVT.getSizeInBits(); - - // Special handling for zero-extending a vector of booleans. - if (OpVT.isVector() && OpVT.getVectorElementType() == MVT::i1 && OpBW <= 64) { - SDNode *Mask = CurDAG->getMachineNode(Hexagon::C2_mask, dl, MVT::i64, Op0); - unsigned NE = OpVT.getVectorNumElements(); - EVT ExVT = N->getValueType(0); - unsigned ES = ExVT.getScalarSizeInBits(); - uint64_t MV = 0, Bit = 1; - for (unsigned i = 0; i < NE; ++i) { - MV |= Bit; - Bit <<= ES; - } - SDValue Ones = CurDAG->getTargetConstant(MV, dl, MVT::i64); - SDNode *OnesReg = CurDAG->getMachineNode(Hexagon::CONST64, dl, - MVT::i64, Ones); - if (ExVT.getSizeInBits() == 32) { - SDNode *And = CurDAG->getMachineNode(Hexagon::A2_andp, dl, MVT::i64, - SDValue(Mask,0), SDValue(OnesReg,0)); - SDValue SubR = CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32); - ReplaceNode(N, CurDAG->getMachineNode(Hexagon::EXTRACT_SUBREG, dl, ExVT, - SDValue(And, 0), SubR)); - return; - } - ReplaceNode(N, - CurDAG->getMachineNode(Hexagon::A2_andp, dl, ExVT, - SDValue(Mask, 0), SDValue(OnesReg, 0))); - return; - } - - SDNode *Int = N->getOperand(0).getNode(); - if ((Int->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) { - unsigned ID = cast<ConstantSDNode>(Int->getOperand(0))->getZExtValue(); - if (doesIntrinsicReturnPredicate(ID)) { - // Now we need to differentiate target data types. - if (N->getValueType(0) == MVT::i64) { - // Convert the zero_extend to Rs = Pd followed by A2_combinew(0,Rs). - SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32); - SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl, - MVT::i32, SDValue(Int, 0)); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, - MVT::i32, TargetConst0); - SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl, - MVT::i64, MVT::Other, - SDValue(Result_2, 0), - SDValue(Result_1, 0)); - ReplaceNode(N, Result_3); - return; - } - if (N->getValueType(0) == MVT::i32) { - // Convert the zero_extend to Rs = Pd - SDNode* RsPd = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl, - MVT::i32, SDValue(Int, 0)); - ReplaceNode(N, RsPd); - return; - } - llvm_unreachable("Unexpected value type"); - } - } - SelectCode(N); -} - - // // Handling intrinsics for circular load and bitreverse load. // @@ -642,6 +633,13 @@ void HexagonDAGToDAGISel::SelectIntrinsicWChain(SDNode *N) { return; } + // Handle bit-reverse load intrinsics. + if (SelectBrevLdIntrinsic(N)) + return; + + if (SelectNewCircIntrinsic(N)) + return; + unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); if (IntNo == Intrinsic::hexagon_V6_vgathermw || IntNo == Intrinsic::hexagon_V6_vgathermw_128B || @@ -735,7 +733,6 @@ void HexagonDAGToDAGISel::SelectConstant(SDNode *N) { SelectCode(N); } - void HexagonDAGToDAGISel::SelectFrameIndex(SDNode *N) { MachineFrameInfo &MFI = MF->getFrameInfo(); const HexagonFrameLowering *HFI = HST->getFrameLowering(); @@ -765,20 +762,113 @@ void HexagonDAGToDAGISel::SelectFrameIndex(SDNode *N) { ReplaceNode(N, R); } +void HexagonDAGToDAGISel::SelectAddSubCarry(SDNode *N) { + unsigned OpcCarry = N->getOpcode() == HexagonISD::ADDC ? Hexagon::A4_addp_c + : Hexagon::A4_subp_c; + SDNode *C = CurDAG->getMachineNode(OpcCarry, SDLoc(N), N->getVTList(), + { N->getOperand(0), N->getOperand(1), + N->getOperand(2) }); + ReplaceNode(N, C); +} -void HexagonDAGToDAGISel::SelectBitcast(SDNode *N) { - EVT SVT = N->getOperand(0).getValueType(); - EVT DVT = N->getValueType(0); - if (!SVT.isVector() || !DVT.isVector() || - SVT.getVectorElementType() == MVT::i1 || - DVT.getVectorElementType() == MVT::i1 || - SVT.getSizeInBits() != DVT.getSizeInBits()) { - SelectCode(N); - return; +void HexagonDAGToDAGISel::SelectVAlign(SDNode *N) { + MVT ResTy = N->getValueType(0).getSimpleVT(); + if (HST->isHVXVectorType(ResTy, true)) + return SelectHvxVAlign(N); + + const SDLoc &dl(N); + unsigned VecLen = ResTy.getSizeInBits(); + if (VecLen == 32) { + SDValue Ops[] = { + CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32), + N->getOperand(0), + CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32), + N->getOperand(1), + CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32) + }; + SDNode *R = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, + MVT::i64, Ops); + + // Shift right by "(Addr & 0x3) * 8" bytes. + SDValue M0 = CurDAG->getTargetConstant(0x18, dl, MVT::i32); + SDValue M1 = CurDAG->getTargetConstant(0x03, dl, MVT::i32); + SDNode *C = CurDAG->getMachineNode(Hexagon::S4_andi_asl_ri, dl, MVT::i32, + M0, N->getOperand(2), M1); + SDNode *S = CurDAG->getMachineNode(Hexagon::S2_lsr_r_p, dl, MVT::i64, + SDValue(R, 0), SDValue(C, 0)); + SDValue E = CurDAG->getTargetExtractSubreg(Hexagon::isub_lo, dl, ResTy, + SDValue(S, 0)); + ReplaceNode(N, E.getNode()); + } else { + assert(VecLen == 64); + SDNode *Pu = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::v8i1, + N->getOperand(2)); + SDNode *VA = CurDAG->getMachineNode(Hexagon::S2_valignrb, dl, ResTy, + N->getOperand(0), N->getOperand(1), + SDValue(Pu,0)); + ReplaceNode(N, VA); } +} + +void HexagonDAGToDAGISel::SelectVAlignAddr(SDNode *N) { + const SDLoc &dl(N); + SDValue A = N->getOperand(1); + int Mask = -cast<ConstantSDNode>(A.getNode())->getSExtValue(); + assert(isPowerOf2_32(-Mask)); + + SDValue M = CurDAG->getTargetConstant(Mask, dl, MVT::i32); + SDNode *AA = CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32, + N->getOperand(0), M); + ReplaceNode(N, AA); +} + +// Handle these nodes here to avoid having to write patterns for all +// combinations of input/output types. In all cases, the resulting +// instruction is the same. +void HexagonDAGToDAGISel::SelectTypecast(SDNode *N) { + SDValue Op = N->getOperand(0); + MVT OpTy = Op.getValueType().getSimpleVT(); + SDNode *T = CurDAG->MorphNodeTo(N, N->getOpcode(), + CurDAG->getVTList(OpTy), {Op}); + ReplaceNode(T, Op.getNode()); +} + +void HexagonDAGToDAGISel::SelectP2D(SDNode *N) { + MVT ResTy = N->getValueType(0).getSimpleVT(); + SDNode *T = CurDAG->getMachineNode(Hexagon::C2_mask, SDLoc(N), ResTy, + N->getOperand(0)); + ReplaceNode(N, T); +} + +void HexagonDAGToDAGISel::SelectD2P(SDNode *N) { + const SDLoc &dl(N); + MVT ResTy = N->getValueType(0).getSimpleVT(); + SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32); + SDNode *T = CurDAG->getMachineNode(Hexagon::A4_vcmpbgtui, dl, ResTy, + N->getOperand(0), Zero); + ReplaceNode(N, T); +} + +void HexagonDAGToDAGISel::SelectV2Q(SDNode *N) { + const SDLoc &dl(N); + MVT ResTy = N->getValueType(0).getSimpleVT(); - CurDAG->ReplaceAllUsesOfValueWith(SDValue(N,0), N->getOperand(0)); - CurDAG->RemoveDeadNode(N); + SDValue C = CurDAG->getTargetConstant(-1, dl, MVT::i32); + SDNode *R = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, C); + SDNode *T = CurDAG->getMachineNode(Hexagon::V6_vandvrt, dl, ResTy, + N->getOperand(0), SDValue(R,0)); + ReplaceNode(N, T); +} + +void HexagonDAGToDAGISel::SelectQ2V(SDNode *N) { + const SDLoc &dl(N); + MVT ResTy = N->getValueType(0).getSimpleVT(); + + SDValue C = CurDAG->getTargetConstant(-1, dl, MVT::i32); + SDNode *R = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, C); + SDNode *T = CurDAG->getMachineNode(Hexagon::V6_vandqrt, dl, ResTy, + N->getOperand(0), SDValue(R,0)); + ReplaceNode(N, T); } void HexagonDAGToDAGISel::Select(SDNode *N) { @@ -789,13 +879,21 @@ void HexagonDAGToDAGISel::Select(SDNode *N) { case ISD::Constant: return SelectConstant(N); case ISD::ConstantFP: return SelectConstantFP(N); case ISD::FrameIndex: return SelectFrameIndex(N); - case ISD::BITCAST: return SelectBitcast(N); case ISD::SHL: return SelectSHL(N); case ISD::LOAD: return SelectLoad(N); case ISD::STORE: return SelectStore(N); - case ISD::ZERO_EXTEND: return SelectZeroExtend(N); case ISD::INTRINSIC_W_CHAIN: return SelectIntrinsicWChain(N); case ISD::INTRINSIC_WO_CHAIN: return SelectIntrinsicWOChain(N); + + case HexagonISD::ADDC: + case HexagonISD::SUBC: return SelectAddSubCarry(N); + case HexagonISD::VALIGN: return SelectVAlign(N); + case HexagonISD::VALIGNADDR: return SelectVAlignAddr(N); + case HexagonISD::TYPECAST: return SelectTypecast(N); + case HexagonISD::P2D: return SelectP2D(N); + case HexagonISD::D2P: return SelectD2P(N); + case HexagonISD::Q2V: return SelectQ2V(N); + case HexagonISD::V2Q: return SelectV2Q(N); } if (HST->useHVXOps()) { @@ -1240,7 +1338,7 @@ bool HexagonDAGToDAGISel::SelectAnyImmediate(SDValue &N, SDValue &R, } case HexagonISD::JT: case HexagonISD::CP: - // These are assumed to always be aligned at at least 8-byte boundary. + // These are assumed to always be aligned at least 8-byte boundary. if (LogAlign > 3) return false; R = N.getOperand(0); @@ -1252,7 +1350,7 @@ bool HexagonDAGToDAGISel::SelectAnyImmediate(SDValue &N, SDValue &R, R = N; return true; case ISD::BlockAddress: - // Block address is always aligned at at least 4-byte boundary. + // Block address is always aligned at least 4-byte boundary. if (LogAlign > 2 || !IsAligned(cast<BlockAddressSDNode>(N)->getOffset())) return false; R = N; @@ -1345,9 +1443,13 @@ bool HexagonDAGToDAGISel::DetectUseSxtw(SDValue &N, SDValue &R) { EVT T = Opc == ISD::SIGN_EXTEND ? N.getOperand(0).getValueType() : cast<VTSDNode>(N.getOperand(1))->getVT(); - if (T.getSizeInBits() != 32) + unsigned SW = T.getSizeInBits(); + if (SW == 32) + R = N.getOperand(0); + else if (SW < 32) + R = N; + else return false; - R = N.getOperand(0); break; } case ISD::LOAD: { @@ -1361,6 +1463,13 @@ bool HexagonDAGToDAGISel::DetectUseSxtw(SDValue &N, SDValue &R) { R = N; break; } + case ISD::SRA: { + auto *S = dyn_cast<ConstantSDNode>(N.getOperand(1)); + if (!S || S->getZExtValue() != 32) + return false; + R = N; + break; + } default: return false; } @@ -1500,7 +1609,7 @@ static bool isOpcodeHandled(const SDNode *N) { } } -/// \brief Return the weight of an SDNode +/// Return the weight of an SDNode int HexagonDAGToDAGISel::getWeight(SDNode *N) { if (!isOpcodeHandled(N)) return 1; @@ -1799,15 +1908,15 @@ SDValue HexagonDAGToDAGISel::balanceSubTree(SDNode *N, bool TopLevel) { RootHeights[N] = std::max(getHeight(N->getOperand(0).getNode()), getHeight(N->getOperand(1).getNode())) + 1; - DEBUG(dbgs() << "--> No need to balance root (Weight=" << Weight - << " Height=" << RootHeights[N] << "): "); - DEBUG(N->dump()); + LLVM_DEBUG(dbgs() << "--> No need to balance root (Weight=" << Weight + << " Height=" << RootHeights[N] << "): "); + LLVM_DEBUG(N->dump(CurDAG)); return SDValue(N, 0); } - DEBUG(dbgs() << "** Balancing root node: "); - DEBUG(N->dump()); + LLVM_DEBUG(dbgs() << "** Balancing root node: "); + LLVM_DEBUG(N->dump(CurDAG)); unsigned NOpcode = N->getOpcode(); @@ -1855,7 +1964,7 @@ SDValue HexagonDAGToDAGISel::balanceSubTree(SDNode *N, bool TopLevel) { // Whoops, this node was RAUWd by one of the balanceSubTree calls we // made. Our worklist isn't up to date anymore. // Restart the whole process. - DEBUG(dbgs() << "--> Subtree was RAUWd. Restarting...\n"); + LLVM_DEBUG(dbgs() << "--> Subtree was RAUWd. Restarting...\n"); return balanceSubTree(N, TopLevel); } @@ -1926,15 +2035,15 @@ SDValue HexagonDAGToDAGISel::balanceSubTree(SDNode *N, bool TopLevel) { } } - DEBUG(dbgs() << "--> Current height=" << NodeHeights[SDValue(N, 0)] - << " weight=" << CurrentWeight << " imbalanced=" - << Imbalanced << "\n"); + LLVM_DEBUG(dbgs() << "--> Current height=" << NodeHeights[SDValue(N, 0)] + << " weight=" << CurrentWeight + << " imbalanced=" << Imbalanced << "\n"); // Transform MUL(x, C * 2^Y) + SHL(z, Y) -> SHL(ADD(MUL(x, C), z), Y) // This factors out a shift in order to match memw(a<<Y+b). if (CanFactorize && (willShiftRightEliminate(Mul1.Value, MaxPowerOf2) || willShiftRightEliminate(Mul2.Value, MaxPowerOf2))) { - DEBUG(dbgs() << "--> Found common factor for two MUL children!\n"); + LLVM_DEBUG(dbgs() << "--> Found common factor for two MUL children!\n"); int Weight = Mul1.Weight + Mul2.Weight; int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1; SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2); @@ -1968,9 +2077,9 @@ SDValue HexagonDAGToDAGISel::balanceSubTree(SDNode *N, bool TopLevel) { if (getUsesInFunction(GANode->getGlobal()) == 1 && Offset->hasOneUse() && getTargetLowering()->isOffsetFoldingLegal(GANode)) { - DEBUG(dbgs() << "--> Combining GA and offset (" << Offset->getSExtValue() - << "): "); - DEBUG(GANode->dump()); + LLVM_DEBUG(dbgs() << "--> Combining GA and offset (" + << Offset->getSExtValue() << "): "); + LLVM_DEBUG(GANode->dump(CurDAG)); SDValue NewTGA = CurDAG->getTargetGlobalAddress(GANode->getGlobal(), SDLoc(GA.Value), @@ -2014,7 +2123,7 @@ SDValue HexagonDAGToDAGISel::balanceSubTree(SDNode *N, bool TopLevel) { // If this is the top level and we haven't factored out a shift, we should try // to move a constant to the bottom to match addressing modes like memw(rX+C) if (TopLevel && !CanFactorize && Leaves.hasConst()) { - DEBUG(dbgs() << "--> Pushing constant to tip of tree."); + LLVM_DEBUG(dbgs() << "--> Pushing constant to tip of tree."); Leaves.pushToBottom(Leaves.pop()); } @@ -2041,7 +2150,7 @@ SDValue HexagonDAGToDAGISel::balanceSubTree(SDNode *N, bool TopLevel) { // Make sure that none of these nodes have been RAUW'd if ((RootWeights.count(V0.getNode()) && RootWeights[V0.getNode()] == -2) || (RootWeights.count(V1.getNode()) && RootWeights[V1.getNode()] == -2)) { - DEBUG(dbgs() << "--> Subtree was RAUWd. Restarting...\n"); + LLVM_DEBUG(dbgs() << "--> Subtree was RAUWd. Restarting...\n"); return balanceSubTree(N, TopLevel); } @@ -2075,9 +2184,9 @@ SDValue HexagonDAGToDAGISel::balanceSubTree(SDNode *N, bool TopLevel) { int Weight = V0Weight + V1Weight; Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder)); - DEBUG(dbgs() << "--> Built new node (Weight=" << Weight << ",Height=" - << Height << "):\n"); - DEBUG(NewNode.dump()); + LLVM_DEBUG(dbgs() << "--> Built new node (Weight=" << Weight + << ",Height=" << Height << "):\n"); + LLVM_DEBUG(NewNode.dump()); } assert(Leaves.size() == 1); @@ -2101,15 +2210,15 @@ SDValue HexagonDAGToDAGISel::balanceSubTree(SDNode *N, bool TopLevel) { } if (N != NewRoot.getNode()) { - DEBUG(dbgs() << "--> Root is now: "); - DEBUG(NewRoot.dump()); + LLVM_DEBUG(dbgs() << "--> Root is now: "); + LLVM_DEBUG(NewRoot.dump()); // Replace all uses of old root by new root CurDAG->ReplaceAllUsesWith(N, NewRoot.getNode()); // Mark that we have RAUW'd N RootWeights[N] = -2; } else { - DEBUG(dbgs() << "--> Root unchanged.\n"); + LLVM_DEBUG(dbgs() << "--> Root unchanged.\n"); } RootWeights[NewRoot.getNode()] = Leaves.top().Weight; @@ -2132,8 +2241,8 @@ void HexagonDAGToDAGISel::rebalanceAddressTrees() { if (RootWeights.count(BasePtr.getNode())) continue; - DEBUG(dbgs() << "** Rebalancing address calculation in node: "); - DEBUG(N->dump()); + LLVM_DEBUG(dbgs() << "** Rebalancing address calculation in node: "); + LLVM_DEBUG(N->dump(CurDAG)); // FindRoots SmallVector<SDNode *, 4> Worklist; @@ -2173,8 +2282,8 @@ void HexagonDAGToDAGISel::rebalanceAddressTrees() { N = CurDAG->UpdateNodeOperands(N, N->getOperand(0), N->getOperand(1), NewBasePtr, N->getOperand(3)); - DEBUG(dbgs() << "--> Final node: "); - DEBUG(N->dump()); + LLVM_DEBUG(dbgs() << "--> Final node: "); + LLVM_DEBUG(N->dump(CurDAG)); } CurDAG->RemoveDeadNodes(); @@ -2182,4 +2291,3 @@ void HexagonDAGToDAGISel::rebalanceAddressTrees() { RootHeights.clear(); RootWeights.clear(); } - |