mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[Hexagon] Add support for "new" circular buffer intrinsics
These instructions have been around for a long time, but we haven't supported intrinsics for them. The "new" versions use the CSx register for the start of the buffer instead of the K field in the Mx register. We need to use pseudo instructions for these instructions until after register allocation. The problem is that these instructions allocate a M0/CS0 or M1/CS1 pair. But, we can't generate code for the CSx set-up until after register allocation when the Mx register has been fixed for the instruction. There is a related clang patch. Patch by Brendon Cahoon. llvm-svn: 328724
This commit is contained in:
parent
fa00cfc89a
commit
ff0c489bc6
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -248,7 +248,7 @@ unsigned HexagonInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
|
||||
case Hexagon::V6_vL32b_nt_ai:
|
||||
case Hexagon::V6_vL32Ub_ai:
|
||||
case Hexagon::LDriw_pred:
|
||||
case Hexagon::LDriw_mod:
|
||||
case Hexagon::LDriw_ctr:
|
||||
case Hexagon::PS_vloadrq_ai:
|
||||
case Hexagon::PS_vloadrw_ai:
|
||||
case Hexagon::PS_vloadrw_nt_ai: {
|
||||
@ -297,7 +297,7 @@ unsigned HexagonInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
|
||||
case Hexagon::V6_vS32b_ai:
|
||||
case Hexagon::V6_vS32Ub_ai:
|
||||
case Hexagon::STriw_pred:
|
||||
case Hexagon::STriw_mod:
|
||||
case Hexagon::STriw_ctr:
|
||||
case Hexagon::PS_vstorerq_ai:
|
||||
case Hexagon::PS_vstorerw_ai: {
|
||||
const MachineOperand &OpFI = MI.getOperand(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:
|
||||
|
@ -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>;
|
||||
|
294
test/CodeGen/Hexagon/circ_new.ll
Normal file
294
test/CodeGen/Hexagon/circ_new.ll
Normal file
@ -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 }
|
Loading…
Reference in New Issue
Block a user