aboutsummaryrefslogtreecommitdiff
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.cpp995
1 files changed, 536 insertions, 459 deletions
diff --git a/lib/Target/Hexagon/HexagonInstrInfo.cpp b/lib/Target/Hexagon/HexagonInstrInfo.cpp
index c77c669f4ca7..b82a0157e81f 100644
--- a/lib/Target/Hexagon/HexagonInstrInfo.cpp
+++ b/lib/Target/Hexagon/HexagonInstrInfo.cpp
@@ -1,4 +1,4 @@
-//===-- HexagonInstrInfo.cpp - Hexagon Instruction Information ------------===//
+//===- HexagonInstrInfo.cpp - Hexagon Instruction Information -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,9 +13,11 @@
#include "HexagonInstrInfo.h"
#include "Hexagon.h"
+#include "HexagonFrameLowering.h"
#include "HexagonHazardRecognizer.h"
#include "HexagonRegisterInfo.h"
#include "HexagonSubtarget.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -32,7 +34,13 @@
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/ScheduleDAG.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetOpcodes.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/IR/DebugLoc.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCInstrItineraries.h"
@@ -43,13 +51,14 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetSubtargetInfo.h"
+#include "llvm/Target/TargetMachine.h"
#include <cassert>
#include <cctype>
#include <cstdint>
#include <cstring>
#include <iterator>
+#include <string>
+#include <utility>
using namespace llvm;
@@ -91,9 +100,7 @@ static cl::opt<bool> UseDFAHazardRec("dfa-hazard-rec",
cl::init(true), cl::Hidden, cl::ZeroOrMore,
cl::desc("Use the DFA based hazard recognizer."));
-///
/// Constants for Hexagon instructions.
-///
const int Hexagon_MEMW_OFFSET_MAX = 4095;
const int Hexagon_MEMW_OFFSET_MIN = -4096;
const int Hexagon_MEMD_OFFSET_MAX = 8191;
@@ -104,25 +111,13 @@ const int Hexagon_MEMB_OFFSET_MAX = 1023;
const int Hexagon_MEMB_OFFSET_MIN = -1024;
const int Hexagon_ADDI_OFFSET_MAX = 32767;
const int Hexagon_ADDI_OFFSET_MIN = -32768;
-const int Hexagon_MEMD_AUTOINC_MAX = 56;
-const int Hexagon_MEMD_AUTOINC_MIN = -64;
-const int Hexagon_MEMW_AUTOINC_MAX = 28;
-const int Hexagon_MEMW_AUTOINC_MIN = -32;
-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; // #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() {}
HexagonInstrInfo::HexagonInstrInfo(HexagonSubtarget &ST)
- : HexagonGenInstrInfo(Hexagon::ADJCALLSTACKDOWN, Hexagon::ADJCALLSTACKUP),
- RI() {}
+ : HexagonGenInstrInfo(Hexagon::ADJCALLSTACKDOWN, Hexagon::ADJCALLSTACKUP),
+ Subtarget(ST) {}
static bool isIntRegForSubInst(unsigned Reg) {
return (Reg >= Hexagon::R0 && Reg <= Hexagon::R7) ||
@@ -251,18 +246,12 @@ unsigned HexagonInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
case Hexagon::L2_loadrd_io:
case Hexagon::V6_vL32b_ai:
case Hexagon::V6_vL32b_nt_ai:
- case Hexagon::V6_vL32b_ai_128B:
- case Hexagon::V6_vL32b_nt_ai_128B:
case Hexagon::V6_vL32Ub_ai:
- case Hexagon::V6_vL32Ub_ai_128B:
case Hexagon::LDriw_pred:
case Hexagon::LDriw_mod:
case Hexagon::PS_vloadrq_ai:
case Hexagon::PS_vloadrw_ai:
- case Hexagon::PS_vloadrw_nt_ai:
- case Hexagon::PS_vloadrq_ai_128B:
- case Hexagon::PS_vloadrw_ai_128B:
- case Hexagon::PS_vloadrw_nt_ai_128B: {
+ case Hexagon::PS_vloadrw_nt_ai: {
const MachineOperand OpFI = MI.getOperand(1);
if (!OpFI.isFI())
return 0;
@@ -306,15 +295,11 @@ unsigned HexagonInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
case Hexagon::S2_storeri_io:
case Hexagon::S2_storerd_io:
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::PS_vstorerq_ai:
- case Hexagon::PS_vstorerw_ai:
- case Hexagon::PS_vstorerq_ai_128B:
- case Hexagon::PS_vstorerw_ai_128B: {
+ case Hexagon::PS_vstorerw_ai: {
const MachineOperand &OpFI = MI.getOperand(0);
if (!OpFI.isFI())
return 0;
@@ -362,7 +347,6 @@ unsigned HexagonInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
/// Cond[0] = Hexagon::CMPEQri_f_Jumpnv_t_V4 -- specific opcode
/// Cond[1] = R
/// Cond[2] = Imm
-///
bool HexagonInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
@@ -479,7 +463,7 @@ bool HexagonInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
Cond.push_back(LastInst->getOperand(1));
return false;
}
- DEBUG(dbgs() << "\nCant analyze BB#" << MBB.getNumber()
+ DEBUG(dbgs() << "\nCant analyze " << printMBBReference(MBB)
<< " with one jump\n";);
// Otherwise, don't know what this is.
return true;
@@ -527,7 +511,7 @@ bool HexagonInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
FBB = LastInst->getOperand(0).getMBB();
return false;
}
- DEBUG(dbgs() << "\nCant analyze BB#" << MBB.getNumber()
+ DEBUG(dbgs() << "\nCant analyze " << printMBBReference(MBB)
<< " with two jumps";);
// Otherwise, can't handle this.
return true;
@@ -537,7 +521,7 @@ unsigned HexagonInstrInfo::removeBranch(MachineBasicBlock &MBB,
int *BytesRemoved) const {
assert(!BytesRemoved && "code size not handled");
- DEBUG(dbgs() << "\nRemoving branches out of BB#" << MBB.getNumber());
+ DEBUG(dbgs() << "\nRemoving branches out of " << printMBBReference(MBB));
MachineBasicBlock::iterator I = MBB.end();
unsigned Count = 0;
while (I != MBB.begin()) {
@@ -599,7 +583,7 @@ unsigned HexagonInstrInfo::insertBranch(MachineBasicBlock &MBB,
SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs;
MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, Cond[1].getMBB(),
VisitedBBs);
- assert(Loop != 0 && "Inserting an ENDLOOP without a LOOP");
+ assert(Loop != nullptr && "Inserting an ENDLOOP without a LOOP");
Loop->getOperand(0).setMBB(TBB);
// Add the ENDLOOP after the finding the LOOP0.
BuildMI(&MBB, DL, get(EndLoopOp)).addMBB(TBB);
@@ -609,7 +593,7 @@ unsigned HexagonInstrInfo::insertBranch(MachineBasicBlock &MBB,
// (ins IntRegs:$src1, IntRegs:$src2, brtarget:$offset)
// (ins IntRegs:$src1, u5Imm:$src2, brtarget:$offset)
unsigned Flags1 = getUndefRegState(Cond[1].isUndef());
- DEBUG(dbgs() << "\nInserting NVJump for BB#" << MBB.getNumber(););
+ DEBUG(dbgs() << "\nInserting NVJump for " << printMBBReference(MBB););
if (Cond[2].isReg()) {
unsigned Flags2 = getUndefRegState(Cond[2].isUndef());
BuildMI(&MBB, DL, get(BccOpc)).addReg(Cond[1].getReg(), Flags1).
@@ -640,7 +624,7 @@ unsigned HexagonInstrInfo::insertBranch(MachineBasicBlock &MBB,
SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs;
MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, Cond[1].getMBB(),
VisitedBBs);
- assert(Loop != 0 && "Inserting an ENDLOOP without a LOOP");
+ assert(Loop != nullptr && "Inserting an ENDLOOP without a LOOP");
Loop->getOperand(0).setMBB(TBB);
// Add the ENDLOOP after the finding the LOOP0.
BuildMI(&MBB, DL, get(EndLoopOp)).addMBB(TBB);
@@ -715,10 +699,11 @@ unsigned HexagonInstrInfo::reduceLoopCount(MachineBasicBlock &MBB,
unsigned NewLoopCount = createVR(MF, MVT::i32);
MachineInstr *NewAdd = BuildMI(&MBB, DL, get(Hexagon::A2_addi), NewLoopCount).
addReg(LoopCount).addImm(-1);
+ const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
// Update the previously generated instructions with the new loop counter.
for (SmallVectorImpl<MachineInstr *>::iterator I = PrevInsts.begin(),
E = PrevInsts.end(); I != E; ++I)
- (*I)->substituteRegister(LoopCount, NewLoopCount, 0, getRegisterInfo());
+ (*I)->substituteRegister(LoopCount, NewLoopCount, 0, HRI);
PrevInsts.clear();
PrevInsts.push_back(NewCmp);
PrevInsts.push_back(NewAdd);
@@ -757,7 +742,7 @@ void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
const DebugLoc &DL, unsigned DestReg,
unsigned SrcReg, bool KillSrc) const {
- auto &HRI = getRegisterInfo();
+ const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
unsigned KillFlag = getKillRegState(KillSrc);
if (Hexagon::IntRegsRegClass.contains(SrcReg, DestReg)) {
@@ -812,12 +797,12 @@ void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
.addReg(SrcReg, KillFlag);
return;
}
- if (Hexagon::VectorRegsRegClass.contains(SrcReg, DestReg)) {
+ if (Hexagon::HvxVRRegClass.contains(SrcReg, DestReg)) {
BuildMI(MBB, I, DL, get(Hexagon::V6_vassign), DestReg).
addReg(SrcReg, KillFlag);
return;
}
- if (Hexagon::VecDblRegsRegClass.contains(SrcReg, DestReg)) {
+ if (Hexagon::HvxWRRegClass.contains(SrcReg, DestReg)) {
unsigned LoSrc = HRI.getSubReg(SrcReg, Hexagon::vsub_lo);
unsigned HiSrc = HRI.getSubReg(SrcReg, Hexagon::vsub_hi);
BuildMI(MBB, I, DL, get(Hexagon::V6_vcombine), DestReg)
@@ -825,39 +810,27 @@ void HexagonInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
.addReg(LoSrc, KillFlag);
return;
}
- if (Hexagon::VecPredRegsRegClass.contains(SrcReg, DestReg)) {
+ if (Hexagon::HvxQRRegClass.contains(SrcReg, DestReg)) {
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)) {
+ if (Hexagon::HvxQRRegClass.contains(SrcReg) &&
+ Hexagon::HvxVRRegClass.contains(DestReg)) {
llvm_unreachable("Unimplemented pred to vec");
return;
}
- if (Hexagon::VecPredRegsRegClass.contains(DestReg) &&
- Hexagon::VectorRegsRegClass.contains(SrcReg)) {
+ if (Hexagon::HvxQRRegClass.contains(DestReg) &&
+ Hexagon::HvxVRRegClass.contains(SrcReg)) {
llvm_unreachable("Unimplemented vec to pred");
return;
}
- if (Hexagon::VecPredRegs128BRegClass.contains(SrcReg, DestReg)) {
- unsigned HiDst = HRI.getSubReg(DestReg, Hexagon::vsub_hi);
- unsigned LoDst = HRI.getSubReg(DestReg, Hexagon::vsub_lo);
- unsigned HiSrc = HRI.getSubReg(SrcReg, Hexagon::vsub_hi);
- unsigned LoSrc = HRI.getSubReg(SrcReg, Hexagon::vsub_lo);
- BuildMI(MBB, I, DL, get(Hexagon::V6_pred_and), HiDst)
- .addReg(HiSrc, KillFlag);
- BuildMI(MBB, I, DL, get(Hexagon::V6_pred_and), LoDst)
- .addReg(LoSrc, KillFlag);
- return;
- }
#ifndef NDEBUG
// Show the invalid registers to ease debugging.
- dbgs() << "Invalid registers for copy in BB#" << MBB.getNumber()
- << ": " << PrintReg(DestReg, &HRI)
- << " = " << PrintReg(SrcReg, &HRI) << '\n';
+ dbgs() << "Invalid registers for copy in " << printMBBReference(MBB) << ": "
+ << printReg(DestReg, &HRI) << " = " << printReg(SrcReg, &HRI) << '\n';
#endif
llvm_unreachable("Unimplemented");
}
@@ -868,15 +841,15 @@ void HexagonInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
DebugLoc DL = MBB.findDebugLoc(I);
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = MF.getFrameInfo();
- unsigned Align = MFI.getObjectAlignment(FI);
+ unsigned SlotAlign = MFI.getObjectAlignment(FI);
+ unsigned RegAlign = TRI->getSpillAlignment(*RC);
unsigned KillFlag = getKillRegState(isKill);
bool HasAlloca = MFI.hasVarSizedObjects();
- const auto &HST = MF.getSubtarget<HexagonSubtarget>();
- const HexagonFrameLowering &HFI = *HST.getFrameLowering();
+ const HexagonFrameLowering &HFI = *Subtarget.getFrameLowering();
MachineMemOperand *MMO = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
- MFI.getObjectSize(FI), Align);
+ MFI.getObjectSize(FI), SlotAlign);
if (Hexagon::IntRegsRegClass.hasSubClassEq(RC)) {
BuildMI(MBB, I, DL, get(Hexagon::S2_storeri_io))
@@ -894,50 +867,34 @@ void HexagonInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
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::PS_vstorerq_ai_128B))
- .addFrameIndex(FI).addImm(0)
- .addReg(SrcReg, KillFlag).addMemOperand(MMO);
- } else if (Hexagon::VecPredRegsRegClass.hasSubClassEq(RC)) {
+ } else if (Hexagon::HvxQRRegClass.hasSubClassEq(RC)) {
BuildMI(MBB, I, DL, get(Hexagon::PS_vstorerq_ai))
.addFrameIndex(FI).addImm(0)
.addReg(SrcReg, KillFlag).addMemOperand(MMO);
- } else if (Hexagon::VectorRegs128BRegClass.hasSubClassEq(RC)) {
+ } else if (Hexagon::HvxVRRegClass.hasSubClassEq(RC)) {
// If there are variable-sized objects, spills will not be aligned.
if (HasAlloca)
- Align = HFI.getStackAlignment();
- unsigned Opc = Align < 128 ? Hexagon::V6_vS32Ub_ai_128B
- : Hexagon::V6_vS32b_ai_128B;
+ SlotAlign = HFI.getStackAlignment();
+ unsigned Opc = SlotAlign < RegAlign ? Hexagon::V6_vS32Ub_ai
+ : Hexagon::V6_vS32b_ai;
+ MachineMemOperand *MMOA = MF.getMachineMemOperand(
+ MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
+ MFI.getObjectSize(FI), SlotAlign);
BuildMI(MBB, I, DL, get(Opc))
.addFrameIndex(FI).addImm(0)
- .addReg(SrcReg, KillFlag).addMemOperand(MMO);
- } else if (Hexagon::VectorRegsRegClass.hasSubClassEq(RC)) {
- // If there are variable-sized objects, spills will not be aligned.
- if (HasAlloca)
- Align = HFI.getStackAlignment();
- unsigned Opc = Align < 64 ? Hexagon::V6_vS32Ub_ai
- : Hexagon::V6_vS32b_ai;
- BuildMI(MBB, I, DL, get(Opc))
- .addFrameIndex(FI).addImm(0)
- .addReg(SrcReg, KillFlag).addMemOperand(MMO);
- } else if (Hexagon::VecDblRegsRegClass.hasSubClassEq(RC)) {
- // If there are variable-sized objects, spills will not be aligned.
- if (HasAlloca)
- Align = HFI.getStackAlignment();
- unsigned Opc = Align < 64 ? Hexagon::PS_vstorerwu_ai
- : Hexagon::PS_vstorerw_ai;
- BuildMI(MBB, I, DL, get(Opc))
- .addFrameIndex(FI).addImm(0)
- .addReg(SrcReg, KillFlag).addMemOperand(MMO);
- } else if (Hexagon::VecDblRegs128BRegClass.hasSubClassEq(RC)) {
+ .addReg(SrcReg, KillFlag).addMemOperand(MMOA);
+ } else if (Hexagon::HvxWRRegClass.hasSubClassEq(RC)) {
// If there are variable-sized objects, spills will not be aligned.
if (HasAlloca)
- Align = HFI.getStackAlignment();
- unsigned Opc = Align < 128 ? Hexagon::PS_vstorerwu_ai_128B
- : Hexagon::PS_vstorerw_ai_128B;
+ SlotAlign = HFI.getStackAlignment();
+ unsigned Opc = SlotAlign < RegAlign ? Hexagon::PS_vstorerwu_ai
+ : Hexagon::PS_vstorerw_ai;
+ MachineMemOperand *MMOA = MF.getMachineMemOperand(
+ MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
+ MFI.getObjectSize(FI), SlotAlign);
BuildMI(MBB, I, DL, get(Opc))
.addFrameIndex(FI).addImm(0)
- .addReg(SrcReg, KillFlag).addMemOperand(MMO);
+ .addReg(SrcReg, KillFlag).addMemOperand(MMOA);
} else {
llvm_unreachable("Unimplemented");
}
@@ -950,14 +907,14 @@ void HexagonInstrInfo::loadRegFromStackSlot(
DebugLoc DL = MBB.findDebugLoc(I);
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = MF.getFrameInfo();
- unsigned Align = MFI.getObjectAlignment(FI);
+ unsigned SlotAlign = MFI.getObjectAlignment(FI);
+ unsigned RegAlign = TRI->getSpillAlignment(*RC);
bool HasAlloca = MFI.hasVarSizedObjects();
- const auto &HST = MF.getSubtarget<HexagonSubtarget>();
- const HexagonFrameLowering &HFI = *HST.getFrameLowering();
+ const HexagonFrameLowering &HFI = *Subtarget.getFrameLowering();
MachineMemOperand *MMO = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
- MFI.getObjectSize(FI), Align);
+ MFI.getObjectSize(FI), SlotAlign);
if (Hexagon::IntRegsRegClass.hasSubClassEq(RC)) {
BuildMI(MBB, I, DL, get(Hexagon::L2_loadri_io), DestReg)
@@ -971,44 +928,31 @@ void HexagonInstrInfo::loadRegFromStackSlot(
} 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::PS_vloadrq_ai_128B), DestReg)
- .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
- } else if (Hexagon::VecPredRegsRegClass.hasSubClassEq(RC)) {
+ } else if (Hexagon::HvxQRRegClass.hasSubClassEq(RC)) {
BuildMI(MBB, I, DL, get(Hexagon::PS_vloadrq_ai), DestReg)
.addFrameIndex(FI).addImm(0).addMemOperand(MMO);
- } else if (Hexagon::VecDblRegs128BRegClass.hasSubClassEq(RC)) {
- // If there are variable-sized objects, spills will not be aligned.
- if (HasAlloca)
- Align = HFI.getStackAlignment();
- unsigned Opc = Align < 128 ? Hexagon::PS_vloadrwu_ai_128B
- : Hexagon::PS_vloadrw_ai_128B;
- BuildMI(MBB, I, DL, get(Opc), DestReg)
- .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
- } else if (Hexagon::VectorRegs128BRegClass.hasSubClassEq(RC)) {
+ } else if (Hexagon::HvxVRRegClass.hasSubClassEq(RC)) {
// If there are variable-sized objects, spills will not be aligned.
if (HasAlloca)
- Align = HFI.getStackAlignment();
- unsigned Opc = Align < 128 ? Hexagon::V6_vL32Ub_ai_128B
- : Hexagon::V6_vL32b_ai_128B;
+ SlotAlign = HFI.getStackAlignment();
+ unsigned Opc = SlotAlign < RegAlign ? Hexagon::V6_vL32Ub_ai
+ : Hexagon::V6_vL32b_ai;
+ MachineMemOperand *MMOA = MF.getMachineMemOperand(
+ MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
+ MFI.getObjectSize(FI), SlotAlign);
BuildMI(MBB, I, DL, get(Opc), DestReg)
- .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
- } else if (Hexagon::VectorRegsRegClass.hasSubClassEq(RC)) {
- // If there are variable-sized objects, spills will not be aligned.
- if (HasAlloca)
- Align = HFI.getStackAlignment();
- unsigned Opc = Align < 64 ? Hexagon::V6_vL32Ub_ai
- : Hexagon::V6_vL32b_ai;
- BuildMI(MBB, I, DL, get(Opc), DestReg)
- .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
- } else if (Hexagon::VecDblRegsRegClass.hasSubClassEq(RC)) {
+ .addFrameIndex(FI).addImm(0).addMemOperand(MMOA);
+ } else if (Hexagon::HvxWRRegClass.hasSubClassEq(RC)) {
// If there are variable-sized objects, spills will not be aligned.
if (HasAlloca)
- Align = HFI.getStackAlignment();
- unsigned Opc = Align < 64 ? Hexagon::PS_vloadrwu_ai
- : Hexagon::PS_vloadrw_ai;
+ SlotAlign = HFI.getStackAlignment();
+ unsigned Opc = SlotAlign < RegAlign ? Hexagon::PS_vloadrwu_ai
+ : Hexagon::PS_vloadrw_ai;
+ MachineMemOperand *MMOA = MF.getMachineMemOperand(
+ MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
+ MFI.getObjectSize(FI), SlotAlign);
BuildMI(MBB, I, DL, get(Opc), DestReg)
- .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
+ .addFrameIndex(FI).addImm(0).addMemOperand(MMOA);
} else {
llvm_unreachable("Can't store this register to stack slot");
}
@@ -1029,12 +973,12 @@ static void getLiveRegsAt(LivePhysRegs &Regs, const MachineInstr &MI) {
/// new instructions and erase MI. The function should return true if
/// anything was changed.
bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
- const HexagonRegisterInfo &HRI = getRegisterInfo();
- MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
MachineBasicBlock &MBB = *MI.getParent();
+ MachineFunction &MF = *MBB.getParent();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+ const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
DebugLoc DL = MI.getDebugLoc();
unsigned Opc = MI.getOpcode();
- const unsigned VecOffset = 1;
switch (Opc) {
case TargetOpcode::COPY: {
@@ -1054,7 +998,6 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
.addImm(-MI.getOperand(1).getImm());
MBB.erase(MI);
return true;
- case Hexagon::V6_vassignp_128B:
case Hexagon::V6_vassignp: {
unsigned SrcReg = MI.getOperand(1).getReg();
unsigned DstReg = MI.getOperand(0).getReg();
@@ -1065,7 +1008,6 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
MBB.erase(MI);
return true;
}
- case Hexagon::V6_lo_128B:
case Hexagon::V6_lo: {
unsigned SrcReg = MI.getOperand(1).getReg();
unsigned DstReg = MI.getOperand(0).getReg();
@@ -1075,7 +1017,6 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
MRI.clearKillFlags(SrcSubLo);
return true;
}
- case Hexagon::V6_hi_128B:
case Hexagon::V6_hi: {
unsigned SrcReg = MI.getOperand(1).getReg();
unsigned DstReg = MI.getOperand(0).getReg();
@@ -1086,25 +1027,14 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
return true;
}
case Hexagon::PS_vstorerw_ai:
- case Hexagon::PS_vstorerwu_ai:
- case Hexagon::PS_vstorerw_ai_128B:
- case Hexagon::PS_vstorerwu_ai_128B: {
- bool Is128B = (Opc == Hexagon::PS_vstorerw_ai_128B ||
- Opc == Hexagon::PS_vstorerwu_ai_128B);
- bool Aligned = (Opc == Hexagon::PS_vstorerw_ai ||
- Opc == Hexagon::PS_vstorerw_ai_128B);
+ case Hexagon::PS_vstorerwu_ai: {
+ bool Aligned = Opc == Hexagon::PS_vstorerw_ai;
unsigned SrcReg = MI.getOperand(2).getReg();
unsigned SrcSubHi = HRI.getSubReg(SrcReg, Hexagon::vsub_hi);
unsigned SrcSubLo = HRI.getSubReg(SrcReg, Hexagon::vsub_lo);
- unsigned NewOpc;
- if (Aligned)
- NewOpc = Is128B ? Hexagon::V6_vS32b_ai_128B
- : Hexagon::V6_vS32b_ai;
- else
- NewOpc = Is128B ? Hexagon::V6_vS32Ub_ai_128B
- : Hexagon::V6_vS32Ub_ai;
+ unsigned NewOpc = Aligned ? Hexagon::V6_vS32b_ai : Hexagon::V6_vS32Ub_ai;
+ unsigned Offset = HRI.getSpillSize(Hexagon::HvxVRRegClass);
- unsigned Offset = Is128B ? VecOffset << 7 : VecOffset << 6;
MachineInstr *MI1New =
BuildMI(MBB, MI, DL, get(NewOpc))
.add(MI.getOperand(0))
@@ -1122,23 +1052,12 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
return true;
}
case Hexagon::PS_vloadrw_ai:
- case Hexagon::PS_vloadrwu_ai:
- case Hexagon::PS_vloadrw_ai_128B:
- case Hexagon::PS_vloadrwu_ai_128B: {
- bool Is128B = (Opc == Hexagon::PS_vloadrw_ai_128B ||
- Opc == Hexagon::PS_vloadrwu_ai_128B);
- bool Aligned = (Opc == Hexagon::PS_vloadrw_ai ||
- Opc == Hexagon::PS_vloadrw_ai_128B);
- unsigned NewOpc;
- if (Aligned)
- NewOpc = Is128B ? Hexagon::V6_vL32b_ai_128B
- : Hexagon::V6_vL32b_ai;
- else
- NewOpc = Is128B ? Hexagon::V6_vL32Ub_ai_128B
- : Hexagon::V6_vL32Ub_ai;
-
+ case Hexagon::PS_vloadrwu_ai: {
+ bool Aligned = Opc == Hexagon::PS_vloadrw_ai;
unsigned DstReg = MI.getOperand(0).getReg();
- unsigned Offset = Is128B ? VecOffset << 7 : VecOffset << 6;
+ unsigned NewOpc = Aligned ? Hexagon::V6_vL32b_ai : Hexagon::V6_vL32Ub_ai;
+ unsigned Offset = HRI.getSpillSize(Hexagon::HvxVRRegClass);
+
MachineInstr *MI1New = BuildMI(MBB, MI, DL, get(NewOpc),
HRI.getSubReg(DstReg, Hexagon::vsub_lo))
.add(MI.getOperand(1))
@@ -1248,8 +1167,7 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
MBB.erase(MI);
return true;
}
- case Hexagon::PS_vselect:
- case Hexagon::PS_vselect_128B: {
+ case Hexagon::PS_vselect: {
const MachineOperand &Op0 = MI.getOperand(0);
const MachineOperand &Op1 = MI.getOperand(1);
const MachineOperand &Op2 = MI.getOperand(2);
@@ -1283,8 +1201,7 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
MBB.erase(MI);
return true;
}
- case Hexagon::PS_wselect:
- case Hexagon::PS_wselect_128B: {
+ case Hexagon::PS_wselect: {
MachineOperand &Op0 = MI.getOperand(0);
MachineOperand &Op1 = MI.getOperand(1);
MachineOperand &Op2 = MI.getOperand(2);
@@ -1325,6 +1242,7 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
MBB.erase(MI);
return true;
}
+
case Hexagon::PS_tailcall_i:
MI.setDesc(get(Hexagon::J2_jump));
return true;
@@ -1350,6 +1268,82 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
case Hexagon::PS_jmpretfnew:
MI.setDesc(get(Hexagon::J2_jumprfnew));
return true;
+
+ case Hexagon::V6_vgathermh_pseudo:
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermh))
+ .add(MI.getOperand(1))
+ .add(MI.getOperand(2))
+ .add(MI.getOperand(3));
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
+ .add(MI.getOperand(0))
+ .addImm(0)
+ .addReg(Hexagon::VTMP);
+ MBB.erase(MI);
+ return true;
+
+ case Hexagon::V6_vgathermw_pseudo:
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermw))
+ .add(MI.getOperand(1))
+ .add(MI.getOperand(2))
+ .add(MI.getOperand(3));
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
+ .add(MI.getOperand(0))
+ .addImm(0)
+ .addReg(Hexagon::VTMP);
+ MBB.erase(MI);
+ return true;
+
+ case Hexagon::V6_vgathermhw_pseudo:
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhw))
+ .add(MI.getOperand(1))
+ .add(MI.getOperand(2))
+ .add(MI.getOperand(3));
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
+ .add(MI.getOperand(0))
+ .addImm(0)
+ .addReg(Hexagon::VTMP);
+ MBB.erase(MI);
+ return true;
+
+ case Hexagon::V6_vgathermhq_pseudo:
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhq))
+ .add(MI.getOperand(1))
+ .add(MI.getOperand(2))
+ .add(MI.getOperand(3))
+ .add(MI.getOperand(4));
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
+ .add(MI.getOperand(0))
+ .addImm(0)
+ .addReg(Hexagon::VTMP);
+ MBB.erase(MI);
+ return true;
+
+ case Hexagon::V6_vgathermwq_pseudo:
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermwq))
+ .add(MI.getOperand(1))
+ .add(MI.getOperand(2))
+ .add(MI.getOperand(3))
+ .add(MI.getOperand(4));
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
+ .add(MI.getOperand(0))
+ .addImm(0)
+ .addReg(Hexagon::VTMP);
+ MBB.erase(MI);
+ return true;
+
+ case Hexagon::V6_vgathermhwq_pseudo:
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhwq))
+ .add(MI.getOperand(1))
+ .add(MI.getOperand(2))
+ .add(MI.getOperand(3))
+ .add(MI.getOperand(4));
+ BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
+ .add(MI.getOperand(0))
+ .addImm(0)
+ .addReg(Hexagon::VTMP);
+ MBB.erase(MI);
+ return true;
+
}
return false;
@@ -1452,9 +1446,10 @@ bool HexagonInstrInfo::SubsumesPredicate(ArrayRef<MachineOperand> Pred1,
return false;
}
-bool HexagonInstrInfo::DefinesPredicate(
- MachineInstr &MI, std::vector<MachineOperand> &Pred) const {
- auto &HRI = getRegisterInfo();
+bool HexagonInstrInfo::DefinesPredicate(MachineInstr &MI,
+ std::vector<MachineOperand> &Pred) const {
+ const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
+
for (unsigned oper = 0; oper < MI.getNumOperands(); ++oper) {
MachineOperand MO = MI.getOperand(oper);
if (MO.isReg()) {
@@ -1483,10 +1478,34 @@ bool HexagonInstrInfo::isPredicable(const MachineInstr &MI) const {
return false;
if (MI.isCall() || isTailCall(MI)) {
- const MachineFunction &MF = *MI.getParent()->getParent();
- if (!MF.getSubtarget<HexagonSubtarget>().usePredicatedCalls())
+ if (!Subtarget.usePredicatedCalls())
return false;
}
+
+ // HVX loads are not predicable on v60, but are on v62.
+ if (!Subtarget.hasV62TOps()) {
+ switch (MI.getOpcode()) {
+ case Hexagon::V6_vL32b_ai:
+ case Hexagon::V6_vL32b_pi:
+ case Hexagon::V6_vL32b_ppu:
+ case Hexagon::V6_vL32b_cur_ai:
+ case Hexagon::V6_vL32b_cur_pi:
+ case Hexagon::V6_vL32b_cur_ppu:
+ case Hexagon::V6_vL32b_nt_ai:
+ case Hexagon::V6_vL32b_nt_pi:
+ case Hexagon::V6_vL32b_nt_ppu:
+ case Hexagon::V6_vL32b_tmp_ai:
+ case Hexagon::V6_vL32b_tmp_pi:
+ case Hexagon::V6_vL32b_tmp_ppu:
+ case Hexagon::V6_vL32b_nt_cur_ai:
+ case Hexagon::V6_vL32b_nt_cur_pi:
+ case Hexagon::V6_vL32b_nt_cur_ppu:
+ case Hexagon::V6_vL32b_nt_tmp_ai:
+ case Hexagon::V6_vL32b_nt_tmp_pi:
+ case Hexagon::V6_vL32b_nt_tmp_ppu:
+ return false;
+ }
+ }
return true;
}
@@ -1562,10 +1581,8 @@ unsigned HexagonInstrInfo::getInlineAsmLength(const char *Str,
ScheduleHazardRecognizer*
HexagonInstrInfo::CreateTargetPostRAHazardRecognizer(
const InstrItineraryData *II, const ScheduleDAG *DAG) const {
- if (UseDFAHazardRec) {
- auto &HST = DAG->MF.getSubtarget<HexagonSubtarget>();
- return new HexagonHazardRecognizer(II, this, HST);
- }
+ if (UseDFAHazardRec)
+ return new HexagonHazardRecognizer(II, this, Subtarget);
return TargetInstrInfo::CreateTargetPostRAHazardRecognizer(II, DAG);
}
@@ -1649,10 +1666,14 @@ bool HexagonInstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
case Hexagon::A4_cmpbgtui:
case Hexagon::A4_cmpheqi:
case Hexagon::A4_cmphgti:
- case Hexagon::A4_cmphgtui:
+ case Hexagon::A4_cmphgtui: {
SrcReg2 = 0;
+ const MachineOperand &Op2 = MI.getOperand(2);
+ if (!Op2.isImm())
+ return false;
Value = MI.getOperand(2).getImm();
return true;
+ }
}
return false;
@@ -1664,7 +1685,6 @@ unsigned HexagonInstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
return getInstrTimingClassLatency(ItinData, MI);
}
-
DFAPacketizer *HexagonInstrInfo::CreateTargetScheduleState(
const TargetSubtargetInfo &STI) const {
const InstrItineraryData *II = STI.getInstrItineraryData();
@@ -1672,14 +1692,11 @@ DFAPacketizer *HexagonInstrInfo::CreateTargetScheduleState(
}
// Inspired by this pair:
-// %R13<def> = L2_loadri_io %R29, 136; mem:LD4[FixedStack0]
-// S2_storeri_io %R29, 132, %R1<kill>; flags: mem:ST4[FixedStack1]
+// %r13 = L2_loadri_io %r29, 136; mem:LD4[FixedStack0]
+// S2_storeri_io %r29, 132, killed %r1; 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 {
- int OffsetA = 0, OffsetB = 0;
- unsigned SizeA = 0, SizeB = 0;
-
if (MIa.hasUnmodeledSideEffects() || MIb.hasUnmodeledSideEffects() ||
MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
return false;
@@ -1689,27 +1706,47 @@ bool HexagonInstrInfo::areMemAccessesTriviallyDisjoint(
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);
- if (!BaseRegA || !SizeA)
+ // Get the base register in MIa.
+ unsigned BasePosA, OffsetPosA;
+ if (!getBaseAndOffsetPosition(MIa, BasePosA, OffsetPosA))
return false;
+ const MachineOperand &BaseA = MIa.getOperand(BasePosA);
+ unsigned BaseRegA = BaseA.getReg();
+ unsigned BaseSubA = BaseA.getSubReg();
- // Get base, offset, and access size in MIb.
- unsigned BaseRegB = getBaseAndOffset(MIb, OffsetB, SizeB);
- if (!BaseRegB || !SizeB)
+ // Get the base register in MIb.
+ unsigned BasePosB, OffsetPosB;
+ if (!getBaseAndOffsetPosition(MIb, BasePosB, OffsetPosB))
return false;
+ const MachineOperand &BaseB = MIb.getOperand(BasePosB);
+ unsigned BaseRegB = BaseB.getReg();
+ unsigned BaseSubB = BaseB.getSubReg();
+
+ if (BaseRegA != BaseRegB || BaseSubA != BaseSubB)
+ return false;
+
+ // Get the access sizes.
+ unsigned SizeA = getMemAccessSize(MIa);
+ unsigned SizeB = getMemAccessSize(MIb);
- if (BaseRegA != BaseRegB)
+ // Get the offsets. Handle immediates only for now.
+ const MachineOperand &OffA = MIa.getOperand(OffsetPosA);
+ const MachineOperand &OffB = MIb.getOperand(OffsetPosB);
+ if (!MIa.getOperand(OffsetPosA).isImm() ||
+ !MIb.getOperand(OffsetPosB).isImm())
return false;
+ int OffsetA = isPostIncrement(MIa) ? 0 : OffA.getImm();
+ int OffsetB = isPostIncrement(MIb) ? 0 : OffB.getImm();
// This is a mem access with the same base register and known offsets from it.
// Reason about it.
if (OffsetA > OffsetB) {
- uint64_t offDiff = (uint64_t)((int64_t)OffsetA - (int64_t)OffsetB);
- return (SizeB <= offDiff);
- } else if (OffsetA < OffsetB) {
- uint64_t offDiff = (uint64_t)((int64_t)OffsetB - (int64_t)OffsetA);
- return (SizeA <= offDiff);
+ uint64_t OffDiff = (uint64_t)((int64_t)OffsetA - (int64_t)OffsetB);
+ return SizeB <= OffDiff;
+ }
+ if (OffsetA < OffsetB) {
+ uint64_t OffDiff = (uint64_t)((int64_t)OffsetB - (int64_t)OffsetA);
+ return SizeA <= OffDiff;
}
return false;
@@ -1719,12 +1756,20 @@ bool HexagonInstrInfo::areMemAccessesTriviallyDisjoint(
bool HexagonInstrInfo::getIncrementValue(const MachineInstr &MI,
int &Value) const {
if (isPostIncrement(MI)) {
- unsigned AccessSize;
- return getBaseAndOffset(MI, Value, AccessSize);
- }
- if (MI.getOpcode() == Hexagon::A2_addi) {
- Value = MI.getOperand(2).getImm();
- return true;
+ unsigned BasePos = 0, OffsetPos = 0;
+ if (!getBaseAndOffsetPosition(MI, BasePos, OffsetPos))
+ return false;
+ const MachineOperand &OffsetOp = MI.getOperand(OffsetPos);
+ if (OffsetOp.isImm()) {
+ Value = OffsetOp.getImm();
+ return true;
+ }
+ } else if (MI.getOpcode() == Hexagon::A2_addi) {
+ const MachineOperand &AddOp = MI.getOperand(2);
+ if (AddOp.isImm()) {
+ Value = AddOp.getImm();
+ return true;
+ }
}
return false;
@@ -1739,6 +1784,7 @@ HexagonInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
ArrayRef<std::pair<unsigned, const char*>>
HexagonInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
using namespace HexagonII;
+
static const std::pair<unsigned, const char*> Flags[] = {
{MO_PCREL, "hexagon-pcrel"},
{MO_GOT, "hexagon-got"},
@@ -1757,6 +1803,7 @@ HexagonInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
ArrayRef<std::pair<unsigned, const char*>>
HexagonInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
using namespace HexagonII;
+
static const std::pair<unsigned, const char*> Flags[] = {
{HMOTF_ConstExtended, "hexagon-ext"}
};
@@ -1790,23 +1837,11 @@ bool HexagonInstrInfo::isAccumulator(const MachineInstr &MI) const {
}
bool HexagonInstrInfo::isComplex(const MachineInstr &MI) const {
- const MachineFunction *MF = MI.getParent()->getParent();
- const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
- const HexagonInstrInfo *QII = (const HexagonInstrInfo *) TII;
-
- if (!(isTC1(MI))
- && !(QII->isTC2Early(MI))
- && !(MI.getDesc().mayLoad())
- && !(MI.getDesc().mayStore())
- && (MI.getDesc().getOpcode() != Hexagon::S2_allocframe)
- && (MI.getDesc().getOpcode() != Hexagon::L2_deallocframe)
- && !(QII->isMemOp(MI))
- && !(MI.isBranch())
- && !(MI.isReturn())
- && !MI.isCall())
- return true;
-
- return false;
+ return !isTC1(MI) && !isTC2Early(MI) && !MI.getDesc().mayLoad() &&
+ !MI.getDesc().mayStore() &&
+ MI.getDesc().getOpcode() != Hexagon::S2_allocframe &&
+ MI.getDesc().getOpcode() != Hexagon::L2_deallocframe &&
+ !isMemOp(MI) && !MI.isBranch() && !MI.isReturn() && !MI.isCall();
}
// Return true if the instruction is a compund branch instruction.
@@ -1861,13 +1896,13 @@ bool HexagonInstrInfo::isConstExtended(const MachineInstr &MI) const {
bool HexagonInstrInfo::isDeallocRet(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
- case Hexagon::L4_return :
- case Hexagon::L4_return_t :
- case Hexagon::L4_return_f :
- case Hexagon::L4_return_tnew_pnt :
- case Hexagon::L4_return_fnew_pnt :
- case Hexagon::L4_return_tnew_pt :
- case Hexagon::L4_return_fnew_pt :
+ case Hexagon::L4_return:
+ case Hexagon::L4_return_t:
+ case Hexagon::L4_return_f:
+ case Hexagon::L4_return_tnew_pnt:
+ case Hexagon::L4_return_fnew_pnt:
+ case Hexagon::L4_return_tnew_pt:
+ case Hexagon::L4_return_fnew_pt:
return true;
}
return false;
@@ -1878,8 +1913,7 @@ bool HexagonInstrInfo::isDependent(const MachineInstr &ProdMI,
const MachineInstr &ConsMI) const {
if (!ProdMI.getDesc().getNumDefs())
return false;
-
- auto &HRI = getRegisterInfo();
+ const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
SmallVector<unsigned, 4> DefsA;
SmallVector<unsigned, 4> DefsB;
@@ -1914,8 +1948,6 @@ bool HexagonInstrInfo::isDotCurInst(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
case Hexagon::V6_vL32b_cur_pi:
case Hexagon::V6_vL32b_cur_ai:
- case Hexagon::V6_vL32b_cur_pi_128B:
- case Hexagon::V6_vL32b_cur_ai_128B:
return true;
}
return false;
@@ -2019,10 +2051,10 @@ bool HexagonInstrInfo::isHVXMemWithAIndirect(const MachineInstr &I,
bool HexagonInstrInfo::isIndirectCall(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
- case Hexagon::J2_callr :
- case Hexagon::J2_callrf :
- case Hexagon::J2_callrt :
- case Hexagon::PS_call_nr :
+ case Hexagon::J2_callr:
+ case Hexagon::J2_callrf:
+ case Hexagon::J2_callrt:
+ case Hexagon::PS_call_nr:
return true;
}
return false;
@@ -2030,13 +2062,13 @@ bool HexagonInstrInfo::isIndirectCall(const MachineInstr &MI) const {
bool HexagonInstrInfo::isIndirectL4Return(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
- case Hexagon::L4_return :
- case Hexagon::L4_return_t :
- case Hexagon::L4_return_f :
- case Hexagon::L4_return_fnew_pnt :
- case Hexagon::L4_return_fnew_pt :
- case Hexagon::L4_return_tnew_pnt :
- case Hexagon::L4_return_tnew_pt :
+ case Hexagon::L4_return:
+ case Hexagon::L4_return_t:
+ case Hexagon::L4_return_f:
+ case Hexagon::L4_return_fnew_pnt:
+ case Hexagon::L4_return_fnew_pt:
+ case Hexagon::L4_return_tnew_pnt:
+ case Hexagon::L4_return_tnew_pt:
return true;
}
return false;
@@ -2044,13 +2076,13 @@ bool HexagonInstrInfo::isIndirectL4Return(const MachineInstr &MI) const {
bool HexagonInstrInfo::isJumpR(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
- case Hexagon::J2_jumpr :
- case Hexagon::J2_jumprt :
- case Hexagon::J2_jumprf :
- case Hexagon::J2_jumprtnewpt :
- case Hexagon::J2_jumprfnewpt :
- case Hexagon::J2_jumprtnew :
- case Hexagon::J2_jumprfnew :
+ case Hexagon::J2_jumpr:
+ case Hexagon::J2_jumprt:
+ case Hexagon::J2_jumprf:
+ case Hexagon::J2_jumprtnewpt:
+ case Hexagon::J2_jumprfnewpt:
+ case Hexagon::J2_jumprtnew:
+ case Hexagon::J2_jumprfnew:
return true;
}
return false;
@@ -2096,6 +2128,8 @@ bool HexagonInstrInfo::isJumpWithinBranchRange(const MachineInstr &MI,
// TODO: Add all the compound branches here. Can we do this in Relation model?
case Hexagon::J4_cmpeqi_tp0_jump_nt:
case Hexagon::J4_cmpeqi_tp1_jump_nt:
+ case Hexagon::J4_cmpeqn1_tp0_jump_nt:
+ case Hexagon::J4_cmpeqn1_tp1_jump_nt:
return isInt<11>(offset);
}
}
@@ -2158,24 +2192,24 @@ bool HexagonInstrInfo::isLoopN(const MachineInstr &MI) const {
bool HexagonInstrInfo::isMemOp(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
default: return false;
- case Hexagon::L4_iadd_memopw_io :
- case Hexagon::L4_isub_memopw_io :
- case Hexagon::L4_add_memopw_io :
- case Hexagon::L4_sub_memopw_io :
- case Hexagon::L4_and_memopw_io :
- case Hexagon::L4_or_memopw_io :
- case Hexagon::L4_iadd_memoph_io :
- case Hexagon::L4_isub_memoph_io :
- case Hexagon::L4_add_memoph_io :
- case Hexagon::L4_sub_memoph_io :
- case Hexagon::L4_and_memoph_io :
- case Hexagon::L4_or_memoph_io :
- case Hexagon::L4_iadd_memopb_io :
- case Hexagon::L4_isub_memopb_io :
- case Hexagon::L4_add_memopb_io :
- case Hexagon::L4_sub_memopb_io :
- case Hexagon::L4_and_memopb_io :
- case Hexagon::L4_or_memopb_io :
+ case Hexagon::L4_iadd_memopw_io:
+ case Hexagon::L4_isub_memopw_io:
+ case Hexagon::L4_add_memopw_io:
+ case Hexagon::L4_sub_memopw_io:
+ case Hexagon::L4_and_memopw_io:
+ case Hexagon::L4_or_memopw_io:
+ case Hexagon::L4_iadd_memoph_io:
+ case Hexagon::L4_isub_memoph_io:
+ case Hexagon::L4_add_memoph_io:
+ case Hexagon::L4_sub_memoph_io:
+ case Hexagon::L4_and_memoph_io:
+ case Hexagon::L4_or_memoph_io:
+ case Hexagon::L4_iadd_memopb_io:
+ case Hexagon::L4_isub_memopb_io:
+ case Hexagon::L4_add_memopb_io:
+ case Hexagon::L4_sub_memopb_io:
+ case Hexagon::L4_and_memopb_io:
+ case Hexagon::L4_or_memopb_io:
case Hexagon::L4_ior_memopb_io:
case Hexagon::L4_ior_memoph_io:
case Hexagon::L4_ior_memopw_io:
@@ -2362,8 +2396,8 @@ bool HexagonInstrInfo::isSolo(const MachineInstr &MI) const {
bool HexagonInstrInfo::isSpillPredRegOp(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
- case Hexagon::STriw_pred :
- case Hexagon::LDriw_pred :
+ case Hexagon::STriw_pred:
+ case Hexagon::LDriw_pred:
return true;
default:
return false;
@@ -2426,45 +2460,38 @@ bool HexagonInstrInfo::isHVXVec(const MachineInstr &MI) const {
}
// Check if the Offset is a valid auto-inc imm by Load/Store Type.
-//
-bool HexagonInstrInfo::isValidAutoIncImm(const EVT VT, const int Offset) const {
- if (VT == MVT::v16i32 || VT == MVT::v8i64 ||
- VT == MVT::v32i16 || VT == MVT::v64i8) {
- return (Offset >= Hexagon_MEMV_AUTOINC_MIN &&
- Offset <= Hexagon_MEMV_AUTOINC_MAX &&
- (Offset & 0x3f) == 0);
- }
- // 128B
- if (VT == MVT::v32i32 || VT == MVT::v16i64 ||
- VT == MVT::v64i16 || VT == MVT::v128i8) {
- return (Offset >= Hexagon_MEMV_AUTOINC_MIN_128B &&
- Offset <= Hexagon_MEMV_AUTOINC_MAX_128B &&
- (Offset & 0x7f) == 0);
- }
- if (VT == MVT::i64) {
- return (Offset >= Hexagon_MEMD_AUTOINC_MIN &&
- Offset <= Hexagon_MEMD_AUTOINC_MAX &&
- (Offset & 0x7) == 0);
- }
- if (VT == MVT::i32) {
- return (Offset >= Hexagon_MEMW_AUTOINC_MIN &&
- Offset <= Hexagon_MEMW_AUTOINC_MAX &&
- (Offset & 0x3) == 0);
- }
- if (VT == MVT::i16) {
- return (Offset >= Hexagon_MEMH_AUTOINC_MIN &&
- Offset <= Hexagon_MEMH_AUTOINC_MAX &&
- (Offset & 0x1) == 0);
- }
- if (VT == MVT::i8) {
- return (Offset >= Hexagon_MEMB_AUTOINC_MIN &&
- Offset <= Hexagon_MEMB_AUTOINC_MAX);
+bool HexagonInstrInfo::isValidAutoIncImm(const EVT VT, int Offset) const {
+ int Size = VT.getSizeInBits() / 8;
+ if (Offset % Size != 0)
+ return false;
+ int Count = Offset / Size;
+
+ switch (VT.getSimpleVT().SimpleTy) {
+ // For scalars the auto-inc is s4
+ case MVT::i8:
+ case MVT::i16:
+ case MVT::i32:
+ case MVT::i64:
+ return isInt<4>(Count);
+ // For HVX vectors the auto-inc is s3
+ case MVT::v64i8:
+ case MVT::v32i16:
+ case MVT::v16i32:
+ case MVT::v8i64:
+ case MVT::v128i8:
+ case MVT::v64i16:
+ case MVT::v32i32:
+ case MVT::v16i64:
+ return isInt<3>(Count);
+ default:
+ break;
}
- llvm_unreachable("Not an auto-inc opc!");
+
+ llvm_unreachable("Not an valid type!");
}
bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
- bool Extend) const {
+ const TargetRegisterInfo *TRI, bool Extend) const {
// This function is to check whether the "Offset" is in the correct range of
// the given "Opcode". If "Offset" is not in the correct range, "A2_addi" is
// inserted to calculate the final address. Due to this reason, the function
@@ -2473,7 +2500,6 @@ bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
// there are cases where a misaligned pointer recast can cause this
// problem, and we need to allow for it. The front end warns of such
// misaligns with respect to load size.
-
switch (Opcode) {
case Hexagon::PS_vstorerq_ai:
case Hexagon::PS_vstorerw_ai:
@@ -2486,22 +2512,13 @@ bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
case Hexagon::V6_vL32b_nt_ai:
case Hexagon::V6_vS32b_nt_ai:
case Hexagon::V6_vL32Ub_ai:
- case Hexagon::V6_vS32Ub_ai:
- return isShiftedInt<4,6>(Offset);
-
- case Hexagon::PS_vstorerq_ai_128B:
- case Hexagon::PS_vstorerw_ai_128B:
- case Hexagon::PS_vstorerw_nt_ai_128B:
- case Hexagon::PS_vloadrq_ai_128B:
- case Hexagon::PS_vloadrw_ai_128B:
- case Hexagon::PS_vloadrw_nt_ai_128B:
- case Hexagon::V6_vL32b_ai_128B:
- case Hexagon::V6_vS32b_ai_128B:
- case Hexagon::V6_vL32b_nt_ai_128B:
- case Hexagon::V6_vS32b_nt_ai_128B:
- case Hexagon::V6_vL32Ub_ai_128B:
- case Hexagon::V6_vS32Ub_ai_128B:
- return isShiftedInt<4,7>(Offset);
+ case Hexagon::V6_vS32Ub_ai: {
+ unsigned VectorSize = TRI->getSpillSize(Hexagon::HvxVRRegClass);
+ assert(isPowerOf2_32(VectorSize));
+ if (Offset & (VectorSize-1))
+ return false;
+ return isInt<4>(Offset >> Log2_32(VectorSize));
+ }
case Hexagon::J2_loop0i:
case Hexagon::J2_loop1i:
@@ -2554,28 +2571,28 @@ bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
return (Offset >= Hexagon_ADDI_OFFSET_MIN) &&
(Offset <= Hexagon_ADDI_OFFSET_MAX);
- case Hexagon::L4_iadd_memopw_io :
- case Hexagon::L4_isub_memopw_io :
- case Hexagon::L4_add_memopw_io :
- case Hexagon::L4_sub_memopw_io :
- case Hexagon::L4_and_memopw_io :
- case Hexagon::L4_or_memopw_io :
+ case Hexagon::L4_iadd_memopw_io:
+ case Hexagon::L4_isub_memopw_io:
+ case Hexagon::L4_add_memopw_io:
+ case Hexagon::L4_sub_memopw_io:
+ case Hexagon::L4_and_memopw_io:
+ case Hexagon::L4_or_memopw_io:
return (0 <= Offset && Offset <= 255);
- case Hexagon::L4_iadd_memoph_io :
- case Hexagon::L4_isub_memoph_io :
- case Hexagon::L4_add_memoph_io :
- case Hexagon::L4_sub_memoph_io :
- case Hexagon::L4_and_memoph_io :
- case Hexagon::L4_or_memoph_io :
+ case Hexagon::L4_iadd_memoph_io:
+ case Hexagon::L4_isub_memoph_io:
+ case Hexagon::L4_add_memoph_io:
+ case Hexagon::L4_sub_memoph_io:
+ case Hexagon::L4_and_memoph_io:
+ case Hexagon::L4_or_memoph_io:
return (0 <= Offset && Offset <= 127);
- case Hexagon::L4_iadd_memopb_io :
- case Hexagon::L4_isub_memopb_io :
- case Hexagon::L4_add_memopb_io :
- case Hexagon::L4_sub_memopb_io :
- case Hexagon::L4_and_memopb_io :
- case Hexagon::L4_or_memopb_io :
+ case Hexagon::L4_iadd_memopb_io:
+ case Hexagon::L4_isub_memopb_io:
+ case Hexagon::L4_add_memopb_io:
+ case Hexagon::L4_sub_memopb_io:
+ case Hexagon::L4_and_memopb_io:
+ case Hexagon::L4_or_memopb_io:
return (0 <= Offset && Offset <= 63);
// LDriw_xxx and STriw_xxx are pseudo operations, so it has to take offset of
@@ -2799,19 +2816,19 @@ bool HexagonInstrInfo::hasNonExtEquivalent(const MachineInstr &MI) const {
// Check addressing mode and retrieve non-ext equivalent instruction.
switch (getAddrMode(MI)) {
- case HexagonII::Absolute :
+ case HexagonII::Absolute:
// Load/store with absolute addressing mode can be converted into
// base+offset mode.
- NonExtOpcode = Hexagon::getBaseWithImmOffset(MI.getOpcode());
+ NonExtOpcode = Hexagon::changeAddrMode_abs_io(MI.getOpcode());
break;
- case HexagonII::BaseImmOffset :
+ case HexagonII::BaseImmOffset:
// Load/store with base+offset addressing mode can be converted into
// base+register offset addressing mode. However left shift operand should
// be set to 0.
- NonExtOpcode = Hexagon::getBaseWithRegOffset(MI.getOpcode());
+ NonExtOpcode = Hexagon::changeAddrMode_io_rr(MI.getOpcode());
break;
case HexagonII::BaseLongOffset:
- NonExtOpcode = Hexagon::getRegShlForm(MI.getOpcode());
+ NonExtOpcode = Hexagon::changeAddrMode_ur_rr(MI.getOpcode());
break;
default:
return false;
@@ -2841,10 +2858,9 @@ bool HexagonInstrInfo::hasUncondBranch(const MachineBasicBlock *B)
// Returns true, if a LD insn can be promoted to a cur load.
bool HexagonInstrInfo::mayBeCurLoad(const MachineInstr &MI) const {
- auto &HST = MI.getParent()->getParent()->getSubtarget<HexagonSubtarget>();
const uint64_t F = MI.getDesc().TSFlags;
return ((F >> HexagonII::mayCVLoadPos) & HexagonII::mayCVLoadMask) &&
- HST.hasV60TOps();
+ Subtarget.hasV60TOps();
}
// Returns true, if a ST insn can be promoted to a new-value store.
@@ -2880,10 +2896,8 @@ bool HexagonInstrInfo::producesStall(const MachineInstr &MI,
MachineBasicBlock::const_instr_iterator MII = BII;
MachineBasicBlock::const_instr_iterator MIE = MII->getParent()->instr_end();
- if (!(*MII).isBundle()) {
- const MachineInstr &J = *MII;
- return producesStall(J, MI);
- }
+ if (!MII->isBundle())
+ return producesStall(*MII, MI);
for (++MII; MII != MIE && MII->isInsideBundle(); ++MII) {
const MachineInstr &J = *MII;
@@ -2926,10 +2940,6 @@ bool HexagonInstrInfo::predOpcodeHasNot(ArrayRef<MachineOperand> Cond) const {
return !isPredicatedTrue(Cond[0].getImm());
}
-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;
@@ -2937,6 +2947,8 @@ unsigned HexagonInstrInfo::getAddrMode(const MachineInstr &MI) const {
// Returns the base register in a memory access (load/store). The offset is
// returned in Offset and the access size is returned in AccessSize.
+// If the base register has a subregister or the offset field does not contain
+// an immediate value, return 0.
unsigned HexagonInstrInfo::getBaseAndOffset(const MachineInstr &MI,
int &Offset, unsigned &AccessSize) const {
// Return if it is not a base+offset type instruction or a MemOp.
@@ -2945,35 +2957,35 @@ unsigned HexagonInstrInfo::getBaseAndOffset(const MachineInstr &MI,
!isMemOp(MI) && !isPostIncrement(MI))
return 0;
- // Since it is a memory access instruction, getMemAccessSize() should never
- // return 0.
- assert (getMemAccessSize(MI) &&
- "BaseImmOffset or BaseLongOffset or MemOp without accessSize");
-
- // Return Values of getMemAccessSize() are
- // 0 - Checked in the assert above.
- // 1, 2, 3, 4 & 7, 8 - The statement below is correct for all these.
- // MemAccessSize is represented as 1+log2(N) where N is size in bits.
- AccessSize = (1U << (getMemAccessSize(MI) - 1));
+ AccessSize = getMemAccessSize(MI);
- unsigned basePos = 0, offsetPos = 0;
- if (!getBaseAndOffsetPosition(MI, basePos, offsetPos))
+ unsigned BasePos = 0, OffsetPos = 0;
+ if (!getBaseAndOffsetPosition(MI, BasePos, OffsetPos))
return 0;
// Post increment updates its EA after the mem access,
// so we need to treat its offset as zero.
- if (isPostIncrement(MI))
+ if (isPostIncrement(MI)) {
Offset = 0;
- else {
- Offset = MI.getOperand(offsetPos).getImm();
+ } else {
+ const MachineOperand &OffsetOp = MI.getOperand(OffsetPos);
+ if (!OffsetOp.isImm())
+ return 0;
+ Offset = OffsetOp.getImm();
}
- return MI.getOperand(basePos).getReg();
+ const MachineOperand &BaseOp = MI.getOperand(BasePos);
+ if (BaseOp.getSubReg() != 0)
+ return 0;
+ return BaseOp.getReg();
}
/// Return the position of the base and offset operands for this instruction.
bool HexagonInstrInfo::getBaseAndOffsetPosition(const MachineInstr &MI,
unsigned &BasePos, unsigned &OffsetPos) const {
+ if (!isAddrModeWithOffset(MI) && !isPostIncrement(MI))
+ return false;
+
// Deal with memops first.
if (isMemOp(MI)) {
BasePos = 0;
@@ -3063,20 +3075,6 @@ SmallVector<MachineInstr*, 2> HexagonInstrInfo::getBranchingInstrs(
return Jumpers;
}
-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;
@@ -3167,7 +3165,6 @@ HexagonII::CompoundGroup HexagonInstrInfo::getCompoundCandidateGroup(
case Hexagon::RESTORE_DEALLOC_RET_JMP_V4:
case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC:
return HexagonII::HCG_C;
- break;
}
return HexagonII::HCG_None;
@@ -3180,15 +3177,24 @@ unsigned HexagonInstrInfo::getCompoundOpcode(const MachineInstr &GA,
assert(getCompoundCandidateGroup(GB) == HexagonII::HCG_B);
if ((GA.getOpcode() != Hexagon::C2_cmpeqi) ||
(GB.getOpcode() != Hexagon::J2_jumptnew))
- return -1;
+ return -1u;
unsigned DestReg = GA.getOperand(0).getReg();
if (!GB.readsRegister(DestReg))
- return -1;
- if (DestReg == Hexagon::P0)
- return Hexagon::J4_cmpeqi_tp0_jump_nt;
- if (DestReg == Hexagon::P1)
- return Hexagon::J4_cmpeqi_tp1_jump_nt;
- return -1;
+ return -1u;
+ if (DestReg != Hexagon::P0 && DestReg != Hexagon::P1)
+ return -1u;
+ // The value compared against must be either u5 or -1.
+ const MachineOperand &CmpOp = GA.getOperand(2);
+ if (!CmpOp.isImm())
+ return -1u;
+ int V = CmpOp.getImm();
+ if (V == -1)
+ return DestReg == Hexagon::P0 ? Hexagon::J4_cmpeqn1_tp0_jump_nt
+ : Hexagon::J4_cmpeqn1_tp1_jump_nt;
+ if (!isUInt<5>(V))
+ return -1u;
+ return DestReg == Hexagon::P0 ? Hexagon::J4_cmpeqi_tp0_jump_nt
+ : Hexagon::J4_cmpeqi_tp1_jump_nt;
}
int HexagonInstrInfo::getCondOpcode(int Opc, bool invertPredicate) const {
@@ -3214,15 +3220,6 @@ int HexagonInstrInfo::getDotCurOp(const MachineInstr &MI) const {
return Hexagon::V6_vL32b_nt_cur_pi;
case Hexagon::V6_vL32b_nt_ai:
return Hexagon::V6_vL32b_nt_cur_ai;
- //128B
- case Hexagon::V6_vL32b_pi_128B:
- return Hexagon::V6_vL32b_cur_pi_128B;
- case Hexagon::V6_vL32b_ai_128B:
- return Hexagon::V6_vL32b_cur_ai_128B;
- case Hexagon::V6_vL32b_nt_pi_128B:
- return Hexagon::V6_vL32b_nt_cur_pi_128B;
- case Hexagon::V6_vL32b_nt_ai_128B:
- return Hexagon::V6_vL32b_nt_cur_ai_128B;
}
return 0;
}
@@ -3239,20 +3236,10 @@ int HexagonInstrInfo::getNonDotCurOp(const MachineInstr &MI) const {
return Hexagon::V6_vL32b_nt_pi;
case Hexagon::V6_vL32b_nt_cur_ai:
return Hexagon::V6_vL32b_nt_ai;
- //128B
- case Hexagon::V6_vL32b_cur_pi_128B:
- return Hexagon::V6_vL32b_pi_128B;
- case Hexagon::V6_vL32b_cur_ai_128B:
- return Hexagon::V6_vL32b_ai_128B;
- case Hexagon::V6_vL32b_nt_cur_pi_128B:
- return Hexagon::V6_vL32b_nt_pi_128B;
- case Hexagon::V6_vL32b_nt_cur_ai_128B:
- return Hexagon::V6_vL32b_nt_ai_128B;
}
return 0;
}
-
// The diagram below shows the steps involved in the conversion of a predicated
// store instruction to its .new predicated new-value form.
//
@@ -3342,8 +3329,8 @@ int HexagonInstrInfo::getDotNewOp(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
default:
- llvm::report_fatal_error(std::string("Unknown .new type: ") +
- std::to_string(MI.getOpcode()).c_str());
+ report_fatal_error(std::string("Unknown .new type: ") +
+ std::to_string(MI.getOpcode()));
case Hexagon::S4_storerb_ur:
return Hexagon::S4_storerbnew_ur;
@@ -3367,13 +3354,6 @@ int HexagonInstrInfo::getDotNewOp(const MachineInstr &MI) const {
case Hexagon::V6_vS32b_pi:
return Hexagon::V6_vS32b_new_pi;
-
- // 128B
- case Hexagon::V6_vS32b_ai_128B:
- return Hexagon::V6_vS32b_new_ai_128B;
-
- case Hexagon::V6_vS32b_pi_128B:
- return Hexagon::V6_vS32b_new_pi_128B;
}
return 0;
}
@@ -3485,15 +3465,13 @@ int HexagonInstrInfo::getDotNewPredOp(const MachineInstr &MI,
}
int HexagonInstrInfo::getDotOldOp(const MachineInstr &MI) const {
- const MachineFunction &MF = *MI.getParent()->getParent();
- const HexagonSubtarget &HST = MF.getSubtarget<HexagonSubtarget>();
int NewOp = MI.getOpcode();
if (isPredicated(NewOp) && isPredicatedNew(NewOp)) { // Get predicate old form
NewOp = Hexagon::getPredOldOpcode(NewOp);
// All Hexagon architectures have prediction bits on dot-new branches,
// but only Hexagon V60+ has prediction bits on dot-old ones. Make sure
// to pick the right opcode when converting back to dot-old.
- if (!HST.getFeatureBits()[Hexagon::ArchV60]) {
+ if (!Subtarget.getFeatureBits()[Hexagon::ArchV60]) {
switch (NewOp) {
case Hexagon::J2_jumptpt:
NewOp = Hexagon::J2_jumpt;
@@ -3518,7 +3496,7 @@ int HexagonInstrInfo::getDotOldOp(const MachineInstr &MI) const {
assert(NewOp >= 0 && "Couldn't change new-value store to its old form.");
}
- if (HST.hasV60TOps())
+ if (Subtarget.hasV60TOps())
return NewOp;
// Subtargets prior to V60 didn't support 'taken' forms of predicated jumps.
@@ -3540,7 +3518,7 @@ int HexagonInstrInfo::getDotOldOp(const MachineInstr &MI) const {
HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup(
const MachineInstr &MI) const {
unsigned DstReg, SrcReg, Src1Reg, Src2Reg;
- auto &HRI = getRegisterInfo();
+ const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
switch (MI.getOpcode()) {
default:
@@ -3625,8 +3603,9 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup(
return HexagonII::HSIG_L2;
case Hexagon::EH_RETURN_JMPR:
case Hexagon::PS_jmpret:
+ case Hexagon::SL2_jumpr31:
// jumpr r31
- // Actual form JMPR %PC<imp-def>, %R31<imp-use>, %R0<imp-use,internal>.
+ // Actual form JMPR implicit-def %pc, implicit %r31, implicit internal %r0
DstReg = MI.getOperand(0).getReg();
if (Hexagon::IntRegsRegClass.contains(DstReg) && (Hexagon::R31 == DstReg))
return HexagonII::HSIG_L2;
@@ -3637,6 +3616,9 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup(
case Hexagon::PS_jmpretfnewpt:
case Hexagon::PS_jmprettnew:
case Hexagon::PS_jmpretfnew:
+ case Hexagon::SL2_jumpr31_t:
+ case Hexagon::SL2_jumpr31_f:
+ case Hexagon::SL2_jumpr31_tnew:
DstReg = MI.getOperand(1).getReg();
SrcReg = MI.getOperand(0).getReg();
// [if ([!]p0[.new])] jumpr r31
@@ -3645,12 +3627,12 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup(
(Hexagon::IntRegsRegClass.contains(DstReg) && (Hexagon::R31 == DstReg)))
return HexagonII::HSIG_L2;
break;
- case Hexagon::L4_return_t :
- case Hexagon::L4_return_f :
- case Hexagon::L4_return_tnew_pnt :
- case Hexagon::L4_return_fnew_pnt :
- case Hexagon::L4_return_tnew_pt :
- case Hexagon::L4_return_fnew_pt :
+ case Hexagon::L4_return_t:
+ case Hexagon::L4_return_f:
+ case Hexagon::L4_return_tnew_pnt:
+ case Hexagon::L4_return_fnew_pnt:
+ case Hexagon::L4_return_tnew_pt:
+ case Hexagon::L4_return_fnew_pt:
// [if ([!]p0[.new])] dealloc_return
SrcReg = MI.getOperand(0).getReg();
if (Hexagon::PredRegsRegClass.contains(SrcReg) && (Hexagon::P0 == SrcReg))
@@ -3730,8 +3712,8 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup(
return HexagonII::HSIG_S2;
break;
case Hexagon::S2_allocframe:
- if (MI.getOperand(0).isImm() &&
- isShiftedUInt<5,3>(MI.getOperand(0).getImm()))
+ if (MI.getOperand(2).isImm() &&
+ isShiftedUInt<5,3>(MI.getOperand(2).getImm()))
return HexagonII::HSIG_S1;
break;
//
@@ -3816,7 +3798,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup(
case Hexagon::C2_cmovenewif:
// if ([!]P0[.new]) Rd = #0
// Actual form:
- // %R16<def> = C2_cmovenewit %P0<internal>, 0, %R16<imp-use,undef>;
+ // %r16 = C2_cmovenewit internal %p0, 0, implicit undef %r16;
DstReg = MI.getOperand(0).getReg();
SrcReg = MI.getOperand(1).getReg();
if (isIntRegForSubInst(DstReg) &&
@@ -3908,14 +3890,15 @@ int HexagonInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
unsigned DefIdx,
const MachineInstr &UseMI,
unsigned UseIdx) const {
- auto &RI = getRegisterInfo();
+ const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
+
// Get DefIdx and UseIdx for super registers.
MachineOperand DefMO = DefMI.getOperand(DefIdx);
- if (RI.isPhysicalRegister(DefMO.getReg())) {
+ if (HRI.isPhysicalRegister(DefMO.getReg())) {
if (DefMO.isImplicit()) {
- for (MCSuperRegIterator SR(DefMO.getReg(), &RI); SR.isValid(); ++SR) {
- int Idx = DefMI.findRegisterDefOperandIdx(*SR, false, false, &RI);
+ for (MCSuperRegIterator SR(DefMO.getReg(), &HRI); SR.isValid(); ++SR) {
+ int Idx = DefMI.findRegisterDefOperandIdx(*SR, false, false, &HRI);
if (Idx != -1) {
DefIdx = Idx;
break;
@@ -3925,8 +3908,8 @@ int HexagonInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
MachineOperand UseMO = UseMI.getOperand(UseIdx);
if (UseMO.isImplicit()) {
- for (MCSuperRegIterator SR(UseMO.getReg(), &RI); SR.isValid(); ++SR) {
- int Idx = UseMI.findRegisterUseOperandIdx(*SR, false, &RI);
+ for (MCSuperRegIterator SR(UseMO.getReg(), &HRI); SR.isValid(); ++SR) {
+ int Idx = UseMI.findRegisterUseOperandIdx(*SR, false, &HRI);
if (Idx != -1) {
UseIdx = Idx;
break;
@@ -3935,8 +3918,14 @@ int HexagonInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
}
}
- return TargetInstrInfo::getOperandLatency(ItinData, DefMI, DefIdx,
- UseMI, UseIdx);
+ int Latency = TargetInstrInfo::getOperandLatency(ItinData, DefMI, DefIdx,
+ UseMI, UseIdx);
+ if (!Latency)
+ // We should never have 0 cycle latency between two instructions unless
+ // they can be packetized together. However, this decision can't be made
+ // here.
+ Latency = 1;
+ return Latency;
}
// inverts the predication logic.
@@ -3975,9 +3964,52 @@ int HexagonInstrInfo::getMaxValue(const MachineInstr &MI) const {
return ~(-1U << bits);
}
+
+bool HexagonInstrInfo::isAddrModeWithOffset(const MachineInstr &MI) const {
+ switch (MI.getOpcode()) {
+ case Hexagon::L2_loadrbgp:
+ case Hexagon::L2_loadrdgp:
+ case Hexagon::L2_loadrhgp:
+ case Hexagon::L2_loadrigp:
+ case Hexagon::L2_loadrubgp:
+ case Hexagon::L2_loadruhgp:
+ case Hexagon::S2_storerbgp:
+ case Hexagon::S2_storerbnewgp:
+ case Hexagon::S2_storerhgp:
+ case Hexagon::S2_storerhnewgp:
+ case Hexagon::S2_storerigp:
+ case Hexagon::S2_storerinewgp:
+ case Hexagon::S2_storerdgp:
+ case Hexagon::S2_storerfgp:
+ return true;
+ }
+ const uint64_t F = MI.getDesc().TSFlags;
+ unsigned addrMode =
+ ((F >> HexagonII::AddrModePos) & HexagonII::AddrModeMask);
+ // Disallow any base+offset instruction. The assembler does not yet reorder
+ // based up any zero offset instruction.
+ return (addrMode == HexagonII::BaseRegOffset ||
+ addrMode == HexagonII::BaseImmOffset ||
+ addrMode == HexagonII::BaseLongOffset);
+}
+
unsigned HexagonInstrInfo::getMemAccessSize(const MachineInstr &MI) const {
+ using namespace HexagonII;
+
const uint64_t F = MI.getDesc().TSFlags;
- return (F >> HexagonII::MemAccessSizePos) & HexagonII::MemAccesSizeMask;
+ unsigned S = (F >> MemAccessSizePos) & MemAccesSizeMask;
+ unsigned Size = getMemAccessSizeInBytes(MemAccessSize(S));
+ if (Size != 0)
+ return Size;
+
+ // Handle vector access sizes.
+ const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
+ switch (S) {
+ case HexagonII::HVXVectorAccess:
+ return HRI.getSpillSize(Hexagon::HvxVRRegClass);
+ default:
+ llvm_unreachable("Unexpected instruction");
+ }
}
// Returns the min value that doesn't need to be extended.
@@ -4005,12 +4037,12 @@ short HexagonInstrInfo::getNonExtOpcode(const MachineInstr &MI) const {
if (MI.getDesc().mayLoad() || MI.getDesc().mayStore()) {
// Check addressing mode and retrieve non-ext equivalent instruction.
switch (getAddrMode(MI)) {
- case HexagonII::Absolute :
- return Hexagon::getBaseWithImmOffset(MI.getOpcode());
- case HexagonII::BaseImmOffset :
- return Hexagon::getBaseWithRegOffset(MI.getOpcode());
+ case HexagonII::Absolute:
+ return Hexagon::changeAddrMode_abs_io(MI.getOpcode());
+ case HexagonII::BaseImmOffset:
+ return Hexagon::changeAddrMode_io_rr(MI.getOpcode());
case HexagonII::BaseLongOffset:
- return Hexagon::getRegShlForm(MI.getOpcode());
+ return Hexagon::changeAddrMode_ur_rr(MI.getOpcode());
default:
return -1;
@@ -4091,8 +4123,7 @@ uint64_t HexagonInstrInfo::getType(const MachineInstr &MI) const {
}
unsigned HexagonInstrInfo::getUnits(const MachineInstr &MI) const {
- const TargetSubtargetInfo &ST = MI.getParent()->getParent()->getSubtarget();
- const InstrItineraryData &II = *ST.getInstrItineraryData();
+ const InstrItineraryData &II = *Subtarget.getInstrItineraryData();
const InstrStage &IS = *II.beginStage(MI.getDesc().getSchedClass());
return IS.getUnits();
@@ -4128,8 +4159,9 @@ void HexagonInstrInfo::immediateExtend(MachineInstr &MI) const {
bool HexagonInstrInfo::invertAndChangeJumpTarget(
MachineInstr &MI, MachineBasicBlock *NewTarget) const {
- DEBUG(dbgs() << "\n[invertAndChangeJumpTarget] to BB#"
- << NewTarget->getNumber(); MI.dump(););
+ DEBUG(dbgs() << "\n[invertAndChangeJumpTarget] to "
+ << printMBBReference(*NewTarget);
+ MI.dump(););
assert(MI.isBranch());
unsigned NewOpcode = getInvertedPredicatedOpcode(MI.getOpcode());
int TargetPos = MI.getNumOperands() - 1;
@@ -4190,6 +4222,51 @@ 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());
+void HexagonInstrInfo::
+setBundleNoShuf(MachineBasicBlock::instr_iterator MIB) const {
+ assert(MIB->isBundle());
+ MachineOperand &Operand = MIB->getOperand(0);
+ if (Operand.isImm())
+ Operand.setImm(Operand.getImm() | memShufDisabledMask);
+ else
+ MIB->addOperand(MachineOperand::CreateImm(memShufDisabledMask));
+}
+
+bool HexagonInstrInfo::getBundleNoShuf(const MachineInstr &MIB) const {
+ assert(MIB.isBundle());
+ const MachineOperand &Operand = MIB.getOperand(0);
+ return (Operand.isImm() && (Operand.getImm() & memShufDisabledMask) != 0);
+}
+
+// Addressing mode relations.
+short HexagonInstrInfo::changeAddrMode_abs_io(short Opc) const {
+ return Opc >= 0 ? Hexagon::changeAddrMode_abs_io(Opc) : Opc;
+}
+
+short HexagonInstrInfo::changeAddrMode_io_abs(short Opc) const {
+ return Opc >= 0 ? Hexagon::changeAddrMode_io_abs(Opc) : Opc;
+}
+
+short HexagonInstrInfo::changeAddrMode_io_pi(short Opc) const {
+ return Opc >= 0 ? Hexagon::changeAddrMode_io_pi(Opc) : Opc;
+}
+
+short HexagonInstrInfo::changeAddrMode_io_rr(short Opc) const {
+ return Opc >= 0 ? Hexagon::changeAddrMode_io_rr(Opc) : Opc;
+}
+
+short HexagonInstrInfo::changeAddrMode_pi_io(short Opc) const {
+ return Opc >= 0 ? Hexagon::changeAddrMode_pi_io(Opc) : Opc;
+}
+
+short HexagonInstrInfo::changeAddrMode_rr_io(short Opc) const {
+ return Opc >= 0 ? Hexagon::changeAddrMode_rr_io(Opc) : Opc;
+}
+
+short HexagonInstrInfo::changeAddrMode_rr_ur(short Opc) const {
+ return Opc >= 0 ? Hexagon::changeAddrMode_rr_ur(Opc) : Opc;
+}
+
+short HexagonInstrInfo::changeAddrMode_ur_rr(short Opc) const {
+ return Opc >= 0 ? Hexagon::changeAddrMode_ur_rr(Opc) : Opc;
}