diff options
-rw-r--r-- | llvm/include/llvm/IR/IntrinsicsHexagon.td | 40 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp | 101 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h | 1 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp | 210 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonPseudo.td | 55 | ||||
-rw-r--r-- | llvm/test/CodeGen/Hexagon/circ_new.ll | 294 |
7 files changed, 614 insertions, 91 deletions
diff --git a/llvm/include/llvm/IR/IntrinsicsHexagon.td b/llvm/include/llvm/IR/IntrinsicsHexagon.td index 5c96702bca7..59403c853ee 100644 --- a/llvm/include/llvm/IR/IntrinsicsHexagon.td +++ b/llvm/include/llvm/IR/IntrinsicsHexagon.td @@ -21,6 +21,13 @@ let TargetPrefix = "hexagon" in { list<IntrinsicProperty> properties> : GCCBuiltin<!strconcat("__builtin_", GCCIntSuffix)>, Intrinsic<ret_types, param_types, properties>; + + /// Hexagon_NonGCC_Intrinsic - Base class for bitcode convertible Hexagon + /// intrinsics. + class Hexagon_NonGCC_Intrinsic<list<LLVMType> ret_types, + list<LLVMType> param_types, + list<IntrinsicProperty> properties> + : Intrinsic<ret_types, param_types, properties>; } //===----------------------------------------------------------------------===// @@ -9300,6 +9307,39 @@ Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstorentq_128B">; def int_hexagon_V6_vmaskedstorentnq_128B : Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstorentnq_128B">; +multiclass Hexagon_custom_circ_ld_Intrinsic<LLVMType ElTy> { + def NAME#_pci : Hexagon_NonGCC_Intrinsic< + [ElTy, llvm_ptr_ty], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], + [IntrArgMemOnly, NoCapture<3>]>; + def NAME#_pcr : Hexagon_NonGCC_Intrinsic< + [ElTy, llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_ptr_ty], + [IntrArgMemOnly, NoCapture<2>]>; +} + +defm int_hexagon_L2_loadrub : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>; +defm int_hexagon_L2_loadrb : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>; +defm int_hexagon_L2_loadruh : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>; +defm int_hexagon_L2_loadrh : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>; +defm int_hexagon_L2_loadri : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>; +defm int_hexagon_L2_loadrd : Hexagon_custom_circ_ld_Intrinsic<llvm_i64_ty>; + +multiclass Hexagon_custom_circ_st_Intrinsic<LLVMType ElTy> { + def NAME#_pci : Hexagon_NonGCC_Intrinsic< + [llvm_ptr_ty], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, ElTy, llvm_ptr_ty], + [IntrArgMemOnly, NoCapture<4>]>; + def NAME#_pcr : Hexagon_NonGCC_Intrinsic< + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, ElTy, llvm_ptr_ty], + [IntrArgMemOnly, NoCapture<3>]>; +} + +defm int_hexagon_S2_storerb : Hexagon_custom_circ_st_Intrinsic<llvm_i32_ty>; +defm int_hexagon_S2_storerh : Hexagon_custom_circ_st_Intrinsic<llvm_i32_ty>; +defm int_hexagon_S2_storerf : Hexagon_custom_circ_st_Intrinsic<llvm_i32_ty>; +defm int_hexagon_S2_storeri : Hexagon_custom_circ_st_Intrinsic<llvm_i32_ty>; +defm int_hexagon_S2_storerd : Hexagon_custom_circ_st_Intrinsic<llvm_i64_ty>; + /// /// HexagonV62 intrinsics 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>; diff --git a/llvm/test/CodeGen/Hexagon/circ_new.ll b/llvm/test/CodeGen/Hexagon/circ_new.ll new file mode 100644 index 00000000000..cf41f27d388 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/circ_new.ll @@ -0,0 +1,294 @@ +; RUN: llc -march=hexagon < %s | FileCheck %s + +; CHECK-LABEL: test1 +; CHECK: m[[REG1:([0-1])]] = r0 +; CHECK: cs[[REG1]] = r1 +; CHECK: = memub(r1++#4:circ(m[[REG1]]) +define zeroext i8 @test1(i32 %mod, i8* %start) local_unnamed_addr #0 { +entry: + %0 = tail call { i32, i8* } @llvm.hexagon.L2.loadrub.pci(i8* %start, i32 4, i32 %mod, i8* %start) + %1 = extractvalue { i32, i8* } %0, 0 + %conv = trunc i32 %1 to i8 + ret i8 %conv +} + +declare { i32, i8* } @llvm.hexagon.L2.loadrub.pci(i8*, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test2 +; CHECK: m[[REG2:([0-1])]] = r0 +; CHECK: cs[[REG2]] = r1 +; CHECK: = memb(r1++#4:circ(m[[REG2]]) +define zeroext i8 @test2(i32 %mod, i8* %start) local_unnamed_addr #0 { +entry: + %0 = tail call { i32, i8* } @llvm.hexagon.L2.loadrb.pci(i8* %start, i32 4, i32 %mod, i8* %start) + %1 = extractvalue { i32, i8* } %0, 0 + %conv = trunc i32 %1 to i8 + ret i8 %conv +} + +declare { i32, i8* } @llvm.hexagon.L2.loadrb.pci(i8*, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test3 +; CHECK: m[[REG3:([0-1])]] = r0 +; CHECK: cs[[REG3]] = r1 +; CHECK: = memuh(r1++#4:circ(m[[REG3]]) +define zeroext i16 @test3(i32 %mod, i8* %start) local_unnamed_addr #0 { +entry: + %0 = tail call { i32, i8* } @llvm.hexagon.L2.loadruh.pci(i8* %start, i32 4, i32 %mod, i8* %start) + %1 = extractvalue { i32, i8* } %0, 0 + %conv = trunc i32 %1 to i16 + ret i16 %conv +} + +declare { i32, i8* } @llvm.hexagon.L2.loadruh.pci(i8*, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test4 +; CHECK: m[[REG4:([0-1])]] = r0 +; CHECK: cs[[REG4]] = r1 +; CHECK: = memh(r1++#4:circ(m[[REG4]]) +define signext i16 @test4(i32 %mod, i8* %start) local_unnamed_addr #0 { +entry: + %0 = tail call { i32, i8* } @llvm.hexagon.L2.loadrh.pci(i8* %start, i32 4, i32 %mod, i8* %start) + %1 = extractvalue { i32, i8* } %0, 0 + %conv = trunc i32 %1 to i16 + ret i16 %conv +} + +declare { i32, i8* } @llvm.hexagon.L2.loadrh.pci(i8*, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test5 +; CHECK: m[[REG5:([0-1])]] = r0 +; CHECK: cs[[REG5]] = r1 +; CHECK: = memw(r1++#4:circ(m[[REG5]]) +define i32 @test5(i32 %mod, i8* %start) local_unnamed_addr #0 { +entry: + %0 = tail call { i32, i8* } @llvm.hexagon.L2.loadri.pci(i8* %start, i32 4, i32 %mod, i8* %start) + %1 = extractvalue { i32, i8* } %0, 0 + ret i32 %1 +} + +declare { i32, i8* } @llvm.hexagon.L2.loadri.pci(i8*, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test6 +; CHECK: m[[REG6:([0-1])]] = r0 +; CHECK: cs[[REG6]] = r1 +; CHECK: = memd(r1++#8:circ(m[[REG6]]) +define i64 @test6(i32 %mod, i8* %start) local_unnamed_addr #0 { +entry: + %0 = tail call { i64, i8* } @llvm.hexagon.L2.loadrd.pci(i8* %start, i32 8, i32 %mod, i8* %start) + %1 = extractvalue { i64, i8* } %0, 0 + ret i64 %1 +} + +declare { i64, i8* } @llvm.hexagon.L2.loadrd.pci(i8*, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test7 +; CHECK: m[[REG7:([0-1])]] = r0 +; CHECK: cs[[REG7]] = r1 +; CHECK: = memub(r1++I:circ(m[[REG7]]) +define zeroext i8 @test7(i32 %mod, i8* %start) local_unnamed_addr #0 { +entry: + %0 = tail call { i32, i8* } @llvm.hexagon.L2.loadrub.pcr(i8* %start, i32 %mod, i8* %start) + %1 = extractvalue { i32, i8* } %0, 0 + %conv = trunc i32 %1 to i8 + ret i8 %conv +} + +declare { i32, i8* } @llvm.hexagon.L2.loadrub.pcr(i8*, i32, i8* nocapture) #1 + +; CHECK-LABEL: test8 +; CHECK: m[[REG8:([0-1])]] = r0 +; CHECK: cs[[REG8]] = r1 +; CHECK: = memb(r1++I:circ(m[[REG8]]) +define zeroext i8 @test8(i32 %mod, i8* %start) local_unnamed_addr #0 { +entry: + %0 = tail call { i32, i8* } @llvm.hexagon.L2.loadrb.pcr(i8* %start, i32 %mod, i8* %start) + %1 = extractvalue { i32, i8* } %0, 0 + %conv = trunc i32 %1 to i8 + ret i8 %conv +} + +declare { i32, i8* } @llvm.hexagon.L2.loadrb.pcr(i8*, i32, i8* nocapture) #1 + +; CHECK-LABEL: test9 +; CHECK: m[[REG9:([0-1])]] = r0 +; CHECK: cs[[REG9]] = r1 +; CHECK: = memuh(r1++I:circ(m[[REG9]]) +define zeroext i16 @test9(i32 %mod, i8* %start) local_unnamed_addr #0 { +entry: + %0 = tail call { i32, i8* } @llvm.hexagon.L2.loadruh.pcr(i8* %start, i32 %mod, i8* %start) + %1 = extractvalue { i32, i8* } %0, 0 + %conv = trunc i32 %1 to i16 + ret i16 %conv +} + +declare { i32, i8* } @llvm.hexagon.L2.loadruh.pcr(i8*, i32, i8* nocapture) #1 + +; CHECK-LABEL: test10 +; CHECK: m[[REG10:([0-1])]] = r0 +; CHECK: cs[[REG10]] = r1 +; CHECK: = memh(r1++I:circ(m[[REG10]]) +define signext i16 @test10(i32 %mod, i8* %start) local_unnamed_addr #0 { +entry: + %0 = tail call { i32, i8* } @llvm.hexagon.L2.loadrh.pcr(i8* %start, i32 %mod, i8* %start) + %1 = extractvalue { i32, i8* } %0, 0 + %conv = trunc i32 %1 to i16 + ret i16 %conv +} + +declare { i32, i8* } @llvm.hexagon.L2.loadrh.pcr(i8*, i32, i8* nocapture) #1 + +; CHECK-LABEL: test11 +; CHECK: m[[REG11:([0-1])]] = r0 +; CHECK: cs[[REG11]] = r1 +; CHECK: = memw(r1++I:circ(m[[REG11]]) +define i32 @test11(i32 %mod, i8* %start) local_unnamed_addr #0 { +entry: + %0 = tail call { i32, i8* } @llvm.hexagon.L2.loadri.pcr(i8* %start, i32 %mod, i8* %start) + %1 = extractvalue { i32, i8* } %0, 0 + ret i32 %1 +} + +declare { i32, i8* } @llvm.hexagon.L2.loadri.pcr(i8*, i32, i8* nocapture) #1 + +; CHECK-LABEL: test12 +; CHECK: m[[REG12:([0-1])]] = r0 +; CHECK: cs[[REG12]] = r1 +; CHECK: = memd(r1++I:circ(m[[REG12]]) +define i64 @test12(i32 %mod, i8* %start) local_unnamed_addr #0 { +entry: + %0 = tail call { i64, i8* } @llvm.hexagon.L2.loadrd.pcr(i8* %start, i32 %mod, i8* %start) + %1 = extractvalue { i64, i8* } %0, 0 + ret i64 %1 +} + +declare { i64, i8* } @llvm.hexagon.L2.loadrd.pcr(i8*, i32, i8* nocapture) #1 + +; CHECK-LABEL: test13 +; CHECK: m[[REG13:([0-1])]] = r0 +; CHECK: cs[[REG13]] = r1 +; CHECK: memb(r1++#4:circ(m[[REG13]])) = +define void @test13(i32 %mod, i8* %start, i8 zeroext %v) local_unnamed_addr #0 { +entry: + %conv = zext i8 %v to i32 + %0 = tail call i8* @llvm.hexagon.S2.storerb.pci(i8* %start, i32 4, i32 %mod, i32 %conv, i8* %start) + ret void +} + +declare i8* @llvm.hexagon.S2.storerb.pci(i8*, i32, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test14 +; CHECK: m[[REG14:([0-1])]] = r0 +; CHECK: cs[[REG14]] = r1 +; CHECK: memh(r1++#4:circ(m[[REG14]])) = +define void @test14(i32 %mod, i8* %start, i16 signext %v) local_unnamed_addr #0 { +entry: + %conv = sext i16 %v to i32 + %0 = tail call i8* @llvm.hexagon.S2.storerh.pci(i8* %start, i32 4, i32 %mod, i32 %conv, i8* %start) + ret void +} + +declare i8* @llvm.hexagon.S2.storerh.pci(i8*, i32, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test15 +; CHECK: m[[REG15:([0-1])]] = r0 +; CHECK: cs[[REG15]] = r1 +; CHECK: memh(r1++#4:circ(m[[REG15]])) = r{{[0-9]+}}.h +define void @test15(i32 %mod, i8* %start, i16 signext %v) local_unnamed_addr #0 { +entry: + %conv = sext i16 %v to i32 + %0 = tail call i8* @llvm.hexagon.S2.storerf.pci(i8* %start, i32 4, i32 %mod, i32 %conv, i8* %start) + ret void +} + +declare i8* @llvm.hexagon.S2.storerf.pci(i8*, i32, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test16 +; CHECK: m[[REG16:([0-1])]] = r0 +; CHECK: cs[[REG16]] = r1 +; CHECK: memw(r1++#4:circ(m[[REG16]])) = +define void @test16(i32 %mod, i8* %start, i32 %v) local_unnamed_addr #0 { +entry: + %0 = tail call i8* @llvm.hexagon.S2.storeri.pci(i8* %start, i32 4, i32 %mod, i32 %v, i8* %start) + ret void +} + +declare i8* @llvm.hexagon.S2.storeri.pci(i8*, i32, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test17 +; CHECK: m[[REG17:([0-1])]] = r0 +; CHECK: cs[[REG17]] = r1 +; CHECK: memd(r1++#8:circ(m[[REG17]])) = +define void @test17(i32 %mod, i8* %start, i64 %v) local_unnamed_addr #0 { +entry: + %0 = tail call i8* @llvm.hexagon.S2.storerd.pci(i8* %start, i32 8, i32 %mod, i64 %v, i8* %start) + ret void +} + +declare i8* @llvm.hexagon.S2.storerd.pci(i8*, i32, i32, i64, i8* nocapture) #1 + +; CHECK-LABEL: test18 +; CHECK: m[[REG18:([0-1])]] = r0 +; CHECK: cs[[REG18]] = r1 +; CHECK: memb(r1++I:circ(m[[REG18]])) = +define void @test18(i32 %mod, i8* %start, i8 zeroext %v) local_unnamed_addr #0 { +entry: + %conv = zext i8 %v to i32 + %0 = tail call i8* @llvm.hexagon.S2.storerb.pcr(i8* %start, i32 %mod, i32 %conv, i8* %start) + ret void +} + +declare i8* @llvm.hexagon.S2.storerb.pcr(i8*, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test19 +; CHECK: m[[REG19:([0-1])]] = r0 +; CHECK: cs[[REG19]] = r1 +; CHECK: memh(r1++I:circ(m[[REG19]])) = +define void @test19(i32 %mod, i8* %start, i16 signext %v) local_unnamed_addr #0 { +entry: + %conv = sext i16 %v to i32 + %0 = tail call i8* @llvm.hexagon.S2.storerh.pcr(i8* %start, i32 %mod, i32 %conv, i8* %start) + ret void +} + +declare i8* @llvm.hexagon.S2.storerh.pcr(i8*, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test20 +; CHECK: m[[REG20:([0-1])]] = r0 +; CHECK: cs[[REG20]] = r1 +; CHECK: memh(r1++I:circ(m[[REG20]])) = r{{[0-9]+}}.h +define void @test20(i32 %mod, i8* %start, i16 signext %v) local_unnamed_addr #0 { +entry: + %conv = sext i16 %v to i32 + %0 = tail call i8* @llvm.hexagon.S2.storerf.pcr(i8* %start, i32 %mod, i32 %conv, i8* %start) + ret void +} + +declare i8* @llvm.hexagon.S2.storerf.pcr(i8*, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test21 +; CHECK: m[[REG21:([0-1])]] = r0 +; CHECK: cs[[REG21]] = r1 +; CHECK: memw(r1++I:circ(m[[REG21]])) = +define void @test21(i32 %mod, i8* %start, i32 %v) local_unnamed_addr #0 { +entry: + %0 = tail call i8* @llvm.hexagon.S2.storeri.pcr(i8* %start, i32 %mod, i32 %v, i8* %start) + ret void +} + +declare i8* @llvm.hexagon.S2.storeri.pcr(i8*, i32, i32, i8* nocapture) #1 + +; CHECK-LABEL: test22 +; CHECK: m[[REG22:([0-1])]] = r0 +; CHECK: cs[[REG22]] = r1 +; CHECK: memd(r1++I:circ(m[[REG1]])) = +define void @test22(i32 %mod, i8* %start, i64 %v) local_unnamed_addr #0 { +entry: + %0 = tail call i8* @llvm.hexagon.S2.storerd.pcr(i8* %start, i32 %mod, i64 %v, i8* %start) + ret void +} + +declare i8* @llvm.hexagon.S2.storerd.pcr(i8*, i32, i64, i8* nocapture) #1 + +attributes #0 = { nounwind "target-cpu"="hexagonv60" } +attributes #1 = { argmemonly nounwind } |