diff options
Diffstat (limited to 'lib/Target/Hexagon/HexagonISelDAGToDAG.cpp')
-rw-r--r-- | lib/Target/Hexagon/HexagonISelDAGToDAG.cpp | 393 |
1 files changed, 228 insertions, 165 deletions
diff --git a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index dc58c42..fb056b5 100644 --- a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -47,7 +47,7 @@ namespace { class HexagonDAGToDAGISel : public SelectionDAGISel { /// Subtarget - Keep a pointer to the Hexagon Subtarget around so that we can /// make the right decision when generating code for different targets. - const HexagonSubtarget &Subtarget; + const HexagonSubtarget *Subtarget; // Keep a reference to HexagonTargetMachine. const HexagonTargetMachine& TM; @@ -55,9 +55,7 @@ class HexagonDAGToDAGISel : public SelectionDAGISel { public: explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine, CodeGenOpt::Level OptLevel) - : SelectionDAGISel(targetmachine, OptLevel), - Subtarget(targetmachine.getSubtarget<HexagonSubtarget>()), - TM(targetmachine) { + : SelectionDAGISel(targetmachine, OptLevel), TM(targetmachine) { initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry()); } bool hasNumUsesBelowThresGA(SDNode *N) const; @@ -79,10 +77,21 @@ public: bool SelectADDRriU6_1(SDValue& N, SDValue &R1, SDValue &R2); bool SelectADDRriU6_2(SDValue& N, SDValue &R1, SDValue &R2); + // Complex Pattern Selectors. + inline bool SelectAddrGA(SDValue &N, SDValue &R); + inline bool SelectAddrGP(SDValue &N, SDValue &R); + bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP); + bool SelectAddrFI(SDValue &N, SDValue &R); + const char *getPassName() const override { return "Hexagon DAG->DAG Pattern Instruction Selection"; } + bool runOnMachineFunction(MachineFunction &MF) override { + Subtarget = &MF.getSubtarget<HexagonSubtarget>(); + return SelectionDAGISel::runOnMachineFunction(MF); + } + /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for /// inline asm expressions. bool SelectInlineAsmMemoryOperand(const SDValue &Op, @@ -138,9 +147,7 @@ SDValue XformMskToBitPosU3Imm(uint8_t Imm) { // Return true if there is exactly one bit set in V, i.e., if V is one of the // following integers: 2^0, 2^1, ..., 2^31. bool ImmIsSingleBit(uint32_t v) const { - uint32_t c = CountPopulation_64(v); - // Only return true if we counted 1 bit. - return c == 1; + return isPowerOf2_32(v); } // XformM5ToU5Imm - Return a target constant with the specified value, of type @@ -170,8 +177,21 @@ inline SDValue XformUToUM1Imm(unsigned Imm) { return CurDAG->getTargetConstant(Imm - 1, MVT::i32); } +// XformSToSM2Imm - Return a target constant decremented by 2. +inline SDValue XformSToSM2Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm - 2, MVT::i32); +} + +// XformSToSM3Imm - Return a target constant decremented by 3. +inline SDValue XformSToSM3Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm - 3, MVT::i32); +} + // Include the pieces autogenerated from the target description. #include "HexagonGenDAGISel.inc" + +private: + bool isValueExtension(SDValue const &Val, unsigned FromBits, SDValue &Src); }; } // end anonymous namespace @@ -312,56 +332,6 @@ static unsigned doesIntrinsicReturnPredicate(unsigned ID) } } - -// Intrinsics that have predicate operands. -static unsigned doesIntrinsicContainPredicate(unsigned ID) -{ - switch (ID) { - default: - return 0; - case Intrinsic::hexagon_C2_tfrpr: - return Hexagon::TFR_RsPd; - case Intrinsic::hexagon_C2_and: - return Hexagon::AND_pp; - case Intrinsic::hexagon_C2_xor: - return Hexagon::XOR_pp; - case Intrinsic::hexagon_C2_or: - return Hexagon::OR_pp; - case Intrinsic::hexagon_C2_not: - return Hexagon::NOT_p; - case Intrinsic::hexagon_C2_any8: - return Hexagon::ANY_pp; - case Intrinsic::hexagon_C2_all8: - return Hexagon::ALL_pp; - case Intrinsic::hexagon_C2_vitpack: - return Hexagon::VITPACK_pp; - case Intrinsic::hexagon_C2_mask: - return Hexagon::MASK_p; - case Intrinsic::hexagon_C2_mux: - return Hexagon::MUX_rr; - - // Mapping hexagon_C2_muxir to MUX_pri. This is pretty weird - but - // that's how it's mapped in q6protos.h. - case Intrinsic::hexagon_C2_muxir: - return Hexagon::MUX_ri; - - // Mapping hexagon_C2_muxri to MUX_pir. This is pretty weird - but - // that's how it's mapped in q6protos.h. - case Intrinsic::hexagon_C2_muxri: - return Hexagon::MUX_ir; - - case Intrinsic::hexagon_C2_muxii: - return Hexagon::MUX_ii; - case Intrinsic::hexagon_C2_vmux: - return Hexagon::VMUX_prr64; - case Intrinsic::hexagon_S2_valignrb: - return Hexagon::VALIGN_rrp; - case Intrinsic::hexagon_S2_vsplicerb: - return Hexagon::VSPLICE_rrp; - } -} - - static bool OffsetFitsS11(EVT MemType, int64_t Offset) { if (MemType == MVT::i64 && isShiftedInt<11,3>(Offset)) { return true; @@ -404,10 +374,10 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, SDLoc dl) { dl, PointerTy, TargAddr); // Figure out base + offset opcode - if (LoadedVT == MVT::i64) Opcode = Hexagon::LDrid_indexed; - else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed; - else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed; - else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed; + if (LoadedVT == MVT::i64) Opcode = Hexagon::L2_loadrd_io; + else if (LoadedVT == MVT::i32) Opcode = Hexagon::L2_loadri_io; + else if (LoadedVT == MVT::i16) Opcode = Hexagon::L2_loadrh_io; + else if (LoadedVT == MVT::i8) Opcode = Hexagon::L2_loadrb_io; else llvm_unreachable("unknown memory type"); // Build indexed load. @@ -446,14 +416,13 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD, if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && N1.getNode()->getValueType(0) == MVT::i32) { - const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); + const HexagonInstrInfo *TII = Subtarget->getInstrInfo(); if (TII->isValidAutoIncImm(LoadedVT, Val)) { SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32); SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, MVT::Other, Base, TargetConst, Chain); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, MVT::i64, + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64, SDValue(Result_1, 0)); MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); MemOp[0] = LD->getMemOperand(); @@ -474,9 +443,9 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD, SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other, Base, TargetConst0, Chain); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64, SDValue(Result_1, 0)); - SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, + SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32, Base, TargetConstVal, SDValue(Result_1, 1)); MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); @@ -513,17 +482,16 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD, if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && N1.getNode()->getValueType(0) == MVT::i32) { - const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); + const HexagonInstrInfo *TII = Subtarget->getInstrInfo(); if (TII->isValidAutoIncImm(LoadedVT, Val)) { SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, MVT::Other, Base, TargetConstVal, Chain); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, TargetConst0); - SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, + SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl, MVT::i64, MVT::Other, SDValue(Result_2,0), SDValue(Result_1,0)); @@ -548,14 +516,14 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD, SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other, Base, TargetConst0, Chain); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, TargetConst0); - SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, + SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl, MVT::i64, MVT::Other, SDValue(Result_2,0), SDValue(Result_1,0)); // Add offset to base. - SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, + SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32, Base, TargetConstVal, SDValue(Result_1, 1)); MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); @@ -591,28 +559,27 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) { bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD); // Figure out the opcode. - const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); + const HexagonInstrInfo *TII = Subtarget->getInstrInfo(); if (LoadedVT == MVT::i64) { if (TII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = Hexagon::POST_LDrid; + Opcode = Hexagon::L2_loadrd_pi; else - Opcode = Hexagon::LDrid; + Opcode = Hexagon::L2_loadrd_io; } else if (LoadedVT == MVT::i32) { if (TII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = Hexagon::POST_LDriw; + Opcode = Hexagon::L2_loadri_pi; else - Opcode = Hexagon::LDriw; + Opcode = Hexagon::L2_loadri_io; } else if (LoadedVT == MVT::i16) { if (TII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = zextval ? Hexagon::POST_LDriuh : Hexagon::POST_LDrih; + Opcode = zextval ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi; else - Opcode = zextval ? Hexagon::LDriuh : Hexagon::LDrih; + Opcode = zextval ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io; } else if (LoadedVT == MVT::i8) { if (TII->isValidAutoIncImm(LoadedVT, Val)) - Opcode = zextval ? Hexagon::POST_LDriub : Hexagon::POST_LDrib; + Opcode = zextval ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi; else - Opcode = zextval ? Hexagon::LDriub : Hexagon::LDrib; + Opcode = zextval ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io; } else llvm_unreachable("unknown memory type"); @@ -652,7 +619,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) { LD->getValueType(0), MVT::Other, Base, TargetConst0, Chain); - SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, + SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32, Base, TargetConstVal, SDValue(Result_1, 1)); MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); @@ -701,18 +668,17 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) { // Offset value must be within representable range // and must have correct alignment properties. - const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); + const HexagonInstrInfo *TII = Subtarget->getInstrInfo(); if (TII->isValidAutoIncImm(StoredVT, Val)) { SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value, Chain}; unsigned Opcode = 0; // Figure out the post inc version of opcode. - if (StoredVT == MVT::i64) Opcode = Hexagon::POST_STdri; - else if (StoredVT == MVT::i32) Opcode = Hexagon::POST_STwri; - else if (StoredVT == MVT::i16) Opcode = Hexagon::POST_SThri; - else if (StoredVT == MVT::i8) Opcode = Hexagon::POST_STbri; + if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_pi; + else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi; + else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi; + else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi; else llvm_unreachable("unknown memory type"); // Build post increment store. @@ -735,17 +701,17 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) { unsigned Opcode = 0; // Figure out the opcode. - if (StoredVT == MVT::i64) Opcode = Hexagon::STrid; - else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed; - else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih; - else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib; + if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io; + else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io; + else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io; + else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io; else llvm_unreachable("unknown memory type"); // Build regular store. SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops); // Build splitted incriment instruction. - SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, + SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::A2_addi, dl, MVT::i32, Base, TargetConstVal, SDValue(Result_1, 0)); @@ -788,10 +754,10 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST, TargAddr); // Figure out base + offset opcode - if (StoredVT == MVT::i64) Opcode = Hexagon::STrid_indexed; - else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed; - else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih_indexed; - else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib_indexed; + if (StoredVT == MVT::i64) Opcode = Hexagon::S2_storerd_io; + else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io; + else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io; + else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io; else llvm_unreachable("unknown memory type"); SDValue Ops[] = {SDValue(NewBase,0), @@ -865,7 +831,7 @@ SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { SDValue Chain = LD->getChain(); SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); - OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, + OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32, MVT::Other, LD->getBasePtr(), TargetConst0, Chain), 0); @@ -891,7 +857,7 @@ SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { SDValue Chain = LD->getChain(); SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); - OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, + OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32, MVT::Other, LD->getBasePtr(), TargetConst0, Chain), 0); @@ -900,7 +866,7 @@ SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { } // Generate a mpy instruction. - SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY64, dl, MVT::i64, + SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_dpmpyss_s0, dl, MVT::i64, OP0, OP1); ReplaceUses(N, Result); return Result; @@ -934,9 +900,9 @@ SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) { if (N000 == N2 && N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 && N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) { - SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl, + SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl, MVT::i32, N000); - SDNode *Result = CurDAG->getMachineNode(Hexagon::MAXw_rr, dl, + SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_max, dl, MVT::i32, SDValue(SextNode, 0), N1); @@ -958,9 +924,9 @@ SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) { if (N000 == N2 && N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 && N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) { - SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl, + SDNode *SextNode = CurDAG->getMachineNode(Hexagon::A2_sxth, dl, MVT::i32, N000); - SDNode *Result = CurDAG->getMachineNode(Hexagon::MINw_rr, dl, + SDNode *Result = CurDAG->getMachineNode(Hexagon::A2_min, dl, MVT::i32, SDValue(SextNode, 0), N1); @@ -1045,7 +1011,7 @@ SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) { SDValue Chain = LD->getChain(); SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); - OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, + OP0 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32, MVT::Other, LD->getBasePtr(), TargetConst0, Chain), 0); @@ -1070,7 +1036,7 @@ SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) { SDValue Chain = LD->getChain(); SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); - OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, + OP1 = SDValue(CurDAG->getMachineNode(Hexagon::L2_loadri_io, dl, MVT::i32, MVT::Other, LD->getBasePtr(), TargetConst0, Chain), 0); @@ -1079,7 +1045,7 @@ SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) { } // Generate a mpy instruction. - SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY, dl, MVT::i32, + SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpy_up, dl, MVT::i32, OP0, OP1); ReplaceUses(N, Result); return Result; @@ -1112,7 +1078,7 @@ SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) { if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode())) if (isInt<9>(CN->getSExtValue())) { SDNode* Result = - CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, + CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32, Mul_0, Val); ReplaceUses(N, Result); return Result; @@ -1140,7 +1106,7 @@ SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) { dyn_cast<ConstantSDNode>(Val.getNode())) if (isInt<9>(CN->getSExtValue())) { SDNode* Result = - CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, MVT::i32, + CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl, MVT::i32, Shl2_0, Val); ReplaceUses(N, Result); return Result; @@ -1177,13 +1143,13 @@ SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) { if (N->getValueType(0) == MVT::i64) { // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs). SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); - SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl, + SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl, MVT::i32, SDValue(IsIntrinsic, 0)); - SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, + SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, TargetConst0); - SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, + SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::A2_combinew, dl, MVT::i64, MVT::Other, SDValue(Result_2, 0), SDValue(Result_1, 0)); @@ -1192,7 +1158,7 @@ SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) { } if (N->getValueType(0) == MVT::i32) { // Convert the zero_extend to Rs = Pd - SDNode* RsPd = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl, + SDNode* RsPd = CurDAG->getMachineNode(Hexagon::C2_tfrpr, dl, MVT::i32, SDValue(IsIntrinsic, 0)); ReplaceUses(N, RsPd); @@ -1204,56 +1170,30 @@ SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) { return SelectCode(N); } - // // Checking for intrinsics which have predicate registers as operand(s) // and lowering to the actual intrinsic. // SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) { - SDLoc dl(N); - unsigned ID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); - unsigned IntrinsicWithPred = doesIntrinsicContainPredicate(ID); - - // We are concerned with only those intrinsics that have predicate registers - // as at least one of the operands. - if (IntrinsicWithPred) { - SmallVector<SDValue, 8> Ops; - const HexagonInstrInfo *TII = static_cast<const HexagonInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); - const MCInstrDesc &MCID = TII->get(IntrinsicWithPred); - const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo(); - - // Iterate over all the operands of the intrinsics. - // For PredRegs, do the transfer. - // For Double/Int Regs, just preserve the value - // For immediates, lower it. - for (unsigned i = 1; i < N->getNumOperands(); ++i) { - SDNode *Arg = N->getOperand(i).getNode(); - const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI, *MF); - - if (RC == &Hexagon::IntRegsRegClass || - RC == &Hexagon::DoubleRegsRegClass) { - Ops.push_back(SDValue(Arg, 0)); - } else if (RC == &Hexagon::PredRegsRegClass) { - // Do the transfer. - SDNode *PdRs = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1, - SDValue(Arg, 0)); - Ops.push_back(SDValue(PdRs,0)); - } else if (!RC && (dyn_cast<ConstantSDNode>(Arg) != nullptr)) { - // This is immediate operand. Lower it here making sure that we DO have - // const SDNode for immediate value. - int32_t Val = cast<ConstantSDNode>(Arg)->getSExtValue(); - SDValue SDVal = CurDAG->getTargetConstant(Val, MVT::i32); - Ops.push_back(SDVal); - } else { - llvm_unreachable("Unimplemented"); - } - } - EVT ReturnValueVT = N->getValueType(0); - SDNode *Result = CurDAG->getMachineNode(IntrinsicWithPred, dl, - ReturnValueVT, Ops); - ReplaceUses(N, Result); - return Result; + unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); + unsigned Bits; + switch (IID) { + case Intrinsic::hexagon_S2_vsplatrb: + Bits = 8; + break; + case Intrinsic::hexagon_S2_vsplatrh: + Bits = 16; + break; + default: + return SelectCode(N); + } + + SDValue const &V = N->getOperand(1); + SDValue U; + if (isValueExtension(V, Bits, U)) { + SDValue R = CurDAG->getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), + N->getOperand(0), U); + return SelectCode(R.getNode()); } return SelectCode(N); } @@ -1289,19 +1229,19 @@ SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) { if (Val == -1) { // Create the IntReg = 1 node. SDNode* IntRegTFR = - CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, + CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, CurDAG->getTargetConstant(0, MVT::i32)); // Pd = IntReg - SDNode* Pd = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1, + SDNode* Pd = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::i1, SDValue(IntRegTFR, 0)); // not(Pd) - SDNode* NotPd = CurDAG->getMachineNode(Hexagon::NOT_p, dl, MVT::i1, + SDNode* NotPd = CurDAG->getMachineNode(Hexagon::C2_not, dl, MVT::i1, SDValue(Pd, 0)); // xor(not(Pd)) - Result = CurDAG->getMachineNode(Hexagon::XOR_pp, dl, MVT::i1, + Result = CurDAG->getMachineNode(Hexagon::C2_xor, dl, MVT::i1, SDValue(Pd, 0), SDValue(NotPd, 0)); // We have just built: @@ -1334,7 +1274,7 @@ SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) { // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that // Rd and Rd' are assigned to the same register - SDNode* Result = CurDAG->getMachineNode(Hexagon::ASR_ADD_rr, dl, MVT::i32, + SDNode* Result = CurDAG->getMachineNode(Hexagon::S2_asr_r_r_acc, dl, MVT::i32, N->getOperand(1), Src1->getOperand(0), Src1->getOperand(1)); @@ -1683,3 +1623,126 @@ bool HexagonDAGToDAGISel::foldGlobalAddressImpl(SDValue &N, SDValue &R, } return false; } + +bool HexagonDAGToDAGISel::SelectAddrFI(SDValue& N, SDValue &R) { + if (N.getOpcode() != ISD::FrameIndex) + return false; + FrameIndexSDNode *FX = cast<FrameIndexSDNode>(N); + R = CurDAG->getTargetFrameIndex(FX->getIndex(), MVT::i32); + return true; +} + +inline bool HexagonDAGToDAGISel::SelectAddrGA(SDValue &N, SDValue &R) { + return SelectGlobalAddress(N, R, false); +} + +inline bool HexagonDAGToDAGISel::SelectAddrGP(SDValue &N, SDValue &R) { + return SelectGlobalAddress(N, R, true); +} + +bool HexagonDAGToDAGISel::SelectGlobalAddress(SDValue &N, SDValue &R, + bool UseGP) { + switch (N.getOpcode()) { + case ISD::ADD: { + SDValue N0 = N.getOperand(0); + SDValue N1 = N.getOperand(1); + unsigned GAOpc = N0.getOpcode(); + if (UseGP && GAOpc != HexagonISD::CONST32_GP) + return false; + if (!UseGP && GAOpc != HexagonISD::CONST32) + return false; + if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1)) { + SDValue Addr = N0.getOperand(0); + if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Addr)) { + if (GA->getOpcode() == ISD::TargetGlobalAddress) { + uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue(); + R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(Const), + N.getValueType(), NewOff); + return true; + } + } + } + break; + } + case HexagonISD::CONST32: + // The operand(0) of CONST32 is TargetGlobalAddress, which is what we + // want in the instruction. + if (!UseGP) + R = N.getOperand(0); + return !UseGP; + case HexagonISD::CONST32_GP: + if (UseGP) + R = N.getOperand(0); + return UseGP; + default: + return false; + } + + return false; +} + +bool HexagonDAGToDAGISel::isValueExtension(SDValue const &Val, + unsigned FromBits, SDValue &Src) { + unsigned Opc = Val.getOpcode(); + switch (Opc) { + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: { + SDValue const &Op0 = Val.getOperand(0); + EVT T = Op0.getValueType(); + if (T.isInteger() && T.getSizeInBits() == FromBits) { + Src = Op0; + return true; + } + break; + } + case ISD::SIGN_EXTEND_INREG: + case ISD::AssertSext: + case ISD::AssertZext: + if (Val.getOperand(0).getValueType().isInteger()) { + VTSDNode *T = cast<VTSDNode>(Val.getOperand(1)); + if (T->getVT().getSizeInBits() == FromBits) { + Src = Val.getOperand(0); + return true; + } + } + break; + case ISD::AND: { + // Check if this is an AND with "FromBits" of lower bits set to 1. + uint64_t FromMask = (1 << FromBits) - 1; + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) { + if (C->getZExtValue() == FromMask) { + Src = Val.getOperand(1); + return true; + } + } + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) { + if (C->getZExtValue() == FromMask) { + Src = Val.getOperand(0); + return true; + } + } + break; + } + case ISD::OR: + case ISD::XOR: { + // OR/XOR with the lower "FromBits" bits set to 0. + uint64_t FromMask = (1 << FromBits) - 1; + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(0))) { + if ((C->getZExtValue() & FromMask) == 0) { + Src = Val.getOperand(1); + return true; + } + } + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val.getOperand(1))) { + if ((C->getZExtValue() & FromMask) == 0) { + Src = Val.getOperand(0); + return true; + } + } + } + default: + break; + } + return false; +} |