summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Hexagon
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Hexagon')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp4
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp101
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h1
-rw-r--r--llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp210
-rw-r--r--llvm/lib/Target/Hexagon/HexagonPseudo.td55
5 files changed, 280 insertions, 91 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
index e8c43de8529..f2f4598ba09 100644
--- a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
@@ -1867,11 +1867,11 @@ bool HexagonFrameLowering::expandSpillMacros(MachineFunction &MF,
Changed |= expandCopy(B, I, MRI, HII, NewRegs);
break;
case Hexagon::STriw_pred:
- case Hexagon::STriw_mod:
+ case Hexagon::STriw_ctr:
Changed |= expandStoreInt(B, I, MRI, HII, NewRegs);
break;
case Hexagon::LDriw_pred:
- case Hexagon::LDriw_mod:
+ case Hexagon::LDriw_ctr:
Changed |= expandLoadInt(B, I, MRI, HII, NewRegs);
break;
case Hexagon::PS_vstorerq_ai:
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
index fa992490f5d..a6744d15403 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
@@ -182,7 +182,6 @@ void HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl) {
CurDAG->RemoveDeadNode(LD);
}
-
MachineSDNode *HexagonDAGToDAGISel::LoadInstrForLoadIntrinsic(SDNode *IntN) {
if (IntN->getOpcode() != ISD::INTRINSIC_W_CHAIN)
return nullptr;
@@ -200,15 +199,14 @@ MachineSDNode *HexagonDAGToDAGISel::LoadInstrForLoadIntrinsic(SDNode *IntN) {
};
auto FLC = LoadPciMap.find(IntNo);
if (FLC != LoadPciMap.end()) {
- SDNode *Mod = CurDAG->getMachineNode(Hexagon::A2_tfrrcr, dl, MVT::i32,
- IntN->getOperand(4));
EVT ValTy = (IntNo == Intrinsic::hexagon_circ_ldd) ? MVT::i64 : MVT::i32;
EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
// Operands: { Base, Increment, Modifier, Chain }
auto Inc = cast<ConstantSDNode>(IntN->getOperand(5));
SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), dl, MVT::i32);
MachineSDNode *Res = CurDAG->getMachineNode(FLC->second, dl, RTys,
- { IntN->getOperand(2), I, SDValue(Mod,0), IntN->getOperand(0) });
+ { IntN->getOperand(2), I, IntN->getOperand(4),
+ IntN->getOperand(0) });
return Res;
}
@@ -337,6 +335,93 @@ bool HexagonDAGToDAGISel::tryLoadOfLoadIntrinsic(LoadSDNode *N) {
CurDAG->RemoveDeadNode(C);
return true;
}
+ return false;
+}
+
+/// Generate a machine instruction node for the new circlar buffer intrinsics.
+/// The new versions use a CSx register instead of the K field.
+bool HexagonDAGToDAGISel::SelectNewCircIntrinsic(SDNode *IntN) {
+ if (IntN->getOpcode() != ISD::INTRINSIC_W_CHAIN)
+ return false;
+
+ SDLoc DL(IntN);
+ unsigned IntNo = cast<ConstantSDNode>(IntN->getOperand(1))->getZExtValue();
+ SmallVector<SDValue, 7> Ops;
+
+ static std::map<unsigned,unsigned> LoadNPcMap = {
+ { Intrinsic::hexagon_L2_loadrub_pci, Hexagon::PS_loadrub_pci },
+ { Intrinsic::hexagon_L2_loadrb_pci, Hexagon::PS_loadrb_pci },
+ { Intrinsic::hexagon_L2_loadruh_pci, Hexagon::PS_loadruh_pci },
+ { Intrinsic::hexagon_L2_loadrh_pci, Hexagon::PS_loadrh_pci },
+ { Intrinsic::hexagon_L2_loadri_pci, Hexagon::PS_loadri_pci },
+ { Intrinsic::hexagon_L2_loadrd_pci, Hexagon::PS_loadrd_pci },
+ { Intrinsic::hexagon_L2_loadrub_pcr, Hexagon::PS_loadrub_pcr },
+ { Intrinsic::hexagon_L2_loadrb_pcr, Hexagon::PS_loadrb_pcr },
+ { Intrinsic::hexagon_L2_loadruh_pcr, Hexagon::PS_loadruh_pcr },
+ { Intrinsic::hexagon_L2_loadrh_pcr, Hexagon::PS_loadrh_pcr },
+ { Intrinsic::hexagon_L2_loadri_pcr, Hexagon::PS_loadri_pcr },
+ { Intrinsic::hexagon_L2_loadrd_pcr, Hexagon::PS_loadrd_pcr }
+ };
+ auto FLI = LoadNPcMap.find (IntNo);
+ if (FLI != LoadNPcMap.end()) {
+ EVT ValTy = MVT::i32;
+ if (IntNo == Intrinsic::hexagon_L2_loadrd_pci ||
+ IntNo == Intrinsic::hexagon_L2_loadrd_pcr)
+ ValTy = MVT::i64;
+ EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
+ // Handle load.*_pci case which has 6 operands.
+ if (IntN->getNumOperands() == 6) {
+ auto Inc = cast<ConstantSDNode>(IntN->getOperand(3));
+ SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), DL, MVT::i32);
+ // Operands: { Base, Increment, Modifier, Start, Chain }.
+ Ops = { IntN->getOperand(2), I, IntN->getOperand(4), IntN->getOperand(5),
+ IntN->getOperand(0) };
+ } else
+ // Handle load.*_pcr case which has 5 operands.
+ // Operands: { Base, Modifier, Start, Chain }.
+ Ops = { IntN->getOperand(2), IntN->getOperand(3), IntN->getOperand(4),
+ IntN->getOperand(0) };
+ MachineSDNode *Res = CurDAG->getMachineNode(FLI->second, DL, RTys, Ops);
+ ReplaceUses(SDValue(IntN, 0), SDValue(Res, 0));
+ ReplaceUses(SDValue(IntN, 1), SDValue(Res, 1));
+ ReplaceUses(SDValue(IntN, 2), SDValue(Res, 2));
+ CurDAG->RemoveDeadNode(IntN);
+ return true;
+ }
+
+ static std::map<unsigned,unsigned> StoreNPcMap = {
+ { Intrinsic::hexagon_S2_storerb_pci, Hexagon::PS_storerb_pci },
+ { Intrinsic::hexagon_S2_storerh_pci, Hexagon::PS_storerh_pci },
+ { Intrinsic::hexagon_S2_storerf_pci, Hexagon::PS_storerf_pci },
+ { Intrinsic::hexagon_S2_storeri_pci, Hexagon::PS_storeri_pci },
+ { Intrinsic::hexagon_S2_storerd_pci, Hexagon::PS_storerd_pci },
+ { Intrinsic::hexagon_S2_storerb_pcr, Hexagon::PS_storerb_pcr },
+ { Intrinsic::hexagon_S2_storerh_pcr, Hexagon::PS_storerh_pcr },
+ { Intrinsic::hexagon_S2_storerf_pcr, Hexagon::PS_storerf_pcr },
+ { Intrinsic::hexagon_S2_storeri_pcr, Hexagon::PS_storeri_pcr },
+ { Intrinsic::hexagon_S2_storerd_pcr, Hexagon::PS_storerd_pcr }
+ };
+ auto FSI = StoreNPcMap.find (IntNo);
+ if (FSI != StoreNPcMap.end()) {
+ EVT RTys[] = { MVT::i32, MVT::Other };
+ // Handle store.*_pci case which has 7 operands.
+ if (IntN->getNumOperands() == 7) {
+ auto Inc = cast<ConstantSDNode>(IntN->getOperand(3));
+ SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), DL, MVT::i32);
+ // Operands: { Base, Increment, Modifier, Value, Start, Chain }.
+ Ops = { IntN->getOperand(2), I, IntN->getOperand(4), IntN->getOperand(5),
+ IntN->getOperand(6), IntN->getOperand(0) };
+ } else
+ // Handle store.*_pcr case which has 6 operands.
+ // Operands: { Base, Modifier, Value, Start, Chain }.
+ Ops = { IntN->getOperand(2), IntN->getOperand(3), IntN->getOperand(4),
+ IntN->getOperand(5), IntN->getOperand(0) };
+ MachineSDNode *Res = CurDAG->getMachineNode(FSI->second, DL, RTys, Ops);
+ ReplaceUses(SDValue(IntN, 0), SDValue(Res, 0));
+ ReplaceUses(SDValue(IntN, 1), SDValue(Res, 1));
+ CurDAG->RemoveDeadNode(IntN);
+ return true;
+ }
return false;
}
@@ -344,9 +429,9 @@ bool HexagonDAGToDAGISel::tryLoadOfLoadIntrinsic(LoadSDNode *N) {
void HexagonDAGToDAGISel::SelectLoad(SDNode *N) {
SDLoc dl(N);
LoadSDNode *LD = cast<LoadSDNode>(N);
- ISD::MemIndexedMode AM = LD->getAddressingMode();
// Handle indexed loads.
+ ISD::MemIndexedMode AM = LD->getAddressingMode();
if (AM != ISD::UNINDEXED) {
SelectIndexedLoad(LD, dl);
return;
@@ -452,9 +537,9 @@ void HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl) {
void HexagonDAGToDAGISel::SelectStore(SDNode *N) {
SDLoc dl(N);
StoreSDNode *ST = cast<StoreSDNode>(N);
- ISD::MemIndexedMode AM = ST->getAddressingMode();
// Handle indexed stores.
+ ISD::MemIndexedMode AM = ST->getAddressingMode();
if (AM != ISD::UNINDEXED) {
SelectIndexedStore(ST, dl);
return;
@@ -527,6 +612,9 @@ void HexagonDAGToDAGISel::SelectIntrinsicWChain(SDNode *N) {
return;
}
+ if (SelectNewCircIntrinsic(N))
+ return;
+
unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
if (IntNo == Intrinsic::hexagon_V6_vgathermw ||
IntNo == Intrinsic::hexagon_V6_vgathermw_128B ||
@@ -620,7 +708,6 @@ void HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
SelectCode(N);
}
-
void HexagonDAGToDAGISel::SelectFrameIndex(SDNode *N) {
MachineFrameInfo &MFI = MF->getFrameInfo();
const HexagonFrameLowering *HFI = HST->getFrameLowering();
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
index e031b08f671..776f288ac44 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
@@ -90,6 +90,7 @@ public:
unsigned ConstraintID,
std::vector<SDValue> &OutOps) override;
bool tryLoadOfLoadIntrinsic(LoadSDNode *N);
+ bool SelectNewCircIntrinsic(SDNode *IntN);
void SelectLoad(SDNode *N);
void SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl);
void SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl);
diff --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
index 3e6670ec34f..759e978ffbb 100644
--- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
@@ -240,41 +240,41 @@ static bool isDuplexPairMatch(unsigned Ga, unsigned Gb) {
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::V6_vL32b_ai:
- case Hexagon::V6_vL32b_nt_ai:
- case Hexagon::V6_vL32Ub_ai:
- case Hexagon::LDriw_pred:
- case Hexagon::LDriw_mod:
- case Hexagon::PS_vloadrq_ai:
- case Hexagon::PS_vloadrw_ai:
- case Hexagon::PS_vloadrw_nt_ai: {
- 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();
- }
+ default:
+ break;
+ case Hexagon::L2_loadri_io:
+ case Hexagon::L2_loadrd_io:
+ case Hexagon::V6_vL32b_ai:
+ case Hexagon::V6_vL32b_nt_ai:
+ case Hexagon::V6_vL32Ub_ai:
+ case Hexagon::LDriw_pred:
+ case Hexagon::LDriw_ctr:
+ case Hexagon::PS_vloadrq_ai:
+ case Hexagon::PS_vloadrw_ai:
+ case Hexagon::PS_vloadrw_nt_ai: {
+ 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_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();
- }
+ 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;
@@ -288,45 +288,45 @@ unsigned HexagonInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
unsigned HexagonInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
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::V6_vS32b_ai:
- case Hexagon::V6_vS32Ub_ai:
- case Hexagon::STriw_pred:
- case Hexagon::STriw_mod:
- case Hexagon::PS_vstorerq_ai:
- case Hexagon::PS_vstorerw_ai: {
- 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();
- }
+ default:
+ break;
+ case Hexagon::S2_storerb_io:
+ case Hexagon::S2_storerh_io:
+ case Hexagon::S2_storeri_io:
+ case Hexagon::S2_storerd_io:
+ case Hexagon::V6_vS32b_ai:
+ case Hexagon::V6_vS32Ub_ai:
+ case Hexagon::STriw_pred:
+ case Hexagon::STriw_ctr:
+ case Hexagon::PS_vstorerq_ai:
+ case Hexagon::PS_vstorerw_ai: {
+ 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();
- }
+ 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;
@@ -900,7 +900,7 @@ void HexagonInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
.addFrameIndex(FI).addImm(0)
.addReg(SrcReg, KillFlag).addMemOperand(MMO);
} else if (Hexagon::ModRegsRegClass.hasSubClassEq(RC)) {
- BuildMI(MBB, I, DL, get(Hexagon::STriw_mod))
+ BuildMI(MBB, I, DL, get(Hexagon::STriw_ctr))
.addFrameIndex(FI).addImm(0)
.addReg(SrcReg, KillFlag).addMemOperand(MMO);
} else if (Hexagon::HvxQRRegClass.hasSubClassEq(RC)) {
@@ -962,7 +962,7 @@ void HexagonInstrInfo::loadRegFromStackSlot(
BuildMI(MBB, I, DL, get(Hexagon::LDriw_pred), DestReg)
.addFrameIndex(FI).addImm(0).addMemOperand(MMO);
} else if (Hexagon::ModRegsRegClass.hasSubClassEq(RC)) {
- BuildMI(MBB, I, DL, get(Hexagon::LDriw_mod), DestReg)
+ BuildMI(MBB, I, DL, get(Hexagon::LDriw_ctr), DestReg)
.addFrameIndex(FI).addImm(0).addMemOperand(MMO);
} else if (Hexagon::HvxQRRegClass.hasSubClassEq(RC)) {
BuildMI(MBB, I, DL, get(Hexagon::PS_vloadrq_ai), DestReg)
@@ -1016,6 +1016,20 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
DebugLoc DL = MI.getDebugLoc();
unsigned Opc = MI.getOpcode();
+ auto RealCirc = [&](unsigned Opc, bool HasImm = true, unsigned MxOp = 4) {
+ unsigned Mx = MI.getOperand(MxOp).getReg();
+ unsigned CSx = (Mx == Hexagon::M0 ? Hexagon::CS0 : Hexagon::CS1);
+ BuildMI(MBB, MI, DL, get(Hexagon::A2_tfrrcr), CSx)
+ .add(MI.getOperand((HasImm ? 5 : 4)));
+ auto MIB = BuildMI(MBB, MI, DL, get(Opc)).add(MI.getOperand(0))
+ .add(MI.getOperand(1)).add(MI.getOperand(2)).add(MI.getOperand(3));
+ if (HasImm)
+ MIB.add(MI.getOperand(4));
+ MIB.addReg(CSx, RegState::Implicit);
+ MBB.erase(MI);
+ return true;
+ };
+
switch (Opc) {
case TargetOpcode::COPY: {
MachineOperand &MD = MI.getOperand(0);
@@ -1394,6 +1408,50 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
MBB.erase(MI);
return true;
+ case Hexagon::PS_loadrub_pci:
+ return RealCirc(Hexagon::L2_loadrub_pci);
+ case Hexagon::PS_loadrb_pci:
+ return RealCirc(Hexagon::L2_loadrb_pci);
+ case Hexagon::PS_loadruh_pci:
+ return RealCirc(Hexagon::L2_loadruh_pci);
+ case Hexagon::PS_loadrh_pci:
+ return RealCirc(Hexagon::L2_loadrh_pci);
+ case Hexagon::PS_loadri_pci:
+ return RealCirc(Hexagon::L2_loadri_pci);
+ case Hexagon::PS_loadrd_pci:
+ return RealCirc(Hexagon::L2_loadrd_pci);
+ case Hexagon::PS_loadrub_pcr:
+ return RealCirc(Hexagon::L2_loadrub_pcr, /*HasImm=*/false, /*MxOp=*/3);
+ case Hexagon::PS_loadrb_pcr:
+ return RealCirc(Hexagon::L2_loadrb_pcr, /*HasImm=*/false, /*MxOp=*/3);
+ case Hexagon::PS_loadruh_pcr:
+ return RealCirc(Hexagon::L2_loadruh_pcr, /*HasImm=*/false, /*MxOp=*/3);
+ case Hexagon::PS_loadrh_pcr:
+ return RealCirc(Hexagon::L2_loadrh_pcr, /*HasImm=*/false, /*MxOp=*/3);
+ case Hexagon::PS_loadri_pcr:
+ return RealCirc(Hexagon::L2_loadri_pcr, /*HasImm=*/false, /*MxOp=*/3);
+ case Hexagon::PS_loadrd_pcr:
+ return RealCirc(Hexagon::L2_loadrd_pcr, /*HasImm=*/false, /*MxOp=*/3);
+ case Hexagon::PS_storerb_pci:
+ return RealCirc(Hexagon::S2_storerb_pci, /*HasImm=*/true, /*MxOp=*/3);
+ case Hexagon::PS_storerh_pci:
+ return RealCirc(Hexagon::S2_storerh_pci, /*HasImm=*/true, /*MxOp=*/3);
+ case Hexagon::PS_storerf_pci:
+ return RealCirc(Hexagon::S2_storerf_pci, /*HasImm=*/true, /*MxOp=*/3);
+ case Hexagon::PS_storeri_pci:
+ return RealCirc(Hexagon::S2_storeri_pci, /*HasImm=*/true, /*MxOp=*/3);
+ case Hexagon::PS_storerd_pci:
+ return RealCirc(Hexagon::S2_storerd_pci, /*HasImm=*/true, /*MxOp=*/3);
+ case Hexagon::PS_storerb_pcr:
+ return RealCirc(Hexagon::S2_storerb_pcr, /*HasImm=*/false, /*MxOp=*/2);
+ case Hexagon::PS_storerh_pcr:
+ return RealCirc(Hexagon::S2_storerh_pcr, /*HasImm=*/false, /*MxOp=*/2);
+ case Hexagon::PS_storerf_pcr:
+ return RealCirc(Hexagon::S2_storerf_pcr, /*HasImm=*/false, /*MxOp=*/2);
+ case Hexagon::PS_storeri_pcr:
+ return RealCirc(Hexagon::S2_storeri_pcr, /*HasImm=*/false, /*MxOp=*/2);
+ case Hexagon::PS_storerd_pcr:
+ return RealCirc(Hexagon::S2_storerd_pcr, /*HasImm=*/false, /*MxOp=*/2);
}
return false;
@@ -2658,8 +2716,8 @@ bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
// 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:
+ case Hexagon::STriw_ctr:
+ case Hexagon::LDriw_ctr:
return true;
case Hexagon::PS_fi:
diff --git a/llvm/lib/Target/Hexagon/HexagonPseudo.td b/llvm/lib/Target/Hexagon/HexagonPseudo.td
index 37610bc6445..b6c837ee807 100644
--- a/llvm/lib/Target/Hexagon/HexagonPseudo.td
+++ b/llvm/lib/Target/Hexagon/HexagonPseudo.td
@@ -24,7 +24,7 @@ let PrintMethod = "printGlobalOperand" in {
let isPseudo = 1 in {
let isCodeGenOnly = 0 in
def A2_iconst : Pseudo<(outs IntRegs:$Rd32),
- (ins s27_2Imm:$Ii), "${Rd32}=iconst(#${Ii})">;
+ (ins s27_2Imm:$Ii), "${Rd32} = iconst(#${Ii})">;
def DUPLEX_Pseudo : InstHexagon<(outs),
(ins s32_0Imm:$offset), "DUPLEX", [], "", DUPLEX, TypePSEUDO>;
@@ -34,7 +34,7 @@ let isExtendable = 1, opExtendable = 1, opExtentBits = 6,
isAsmParserOnly = 1 in
def TFRI64_V2_ext : InstHexagon<(outs DoubleRegs:$dst),
(ins s32_0Imm:$src1, s8_0Imm:$src2),
- "$dst=combine(#$src1,#$src2)", [], "",
+ "$dst = combine(#$src1,#$src2)", [], "",
A2_combineii.Itinerary, TypeALU32_2op>, OpcodeHexagon;
// HI/LO Instructions
@@ -44,7 +44,7 @@ class REG_IMMED<string RegHalf, bit Rs, bits<3> MajOp, bit MinOp,
InstHexagon rootInst>
: InstHexagon<(outs IntRegs:$dst),
(ins u16_0Imm:$imm_value),
- "$dst"#RegHalf#"=#$imm_value", [], "",
+ "$dst"#RegHalf#" = #$imm_value", [], "",
rootInst.Itinerary, rootInst.Type>, OpcodeHexagon {
bits<5> dst;
bits<32> imm_value;
@@ -316,7 +316,7 @@ def LDriw_pred : LDInst<(outs PredRegs:$dst),
// Load modifier.
let isExtendable = 1, opExtendable = 2, isExtentSigned = 1, opExtentBits = 13,
isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
-def LDriw_mod : LDInst<(outs ModRegs:$dst),
+def LDriw_ctr : LDInst<(outs CtrRegs:$dst),
(ins IntRegs:$addr, s32_0Imm:$off),
".error \"should not emit\"", []>;
@@ -465,8 +465,8 @@ def STriw_pred : STInst<(outs),
// Store modifier.
let isExtendable = 1, opExtendable = 1, isExtentSigned = 1, opExtentBits = 13,
isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 0 in
-def STriw_mod : STInst<(outs),
- (ins IntRegs:$addr, s32_0Imm:$off, ModRegs:$src1),
+def STriw_ctr : STInst<(outs),
+ (ins IntRegs:$addr, s32_0Imm:$off, CtrRegs:$src1),
".error \"should not emit\"", []>;
let isExtendable = 1, opExtendable = 1, opExtentBits = 6,
@@ -507,3 +507,46 @@ def DuplexIClassC: InstDuplex < 0xC >;
def DuplexIClassD: InstDuplex < 0xD >;
def DuplexIClassE: InstDuplex < 0xE >;
def DuplexIClassF: InstDuplex < 0xF >;
+
+// Pseudos for circular buffer instructions. These are needed in order to
+// allocate the correct pair of CSx and Mx registers.
+multiclass NewCircularLoad<RegisterClass RC, MemAccessSize MS> {
+
+let isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS],
+ addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in {
+ def NAME#_pci : LDInst<(outs RC:$Rd32, IntRegs:$Rx32),
+ (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, IntRegs:$Cs),
+ ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_4403ca65>;
+
+ def NAME#_pcr : LDInst<(outs RC:$Rd32, IntRegs:$Rx32),
+ (ins IntRegs:$Rx32in, ModRegs:$Mu2, IntRegs:$Cs),
+ ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_2fc0c436>;
+}
+}
+
+defm PS_loadrub : NewCircularLoad<IntRegs, ByteAccess>;
+defm PS_loadrb : NewCircularLoad<IntRegs, ByteAccess>;
+defm PS_loadruh : NewCircularLoad<IntRegs, HalfWordAccess>;
+defm PS_loadrh : NewCircularLoad<IntRegs, HalfWordAccess>;
+defm PS_loadri : NewCircularLoad<IntRegs, WordAccess>;
+defm PS_loadrd : NewCircularLoad<DoubleRegs, DoubleWordAccess>;
+
+multiclass NewCircularStore<RegisterClass RC, MemAccessSize MS> {
+
+let isCodeGenOnly = 1, isPseudo = 1, Defs = [CS], Uses = [CS],
+ addrMode = PostInc, accessSize = MS, hasSideEffects = 0 in {
+ def NAME#_pci : STInst<(outs IntRegs:$Rx32),
+ (ins IntRegs:$Rx32in, s4_0Imm:$Ii, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs),
+ ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_9fdb5406>;
+
+ def NAME#_pcr : STInst<(outs IntRegs:$Rx32),
+ (ins IntRegs:$Rx32in, ModRegs:$Mu2, RC:$Rt32, IntRegs:$Cs),
+ ".error \"should not emit\" ", [], "$Rx32 = $Rx32in", tc_f86c328a>;
+}
+}
+
+defm PS_storerb : NewCircularStore<IntRegs, ByteAccess>;
+defm PS_storerh : NewCircularStore<IntRegs, HalfWordAccess>;
+defm PS_storerf : NewCircularStore<IntRegs, HalfWordAccess>;
+defm PS_storeri : NewCircularStore<IntRegs, WordAccess>;
+defm PS_storerd : NewCircularStore<DoubleRegs, WordAccess>;
OpenPOWER on IntegriCloud