summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp260
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());