summaryrefslogtreecommitdiff
path: root/lib/Target/Hexagon/HexagonInstrInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Hexagon/HexagonInstrInfo.cpp')
-rw-r--r--lib/Target/Hexagon/HexagonInstrInfo.cpp1067
1 files changed, 728 insertions, 339 deletions
diff --git a/lib/Target/Hexagon/HexagonInstrInfo.cpp b/lib/Target/Hexagon/HexagonInstrInfo.cpp
index eb3590cb10767..fe9f97d1d5e76 100644
--- a/lib/Target/Hexagon/HexagonInstrInfo.cpp
+++ b/lib/Target/Hexagon/HexagonInstrInfo.cpp
@@ -24,6 +24,7 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
@@ -69,10 +70,10 @@ static cl::opt<bool> BranchRelaxAsmLarge("branch-relax-asm-large",
///
/// Constants for Hexagon instructions.
///
-const int Hexagon_MEMV_OFFSET_MAX_128B = 2047; // #s7
-const int Hexagon_MEMV_OFFSET_MIN_128B = -2048; // #s7
-const int Hexagon_MEMV_OFFSET_MAX = 1023; // #s6
-const int Hexagon_MEMV_OFFSET_MIN = -1024; // #s6
+const int Hexagon_MEMV_OFFSET_MAX_128B = 896; // #s4: -8*128...7*128
+const int Hexagon_MEMV_OFFSET_MIN_128B = -1024; // #s4
+const int Hexagon_MEMV_OFFSET_MAX = 448; // #s4: -8*64...7*64
+const int Hexagon_MEMV_OFFSET_MIN = -512; // #s4
const int Hexagon_MEMW_OFFSET_MAX = 4095;
const int Hexagon_MEMW_OFFSET_MIN = -4096;
const int Hexagon_MEMD_OFFSET_MAX = 8191;
@@ -91,10 +92,10 @@ const int Hexagon_MEMH_AUTOINC_MAX = 14;
const int Hexagon_MEMH_AUTOINC_MIN = -16;
const int Hexagon_MEMB_AUTOINC_MAX = 7;
const int Hexagon_MEMB_AUTOINC_MIN = -8;
-const int Hexagon_MEMV_AUTOINC_MAX = 192;
-const int Hexagon_MEMV_AUTOINC_MIN = -256;
-const int Hexagon_MEMV_AUTOINC_MAX_128B = 384;
-const int Hexagon_MEMV_AUTOINC_MIN_128B = -512;
+const int Hexagon_MEMV_AUTOINC_MAX = 192; // #s3
+const int Hexagon_MEMV_AUTOINC_MIN = -256; // #s3
+const int Hexagon_MEMV_AUTOINC_MAX_128B = 384; // #s3
+const int Hexagon_MEMV_AUTOINC_MIN_128B = -512; // #s3
// Pin the vtable to this file.
void HexagonInstrInfo::anchor() {}
@@ -230,22 +231,64 @@ static bool isDuplexPairMatch(unsigned Ga, unsigned Gb) {
/// the destination along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than loading from the stack slot.
-unsigned HexagonInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
+unsigned HexagonInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
- switch (MI->getOpcode()) {
- default: break;
- case Hexagon::L2_loadri_io:
- case Hexagon::L2_loadrd_io:
- case Hexagon::L2_loadrh_io:
+ switch (MI.getOpcode()) {
+ default:
+ break;
case Hexagon::L2_loadrb_io:
case Hexagon::L2_loadrub_io:
- if (MI->getOperand(2).isFI() &&
- MI->getOperand(1).isImm() && (MI->getOperand(1).getImm() == 0)) {
- FrameIndex = MI->getOperand(2).getIndex();
- return MI->getOperand(0).getReg();
- }
- break;
+ case Hexagon::L2_loadrh_io:
+ case Hexagon::L2_loadruh_io:
+ case Hexagon::L2_loadri_io:
+ case Hexagon::L2_loadrd_io:
+ case Hexagon::V6_vL32b_ai:
+ case Hexagon::V6_vL32b_ai_128B:
+ case Hexagon::V6_vL32Ub_ai:
+ case Hexagon::V6_vL32Ub_ai_128B:
+ case Hexagon::LDriw_pred:
+ case Hexagon::LDriw_mod:
+ case Hexagon::LDriq_pred_V6:
+ case Hexagon::LDriq_pred_vec_V6:
+ case Hexagon::LDriv_pseudo_V6:
+ case Hexagon::LDrivv_pseudo_V6:
+ case Hexagon::LDriq_pred_V6_128B:
+ case Hexagon::LDriq_pred_vec_V6_128B:
+ case Hexagon::LDriv_pseudo_V6_128B:
+ case Hexagon::LDrivv_pseudo_V6_128B: {
+ const MachineOperand OpFI = MI.getOperand(1);
+ if (!OpFI.isFI())
+ return 0;
+ const MachineOperand OpOff = MI.getOperand(2);
+ if (!OpOff.isImm() || OpOff.getImm() != 0)
+ return 0;
+ FrameIndex = OpFI.getIndex();
+ return MI.getOperand(0).getReg();
+ }
+
+ case Hexagon::L2_ploadrbt_io:
+ case Hexagon::L2_ploadrbf_io:
+ case Hexagon::L2_ploadrubt_io:
+ case Hexagon::L2_ploadrubf_io:
+ case Hexagon::L2_ploadrht_io:
+ case Hexagon::L2_ploadrhf_io:
+ case Hexagon::L2_ploadruht_io:
+ case Hexagon::L2_ploadruhf_io:
+ case Hexagon::L2_ploadrit_io:
+ case Hexagon::L2_ploadrif_io:
+ case Hexagon::L2_ploadrdt_io:
+ case Hexagon::L2_ploadrdf_io: {
+ const MachineOperand OpFI = MI.getOperand(2);
+ if (!OpFI.isFI())
+ return 0;
+ const MachineOperand OpOff = MI.getOperand(3);
+ if (!OpOff.isImm() || OpOff.getImm() != 0)
+ return 0;
+ FrameIndex = OpFI.getIndex();
+ return MI.getOperand(0).getReg();
+ }
}
+
return 0;
}
@@ -255,21 +298,58 @@ unsigned HexagonInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
/// the source reg along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than storing to the stack slot.
-unsigned HexagonInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
+unsigned HexagonInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
- switch (MI->getOpcode()) {
- default: break;
+ switch (MI.getOpcode()) {
+ default:
+ break;
+ case Hexagon::S2_storerb_io:
+ case Hexagon::S2_storerh_io:
case Hexagon::S2_storeri_io:
case Hexagon::S2_storerd_io:
- case Hexagon::S2_storerh_io:
- case Hexagon::S2_storerb_io:
- if (MI->getOperand(2).isFI() &&
- MI->getOperand(1).isImm() && (MI->getOperand(1).getImm() == 0)) {
- FrameIndex = MI->getOperand(0).getIndex();
- return MI->getOperand(2).getReg();
- }
- break;
+ case Hexagon::V6_vS32b_ai:
+ case Hexagon::V6_vS32b_ai_128B:
+ case Hexagon::V6_vS32Ub_ai:
+ case Hexagon::V6_vS32Ub_ai_128B:
+ case Hexagon::STriw_pred:
+ case Hexagon::STriw_mod:
+ case Hexagon::STriq_pred_V6:
+ case Hexagon::STriq_pred_vec_V6:
+ case Hexagon::STriv_pseudo_V6:
+ case Hexagon::STrivv_pseudo_V6:
+ case Hexagon::STriq_pred_V6_128B:
+ case Hexagon::STriq_pred_vec_V6_128B:
+ case Hexagon::STriv_pseudo_V6_128B:
+ case Hexagon::STrivv_pseudo_V6_128B: {
+ const MachineOperand &OpFI = MI.getOperand(0);
+ if (!OpFI.isFI())
+ return 0;
+ const MachineOperand &OpOff = MI.getOperand(1);
+ if (!OpOff.isImm() || OpOff.getImm() != 0)
+ return 0;
+ FrameIndex = OpFI.getIndex();
+ return MI.getOperand(2).getReg();
}
+
+ case Hexagon::S2_pstorerbt_io:
+ case Hexagon::S2_pstorerbf_io:
+ case Hexagon::S2_pstorerht_io:
+ case Hexagon::S2_pstorerhf_io:
+ case Hexagon::S2_pstorerit_io:
+ case Hexagon::S2_pstorerif_io:
+ case Hexagon::S2_pstorerdt_io:
+ case Hexagon::S2_pstorerdf_io: {
+ const MachineOperand &OpFI = MI.getOperand(1);
+ if (!OpFI.isFI())
+ return 0;
+ const MachineOperand &OpOff = MI.getOperand(2);
+ if (!OpOff.isImm() || OpOff.getImm() != 0)
+ return 0;
+ FrameIndex = OpFI.getIndex();
+ return MI.getOperand(3).getReg();
+ }
+ }
+
return 0;
}
@@ -290,7 +370,7 @@ unsigned HexagonInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
/// Cond[1] = R
/// Cond[2] = Imm
///
-bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
+bool HexagonInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
@@ -344,7 +424,7 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
return false;
--I;
}
- if (!isUnpredicatedTerminator(&*I))
+ if (!isUnpredicatedTerminator(*I))
return false;
// Get the last instruction in the block.
@@ -352,7 +432,7 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
MachineInstr *SecondLastInst = nullptr;
// Find one more terminator if present.
for (;;) {
- if (&*I != LastInst && !I->isBundle() && isUnpredicatedTerminator(&*I)) {
+ if (&*I != LastInst && !I->isBundle() && isUnpredicatedTerminator(*I)) {
if (!SecondLastInst)
SecondLastInst = &*I;
else
@@ -377,6 +457,9 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
bool LastOpcodeHasJMP_c = PredOpcodeHasJMP_c(LastOpcode);
bool LastOpcodeHasNVJump = isNewValueJump(LastInst);
+ if (LastOpcodeHasJMP_c && !LastInst->getOperand(1).isMBB())
+ return true;
+
// If there is only one terminator instruction, process it.
if (LastInst && !SecondLastInst) {
if (LastOpcode == Hexagon::J2_jump) {
@@ -412,6 +495,8 @@ bool HexagonInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
bool SecLastOpcodeHasJMP_c = PredOpcodeHasJMP_c(SecLastOpcode);
bool SecLastOpcodeHasNVJump = isNewValueJump(SecondLastInst);
if (SecLastOpcodeHasJMP_c && (LastOpcode == Hexagon::J2_jump)) {
+ if (!SecondLastInst->getOperand(1).isMBB())
+ return true;
TBB = SecondLastInst->getOperand(1).getMBB();
Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode()));
Cond.push_back(SecondLastInst->getOperand(0));
@@ -476,10 +561,11 @@ unsigned HexagonInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
return Count;
}
-
unsigned HexagonInstrInfo::InsertBranch(MachineBasicBlock &MBB,
- MachineBasicBlock *TBB, MachineBasicBlock *FBB,
- ArrayRef<MachineOperand> Cond, DebugLoc DL) const {
+ MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB,
+ ArrayRef<MachineOperand> Cond,
+ const DebugLoc &DL) const {
unsigned BOpc = Hexagon::J2_jump;
unsigned BccOpc = Hexagon::J2_jumpt;
assert(validateBranchCond(Cond) && "Invalid branching condition");
@@ -499,9 +585,9 @@ unsigned HexagonInstrInfo::InsertBranch(MachineBasicBlock &MBB,
// into an infinite loop.
MachineBasicBlock *NewTBB, *NewFBB;
SmallVector<MachineOperand, 4> Cond;
- MachineInstr *Term = MBB.getFirstTerminator();
- if (Term != MBB.end() && isPredicated(Term) &&
- !AnalyzeBranch(MBB, NewTBB, NewFBB, Cond, false)) {
+ auto Term = MBB.getFirstTerminator();
+ if (Term != MBB.end() && isPredicated(*Term) &&
+ !analyzeBranch(MBB, NewTBB, NewFBB, Cond, false)) {
MachineBasicBlock *NextBB = &*++MBB.getIterator();
if (NewTBB == NextBB) {
ReverseBranchCondition(Cond);
@@ -592,85 +678,84 @@ bool HexagonInstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB,
return NumInstrs <= 4;
}
-
void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg,
- unsigned SrcReg, bool KillSrc) const {
+ MachineBasicBlock::iterator I,
+ const DebugLoc &DL, unsigned DestReg,
+ unsigned SrcReg, bool KillSrc) const {
auto &HRI = getRegisterInfo();
+ unsigned KillFlag = getKillRegState(KillSrc);
+
if (Hexagon::IntRegsRegClass.contains(SrcReg, DestReg)) {
- BuildMI(MBB, I, DL, get(Hexagon::A2_tfr), DestReg).addReg(SrcReg);
+ BuildMI(MBB, I, DL, get(Hexagon::A2_tfr), DestReg)
+ .addReg(SrcReg, KillFlag);
return;
}
if (Hexagon::DoubleRegsRegClass.contains(SrcReg, DestReg)) {
- BuildMI(MBB, I, DL, get(Hexagon::A2_tfrp), DestReg).addReg(SrcReg);
+ BuildMI(MBB, I, DL, get(Hexagon::A2_tfrp), DestReg)
+ .addReg(SrcReg, KillFlag);
return;
}
if (Hexagon::PredRegsRegClass.contains(SrcReg, DestReg)) {
// Map Pd = Ps to Pd = or(Ps, Ps).
- BuildMI(MBB, I, DL, get(Hexagon::C2_or),
- DestReg).addReg(SrcReg).addReg(SrcReg);
+ BuildMI(MBB, I, DL, get(Hexagon::C2_or), DestReg)
+ .addReg(SrcReg).addReg(SrcReg, KillFlag);
return;
}
- if (Hexagon::DoubleRegsRegClass.contains(DestReg) &&
+ if (Hexagon::CtrRegsRegClass.contains(DestReg) &&
Hexagon::IntRegsRegClass.contains(SrcReg)) {
- // We can have an overlap between single and double reg: r1:0 = r0.
- if(SrcReg == RI.getSubReg(DestReg, Hexagon::subreg_loreg)) {
- // r1:0 = r0
- BuildMI(MBB, I, DL, get(Hexagon::A2_tfrsi), (RI.getSubReg(DestReg,
- Hexagon::subreg_hireg))).addImm(0);
- } else {
- // r1:0 = r1 or no overlap.
- BuildMI(MBB, I, DL, get(Hexagon::A2_tfr), (RI.getSubReg(DestReg,
- Hexagon::subreg_loreg))).addReg(SrcReg);
- BuildMI(MBB, I, DL, get(Hexagon::A2_tfrsi), (RI.getSubReg(DestReg,
- Hexagon::subreg_hireg))).addImm(0);
- }
+ BuildMI(MBB, I, DL, get(Hexagon::A2_tfrrcr), DestReg)
+ .addReg(SrcReg, KillFlag);
return;
}
- if (Hexagon::CtrRegsRegClass.contains(DestReg) &&
+ if (Hexagon::IntRegsRegClass.contains(DestReg) &&
+ Hexagon::CtrRegsRegClass.contains(SrcReg)) {
+ BuildMI(MBB, I, DL, get(Hexagon::A2_tfrcrr), DestReg)
+ .addReg(SrcReg, KillFlag);
+ return;
+ }
+ if (Hexagon::ModRegsRegClass.contains(DestReg) &&
Hexagon::IntRegsRegClass.contains(SrcReg)) {
- BuildMI(MBB, I, DL, get(Hexagon::A2_tfrrcr), DestReg).addReg(SrcReg);
+ BuildMI(MBB, I, DL, get(Hexagon::A2_tfrrcr), DestReg)
+ .addReg(SrcReg, KillFlag);
return;
}
if (Hexagon::PredRegsRegClass.contains(SrcReg) &&
Hexagon::IntRegsRegClass.contains(DestReg)) {
- BuildMI(MBB, I, DL, get(Hexagon::C2_tfrpr), DestReg).
- addReg(SrcReg, getKillRegState(KillSrc));
+ BuildMI(MBB, I, DL, get(Hexagon::C2_tfrpr), DestReg)
+ .addReg(SrcReg, KillFlag);
return;
}
if (Hexagon::IntRegsRegClass.contains(SrcReg) &&
Hexagon::PredRegsRegClass.contains(DestReg)) {
- BuildMI(MBB, I, DL, get(Hexagon::C2_tfrrp), DestReg).
- addReg(SrcReg, getKillRegState(KillSrc));
+ BuildMI(MBB, I, DL, get(Hexagon::C2_tfrrp), DestReg)
+ .addReg(SrcReg, KillFlag);
return;
}
if (Hexagon::PredRegsRegClass.contains(SrcReg) &&
Hexagon::IntRegsRegClass.contains(DestReg)) {
- BuildMI(MBB, I, DL, get(Hexagon::C2_tfrpr), DestReg).
- addReg(SrcReg, getKillRegState(KillSrc));
+ BuildMI(MBB, I, DL, get(Hexagon::C2_tfrpr), DestReg)
+ .addReg(SrcReg, KillFlag);
return;
}
if (Hexagon::VectorRegsRegClass.contains(SrcReg, DestReg)) {
BuildMI(MBB, I, DL, get(Hexagon::V6_vassign), DestReg).
- addReg(SrcReg, getKillRegState(KillSrc));
+ addReg(SrcReg, KillFlag);
return;
}
if (Hexagon::VecDblRegsRegClass.contains(SrcReg, DestReg)) {
- BuildMI(MBB, I, DL, get(Hexagon::V6_vcombine), DestReg).
- addReg(HRI.getSubReg(SrcReg, Hexagon::subreg_hireg),
- getKillRegState(KillSrc)).
- addReg(HRI.getSubReg(SrcReg, Hexagon::subreg_loreg),
- getKillRegState(KillSrc));
+ BuildMI(MBB, I, DL, get(Hexagon::V6_vcombine), DestReg)
+ .addReg(HRI.getSubReg(SrcReg, Hexagon::subreg_hireg), KillFlag)
+ .addReg(HRI.getSubReg(SrcReg, Hexagon::subreg_loreg), KillFlag);
return;
}
if (Hexagon::VecPredRegsRegClass.contains(SrcReg, DestReg)) {
- BuildMI(MBB, I, DL, get(Hexagon::V6_pred_and), DestReg).
- addReg(SrcReg).
- addReg(SrcReg, getKillRegState(KillSrc));
+ BuildMI(MBB, I, DL, get(Hexagon::V6_pred_and), DestReg)
+ .addReg(SrcReg)
+ .addReg(SrcReg, KillFlag);
return;
}
if (Hexagon::VecPredRegsRegClass.contains(SrcReg) &&
- Hexagon::VectorRegsRegClass.contains(DestReg)) {
+ Hexagon::VectorRegsRegClass.contains(DestReg)) {
llvm_unreachable("Unimplemented pred to vec");
return;
}
@@ -680,14 +765,12 @@ void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
return;
}
if (Hexagon::VecPredRegs128BRegClass.contains(SrcReg, DestReg)) {
- BuildMI(MBB, I, DL, get(Hexagon::V6_pred_and),
- HRI.getSubReg(DestReg, Hexagon::subreg_hireg)).
- addReg(HRI.getSubReg(SrcReg, Hexagon::subreg_hireg),
- getKillRegState(KillSrc));
- BuildMI(MBB, I, DL, get(Hexagon::V6_pred_and),
- HRI.getSubReg(DestReg, Hexagon::subreg_loreg)).
- addReg(HRI.getSubReg(SrcReg, Hexagon::subreg_loreg),
- getKillRegState(KillSrc));
+ unsigned DstHi = HRI.getSubReg(DestReg, Hexagon::subreg_hireg);
+ BuildMI(MBB, I, DL, get(Hexagon::V6_pred_and), DstHi)
+ .addReg(HRI.getSubReg(SrcReg, Hexagon::subreg_hireg), KillFlag);
+ unsigned DstLo = HRI.getSubReg(DestReg, Hexagon::subreg_loreg);
+ BuildMI(MBB, I, DL, get(Hexagon::V6_pred_and), DstLo)
+ .addReg(HRI.getSubReg(SrcReg, Hexagon::subreg_loreg), KillFlag);
return;
}
@@ -708,6 +791,7 @@ void HexagonInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = *MF.getFrameInfo();
unsigned Align = MFI.getObjectAlignment(FI);
+ unsigned KillFlag = getKillRegState(isKill);
MachineMemOperand *MMO = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
@@ -715,25 +799,57 @@ void HexagonInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
if (Hexagon::IntRegsRegClass.hasSubClassEq(RC)) {
BuildMI(MBB, I, DL, get(Hexagon::S2_storeri_io))
- .addFrameIndex(FI).addImm(0)
- .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
+ .addFrameIndex(FI).addImm(0)
+ .addReg(SrcReg, KillFlag).addMemOperand(MMO);
} else if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC)) {
BuildMI(MBB, I, DL, get(Hexagon::S2_storerd_io))
- .addFrameIndex(FI).addImm(0)
- .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
+ .addFrameIndex(FI).addImm(0)
+ .addReg(SrcReg, KillFlag).addMemOperand(MMO);
} else if (Hexagon::PredRegsRegClass.hasSubClassEq(RC)) {
BuildMI(MBB, I, DL, get(Hexagon::STriw_pred))
- .addFrameIndex(FI).addImm(0)
- .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
+ .addFrameIndex(FI).addImm(0)
+ .addReg(SrcReg, KillFlag).addMemOperand(MMO);
+ } else if (Hexagon::ModRegsRegClass.hasSubClassEq(RC)) {
+ BuildMI(MBB, I, DL, get(Hexagon::STriw_mod))
+ .addFrameIndex(FI).addImm(0)
+ .addReg(SrcReg, KillFlag).addMemOperand(MMO);
+ } else if (Hexagon::VecPredRegs128BRegClass.hasSubClassEq(RC)) {
+ BuildMI(MBB, I, DL, get(Hexagon::STriq_pred_V6_128B))
+ .addFrameIndex(FI).addImm(0)
+ .addReg(SrcReg, KillFlag).addMemOperand(MMO);
+ } else if (Hexagon::VecPredRegsRegClass.hasSubClassEq(RC)) {
+ BuildMI(MBB, I, DL, get(Hexagon::STriq_pred_V6))
+ .addFrameIndex(FI).addImm(0)
+ .addReg(SrcReg, KillFlag).addMemOperand(MMO);
+ } else if (Hexagon::VectorRegs128BRegClass.hasSubClassEq(RC)) {
+ DEBUG(dbgs() << "++Generating 128B vector spill");
+ BuildMI(MBB, I, DL, get(Hexagon::STriv_pseudo_V6_128B))
+ .addFrameIndex(FI).addImm(0)
+ .addReg(SrcReg, KillFlag).addMemOperand(MMO);
+ } else if (Hexagon::VectorRegsRegClass.hasSubClassEq(RC)) {
+ DEBUG(dbgs() << "++Generating vector spill");
+ BuildMI(MBB, I, DL, get(Hexagon::STriv_pseudo_V6))
+ .addFrameIndex(FI).addImm(0)
+ .addReg(SrcReg, KillFlag).addMemOperand(MMO);
+ } else if (Hexagon::VecDblRegsRegClass.hasSubClassEq(RC)) {
+ DEBUG(dbgs() << "++Generating double vector spill");
+ BuildMI(MBB, I, DL, get(Hexagon::STrivv_pseudo_V6))
+ .addFrameIndex(FI).addImm(0)
+ .addReg(SrcReg, KillFlag).addMemOperand(MMO);
+ } else if (Hexagon::VecDblRegs128BRegClass.hasSubClassEq(RC)) {
+ DEBUG(dbgs() << "++Generating 128B double vector spill");
+ BuildMI(MBB, I, DL, get(Hexagon::STrivv_pseudo_V6_128B))
+ .addFrameIndex(FI).addImm(0)
+ .addReg(SrcReg, KillFlag).addMemOperand(MMO);
} else {
llvm_unreachable("Unimplemented");
}
}
-
-void HexagonInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I, unsigned DestReg, int FI,
- const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const {
+void HexagonInstrInfo::loadRegFromStackSlot(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned DestReg,
+ int FI, const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const {
DebugLoc DL = MBB.findDebugLoc(I);
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = *MF.getFrameInfo();
@@ -742,15 +858,41 @@ void HexagonInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineMemOperand *MMO = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
MFI.getObjectSize(FI), Align);
- if (RC == &Hexagon::IntRegsRegClass) {
+
+ if (Hexagon::IntRegsRegClass.hasSubClassEq(RC)) {
BuildMI(MBB, I, DL, get(Hexagon::L2_loadri_io), DestReg)
- .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
- } else if (RC == &Hexagon::DoubleRegsRegClass) {
+ .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
+ } else if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC)) {
BuildMI(MBB, I, DL, get(Hexagon::L2_loadrd_io), DestReg)
- .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
- } else if (RC == &Hexagon::PredRegsRegClass) {
+ .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
+ } else if (Hexagon::PredRegsRegClass.hasSubClassEq(RC)) {
BuildMI(MBB, I, DL, get(Hexagon::LDriw_pred), DestReg)
- .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
+ .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
+ } else if (Hexagon::ModRegsRegClass.hasSubClassEq(RC)) {
+ BuildMI(MBB, I, DL, get(Hexagon::LDriw_mod), DestReg)
+ .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
+ } else if (Hexagon::VecPredRegs128BRegClass.hasSubClassEq(RC)) {
+ BuildMI(MBB, I, DL, get(Hexagon::LDriq_pred_V6_128B), DestReg)
+ .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
+ } else if (Hexagon::VecPredRegsRegClass.hasSubClassEq(RC)) {
+ BuildMI(MBB, I, DL, get(Hexagon::LDriq_pred_V6), DestReg)
+ .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
+ } else if (Hexagon::VecDblRegs128BRegClass.hasSubClassEq(RC)) {
+ DEBUG(dbgs() << "++Generating 128B double vector restore");
+ BuildMI(MBB, I, DL, get(Hexagon::LDrivv_pseudo_V6_128B), DestReg)
+ .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
+ } else if (Hexagon::VectorRegs128BRegClass.hasSubClassEq(RC)) {
+ DEBUG(dbgs() << "++Generating 128B vector restore");
+ BuildMI(MBB, I, DL, get(Hexagon::LDriv_pseudo_V6_128B), DestReg)
+ .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
+ } else if (Hexagon::VectorRegsRegClass.hasSubClassEq(RC)) {
+ DEBUG(dbgs() << "++Generating vector restore");
+ BuildMI(MBB, I, DL, get(Hexagon::LDriv_pseudo_V6), DestReg)
+ .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
+ } else if (Hexagon::VecDblRegsRegClass.hasSubClassEq(RC)) {
+ DEBUG(dbgs() << "++Generating double vector restore");
+ BuildMI(MBB, I, DL, get(Hexagon::LDrivv_pseudo_V6), DestReg)
+ .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
} else {
llvm_unreachable("Can't store this register to stack slot");
}
@@ -763,48 +905,58 @@ void HexagonInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
/// into real instructions. The target can edit MI in place, or it can insert
/// new instructions and erase MI. The function should return true if
/// anything was changed.
-bool HexagonInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI)
- const {
+bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
const HexagonRegisterInfo &HRI = getRegisterInfo();
- MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo();
- MachineBasicBlock &MBB = *MI->getParent();
- DebugLoc DL = MI->getDebugLoc();
- unsigned Opc = MI->getOpcode();
+ MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
+ MachineBasicBlock &MBB = *MI.getParent();
+ DebugLoc DL = MI.getDebugLoc();
+ unsigned Opc = MI.getOpcode();
const unsigned VecOffset = 1;
bool Is128B = false;
switch (Opc) {
+ case TargetOpcode::COPY: {
+ MachineOperand &MD = MI.getOperand(0);
+ MachineOperand &MS = MI.getOperand(1);
+ MachineBasicBlock::iterator MBBI = MI.getIterator();
+ if (MD.getReg() != MS.getReg() && !MS.isUndef()) {
+ copyPhysReg(MBB, MI, DL, MD.getReg(), MS.getReg(), MS.isKill());
+ std::prev(MBBI)->copyImplicitOps(*MBB.getParent(), MI);
+ }
+ MBB.erase(MBBI);
+ return true;
+ }
case Hexagon::ALIGNA:
- BuildMI(MBB, MI, DL, get(Hexagon::A2_andir), MI->getOperand(0).getReg())
+ BuildMI(MBB, MI, DL, get(Hexagon::A2_andir), MI.getOperand(0).getReg())
.addReg(HRI.getFrameRegister())
- .addImm(-MI->getOperand(1).getImm());
+ .addImm(-MI.getOperand(1).getImm());
MBB.erase(MI);
return true;
case Hexagon::HEXAGON_V6_vassignp_128B:
case Hexagon::HEXAGON_V6_vassignp: {
- unsigned SrcReg = MI->getOperand(1).getReg();
- unsigned DstReg = MI->getOperand(0).getReg();
+ unsigned SrcReg = MI.getOperand(1).getReg();
+ unsigned DstReg = MI.getOperand(0).getReg();
if (SrcReg != DstReg)
- copyPhysReg(MBB, MI, DL, DstReg, SrcReg, MI->getOperand(1).isKill());
+ copyPhysReg(MBB, MI, DL, DstReg, SrcReg, MI.getOperand(1).isKill());
MBB.erase(MI);
return true;
}
case Hexagon::HEXAGON_V6_lo_128B:
case Hexagon::HEXAGON_V6_lo: {
- unsigned SrcReg = MI->getOperand(1).getReg();
- unsigned DstReg = MI->getOperand(0).getReg();
+ unsigned SrcReg = MI.getOperand(1).getReg();
+ unsigned DstReg = MI.getOperand(0).getReg();
unsigned SrcSubLo = HRI.getSubReg(SrcReg, Hexagon::subreg_loreg);
- copyPhysReg(MBB, MI, DL, DstReg, SrcSubLo, MI->getOperand(1).isKill());
+ copyPhysReg(MBB, MI, DL, DstReg, SrcSubLo, MI.getOperand(1).isKill());
MBB.erase(MI);
MRI.clearKillFlags(SrcSubLo);
return true;
}
case Hexagon::HEXAGON_V6_hi_128B:
case Hexagon::HEXAGON_V6_hi: {
- unsigned SrcReg = MI->getOperand(1).getReg();
- unsigned DstReg = MI->getOperand(0).getReg();
+ unsigned SrcReg = MI.getOperand(1).getReg();
+ unsigned DstReg = MI.getOperand(0).getReg();
unsigned SrcSubHi = HRI.getSubReg(SrcReg, Hexagon::subreg_hireg);
- copyPhysReg(MBB, MI, DL, DstReg, SrcSubHi, MI->getOperand(1).isKill());
+ copyPhysReg(MBB, MI, DL, DstReg, SrcSubHi, MI.getOperand(1).isKill());
MBB.erase(MI);
MRI.clearKillFlags(SrcSubHi);
return true;
@@ -812,24 +964,25 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI)
case Hexagon::STrivv_indexed_128B:
Is128B = true;
case Hexagon::STrivv_indexed: {
- unsigned SrcReg = MI->getOperand(2).getReg();
+ unsigned SrcReg = MI.getOperand(2).getReg();
unsigned SrcSubHi = HRI.getSubReg(SrcReg, Hexagon::subreg_hireg);
unsigned SrcSubLo = HRI.getSubReg(SrcReg, Hexagon::subreg_loreg);
unsigned NewOpcd = Is128B ? Hexagon::V6_vS32b_ai_128B
: Hexagon::V6_vS32b_ai;
unsigned Offset = Is128B ? VecOffset << 7 : VecOffset << 6;
- MachineInstr *MI1New = BuildMI(MBB, MI, DL, get(NewOpcd))
- .addOperand(MI->getOperand(0))
- .addImm(MI->getOperand(1).getImm())
- .addReg(SrcSubLo)
- .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+ MachineInstr *MI1New =
+ BuildMI(MBB, MI, DL, get(NewOpcd))
+ .addOperand(MI.getOperand(0))
+ .addImm(MI.getOperand(1).getImm())
+ .addReg(SrcSubLo)
+ .setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
MI1New->getOperand(0).setIsKill(false);
BuildMI(MBB, MI, DL, get(NewOpcd))
- .addOperand(MI->getOperand(0))
- // The Vectors are indexed in multiples of vector size.
- .addImm(MI->getOperand(1).getImm()+Offset)
- .addReg(SrcSubHi)
- .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+ .addOperand(MI.getOperand(0))
+ // The Vectors are indexed in multiples of vector size.
+ .addImm(MI.getOperand(1).getImm() + Offset)
+ .addReg(SrcSubHi)
+ .setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
MBB.erase(MI);
return true;
}
@@ -840,35 +993,34 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI)
case Hexagon::LDrivv_indexed: {
unsigned NewOpcd = Is128B ? Hexagon::V6_vL32b_ai_128B
: Hexagon::V6_vL32b_ai;
- unsigned DstReg = MI->getOperand(0).getReg();
+ unsigned DstReg = MI.getOperand(0).getReg();
unsigned Offset = Is128B ? VecOffset << 7 : VecOffset << 6;
MachineInstr *MI1New =
BuildMI(MBB, MI, DL, get(NewOpcd),
HRI.getSubReg(DstReg, Hexagon::subreg_loreg))
- .addOperand(MI->getOperand(1))
- .addImm(MI->getOperand(2).getImm());
+ .addOperand(MI.getOperand(1))
+ .addImm(MI.getOperand(2).getImm());
MI1New->getOperand(1).setIsKill(false);
BuildMI(MBB, MI, DL, get(NewOpcd),
HRI.getSubReg(DstReg, Hexagon::subreg_hireg))
- .addOperand(MI->getOperand(1))
+ .addOperand(MI.getOperand(1))
// The Vectors are indexed in multiples of vector size.
- .addImm(MI->getOperand(2).getImm() + Offset)
- .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+ .addImm(MI.getOperand(2).getImm() + Offset)
+ .setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
MBB.erase(MI);
return true;
}
case Hexagon::LDriv_pseudo_V6_128B:
Is128B = true;
case Hexagon::LDriv_pseudo_V6: {
- unsigned DstReg = MI->getOperand(0).getReg();
+ unsigned DstReg = MI.getOperand(0).getReg();
unsigned NewOpc = Is128B ? Hexagon::V6_vL32b_ai_128B
: Hexagon::V6_vL32b_ai;
- int32_t Off = MI->getOperand(2).getImm();
- int32_t Idx = Off;
+ int32_t Off = MI.getOperand(2).getImm();
BuildMI(MBB, MI, DL, get(NewOpc), DstReg)
- .addOperand(MI->getOperand(1))
- .addImm(Idx)
- .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+ .addOperand(MI.getOperand(1))
+ .addImm(Off)
+ .setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
MBB.erase(MI);
return true;
}
@@ -877,18 +1029,17 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI)
case Hexagon::STriv_pseudo_V6: {
unsigned NewOpc = Is128B ? Hexagon::V6_vS32b_ai_128B
: Hexagon::V6_vS32b_ai;
- int32_t Off = MI->getOperand(1).getImm();
- int32_t Idx = Is128B ? (Off >> 7) : (Off >> 6);
+ int32_t Off = MI.getOperand(1).getImm();
BuildMI(MBB, MI, DL, get(NewOpc))
- .addOperand(MI->getOperand(0))
- .addImm(Idx)
- .addOperand(MI->getOperand(2))
- .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+ .addOperand(MI.getOperand(0))
+ .addImm(Off)
+ .addOperand(MI.getOperand(2))
+ .setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
MBB.erase(MI);
return true;
}
case Hexagon::TFR_PdTrue: {
- unsigned Reg = MI->getOperand(0).getReg();
+ unsigned Reg = MI.getOperand(0).getReg();
BuildMI(MBB, MI, DL, get(Hexagon::C2_orn), Reg)
.addReg(Reg, RegState::Undef)
.addReg(Reg, RegState::Undef);
@@ -896,7 +1047,7 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI)
return true;
}
case Hexagon::TFR_PdFalse: {
- unsigned Reg = MI->getOperand(0).getReg();
+ unsigned Reg = MI.getOperand(0).getReg();
BuildMI(MBB, MI, DL, get(Hexagon::C2_andn), Reg)
.addReg(Reg, RegState::Undef)
.addReg(Reg, RegState::Undef);
@@ -905,18 +1056,20 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI)
}
case Hexagon::VMULW: {
// Expand a 64-bit vector multiply into 2 32-bit scalar multiplies.
- unsigned DstReg = MI->getOperand(0).getReg();
- unsigned Src1Reg = MI->getOperand(1).getReg();
- unsigned Src2Reg = MI->getOperand(2).getReg();
+ unsigned DstReg = MI.getOperand(0).getReg();
+ unsigned Src1Reg = MI.getOperand(1).getReg();
+ unsigned Src2Reg = MI.getOperand(2).getReg();
unsigned Src1SubHi = HRI.getSubReg(Src1Reg, Hexagon::subreg_hireg);
unsigned Src1SubLo = HRI.getSubReg(Src1Reg, Hexagon::subreg_loreg);
unsigned Src2SubHi = HRI.getSubReg(Src2Reg, Hexagon::subreg_hireg);
unsigned Src2SubLo = HRI.getSubReg(Src2Reg, Hexagon::subreg_loreg);
- BuildMI(MBB, MI, MI->getDebugLoc(), get(Hexagon::M2_mpyi),
- HRI.getSubReg(DstReg, Hexagon::subreg_hireg)).addReg(Src1SubHi)
+ BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::M2_mpyi),
+ HRI.getSubReg(DstReg, Hexagon::subreg_hireg))
+ .addReg(Src1SubHi)
.addReg(Src2SubHi);
- BuildMI(MBB, MI, MI->getDebugLoc(), get(Hexagon::M2_mpyi),
- HRI.getSubReg(DstReg, Hexagon::subreg_loreg)).addReg(Src1SubLo)
+ BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::M2_mpyi),
+ HRI.getSubReg(DstReg, Hexagon::subreg_loreg))
+ .addReg(Src1SubLo)
.addReg(Src2SubLo);
MBB.erase(MI);
MRI.clearKillFlags(Src1SubHi);
@@ -927,22 +1080,26 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI)
}
case Hexagon::VMULW_ACC: {
// Expand 64-bit vector multiply with addition into 2 scalar multiplies.
- unsigned DstReg = MI->getOperand(0).getReg();
- unsigned Src1Reg = MI->getOperand(1).getReg();
- unsigned Src2Reg = MI->getOperand(2).getReg();
- unsigned Src3Reg = MI->getOperand(3).getReg();
+ unsigned DstReg = MI.getOperand(0).getReg();
+ unsigned Src1Reg = MI.getOperand(1).getReg();
+ unsigned Src2Reg = MI.getOperand(2).getReg();
+ unsigned Src3Reg = MI.getOperand(3).getReg();
unsigned Src1SubHi = HRI.getSubReg(Src1Reg, Hexagon::subreg_hireg);
unsigned Src1SubLo = HRI.getSubReg(Src1Reg, Hexagon::subreg_loreg);
unsigned Src2SubHi = HRI.getSubReg(Src2Reg, Hexagon::subreg_hireg);
unsigned Src2SubLo = HRI.getSubReg(Src2Reg, Hexagon::subreg_loreg);
unsigned Src3SubHi = HRI.getSubReg(Src3Reg, Hexagon::subreg_hireg);
unsigned Src3SubLo = HRI.getSubReg(Src3Reg, Hexagon::subreg_loreg);
- BuildMI(MBB, MI, MI->getDebugLoc(), get(Hexagon::M2_maci),
- HRI.getSubReg(DstReg, Hexagon::subreg_hireg)).addReg(Src1SubHi)
- .addReg(Src2SubHi).addReg(Src3SubHi);
- BuildMI(MBB, MI, MI->getDebugLoc(), get(Hexagon::M2_maci),
- HRI.getSubReg(DstReg, Hexagon::subreg_loreg)).addReg(Src1SubLo)
- .addReg(Src2SubLo).addReg(Src3SubLo);
+ BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::M2_maci),
+ HRI.getSubReg(DstReg, Hexagon::subreg_hireg))
+ .addReg(Src1SubHi)
+ .addReg(Src2SubHi)
+ .addReg(Src3SubHi);
+ BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::M2_maci),
+ HRI.getSubReg(DstReg, Hexagon::subreg_loreg))
+ .addReg(Src1SubLo)
+ .addReg(Src2SubLo)
+ .addReg(Src3SubLo);
MBB.erase(MI);
MRI.clearKillFlags(Src1SubHi);
MRI.clearKillFlags(Src1SubLo);
@@ -952,16 +1109,58 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI)
MRI.clearKillFlags(Src3SubLo);
return true;
}
+ case Hexagon::Insert4: {
+ unsigned DstReg = MI.getOperand(0).getReg();
+ unsigned Src1Reg = MI.getOperand(1).getReg();
+ unsigned Src2Reg = MI.getOperand(2).getReg();
+ unsigned Src3Reg = MI.getOperand(3).getReg();
+ unsigned Src4Reg = MI.getOperand(4).getReg();
+ unsigned Src1RegIsKill = getKillRegState(MI.getOperand(1).isKill());
+ unsigned Src2RegIsKill = getKillRegState(MI.getOperand(2).isKill());
+ unsigned Src3RegIsKill = getKillRegState(MI.getOperand(3).isKill());
+ unsigned Src4RegIsKill = getKillRegState(MI.getOperand(4).isKill());
+ unsigned DstSubHi = HRI.getSubReg(DstReg, Hexagon::subreg_hireg);
+ unsigned DstSubLo = HRI.getSubReg(DstReg, Hexagon::subreg_loreg);
+ BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::S2_insert),
+ HRI.getSubReg(DstReg, Hexagon::subreg_loreg))
+ .addReg(DstSubLo)
+ .addReg(Src1Reg, Src1RegIsKill)
+ .addImm(16)
+ .addImm(0);
+ BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::S2_insert),
+ HRI.getSubReg(DstReg, Hexagon::subreg_loreg))
+ .addReg(DstSubLo)
+ .addReg(Src2Reg, Src2RegIsKill)
+ .addImm(16)
+ .addImm(16);
+ BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::S2_insert),
+ HRI.getSubReg(DstReg, Hexagon::subreg_hireg))
+ .addReg(DstSubHi)
+ .addReg(Src3Reg, Src3RegIsKill)
+ .addImm(16)
+ .addImm(0);
+ BuildMI(MBB, MI, MI.getDebugLoc(), get(Hexagon::S2_insert),
+ HRI.getSubReg(DstReg, Hexagon::subreg_hireg))
+ .addReg(DstSubHi)
+ .addReg(Src4Reg, Src4RegIsKill)
+ .addImm(16)
+ .addImm(16);
+ MBB.erase(MI);
+ MRI.clearKillFlags(DstReg);
+ MRI.clearKillFlags(DstSubHi);
+ MRI.clearKillFlags(DstSubLo);
+ return true;
+ }
case Hexagon::MUX64_rr: {
- const MachineOperand &Op0 = MI->getOperand(0);
- const MachineOperand &Op1 = MI->getOperand(1);
- const MachineOperand &Op2 = MI->getOperand(2);
- const MachineOperand &Op3 = MI->getOperand(3);
+ const MachineOperand &Op0 = MI.getOperand(0);
+ const MachineOperand &Op1 = MI.getOperand(1);
+ const MachineOperand &Op2 = MI.getOperand(2);
+ const MachineOperand &Op3 = MI.getOperand(3);
unsigned Rd = Op0.getReg();
unsigned Pu = Op1.getReg();
unsigned Rs = Op2.getReg();
unsigned Rt = Op3.getReg();
- DebugLoc DL = MI->getDebugLoc();
+ DebugLoc DL = MI.getDebugLoc();
unsigned K1 = getKillRegState(Op1.isKill());
unsigned K2 = getKillRegState(Op2.isKill());
unsigned K3 = getKillRegState(Op3.isKill());
@@ -976,24 +1175,62 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI)
MBB.erase(MI);
return true;
}
+ case Hexagon::VSelectPseudo_V6: {
+ const MachineOperand &Op0 = MI.getOperand(0);
+ const MachineOperand &Op1 = MI.getOperand(1);
+ const MachineOperand &Op2 = MI.getOperand(2);
+ const MachineOperand &Op3 = MI.getOperand(3);
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vcmov))
+ .addOperand(Op0)
+ .addOperand(Op1)
+ .addOperand(Op2);
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vncmov))
+ .addOperand(Op0)
+ .addOperand(Op1)
+ .addOperand(Op3);
+ MBB.erase(MI);
+ return true;
+ }
+ case Hexagon::VSelectDblPseudo_V6: {
+ MachineOperand &Op0 = MI.getOperand(0);
+ MachineOperand &Op1 = MI.getOperand(1);
+ MachineOperand &Op2 = MI.getOperand(2);
+ MachineOperand &Op3 = MI.getOperand(3);
+ unsigned SrcLo = HRI.getSubReg(Op2.getReg(), Hexagon::subreg_loreg);
+ unsigned SrcHi = HRI.getSubReg(Op2.getReg(), Hexagon::subreg_hireg);
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vccombine))
+ .addOperand(Op0)
+ .addOperand(Op1)
+ .addReg(SrcHi)
+ .addReg(SrcLo);
+ SrcLo = HRI.getSubReg(Op3.getReg(), Hexagon::subreg_loreg);
+ SrcHi = HRI.getSubReg(Op3.getReg(), Hexagon::subreg_hireg);
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vnccombine))
+ .addOperand(Op0)
+ .addOperand(Op1)
+ .addReg(SrcHi)
+ .addReg(SrcLo);
+ MBB.erase(MI);
+ return true;
+ }
case Hexagon::TCRETURNi:
- MI->setDesc(get(Hexagon::J2_jump));
+ MI.setDesc(get(Hexagon::J2_jump));
return true;
case Hexagon::TCRETURNr:
- MI->setDesc(get(Hexagon::J2_jumpr));
+ MI.setDesc(get(Hexagon::J2_jumpr));
return true;
case Hexagon::TFRI_f:
case Hexagon::TFRI_cPt_f:
case Hexagon::TFRI_cNotPt_f: {
unsigned Opx = (Opc == Hexagon::TFRI_f) ? 1 : 2;
- APFloat FVal = MI->getOperand(Opx).getFPImm()->getValueAPF();
+ APFloat FVal = MI.getOperand(Opx).getFPImm()->getValueAPF();
APInt IVal = FVal.bitcastToAPInt();
- MI->RemoveOperand(Opx);
+ MI.RemoveOperand(Opx);
unsigned NewOpc = (Opc == Hexagon::TFRI_f) ? Hexagon::A2_tfrsi :
(Opc == Hexagon::TFRI_cPt_f) ? Hexagon::C2_cmoveit :
Hexagon::C2_cmoveif;
- MI->setDesc(get(NewOpc));
- MI->addOperand(MachineOperand::CreateImm(IVal.getZExtValue()));
+ MI.setDesc(get(NewOpc));
+ MI.addOperand(MachineOperand::CreateImm(IVal.getZExtValue()));
return true;
}
}
@@ -1035,20 +1272,20 @@ void HexagonInstrInfo::insertNoop(MachineBasicBlock &MBB,
// if (!p0.new) R1 = add(R2, R3)
// Note: New-value stores are not included here as in the current
// implementation, we don't need to check their predicate sense.
-bool HexagonInstrInfo::isPredicated(const MachineInstr *MI) const {
- const uint64_t F = MI->getDesc().TSFlags;
+bool HexagonInstrInfo::isPredicated(const MachineInstr &MI) const {
+ const uint64_t F = MI.getDesc().TSFlags;
return (F >> HexagonII::PredicatedPos) & HexagonII::PredicatedMask;
}
-bool HexagonInstrInfo::PredicateInstruction(MachineInstr *MI,
- ArrayRef<MachineOperand> Cond) const {
+bool HexagonInstrInfo::PredicateInstruction(
+ MachineInstr &MI, ArrayRef<MachineOperand> Cond) const {
if (Cond.empty() || isNewValueJump(Cond[0].getImm()) ||
isEndLoopN(Cond[0].getImm())) {
- DEBUG(dbgs() << "\nCannot predicate:"; MI->dump(););
+ DEBUG(dbgs() << "\nCannot predicate:"; MI.dump(););
return false;
}
- int Opc = MI->getOpcode();
+ int Opc = MI.getOpcode();
assert (isPredicable(MI) && "Expected predicable instruction");
bool invertJump = predOpcodeHasNot(Cond);
@@ -1057,13 +1294,13 @@ bool HexagonInstrInfo::PredicateInstruction(MachineInstr *MI,
// plicated manipulations with the operands (handling tied operands,
// etc.), build a new temporary instruction, then overwrite MI with it.
- MachineBasicBlock &B = *MI->getParent();
- DebugLoc DL = MI->getDebugLoc();
+ MachineBasicBlock &B = *MI.getParent();
+ DebugLoc DL = MI.getDebugLoc();
unsigned PredOpc = getCondOpcode(Opc, invertJump);
MachineInstrBuilder T = BuildMI(B, MI, DL, get(PredOpc));
- unsigned NOp = 0, NumOps = MI->getNumOperands();
+ unsigned NOp = 0, NumOps = MI.getNumOperands();
while (NOp < NumOps) {
- MachineOperand &Op = MI->getOperand(NOp);
+ MachineOperand &Op = MI.getOperand(NOp);
if (!Op.isReg() || !Op.isDef() || Op.isImplicit())
break;
T.addOperand(Op);
@@ -1076,13 +1313,13 @@ bool HexagonInstrInfo::PredicateInstruction(MachineInstr *MI,
assert(GotPredReg);
T.addReg(PredReg, PredRegFlags);
while (NOp < NumOps)
- T.addOperand(MI->getOperand(NOp++));
+ T.addOperand(MI.getOperand(NOp++));
- MI->setDesc(get(PredOpc));
- while (unsigned n = MI->getNumOperands())
- MI->RemoveOperand(n-1);
+ MI.setDesc(get(PredOpc));
+ while (unsigned n = MI.getNumOperands())
+ MI.RemoveOperand(n-1);
for (unsigned i = 0, n = T->getNumOperands(); i < n; ++i)
- MI->addOperand(T->getOperand(i));
+ MI.addOperand(T->getOperand(i));
MachineBasicBlock::instr_iterator TI = T->getIterator();
B.erase(TI);
@@ -1100,11 +1337,11 @@ bool HexagonInstrInfo::SubsumesPredicate(ArrayRef<MachineOperand> Pred1,
}
-bool HexagonInstrInfo::DefinesPredicate(MachineInstr *MI,
- std::vector<MachineOperand> &Pred) const {
+bool HexagonInstrInfo::DefinesPredicate(
+ MachineInstr &MI, std::vector<MachineOperand> &Pred) const {
auto &HRI = getRegisterInfo();
- for (unsigned oper = 0; oper < MI->getNumOperands(); ++oper) {
- MachineOperand MO = MI->getOperand(oper);
+ for (unsigned oper = 0; oper < MI.getNumOperands(); ++oper) {
+ MachineOperand MO = MI.getOperand(oper);
if (MO.isReg() && MO.isDef()) {
const TargetRegisterClass* RC = HRI.getMinimalPhysRegClass(MO.getReg());
if (RC == &Hexagon::PredRegsRegClass) {
@@ -1116,107 +1353,25 @@ bool HexagonInstrInfo::DefinesPredicate(MachineInstr *MI,
return false;
}
-bool HexagonInstrInfo::isPredicable(MachineInstr *MI) const {
- bool isPred = MI->getDesc().isPredicable();
-
- if (!isPred)
- return false;
-
- const int Opc = MI->getOpcode();
- int NumOperands = MI->getNumOperands();
-
- // Keep a flag for upto 4 operands in the instructions, to indicate if
- // that operand has been constant extended.
- bool OpCExtended[4];
- if (NumOperands > 4)
- NumOperands = 4;
-
- for (int i = 0; i < NumOperands; i++)
- OpCExtended[i] = (isOperandExtended(MI, i) && isConstExtended(MI));
-
- switch(Opc) {
- case Hexagon::A2_tfrsi:
- return (isOperandExtended(MI, 1) && isConstExtended(MI)) ||
- isInt<12>(MI->getOperand(1).getImm());
-
- case Hexagon::S2_storerd_io:
- return isShiftedUInt<6,3>(MI->getOperand(1).getImm());
-
- case Hexagon::S2_storeri_io:
- case Hexagon::S2_storerinew_io:
- return isShiftedUInt<6,2>(MI->getOperand(1).getImm());
-
- case Hexagon::S2_storerh_io:
- case Hexagon::S2_storerhnew_io:
- return isShiftedUInt<6,1>(MI->getOperand(1).getImm());
-
- case Hexagon::S2_storerb_io:
- case Hexagon::S2_storerbnew_io:
- return isUInt<6>(MI->getOperand(1).getImm());
-
- case Hexagon::L2_loadrd_io:
- return isShiftedUInt<6,3>(MI->getOperand(2).getImm());
-
- case Hexagon::L2_loadri_io:
- return isShiftedUInt<6,2>(MI->getOperand(2).getImm());
-
- case Hexagon::L2_loadrh_io:
- case Hexagon::L2_loadruh_io:
- return isShiftedUInt<6,1>(MI->getOperand(2).getImm());
-
- case Hexagon::L2_loadrb_io:
- case Hexagon::L2_loadrub_io:
- return isUInt<6>(MI->getOperand(2).getImm());
-
- case Hexagon::L2_loadrd_pi:
- return isShiftedInt<4,3>(MI->getOperand(3).getImm());
-
- case Hexagon::L2_loadri_pi:
- return isShiftedInt<4,2>(MI->getOperand(3).getImm());
-
- case Hexagon::L2_loadrh_pi:
- case Hexagon::L2_loadruh_pi:
- return isShiftedInt<4,1>(MI->getOperand(3).getImm());
-
- case Hexagon::L2_loadrb_pi:
- case Hexagon::L2_loadrub_pi:
- return isInt<4>(MI->getOperand(3).getImm());
-
- case Hexagon::S4_storeirb_io:
- case Hexagon::S4_storeirh_io:
- case Hexagon::S4_storeiri_io:
- return (OpCExtended[1] || isUInt<6>(MI->getOperand(1).getImm())) &&
- (OpCExtended[2] || isInt<6>(MI->getOperand(2).getImm()));
-
- case Hexagon::A2_addi:
- return isInt<8>(MI->getOperand(2).getImm());
- case Hexagon::A2_aslh:
- case Hexagon::A2_asrh:
- case Hexagon::A2_sxtb:
- case Hexagon::A2_sxth:
- case Hexagon::A2_zxtb:
- case Hexagon::A2_zxth:
- return true;
- }
-
- return true;
+bool HexagonInstrInfo::isPredicable(MachineInstr &MI) const {
+ return MI.getDesc().isPredicable();
}
-
-bool HexagonInstrInfo::isSchedulingBoundary(const MachineInstr *MI,
- const MachineBasicBlock *MBB, const MachineFunction &MF) const {
+bool HexagonInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
+ const MachineBasicBlock *MBB,
+ const MachineFunction &MF) const {
// Debug info is never a scheduling boundary. It's necessary to be explicit
// due to the special treatment of IT instructions below, otherwise a
// dbg_value followed by an IT will result in the IT instruction being
// considered a scheduling hazard, which is wrong. It should be the actual
// instruction preceding the dbg_value instruction(s), just like it is
// when debug info is not present.
- if (MI->isDebugValue())
+ if (MI.isDebugValue())
return false;
// Throwing call is a boundary.
- if (MI->isCall()) {
+ if (MI.isCall()) {
// If any of the block's successors is a landing pad, this could be a
// throwing call.
for (auto I : MBB->successors())
@@ -1225,15 +1380,15 @@ bool HexagonInstrInfo::isSchedulingBoundary(const MachineInstr *MI,
}
// Don't mess around with no return calls.
- if (MI->getOpcode() == Hexagon::CALLv3nr)
+ if (MI.getOpcode() == Hexagon::CALLv3nr)
return true;
// Terminators and labels can't be scheduled around.
- if (MI->getDesc().isTerminator() || MI->isPosition())
+ if (MI.getDesc().isTerminator() || MI.isPosition())
return true;
- if (MI->isInlineAsm() && !ScheduleInlineAsm)
- return true;
+ if (MI.isInlineAsm() && !ScheduleInlineAsm)
+ return true;
return false;
}
@@ -1286,9 +1441,10 @@ 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, int &Value) const {
- unsigned Opc = MI->getOpcode();
+bool HexagonInstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
+ unsigned &SrcReg2, int &Mask,
+ int &Value) const {
+ unsigned Opc = MI.getOpcode();
// Set mask and the first source register.
switch (Opc) {
@@ -1307,7 +1463,7 @@ bool HexagonInstrInfo::analyzeCompare(const MachineInstr *MI,
case Hexagon::C4_cmpneqi:
case Hexagon::C4_cmplteui:
case Hexagon::C4_cmpltei:
- SrcReg = MI->getOperand(1).getReg();
+ SrcReg = MI.getOperand(1).getReg();
Mask = ~0;
break;
case Hexagon::A4_cmpbeq:
@@ -1316,7 +1472,7 @@ bool HexagonInstrInfo::analyzeCompare(const MachineInstr *MI,
case Hexagon::A4_cmpbeqi:
case Hexagon::A4_cmpbgti:
case Hexagon::A4_cmpbgtui:
- SrcReg = MI->getOperand(1).getReg();
+ SrcReg = MI.getOperand(1).getReg();
Mask = 0xFF;
break;
case Hexagon::A4_cmpheq:
@@ -1325,7 +1481,7 @@ bool HexagonInstrInfo::analyzeCompare(const MachineInstr *MI,
case Hexagon::A4_cmpheqi:
case Hexagon::A4_cmphgti:
case Hexagon::A4_cmphgtui:
- SrcReg = MI->getOperand(1).getReg();
+ SrcReg = MI.getOperand(1).getReg();
Mask = 0xFFFF;
break;
}
@@ -1347,7 +1503,7 @@ bool HexagonInstrInfo::analyzeCompare(const MachineInstr *MI,
case Hexagon::C4_cmpneq:
case Hexagon::C4_cmplte:
case Hexagon::C4_cmplteu:
- SrcReg2 = MI->getOperand(2).getReg();
+ SrcReg2 = MI.getOperand(2).getReg();
return true;
case Hexagon::C2_cmpeqi:
@@ -1363,17 +1519,17 @@ bool HexagonInstrInfo::analyzeCompare(const MachineInstr *MI,
case Hexagon::A4_cmphgti:
case Hexagon::A4_cmphgtui:
SrcReg2 = 0;
- Value = MI->getOperand(2).getImm();
+ Value = MI.getOperand(2).getImm();
return true;
}
return false;
}
-
unsigned HexagonInstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
- const MachineInstr *MI, unsigned *PredCost) const {
- return getInstrTimingClassLatency(ItinData, MI);
+ const MachineInstr &MI,
+ unsigned *PredCost) const {
+ return getInstrTimingClassLatency(ItinData, &MI);
}
@@ -1388,27 +1544,27 @@ DFAPacketizer *HexagonInstrInfo::CreateTargetScheduleState(
// %R13<def> = L2_loadri_io %R29, 136; mem:LD4[FixedStack0]
// S2_storeri_io %R29, 132, %R1<kill>; flags: mem:ST4[FixedStack1]
// Currently AA considers the addresses in these instructions to be aliasing.
-bool HexagonInstrInfo::areMemAccessesTriviallyDisjoint(MachineInstr *MIa,
- MachineInstr *MIb, AliasAnalysis *AA) const {
+bool HexagonInstrInfo::areMemAccessesTriviallyDisjoint(
+ MachineInstr &MIa, MachineInstr &MIb, AliasAnalysis *AA) const {
int OffsetA = 0, OffsetB = 0;
unsigned SizeA = 0, SizeB = 0;
- if (MIa->hasUnmodeledSideEffects() || MIb->hasUnmodeledSideEffects() ||
- MIa->hasOrderedMemoryRef() || MIa->hasOrderedMemoryRef())
+ if (MIa.hasUnmodeledSideEffects() || MIb.hasUnmodeledSideEffects() ||
+ MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
return false;
// Instructions that are pure loads, not loads and stores like memops are not
// dependent.
- if (MIa->mayLoad() && !isMemOp(MIa) && MIb->mayLoad() && !isMemOp(MIb))
+ if (MIa.mayLoad() && !isMemOp(&MIa) && MIb.mayLoad() && !isMemOp(&MIb))
return true;
// Get base, offset, and access size in MIa.
- unsigned BaseRegA = getBaseAndOffset(MIa, OffsetA, SizeA);
+ unsigned BaseRegA = getBaseAndOffset(&MIa, OffsetA, SizeA);
if (!BaseRegA || !SizeA)
return false;
// Get base, offset, and access size in MIb.
- unsigned BaseRegB = getBaseAndOffset(MIb, OffsetB, SizeB);
+ unsigned BaseRegB = getBaseAndOffset(&MIb, OffsetB, SizeB);
if (!BaseRegB || !SizeB)
return false;
@@ -1486,13 +1642,13 @@ bool HexagonInstrInfo::isCompoundBranchInstr(const MachineInstr *MI) const {
bool HexagonInstrInfo::isCondInst(const MachineInstr *MI) const {
- return (MI->isBranch() && isPredicated(MI)) ||
+ return (MI->isBranch() && isPredicated(*MI)) ||
isConditionalTransfer(MI) ||
isConditionalALU32(MI) ||
isConditionalLoad(MI) ||
// Predicated stores which don't have a .new on any operands.
- (MI->mayStore() && isPredicated(MI) && !isNewValueStore(MI) &&
- !isPredicatedNew(MI));
+ (MI->mayStore() && isPredicated(*MI) && !isNewValueStore(MI) &&
+ !isPredicatedNew(*MI));
}
@@ -1557,7 +1713,7 @@ bool HexagonInstrInfo::isConditionalALU32(const MachineInstr* MI) const {
// FIXME - Function name and it's functionality don't match.
// It should be renamed to hasPredNewOpcode()
bool HexagonInstrInfo::isConditionalLoad(const MachineInstr* MI) const {
- if (!MI->getDesc().mayLoad() || !isPredicated(MI))
+ if (!MI->getDesc().mayLoad() || !isPredicated(*MI))
return false;
int PNewOpcode = Hexagon::getPredNewOpcode(MI->getOpcode());
@@ -1763,8 +1919,7 @@ bool HexagonInstrInfo::isDotCurInst(const MachineInstr* MI) const {
// Returns true, if any one of the operands is a dot new
// insn, whether it is predicated dot new or register dot new.
bool HexagonInstrInfo::isDotNewInst(const MachineInstr* MI) const {
- if (isNewValueInst(MI) ||
- (isPredicated(MI) && isPredicatedNew(MI)))
+ if (isNewValueInst(MI) || (isPredicated(*MI) && isPredicatedNew(*MI)))
return true;
return false;
@@ -2129,8 +2284,8 @@ bool HexagonInstrInfo::isPostIncrement(const MachineInstr* MI) const {
}
-bool HexagonInstrInfo::isPredicatedNew(const MachineInstr *MI) const {
- const uint64_t F = MI->getDesc().TSFlags;
+bool HexagonInstrInfo::isPredicatedNew(const MachineInstr &MI) const {
+ const uint64_t F = MI.getDesc().TSFlags;
assert(isPredicated(MI));
return (F >> HexagonII::PredicatedNewPos) & HexagonII::PredicatedNewMask;
}
@@ -2143,8 +2298,8 @@ bool HexagonInstrInfo::isPredicatedNew(unsigned Opcode) const {
}
-bool HexagonInstrInfo::isPredicatedTrue(const MachineInstr *MI) const {
- const uint64_t F = MI->getDesc().TSFlags;
+bool HexagonInstrInfo::isPredicatedTrue(const MachineInstr &MI) const {
+ const uint64_t F = MI.getDesc().TSFlags;
return !((F >> HexagonII::PredicatedFalsePos) &
HexagonII::PredicatedFalseMask);
}
@@ -2181,7 +2336,87 @@ bool HexagonInstrInfo::isPredictedTaken(unsigned Opcode) const {
bool HexagonInstrInfo::isSaveCalleeSavedRegsCall(const MachineInstr *MI) const {
return MI->getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4 ||
- MI->getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4_EXT;
+ MI->getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4_EXT ||
+ MI->getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4_PIC ||
+ MI->getOpcode() == Hexagon::SAVE_REGISTERS_CALL_V4_EXT_PIC;
+}
+
+bool HexagonInstrInfo::isSignExtendingLoad(const MachineInstr &MI) const {
+ switch (MI.getOpcode()) {
+ // Byte
+ case Hexagon::L2_loadrb_io:
+ case Hexagon::L4_loadrb_ur:
+ case Hexagon::L4_loadrb_ap:
+ case Hexagon::L2_loadrb_pr:
+ case Hexagon::L2_loadrb_pbr:
+ case Hexagon::L2_loadrb_pi:
+ case Hexagon::L2_loadrb_pci:
+ case Hexagon::L2_loadrb_pcr:
+ case Hexagon::L2_loadbsw2_io:
+ case Hexagon::L4_loadbsw2_ur:
+ case Hexagon::L4_loadbsw2_ap:
+ case Hexagon::L2_loadbsw2_pr:
+ case Hexagon::L2_loadbsw2_pbr:
+ case Hexagon::L2_loadbsw2_pi:
+ case Hexagon::L2_loadbsw2_pci:
+ case Hexagon::L2_loadbsw2_pcr:
+ case Hexagon::L2_loadbsw4_io:
+ case Hexagon::L4_loadbsw4_ur:
+ case Hexagon::L4_loadbsw4_ap:
+ case Hexagon::L2_loadbsw4_pr:
+ case Hexagon::L2_loadbsw4_pbr:
+ case Hexagon::L2_loadbsw4_pi:
+ case Hexagon::L2_loadbsw4_pci:
+ case Hexagon::L2_loadbsw4_pcr:
+ case Hexagon::L4_loadrb_rr:
+ case Hexagon::L2_ploadrbt_io:
+ case Hexagon::L2_ploadrbt_pi:
+ case Hexagon::L2_ploadrbf_io:
+ case Hexagon::L2_ploadrbf_pi:
+ case Hexagon::L2_ploadrbtnew_io:
+ case Hexagon::L2_ploadrbfnew_io:
+ case Hexagon::L4_ploadrbt_rr:
+ case Hexagon::L4_ploadrbf_rr:
+ case Hexagon::L4_ploadrbtnew_rr:
+ case Hexagon::L4_ploadrbfnew_rr:
+ case Hexagon::L2_ploadrbtnew_pi:
+ case Hexagon::L2_ploadrbfnew_pi:
+ case Hexagon::L4_ploadrbt_abs:
+ case Hexagon::L4_ploadrbf_abs:
+ case Hexagon::L4_ploadrbtnew_abs:
+ case Hexagon::L4_ploadrbfnew_abs:
+ case Hexagon::L2_loadrbgp:
+ // Half
+ case Hexagon::L2_loadrh_io:
+ case Hexagon::L4_loadrh_ur:
+ case Hexagon::L4_loadrh_ap:
+ case Hexagon::L2_loadrh_pr:
+ case Hexagon::L2_loadrh_pbr:
+ case Hexagon::L2_loadrh_pi:
+ case Hexagon::L2_loadrh_pci:
+ case Hexagon::L2_loadrh_pcr:
+ case Hexagon::L4_loadrh_rr:
+ case Hexagon::L2_ploadrht_io:
+ case Hexagon::L2_ploadrht_pi:
+ case Hexagon::L2_ploadrhf_io:
+ case Hexagon::L2_ploadrhf_pi:
+ case Hexagon::L2_ploadrhtnew_io:
+ case Hexagon::L2_ploadrhfnew_io:
+ case Hexagon::L4_ploadrht_rr:
+ case Hexagon::L4_ploadrhf_rr:
+ case Hexagon::L4_ploadrhtnew_rr:
+ case Hexagon::L4_ploadrhfnew_rr:
+ case Hexagon::L2_ploadrhtnew_pi:
+ case Hexagon::L2_ploadrhfnew_pi:
+ case Hexagon::L4_ploadrht_abs:
+ case Hexagon::L4_ploadrhf_abs:
+ case Hexagon::L4_ploadrhtnew_abs:
+ case Hexagon::L4_ploadrhfnew_abs:
+ case Hexagon::L2_loadrhgp:
+ return true;
+ default:
+ return false;
+ }
}
@@ -2202,6 +2437,17 @@ bool HexagonInstrInfo::isSpillPredRegOp(const MachineInstr *MI) const {
}
+bool HexagonInstrInfo::isTailCall(const MachineInstr *MI) const {
+ if (!MI->isBranch())
+ return false;
+
+ for (auto &Op : MI->operands())
+ if (Op.isGlobal() || Op.isSymbol())
+ return true;
+ return false;
+}
+
+
// Returns true when SU has a timing class TC1.
bool HexagonInstrInfo::isTC1(const MachineInstr *MI) const {
unsigned SchedClass = MI->getDesc().getSchedClass();
@@ -2269,6 +2515,28 @@ bool HexagonInstrInfo::isTC4x(const MachineInstr *MI) const {
}
+// Schedule this ASAP.
+bool HexagonInstrInfo::isToBeScheduledASAP(const MachineInstr *MI1,
+ const MachineInstr *MI2) const {
+ if (!MI1 || !MI2)
+ return false;
+ if (mayBeCurLoad(MI1)) {
+ // if (result of SU is used in Next) return true;
+ unsigned DstReg = MI1->getOperand(0).getReg();
+ int N = MI2->getNumOperands();
+ for (int I = 0; I < N; I++)
+ if (MI2->getOperand(I).isReg() && DstReg == MI2->getOperand(I).getReg())
+ return true;
+ }
+ if (mayBeNewStore(MI2))
+ if (MI2->getOpcode() == Hexagon::V6_vS32b_pi)
+ if (MI1->getOperand(0).isReg() && MI2->getOperand(3).isReg() &&
+ MI1->getOperand(0).getReg() == MI2->getOperand(3).getReg())
+ return true;
+ return false;
+}
+
+
bool HexagonInstrInfo::isV60VectorInstruction(const MachineInstr *MI) const {
if (!MI)
return false;
@@ -2366,6 +2634,21 @@ bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
case Hexagon::J2_loop0i:
case Hexagon::J2_loop1i:
return isUInt<10>(Offset);
+
+ case Hexagon::S4_storeirb_io:
+ case Hexagon::S4_storeirbt_io:
+ case Hexagon::S4_storeirbf_io:
+ return isUInt<6>(Offset);
+
+ case Hexagon::S4_storeirh_io:
+ case Hexagon::S4_storeirht_io:
+ case Hexagon::S4_storeirhf_io:
+ return isShiftedUInt<6,1>(Offset);
+
+ case Hexagon::S4_storeiri_io:
+ case Hexagon::S4_storeirit_io:
+ case Hexagon::S4_storeirif_io:
+ return isShiftedUInt<6,2>(Offset);
}
if (Extend)
@@ -2422,10 +2705,12 @@ bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
case Hexagon::L4_or_memopb_io :
return (0 <= Offset && Offset <= 63);
- // LDri_pred and STriw_pred are pseudo operations, so it has to take offset of
+ // LDriw_xxx and STriw_xxx are pseudo operations, so it has to take offset of
// any size. Later pass knows how to handle it.
case Hexagon::STriw_pred:
case Hexagon::LDriw_pred:
+ case Hexagon::STriw_mod:
+ case Hexagon::LDriw_mod:
return true;
case Hexagon::TFR_FI:
@@ -2439,9 +2724,6 @@ bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
case Hexagon::L2_ploadrubf_io:
case Hexagon::S2_pstorerbt_io:
case Hexagon::S2_pstorerbf_io:
- case Hexagon::S4_storeirb_io:
- case Hexagon::S4_storeirbt_io:
- case Hexagon::S4_storeirbf_io:
return isUInt<6>(Offset);
case Hexagon::L2_ploadrht_io:
@@ -2450,18 +2732,12 @@ bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
case Hexagon::L2_ploadruhf_io:
case Hexagon::S2_pstorerht_io:
case Hexagon::S2_pstorerhf_io:
- case Hexagon::S4_storeirh_io:
- case Hexagon::S4_storeirht_io:
- case Hexagon::S4_storeirhf_io:
return isShiftedUInt<6,1>(Offset);
case Hexagon::L2_ploadrit_io:
case Hexagon::L2_ploadrif_io:
case Hexagon::S2_pstorerit_io:
case Hexagon::S2_pstorerif_io:
- case Hexagon::S4_storeiri_io:
- case Hexagon::S4_storeirit_io:
- case Hexagon::S4_storeirif_io:
return isShiftedUInt<6,2>(Offset);
case Hexagon::L2_ploadrdt_io:
@@ -2506,6 +2782,94 @@ bool HexagonInstrInfo::isVecUsableNextPacket(const MachineInstr *ProdMI,
return false;
}
+bool HexagonInstrInfo::isZeroExtendingLoad(const MachineInstr &MI) const {
+ switch (MI.getOpcode()) {
+ // Byte
+ case Hexagon::L2_loadrub_io:
+ case Hexagon::L4_loadrub_ur:
+ case Hexagon::L4_loadrub_ap:
+ case Hexagon::L2_loadrub_pr:
+ case Hexagon::L2_loadrub_pbr:
+ case Hexagon::L2_loadrub_pi:
+ case Hexagon::L2_loadrub_pci:
+ case Hexagon::L2_loadrub_pcr:
+ case Hexagon::L2_loadbzw2_io:
+ case Hexagon::L4_loadbzw2_ur:
+ case Hexagon::L4_loadbzw2_ap:
+ case Hexagon::L2_loadbzw2_pr:
+ case Hexagon::L2_loadbzw2_pbr:
+ case Hexagon::L2_loadbzw2_pi:
+ case Hexagon::L2_loadbzw2_pci:
+ case Hexagon::L2_loadbzw2_pcr:
+ case Hexagon::L2_loadbzw4_io:
+ case Hexagon::L4_loadbzw4_ur:
+ case Hexagon::L4_loadbzw4_ap:
+ case Hexagon::L2_loadbzw4_pr:
+ case Hexagon::L2_loadbzw4_pbr:
+ case Hexagon::L2_loadbzw4_pi:
+ case Hexagon::L2_loadbzw4_pci:
+ case Hexagon::L2_loadbzw4_pcr:
+ case Hexagon::L4_loadrub_rr:
+ case Hexagon::L2_ploadrubt_io:
+ case Hexagon::L2_ploadrubt_pi:
+ case Hexagon::L2_ploadrubf_io:
+ case Hexagon::L2_ploadrubf_pi:
+ case Hexagon::L2_ploadrubtnew_io:
+ case Hexagon::L2_ploadrubfnew_io:
+ case Hexagon::L4_ploadrubt_rr:
+ case Hexagon::L4_ploadrubf_rr:
+ case Hexagon::L4_ploadrubtnew_rr:
+ case Hexagon::L4_ploadrubfnew_rr:
+ case Hexagon::L2_ploadrubtnew_pi:
+ case Hexagon::L2_ploadrubfnew_pi:
+ case Hexagon::L4_ploadrubt_abs:
+ case Hexagon::L4_ploadrubf_abs:
+ case Hexagon::L4_ploadrubtnew_abs:
+ case Hexagon::L4_ploadrubfnew_abs:
+ case Hexagon::L2_loadrubgp:
+ // Half
+ case Hexagon::L2_loadruh_io:
+ case Hexagon::L4_loadruh_ur:
+ case Hexagon::L4_loadruh_ap:
+ case Hexagon::L2_loadruh_pr:
+ case Hexagon::L2_loadruh_pbr:
+ case Hexagon::L2_loadruh_pi:
+ case Hexagon::L2_loadruh_pci:
+ case Hexagon::L2_loadruh_pcr:
+ case Hexagon::L4_loadruh_rr:
+ case Hexagon::L2_ploadruht_io:
+ case Hexagon::L2_ploadruht_pi:
+ case Hexagon::L2_ploadruhf_io:
+ case Hexagon::L2_ploadruhf_pi:
+ case Hexagon::L2_ploadruhtnew_io:
+ case Hexagon::L2_ploadruhfnew_io:
+ case Hexagon::L4_ploadruht_rr:
+ case Hexagon::L4_ploadruhf_rr:
+ case Hexagon::L4_ploadruhtnew_rr:
+ case Hexagon::L4_ploadruhfnew_rr:
+ case Hexagon::L2_ploadruhtnew_pi:
+ case Hexagon::L2_ploadruhfnew_pi:
+ case Hexagon::L4_ploadruht_abs:
+ case Hexagon::L4_ploadruhf_abs:
+ case Hexagon::L4_ploadruhtnew_abs:
+ case Hexagon::L4_ploadruhfnew_abs:
+ case Hexagon::L2_loadruhgp:
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+// Add latency to instruction.
+bool HexagonInstrInfo::addLatencyToSchedule(const MachineInstr *MI1,
+ const MachineInstr *MI2) const {
+ if (isV60VectorInstruction(MI1) && isV60VectorInstruction(MI2))
+ if (!isVecUsableNextPacket(MI1, MI2))
+ return true;
+ return false;
+}
+
/// \brief Can these instructions execute at the same time in a bundle.
bool HexagonInstrInfo::canExecuteInBundle(const MachineInstr *First,
@@ -2687,6 +3051,11 @@ bool HexagonInstrInfo::predOpcodeHasNot(ArrayRef<MachineOperand> Cond) const {
}
+short HexagonInstrInfo::getAbsoluteForm(const MachineInstr *MI) const {
+ return Hexagon::getAbsoluteForm(MI->getOpcode());
+}
+
+
unsigned HexagonInstrInfo::getAddrMode(const MachineInstr* MI) const {
const uint64_t F = MI->getDesc().TSFlags;
return (F >> HexagonII::AddrModePos) & HexagonII::AddrModeMask;
@@ -2735,8 +3104,6 @@ bool HexagonInstrInfo::getBaseAndOffsetPosition(const MachineInstr *MI,
unsigned &BasePos, unsigned &OffsetPos) const {
// Deal with memops first.
if (isMemOp(MI)) {
- assert (MI->getOperand(0).isReg() && MI->getOperand(1).isImm() &&
- "Bad Memop.");
BasePos = 0;
OffsetPos = 1;
} else if (MI->mayStore()) {
@@ -2748,7 +3115,7 @@ bool HexagonInstrInfo::getBaseAndOffsetPosition(const MachineInstr *MI,
} else
return false;
- if (isPredicated(MI)) {
+ if (isPredicated(*MI)) {
BasePos++;
OffsetPos++;
}
@@ -2802,7 +3169,7 @@ SmallVector<MachineInstr*, 2> HexagonInstrInfo::getBranchingInstrs(
return Jumpers;
--I;
}
- if (!isUnpredicatedTerminator(&*I))
+ if (!isUnpredicatedTerminator(*I))
return Jumpers;
// Get the last instruction in the block.
@@ -2811,7 +3178,7 @@ SmallVector<MachineInstr*, 2> HexagonInstrInfo::getBranchingInstrs(
MachineInstr *SecondLastInst = nullptr;
// Find one more terminator if present.
do {
- if (&*I != LastInst && !I->isBundle() && isUnpredicatedTerminator(&*I)) {
+ if (&*I != LastInst && !I->isBundle() && isUnpredicatedTerminator(*I)) {
if (!SecondLastInst) {
SecondLastInst = &*I;
Jumpers.push_back(SecondLastInst);
@@ -2826,6 +3193,23 @@ SmallVector<MachineInstr*, 2> HexagonInstrInfo::getBranchingInstrs(
}
+short HexagonInstrInfo::getBaseWithLongOffset(short Opcode) const {
+ if (Opcode < 0)
+ return -1;
+ return Hexagon::getBaseWithLongOffset(Opcode);
+}
+
+
+short HexagonInstrInfo::getBaseWithLongOffset(const MachineInstr *MI) const {
+ return Hexagon::getBaseWithLongOffset(MI->getOpcode());
+}
+
+
+short HexagonInstrInfo::getBaseWithRegOffset(const MachineInstr *MI) const {
+ return Hexagon::getBaseWithRegOffset(MI->getOpcode());
+}
+
+
// Returns Operand Index for the constant extended instruction.
unsigned HexagonInstrInfo::getCExtOpNum(const MachineInstr *MI) const {
const uint64_t F = MI->getDesc().TSFlags;
@@ -3102,6 +3486,7 @@ int HexagonInstrInfo::getDotNewOp(const MachineInstr* MI) const {
return 0;
}
+
// Returns the opcode to use when converting MI, which is a conditional jump,
// into a conditional instruction which uses the .new value of the predicate.
// We also use branch probabilities to add a hint to the jump.
@@ -3353,8 +3738,8 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup(
case Hexagon::S4_storeirb_io:
// memb(Rs+#u4) = #U1
Src1Reg = MI->getOperand(0).getReg();
- if (isIntRegForSubInst(Src1Reg) && MI->getOperand(1).isImm() &&
- isUInt<4>(MI->getOperand(1).getImm()) && MI->getOperand(2).isImm() &&
+ if (isIntRegForSubInst(Src1Reg) &&
+ MI->getOperand(1).isImm() && isUInt<4>(MI->getOperand(1).getImm()) &&
MI->getOperand(2).isImm() && isUInt<1>(MI->getOperand(2).getImm()))
return HexagonII::HSIG_S2;
break;
@@ -3532,7 +3917,7 @@ unsigned HexagonInstrInfo::getInstrTimingClassLatency(
// Default to one cycle for no itinerary. However, an "empty" itinerary may
// still have a MinLatency property, which getStageLatency checks.
if (!ItinData)
- return getInstrLatency(ItinData, MI);
+ return getInstrLatency(ItinData, *MI);
// Get the latency embedded in the itinerary. If we're not using timing class
// latencies or if we using BSB scheduling, then restrict the maximum latency
@@ -3737,7 +4122,7 @@ unsigned HexagonInstrInfo::nonDbgBundleSize(
assert(BundleHead->isBundle() && "Not a bundle header");
auto MII = BundleHead.getInstrIterator();
// Skip the bundle header.
- return nonDbgMICount(++MII, getBundleEnd(BundleHead));
+ return nonDbgMICount(++MII, getBundleEnd(*BundleHead));
}
@@ -3770,7 +4155,7 @@ bool HexagonInstrInfo::invertAndChangeJumpTarget(
--TargetPos;
assert((TargetPos >= 0) && MI->getOperand(TargetPos).isMBB());
MI->getOperand(TargetPos).setMBB(NewTarget);
- if (EnableBranchPrediction && isPredicatedNew(MI)) {
+ if (EnableBranchPrediction && isPredicatedNew(*MI)) {
NewOpcode = reversePrediction(NewOpcode);
}
MI->setDesc(get(NewOpcode));
@@ -3826,3 +4211,7 @@ bool HexagonInstrInfo::validateBranchCond(const ArrayRef<MachineOperand> &Cond)
return Cond.empty() || (Cond[0].isImm() && (Cond.size() != 1));
}
+
+short HexagonInstrInfo::xformRegToImmOffset(const MachineInstr *MI) const {
+ return Hexagon::xformRegToImmOffset(MI->getOpcode());
+}