diff options
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp')
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp | 260 |
1 files changed, 219 insertions, 41 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp index 39ec8936214e7..d1cd23c3be3e5 100644 --- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp +++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -118,6 +118,12 @@ HexagonInstrInfo::HexagonInstrInfo(HexagonSubtarget &ST) : HexagonGenInstrInfo(Hexagon::ADJCALLSTACKDOWN, Hexagon::ADJCALLSTACKUP), Subtarget(ST) {} +namespace llvm { +namespace HexagonFUnits { + bool isSlot0Only(unsigned units); +} +} + static bool isIntRegForSubInst(unsigned Reg) { return (Reg >= Hexagon::R0 && Reg <= Hexagon::R7) || (Reg >= Hexagon::R16 && Reg <= Hexagon::R23); @@ -370,7 +376,7 @@ bool HexagonInstrInfo::hasStoreToStackSlot( /// This function can analyze one/two way branching only and should (mostly) be /// called by target independent side. /// First entry is always the opcode of the branching instruction, except when -/// the Cond vector is supposed to be empty, e.g., when AnalyzeBranch fails, a +/// the Cond vector is supposed to be empty, e.g., when analyzeBranch fails, a /// BB with only unconditional jump. Subsequent entries depend upon the opcode, /// e.g. Jump_c p will have /// Cond[0] = Jump_c @@ -784,6 +790,25 @@ bool HexagonInstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB, return NumInstrs <= 4; } +static void getLiveInRegsAt(LivePhysRegs &Regs, const MachineInstr &MI) { + SmallVector<std::pair<MCPhysReg, const MachineOperand*>,2> Clobbers; + const MachineBasicBlock &B = *MI.getParent(); + Regs.addLiveIns(B); + auto E = MachineBasicBlock::const_iterator(MI.getIterator()); + for (auto I = B.begin(); I != E; ++I) { + Clobbers.clear(); + Regs.stepForward(*I, Clobbers); + } +} + +static void getLiveOutRegsAt(LivePhysRegs &Regs, const MachineInstr &MI) { + const MachineBasicBlock &B = *MI.getParent(); + Regs.addLiveOuts(B); + auto E = ++MachineBasicBlock::const_iterator(MI.getIterator()).getReverse(); + for (auto I = B.rbegin(); I != E; ++I) + Regs.stepBackward(*I); +} + void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, @@ -849,11 +874,15 @@ void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB, return; } if (Hexagon::HvxWRRegClass.contains(SrcReg, DestReg)) { - Register LoSrc = HRI.getSubReg(SrcReg, Hexagon::vsub_lo); - Register HiSrc = HRI.getSubReg(SrcReg, Hexagon::vsub_hi); + LivePhysRegs LiveAtMI(HRI); + getLiveInRegsAt(LiveAtMI, *I); + Register SrcLo = HRI.getSubReg(SrcReg, Hexagon::vsub_lo); + Register SrcHi = HRI.getSubReg(SrcReg, Hexagon::vsub_hi); + unsigned UndefLo = getUndefRegState(!LiveAtMI.contains(SrcLo)); + unsigned UndefHi = getUndefRegState(!LiveAtMI.contains(SrcHi)); BuildMI(MBB, I, DL, get(Hexagon::V6_vcombine), DestReg) - .addReg(HiSrc, KillFlag) - .addReg(LoSrc, KillFlag); + .addReg(SrcHi, KillFlag | UndefHi) + .addReg(SrcLo, KillFlag | UndefLo); return; } if (Hexagon::HvxQRRegClass.contains(SrcReg, DestReg)) { @@ -882,17 +911,16 @@ void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB, } void HexagonInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, unsigned SrcReg, bool isKill, int FI, + MachineBasicBlock::iterator I, Register SrcReg, bool isKill, int FI, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const { DebugLoc DL = MBB.findDebugLoc(I); MachineFunction &MF = *MBB.getParent(); MachineFrameInfo &MFI = MF.getFrameInfo(); - unsigned SlotAlign = MFI.getObjectAlignment(FI); unsigned KillFlag = getKillRegState(isKill); MachineMemOperand *MMO = MF.getMachineMemOperand( MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore, - MFI.getObjectSize(FI), SlotAlign); + MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); if (Hexagon::IntRegsRegClass.hasSubClassEq(RC)) { BuildMI(MBB, I, DL, get(Hexagon::S2_storeri_io)) @@ -928,17 +956,16 @@ void HexagonInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, } void HexagonInstrInfo::loadRegFromStackSlot( - MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned DestReg, + MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register DestReg, int FI, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const { DebugLoc DL = MBB.findDebugLoc(I); MachineFunction &MF = *MBB.getParent(); MachineFrameInfo &MFI = MF.getFrameInfo(); - unsigned SlotAlign = MFI.getObjectAlignment(FI); MachineMemOperand *MMO = MF.getMachineMemOperand( MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad, - MFI.getObjectSize(FI), SlotAlign); + MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); if (Hexagon::IntRegsRegClass.hasSubClassEq(RC)) { BuildMI(MBB, I, DL, get(Hexagon::L2_loadri_io), DestReg) @@ -966,14 +993,6 @@ void HexagonInstrInfo::loadRegFromStackSlot( } } -static void getLiveRegsAt(LivePhysRegs &Regs, const MachineInstr &MI) { - const MachineBasicBlock &B = *MI.getParent(); - Regs.addLiveOuts(B); - auto E = ++MachineBasicBlock::const_iterator(MI.getIterator()).getReverse(); - for (auto I = B.rbegin(); I != E; ++I) - Regs.stepBackward(*I); -} - /// expandPostRAPseudo - This function is called for all pseudo instructions /// that remain after register allocation. Many pseudo instructions are /// created to help register allocation. This is the place to convert them @@ -985,6 +1004,7 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { MachineFunction &MF = *MBB.getParent(); MachineRegisterInfo &MRI = MF.getRegInfo(); const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo(); + LivePhysRegs LiveIn(HRI), LiveOut(HRI); DebugLoc DL = MI.getDebugLoc(); unsigned Opc = MI.getOpcode(); @@ -1005,10 +1025,9 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { auto UseAligned = [&] (const MachineInstr &MI, unsigned NeedAlign) { if (MI.memoperands().empty()) return false; - return all_of(MI.memoperands(), - [NeedAlign] (const MachineMemOperand *MMO) { - return NeedAlign <= MMO->getAlignment(); - }); + return all_of(MI.memoperands(), [NeedAlign](const MachineMemOperand *MMO) { + return MMO->getAlign() >= NeedAlign; + }); }; switch (Opc) { @@ -1032,10 +1051,15 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { case Hexagon::V6_vassignp: { Register SrcReg = MI.getOperand(1).getReg(); Register DstReg = MI.getOperand(0).getReg(); + Register SrcLo = HRI.getSubReg(SrcReg, Hexagon::vsub_lo); + Register SrcHi = HRI.getSubReg(SrcReg, Hexagon::vsub_hi); + getLiveInRegsAt(LiveIn, MI); + unsigned UndefLo = getUndefRegState(!LiveIn.contains(SrcLo)); + unsigned UndefHi = getUndefRegState(!LiveIn.contains(SrcHi)); unsigned Kill = getKillRegState(MI.getOperand(1).isKill()); BuildMI(MBB, MI, DL, get(Hexagon::V6_vcombine), DstReg) - .addReg(HRI.getSubReg(SrcReg, Hexagon::vsub_hi), Kill) - .addReg(HRI.getSubReg(SrcReg, Hexagon::vsub_lo), Kill); + .addReg(SrcHi, UndefHi) + .addReg(SrcLo, Kill | UndefLo); MBB.erase(MI); return true; } @@ -1255,9 +1279,8 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { const MachineOperand &Op1 = MI.getOperand(1); const MachineOperand &Op2 = MI.getOperand(2); const MachineOperand &Op3 = MI.getOperand(3); - LivePhysRegs LiveAtMI(HRI); - getLiveRegsAt(LiveAtMI, MI); - bool IsDestLive = !LiveAtMI.available(MRI, Op0.getReg()); + getLiveOutRegsAt(LiveOut, MI); + bool IsDestLive = !LiveOut.available(MRI, Op0.getReg()); Register PReg = Op1.getReg(); assert(Op1.getSubReg() == 0); unsigned PState = getRegState(Op1); @@ -1289,9 +1312,8 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { MachineOperand &Op1 = MI.getOperand(1); MachineOperand &Op2 = MI.getOperand(2); MachineOperand &Op3 = MI.getOperand(3); - LivePhysRegs LiveAtMI(HRI); - getLiveRegsAt(LiveAtMI, MI); - bool IsDestLive = !LiveAtMI.available(MRI, Op0.getReg()); + getLiveOutRegsAt(LiveOut, MI); + bool IsDestLive = !LiveOut.available(MRI, Op0.getReg()); Register PReg = Op1.getReg(); assert(Op1.getSubReg() == 0); unsigned PState = getRegState(Op1); @@ -1349,7 +1371,8 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { static const CrashPseudoSourceValue CrashPSV(*this); MachineMemOperand *MMO = MF.getMachineMemOperand( MachinePointerInfo(&CrashPSV), - MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile, 8, 1); + MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile, 8, + Align(1)); BuildMI(MBB, MI, DL, get(Hexagon::PS_loadrdabs), Hexagon::D13) .addImm(0xBADC0FEE) // Misaligned load. .addMemOperand(MMO); @@ -1707,6 +1730,10 @@ bool HexagonInstrInfo::isSchedulingBoundary(const MachineInstr &MI, if (MI.getDesc().isTerminator() || MI.isPosition()) return true; + // INLINEASM_BR can jump to another block + if (MI.getOpcode() == TargetOpcode::INLINEASM_BR) + return true; + if (MI.isInlineAsm() && !ScheduleInlineAsm) return true; @@ -1735,7 +1762,7 @@ unsigned HexagonInstrInfo::getInlineAsmLength(const char *Str, if (*Str == '\n' || strncmp(Str, MAI.getSeparatorString(), strlen(MAI.getSeparatorString())) == 0) atInsnStart = true; - if (atInsnStart && !std::isspace(static_cast<unsigned char>(*Str))) { + if (atInsnStart && !isSpace(static_cast<unsigned char>(*Str))) { Length += MaxInstLength; atInsnStart = false; } @@ -1762,8 +1789,8 @@ HexagonInstrInfo::CreateTargetPostRAHazardRecognizer( /// \p SrcReg and \p SrcReg2 if having two register operands, and the value it /// compares against in CmpValue. Return true if the comparison instruction /// can be analyzed. -bool HexagonInstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg, - unsigned &SrcReg2, int &Mask, +bool HexagonInstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg, + Register &SrcReg2, int &Mask, int &Value) const { unsigned Opc = MI.getOpcode(); @@ -2940,12 +2967,16 @@ bool HexagonInstrInfo::addLatencyToSchedule(const MachineInstr &MI1, } /// Get the base register and byte offset of a load/store instr. -bool HexagonInstrInfo::getMemOperandWithOffset( - const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset, +bool HexagonInstrInfo::getMemOperandsWithOffsetWidth( + const MachineInstr &LdSt, SmallVectorImpl<const MachineOperand *> &BaseOps, + int64_t &Offset, bool &OffsetIsScalable, unsigned &Width, const TargetRegisterInfo *TRI) const { - unsigned AccessSize = 0; - BaseOp = getBaseAndOffset(LdSt, Offset, AccessSize); - return BaseOp != nullptr && BaseOp->isReg(); + OffsetIsScalable = false; + const MachineOperand *BaseOp = getBaseAndOffset(LdSt, Offset, Width); + if (!BaseOp || !BaseOp->isReg()) + return false; + BaseOps.push_back(BaseOp); + return true; } /// Can these instructions execute at the same time in a bundle. @@ -3403,6 +3434,64 @@ unsigned HexagonInstrInfo::getCompoundOpcode(const MachineInstr &GA, : Hexagon::J4_cmpeqi_tp1_jump_nt; } +// Returns -1 if there is no opcode found. +int HexagonInstrInfo::getDuplexOpcode(const MachineInstr &MI, + bool ForBigCore) const { + // Static table to switch the opcodes across Tiny Core and Big Core. + // dup_ opcodes are Big core opcodes. + // NOTE: There are special instructions that need to handled later. + // L4_return* instructions, they will only occupy SLOT0 (on big core too). + // PS_jmpret - This pseudo translates to J2_jumpr which occupies only SLOT2. + // The compiler need to base the root instruction to L6_return_map_to_raw + // which can go any slot. + static const std::map<unsigned, unsigned> DupMap = { + {Hexagon::A2_add, Hexagon::dup_A2_add}, + {Hexagon::A2_addi, Hexagon::dup_A2_addi}, + {Hexagon::A2_andir, Hexagon::dup_A2_andir}, + {Hexagon::A2_combineii, Hexagon::dup_A2_combineii}, + {Hexagon::A2_sxtb, Hexagon::dup_A2_sxtb}, + {Hexagon::A2_sxth, Hexagon::dup_A2_sxth}, + {Hexagon::A2_tfr, Hexagon::dup_A2_tfr}, + {Hexagon::A2_tfrsi, Hexagon::dup_A2_tfrsi}, + {Hexagon::A2_zxtb, Hexagon::dup_A2_zxtb}, + {Hexagon::A2_zxth, Hexagon::dup_A2_zxth}, + {Hexagon::A4_combineii, Hexagon::dup_A4_combineii}, + {Hexagon::A4_combineir, Hexagon::dup_A4_combineir}, + {Hexagon::A4_combineri, Hexagon::dup_A4_combineri}, + {Hexagon::C2_cmoveif, Hexagon::dup_C2_cmoveif}, + {Hexagon::C2_cmoveit, Hexagon::dup_C2_cmoveit}, + {Hexagon::C2_cmovenewif, Hexagon::dup_C2_cmovenewif}, + {Hexagon::C2_cmovenewit, Hexagon::dup_C2_cmovenewit}, + {Hexagon::C2_cmpeqi, Hexagon::dup_C2_cmpeqi}, + {Hexagon::L2_deallocframe, Hexagon::dup_L2_deallocframe}, + {Hexagon::L2_loadrb_io, Hexagon::dup_L2_loadrb_io}, + {Hexagon::L2_loadrd_io, Hexagon::dup_L2_loadrd_io}, + {Hexagon::L2_loadrh_io, Hexagon::dup_L2_loadrh_io}, + {Hexagon::L2_loadri_io, Hexagon::dup_L2_loadri_io}, + {Hexagon::L2_loadrub_io, Hexagon::dup_L2_loadrub_io}, + {Hexagon::L2_loadruh_io, Hexagon::dup_L2_loadruh_io}, + {Hexagon::S2_allocframe, Hexagon::dup_S2_allocframe}, + {Hexagon::S2_storerb_io, Hexagon::dup_S2_storerb_io}, + {Hexagon::S2_storerd_io, Hexagon::dup_S2_storerd_io}, + {Hexagon::S2_storerh_io, Hexagon::dup_S2_storerh_io}, + {Hexagon::S2_storeri_io, Hexagon::dup_S2_storeri_io}, + {Hexagon::S4_storeirb_io, Hexagon::dup_S4_storeirb_io}, + {Hexagon::S4_storeiri_io, Hexagon::dup_S4_storeiri_io}, + }; + unsigned OpNum = MI.getOpcode(); + // Conversion to Big core. + if (ForBigCore) { + auto Iter = DupMap.find(OpNum); + if (Iter != DupMap.end()) + return Iter->second; + } else { // Conversion to Tiny core. + for (auto Iter = DupMap.begin(), End = DupMap.end(); Iter != End; ++Iter) + if (Iter->second == OpNum) + return Iter->first; + } + return -1; +} + int HexagonInstrInfo::getCondOpcode(int Opc, bool invertPredicate) const { enum Hexagon::PredSense inPredSense; inPredSense = invertPredicate ? Hexagon::PredSense_false : @@ -3735,6 +3824,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( // Rd = memw(Rs+#u4:2) // Rd = memub(Rs+#u4:0) case Hexagon::L2_loadri_io: + case Hexagon::dup_L2_loadri_io: DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(1).getReg(); // Special case this one from Group L2. @@ -3753,6 +3843,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( } break; case Hexagon::L2_loadrub_io: + case Hexagon::dup_L2_loadrub_io: // Rd = memub(Rs+#u4:0) DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(1).getReg(); @@ -3772,6 +3863,8 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( // [if ([!]p0[.new])] jumpr r31 case Hexagon::L2_loadrh_io: case Hexagon::L2_loadruh_io: + case Hexagon::dup_L2_loadrh_io: + case Hexagon::dup_L2_loadruh_io: // Rd = memh/memuh(Rs+#u3:1) DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(1).getReg(); @@ -3781,6 +3874,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( return HexagonII::HSIG_L2; break; case Hexagon::L2_loadrb_io: + case Hexagon::dup_L2_loadrb_io: // Rd = memb(Rs+#u3:0) DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(1).getReg(); @@ -3790,6 +3884,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( return HexagonII::HSIG_L2; break; case Hexagon::L2_loadrd_io: + case Hexagon::dup_L2_loadrd_io: // Rdd = memd(r29+#u5:3) DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(1).getReg(); @@ -3806,6 +3901,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC: case Hexagon::L4_return: case Hexagon::L2_deallocframe: + case Hexagon::dup_L2_deallocframe: return HexagonII::HSIG_L2; case Hexagon::EH_RETURN_JMPR: case Hexagon::PS_jmpret: @@ -3825,6 +3921,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( case Hexagon::SL2_jumpr31_t: case Hexagon::SL2_jumpr31_f: case Hexagon::SL2_jumpr31_tnew: + case Hexagon::SL2_jumpr31_fnew: DstReg = MI.getOperand(1).getReg(); SrcReg = MI.getOperand(0).getReg(); // [if ([!]p0[.new])] jumpr r31 @@ -3850,6 +3947,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( // memw(Rs+#u4:2) = Rt // memb(Rs+#u4:0) = Rt case Hexagon::S2_storeri_io: + case Hexagon::dup_S2_storeri_io: // Special case this one from Group S2. // memw(r29+#u5:2) = Rt Src1Reg = MI.getOperand(0).getReg(); @@ -3866,6 +3964,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( return HexagonII::HSIG_S1; break; case Hexagon::S2_storerb_io: + case Hexagon::dup_S2_storerb_io: // memb(Rs+#u4:0) = Rt Src1Reg = MI.getOperand(0).getReg(); Src2Reg = MI.getOperand(2).getReg(); @@ -3883,6 +3982,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( // memb(Rs+#u4) = #U1 // allocframe(#u5:3) case Hexagon::S2_storerh_io: + case Hexagon::dup_S2_storerh_io: // memh(Rs+#u3:1) = Rt Src1Reg = MI.getOperand(0).getReg(); Src2Reg = MI.getOperand(2).getReg(); @@ -3892,6 +3992,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( return HexagonII::HSIG_S1; break; case Hexagon::S2_storerd_io: + case Hexagon::dup_S2_storerd_io: // memd(r29+#s6:3) = Rtt Src1Reg = MI.getOperand(0).getReg(); Src2Reg = MI.getOperand(2).getReg(); @@ -3902,6 +4003,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( return HexagonII::HSIG_S2; break; case Hexagon::S4_storeiri_io: + case Hexagon::dup_S4_storeiri_io: // memw(Rs+#u4:2) = #U1 Src1Reg = MI.getOperand(0).getReg(); if (isIntRegForSubInst(Src1Reg) && MI.getOperand(1).isImm() && @@ -3910,6 +4012,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( return HexagonII::HSIG_S2; break; case Hexagon::S4_storeirb_io: + case Hexagon::dup_S4_storeirb_io: // memb(Rs+#u4) = #U1 Src1Reg = MI.getOperand(0).getReg(); if (isIntRegForSubInst(Src1Reg) && @@ -3918,6 +4021,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( return HexagonII::HSIG_S2; break; case Hexagon::S2_allocframe: + case Hexagon::dup_S2_allocframe: if (MI.getOperand(2).isImm() && isShiftedUInt<5,3>(MI.getOperand(2).getImm())) return HexagonII::HSIG_S1; @@ -3941,6 +4045,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( // Rd = sxth/sxtb/zxtb/zxth(Rs) // Rd = and(Rs,#1) case Hexagon::A2_addi: + case Hexagon::dup_A2_addi: DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(1).getReg(); if (isIntRegForSubInst(DstReg)) { @@ -3962,6 +4067,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( } break; case Hexagon::A2_add: + case Hexagon::dup_A2_add: // Rx = add(Rx,Rs) DstReg = MI.getOperand(0).getReg(); Src1Reg = MI.getOperand(1).getReg(); @@ -3971,6 +4077,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( return HexagonII::HSIG_A; break; case Hexagon::A2_andir: + case Hexagon::dup_A2_andir: // Same as zxtb. // Rd16=and(Rs16,#255) // Rd16=and(Rs16,#1) @@ -3983,6 +4090,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( return HexagonII::HSIG_A; break; case Hexagon::A2_tfr: + case Hexagon::dup_A2_tfr: // Rd = Rs DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(1).getReg(); @@ -3990,6 +4098,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( return HexagonII::HSIG_A; break; case Hexagon::A2_tfrsi: + case Hexagon::dup_A2_tfrsi: // Rd = #u6 // Do not test for #u6 size since the const is getting extended // regardless and compound could be formed. @@ -4002,6 +4111,10 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( case Hexagon::C2_cmovenewit: case Hexagon::C2_cmoveif: case Hexagon::C2_cmovenewif: + case Hexagon::dup_C2_cmoveit: + case Hexagon::dup_C2_cmovenewit: + case Hexagon::dup_C2_cmoveif: + case Hexagon::dup_C2_cmovenewif: // if ([!]P0[.new]) Rd = #0 // Actual form: // %r16 = C2_cmovenewit internal %p0, 0, implicit undef %r16; @@ -4013,6 +4126,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( return HexagonII::HSIG_A; break; case Hexagon::C2_cmpeqi: + case Hexagon::dup_C2_cmpeqi: // P0 = cmp.eq(Rs,#u2) DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(1).getReg(); @@ -4023,6 +4137,8 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( break; case Hexagon::A2_combineii: case Hexagon::A4_combineii: + case Hexagon::dup_A2_combineii: + case Hexagon::dup_A4_combineii: // Rdd = combine(#u2,#U2) DstReg = MI.getOperand(0).getReg(); if (isDblRegForSubInst(DstReg, HRI) && @@ -4035,6 +4151,8 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( return HexagonII::HSIG_A; break; case Hexagon::A4_combineri: + case Hexagon::dup_A4_combineri: + // Rdd = combine(Rs,#0) // Rdd = combine(Rs,#0) DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(1).getReg(); @@ -4044,6 +4162,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( return HexagonII::HSIG_A; break; case Hexagon::A4_combineir: + case Hexagon::dup_A4_combineir: // Rdd = combine(#0,Rs) DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(2).getReg(); @@ -4056,6 +4175,10 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup( case Hexagon::A2_sxth: case Hexagon::A2_zxtb: case Hexagon::A2_zxth: + case Hexagon::dup_A2_sxtb: + case Hexagon::dup_A2_sxth: + case Hexagon::dup_A2_zxtb: + case Hexagon::dup_A2_zxth: // Rd = sxth/sxtb/zxtb/zxth(Rs) DstReg = MI.getOperand(0).getReg(); SrcReg = MI.getOperand(1).getReg(); @@ -4199,6 +4322,61 @@ bool HexagonInstrInfo::isAddrModeWithOffset(const MachineInstr &MI) const { addrMode == HexagonII::BaseLongOffset); } +bool HexagonInstrInfo::isPureSlot0(const MachineInstr &MI) const { + // Workaround for the Global Scheduler. Sometimes, it creates + // A4_ext as a Pseudo instruction and calls this function to see if + // it can be added to an existing bundle. Since the instruction doesn't + // belong to any BB yet, we can't use getUnits API. + if (MI.getOpcode() == Hexagon::A4_ext) + return false; + + unsigned FuncUnits = getUnits(MI); + return HexagonFUnits::isSlot0Only(FuncUnits); +} + +bool HexagonInstrInfo::isRestrictNoSlot1Store(const MachineInstr &MI) const { + const uint64_t F = MI.getDesc().TSFlags; + return ((F >> HexagonII::RestrictNoSlot1StorePos) & + HexagonII::RestrictNoSlot1StoreMask); +} + +void HexagonInstrInfo::changeDuplexOpcode(MachineBasicBlock::instr_iterator MII, + bool ToBigInstrs) const { + int Opcode = -1; + if (ToBigInstrs) { // To BigCore Instr. + // Check if the instruction can form a Duplex. + if (getDuplexCandidateGroup(*MII)) + // Get the opcode marked "dup_*" tag. + Opcode = getDuplexOpcode(*MII, ToBigInstrs); + } else // To TinyCore Instr. + Opcode = getDuplexOpcode(*MII, ToBigInstrs); + + // Change the opcode of the instruction. + if (Opcode >= 0) + MII->setDesc(get(Opcode)); +} + +// This function is used to translate instructions to facilitate generating +// Duplexes on TinyCore. +void HexagonInstrInfo::translateInstrsForDup(MachineFunction &MF, + bool ToBigInstrs) const { + for (auto &MB : MF) + for (MachineBasicBlock::instr_iterator Instr = MB.instr_begin(), + End = MB.instr_end(); + Instr != End; ++Instr) + changeDuplexOpcode(Instr, ToBigInstrs); +} + +// This is a specialized form of above function. +void HexagonInstrInfo::translateInstrsForDup( + MachineBasicBlock::instr_iterator MII, bool ToBigInstrs) const { + MachineBasicBlock *MBB = MII->getParent(); + while ((MII != MBB->instr_end()) && MII->isInsideBundle()) { + changeDuplexOpcode(MII, ToBigInstrs); + ++MII; + } +} + unsigned HexagonInstrInfo::getMemAccessSize(const MachineInstr &MI) const { using namespace HexagonII; @@ -4328,7 +4506,7 @@ uint64_t HexagonInstrInfo::getType(const MachineInstr &MI) const { return (F >> HexagonII::TypePos) & HexagonII::TypeMask; } -unsigned HexagonInstrInfo::getUnits(const MachineInstr &MI) const { +InstrStage::FuncUnits HexagonInstrInfo::getUnits(const MachineInstr &MI) const { const InstrItineraryData &II = *Subtarget.getInstrItineraryData(); const InstrStage &IS = *II.beginStage(MI.getDesc().getSchedClass()); |