63 #define DEBUG_TYPE "expand-condsets"
95 HexagonExpandCondsets() :
97 LIS(0), CoaLimitActive(
false),
98 TfrLimitActive(
false), CoaCounter(0), TfrCounter(0) {
106 virtual const char *getPassName()
const {
107 return "Hexagon Expand Condsets";
123 bool CoaLimitActive, TfrLimitActive;
124 unsigned CoaLimit, TfrLimit, CoaCounter, TfrCounter;
128 Sub(Op.getSubReg()) {}
129 RegisterRef(
unsigned R = 0,
unsigned S = 0) :
Reg(R), Sub(S) {}
131 return Reg == RR.Reg && Sub == RR.Sub;
138 enum { Sub_Low = 0x1, Sub_High = 0x2, Sub_None = (Sub_Low | Sub_High) };
139 enum { Exec_Then = 0x10, Exec_Else = 0x20 };
140 unsigned getMaskForSub(
unsigned Sub);
143 void addRefToMap(RegisterRef RR, ReferenceMap &Map,
unsigned Exec);
144 bool isRefInMap(RegisterRef, ReferenceMap &Map,
unsigned Exec);
148 void makeDefined(
unsigned Reg,
SlotIndex S,
bool SetDef);
166 bool canMoveOver(
MachineInstr *
MI, ReferenceMap &Defs, ReferenceMap &Uses);
170 void renameInRange(RegisterRef RO, RegisterRef
RN,
unsigned PredR,
180 bool isIntReg(RegisterRef RR,
unsigned &BW);
182 bool coalesceRegisters(RegisterRef R1, RegisterRef
R2);
190 unsigned HexagonExpandCondsets::getMaskForSub(
unsigned Sub) {
192 case Hexagon::subreg_loreg:
194 case Hexagon::subreg_hireg:
196 case Hexagon::NoSubRegister:
206 case Hexagon::C2_mux:
207 case Hexagon::C2_muxii:
208 case Hexagon::C2_muxir:
209 case Hexagon::C2_muxri:
210 case Hexagon::MUX64_rr:
218 void HexagonExpandCondsets::addRefToMap(RegisterRef RR, ReferenceMap &Map,
220 unsigned Mask = getMaskForSub(RR.Sub) | Exec;
221 ReferenceMap::iterator
F = Map.find(RR.Reg);
223 Map.insert(std::make_pair(RR.Reg, Mask));
229 bool HexagonExpandCondsets::isRefInMap(RegisterRef RR, ReferenceMap &Map,
231 ReferenceMap::iterator F = Map.find(RR.Reg);
234 unsigned Mask = getMaskForSub(RR.Sub) | Exec;
235 if (Mask & F->second)
270 void HexagonExpandCondsets::makeDefined(
unsigned Reg,
SlotIndex S,
275 assert(MI &&
"Expecting instruction");
277 if (!Op.isReg() || !Op.isUse() || Op.getReg() !=
Reg)
279 bool IsDef = !Op.isUndef();
280 if (Op.isImplicit() && IsDef != SetDef)
281 Op.setIsUndef(!SetDef);
286 void HexagonExpandCondsets::makeUndead(
unsigned Reg,
SlotIndex S) {
296 if (!
I->start.isRegister() || !
I->end.isBlock())
306 for (
unsigned i = 0, n = Defs.
size(); i < n; ++i) {
309 if (!Op.isReg() || !Op.isDef() || Op.getReg() !=
Reg)
327 void HexagonExpandCondsets::shrinkToUses(
unsigned Reg,
LiveInterval &LI) {
329 LIS->shrinkToUses(&LI, &Deads);
333 for (
unsigned i = 0, n = Deads.
size(); i < n; ++i) {
337 if (!Op.isReg() || !Op.isDef() || Op.getReg() !=
Reg)
350 T->end = LIS->getMBBEndIdx(MI->
getParent());
352 updateKillFlags(Reg, LI);
358 void HexagonExpandCondsets::updateKillFlags(
unsigned Reg,
LiveInterval &LI) {
359 MRI->clearKillFlags(Reg);
366 if (!Op.isReg() || !Op.isUse() || Op.getReg() !=
Reg)
390 VNInfo *OldVN = LT->valno;
402 if (!
I->start.isBlock() ||
I->valno != OldVN)
407 NewVN = LI.
getNextValue(
I->start, LIS->getVNInfoAllocator());
418 void HexagonExpandCondsets::addInstrToLiveness(
MachineInstr *MI) {
419 SlotIndex MX = LIS->isNotInMIMap(MI) ? LIS->InsertMachineInstrInMaps(MI)
420 : LIS->getInstructionIndex(MI);
421 DEBUG(
dbgs() <<
"adding liveness info for instr\n " << MX <<
" " << *MI);
424 bool Predicated = HII->isPredicated(MI);
430 removeImplicitUses(MI);
437 if (Op.isReg() && Op.isDef())
440 for (
unsigned i = 0, n = Defs.
size(); i < n; ++i) {
441 unsigned DefR = Defs[i].Reg;
444 <<
" with interval\n " << LID <<
"\n");
448 terminateSegment(LT, MX, LID);
449 DEBUG(
dbgs() <<
"after terminating segment\n " << LID <<
"\n");
455 if (N == LID.
end()) {
458 EX = LIS->getMBBEndIdx(MB);
464 EX = N->start.
isBlock() ? N->start.getPrevIndex() : N->start;
485 if (PB != MB && !LIS->isLiveInToMBB(LID, MB))
489 makeUndead(DefR, P->valno->def);
500 makeDefined(DefR, N->start,
true);
504 DEBUG(
dbgs() <<
"added a new segment " << NR <<
"\n " << LID <<
"\n");
505 shrinkToUses(DefR, LID);
506 DEBUG(
dbgs() <<
"updated imp-uses: " << *MI);
514 if (!Op.isReg() || !Op.isUse() || Op.isImplicit() || Op.isUndef())
516 unsigned UseR = Op.getReg();
521 P = prevSegment(LIU, MX);
523 assert(P != LIU.
end() &&
"MI uses undefined register?");
534 if (
MachineInstr *KI = LIS->getInstructionFromIndex(MX))
535 KI->clearRegisterKills(UseR,
nullptr);
536 shrinkToUses(UseR, LIU);
545 void HexagonExpandCondsets::removeInstrFromLiveness(
MachineInstr *MI) {
547 DEBUG(
dbgs() <<
"removing instr\n " << MX <<
" " << *MI);
553 if (!Op.isReg() || !Op.isDef())
555 unsigned DefR = Op.getReg();
558 assert(LT != LID.
end() &&
"Expecting live segments");
560 <<
" with interval\n " << LID <<
"\n");
565 if (LT != LID.
begin()) {
574 if (PB != MB && !LIS->isLiveInToMBB(LID, MB)) {
575 makeDefined(DefR, LT->end,
false);
581 makeUndead(DefR, P->valno->def);
587 while (N != LID.
end()) {
591 if (N->start.isRegister()) {
592 makeDefined(DefR, N->start,
false);
595 if (N->end.isRegister()) {
596 makeDefined(DefR, N->end,
false);
623 LIS->removeInterval(DefR);
631 if (!Op.isReg() || !Op.isUse())
633 unsigned R = Op.getReg();
638 LIS->RemoveMachineInstrFromMaps(MI);
640 for (
unsigned i = 0, n = Uses.
size(); i < n; ++i) {
642 shrinkToUses(Uses[i], LI);
649 unsigned HexagonExpandCondsets::getCondTfrOpcode(
const MachineOperand &SO,
651 using namespace Hexagon;
657 assert(VC->
begin() != VC->
end() &&
"Empty register class");
658 PhysR = *VC->
begin();
663 unsigned PhysS = (RS.Sub == 0) ? PhysR : TRI->getSubReg(PhysR, RS.Sub);
667 return Cond ? A2_tfrt : A2_tfrf;
669 return Cond ? A2_tfrpt : A2_tfrpf;
674 return Cond ? C2_cmoveit : C2_cmoveif;
684 unsigned DstR,
unsigned DstSR,
const MachineOperand &PredOp,
bool Cond) {
696 unsigned Opc = getCondTfrOpcode(SrcOp, Cond);
703 DEBUG(
dbgs() <<
"created an initial copy: " << *TfrI);
711 if (TfrLimitActive) {
712 if (TfrCounter >= TfrLimit)
721 unsigned DR = MD.
getReg(), DSR = MD.getSubReg();
727 addInstrToLiveness(TfrT);
729 addInstrToLiveness(TfrF);
730 removeInstrFromLiveness(MI);
739 bool Changed =
false;
741 for (I = B.
begin(), E = B.
end(); I != E; I = NextI) {
742 NextI = std::next(I);
750 bool HexagonExpandCondsets::isPredicable(
MachineInstr *MI) {
751 if (HII->isPredicated(MI) || !HII->isPredicable(MI))
758 if (!Op.isReg() || !Op.isDef())
765 if (Mo->isVolatile())
774 MachineInstr *HexagonExpandCondsets::getReachingDefForPred(RegisterRef RD,
781 bool PredValid =
true;
787 if (PredValid && HII->isPredicated(MI)) {
788 if (MI->
readsRegister(PredR) && (Cond != HII->isPredicatedTrue(MI)))
795 if (!Op.isReg() || !Op.isDef())
798 if (RR.Reg == PredR) {
802 if (RR.Reg != RD.Reg)
807 if (RR.Sub == RD.Sub)
809 if (RR.Sub == 0 || RD.Sub == 0)
824 bool HexagonExpandCondsets::canMoveOver(
MachineInstr *MI, ReferenceMap &Defs,
825 ReferenceMap &Uses) {
839 if (isRefInMap(RR, Defs, Exec_Then))
842 if (Op.isDef() && isRefInMap(RR, Uses, Exec_Then))
854 if (!IsLoad && !IsStore)
856 if (HII->areMemAccessesTriviallyDisjoint(TheI, ToI))
876 bool Conflict = (L && IsStore) || S;
886 void HexagonExpandCondsets::predicateAt(RegisterRef RD,
MachineInstr *MI,
902 unsigned PredOpc = HII->getCondOpcode(Opc, !Cond);
927 for (
unsigned i = 0; i < NR; ++i)
933 addInstrToLiveness(NewI);
940 void HexagonExpandCondsets::renameInRange(RegisterRef RO, RegisterRef
RN,
948 if (!HII->isPredicated(MI))
950 if (!MI->
readsRegister(PredR) || (Cond != HII->isPredicatedTrue(MI)))
954 if (!Op.isReg() || RO != RegisterRef(Op))
957 Op.setSubReg(RN.Sub);
959 assert(!Op.isDef() &&
"Not expecting a def");
968 bool HexagonExpandCondsets::predicate(
MachineInstr *TfrI,
bool Cond) {
972 assert(Opc == Hexagon::A2_tfrt || Opc == Hexagon::A2_tfrf);
973 DEBUG(
dbgs() <<
"\nattempt to predicate if-" << (Cond ?
"true" :
"false")
986 unsigned PredR = MP.
getReg();
987 MachineInstr *DefI = getReachingDefForPred(RT, TfrI, PredR, Cond);
988 if (!DefI || !isPredicable(DefI))
991 DEBUG(
dbgs() <<
"Source def: " << *DefI);
996 ReferenceMap Uses, Defs;
1002 bool PredValid =
true;
1004 if (!I->modifiesRegister(PredR, 0))
1016 unsigned Exec = Exec_Then | Exec_Else;
1017 if (PredValid && HII->isPredicated(MI) && MI->
readsRegister(PredR))
1018 Exec = (Cond == HII->isPredicatedTrue(MI)) ? Exec_Then : Exec_Else;
1030 RegisterRef RR = Op;
1034 ReferenceMap &Map = Op.isDef() ? Defs : Uses;
1035 addRefToMap(RR, Map, Exec);
1052 if (isRefInMap(RT, Defs, Exec_Then) || isRefInMap(RT, Uses, Exec_Else))
1054 RegisterRef RD = MD;
1061 bool CanUp = canMoveOver(TfrI, Defs, Uses);
1062 bool CanDown = canMoveOver(DefI, Defs, Uses);
1066 if (!canMoveMemTo(DefI, TfrI,
true))
1069 DEBUG(
dbgs() <<
"Can move up: " << (CanUp ?
"yes" :
"no")
1070 <<
", can move down: " << (CanDown ?
"yes\n" :
"no\n"));
1073 predicateAt(RD, DefI, PastDefIt, PredR, Cond);
1075 predicateAt(RD, DefI, TfrIt, PredR, Cond);
1080 renameInRange(RT, RD, PredR, Cond, PastDefIt, TfrIt);
1084 removeInstrFromLiveness(TfrI);
1085 removeInstrFromLiveness(DefI);
1092 bool Changed =
false;
1094 for (I = B.
begin(), E = B.
end(); I != E; I = NextI) {
1095 NextI = std::next(I);
1096 unsigned Opc = I->getOpcode();
1097 if (Opc == Hexagon::A2_tfrt || Opc == Hexagon::A2_tfrf) {
1098 bool Done = predicate(I, (Opc == Hexagon::A2_tfrt));
1102 if (RegisterRef(I->getOperand(0)) == RegisterRef(I->getOperand(2)))
1103 removeInstrFromLiveness(I);
1112 void HexagonExpandCondsets::removeImplicitUses(
MachineInstr *MI) {
1124 if (HII->isPredicated(MI))
1125 removeImplicitUses(MI);
1130 void HexagonExpandCondsets::postprocessUndefImplicitUses(
MachineBasicBlock &B) {
1144 Undefs.insert(MO.
getReg());
1148 if (!Op.isReg() || !Op.isDef() || !Op.getSubReg())
1150 if (Undefs.count(Op.getReg()))
1151 Op.setIsUndef(
true);
1161 if (RC == &Hexagon::IntRegsRegClass) {
1165 if (RC == &Hexagon::DoubleRegsRegClass) {
1166 BW = (RR.Sub != 0) ? 32 : 64;
1173 bool HexagonExpandCondsets::isIntraBlocks(
LiveInterval &LI) {
1187 bool HexagonExpandCondsets::coalesceRegisters(RegisterRef R1, RegisterRef
R2) {
1188 if (CoaLimitActive) {
1189 if (CoaCounter >= CoaLimit)
1196 if (MRI->isLiveIn(R1.Reg))
1198 if (MRI->isLiveIn(R2.Reg))
1205 DEBUG(
dbgs() <<
"compatible registers: ("
1206 << (Overlap ?
"overlap" :
"disjoint") <<
")\n "
1207 <<
PrintReg(R1.Reg, TRI, R1.Sub) <<
" " << L1 <<
"\n "
1208 <<
PrintReg(R2.Reg, TRI, R2.Sub) <<
" " << L2 <<
"\n");
1209 if (R1.Sub || R2.Sub)
1217 if (!isIntraBlocks(L1) && !isIntraBlocks(L2))
1220 MRI->replaceRegWith(R2.Reg, R1.Reg);
1226 VNInfo *NewVN, *OldVN = I->valno;
1227 ValueInfoMap::iterator F = VM.find(OldVN);
1228 if (F == VM.end()) {
1229 NewVN = L1.
getNextValue(I->valno->def, LIS->getVNInfoAllocator());
1230 VM.insert(std::make_pair(OldVN, NewVN));
1239 updateKillFlags(R1.Reg, L1);
1240 DEBUG(
dbgs() <<
"coalesced: " << L1 <<
"\n");
1259 if (!S1.
isReg() && !S2.isReg())
1265 bool Changed =
false;
1266 for (
unsigned i = 0, n = Condsets.
size(); i < n; ++i) {
1291 RegisterRef RS = S1;
1292 MachineInstr *RDef = getReachingDefForPred(RS, CI, RP.Reg,
true);
1294 Done = coalesceRegisters(RD, RegisterRef(S1));
1296 if (!Done && S2.isReg()) {
1297 RegisterRef RS = S2;
1298 MachineInstr *RDef = getReachingDefForPred(RS, CI, RP.Reg,
false);
1300 Done = coalesceRegisters(RD, RegisterRef(S2));
1308 bool HexagonExpandCondsets::runOnMachineFunction(
MachineFunction &MF) {
1311 LIS = &getAnalysis<LiveIntervals>();
1314 bool Changed =
false;
1318 Changed |= coalesceSegments(MF);
1325 Changed |= splitInBlock(*I);
1330 Changed |= predicateInBlock(*I);
1334 postprocessUndefImplicitUses(*I);
1344 const char *
Name =
"Hexagon Expand Condsets";
1346 &HexagonExpandCondsets::ID, 0,
false,
false);
1356 return new HexagonExpandCondsets();
void push_back(const T &Elt)
const MachineFunction * getParent() const
getParent - Return the MachineFunction containing this basic block.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Segments::iterator iterator
int getNumber() const
getNumber - MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a M...
LiveInterval - This class represents the liveness of a register, or stack slot.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
void setIsUndef(bool Val=true)
FunctionPass * createHexagonExpandCondsets()
static bool isVirtualRegister(unsigned Reg)
isVirtualRegister - Return true if the specified register number is in the virtual register namespace...
A global registry used in conjunction with static constructors to make pluggable components (like tar...
bool isPredicable(QueryType Type=AllInBundle) const
Return true if this instruction has a predicate operand that controls execution.
bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
This represents a simple continuous liveness interval for a value.
static std::pair< StringRef, StringRef > split(StringRef Str, char Separator)
Checked version of split, to ensure mandatory subparts.
bool isRegister() const
isRegister - Returns true if this is a normal register use/def slot.
void markUnused()
Mark this value as unused.
iterator_range< mmo_iterator > memoperands()
VNInfo - Value Number Information.
iterator_range< mop_iterator > operands()
static void initializePassOnce(PassRegistry &Registry)
void clearKillInfo()
Clears kill flags on all operands.
unsigned getSize() const
getSize - Return the size of the register in bytes, which is also the size of a stack slot allocated ...
AnalysisUsage & addRequired()
MachineMemOperand - A description of a memory reference used in the backend.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
static MachineOperand CreateReg(unsigned Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false)
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
iterator begin() const
begin/end - Return all of the registers in this class.
Reg
All possible values of the reg field in the ModR/M byte.
bool isBlock() const
isBlock - Returns true if this is a block boundary slot.
unsigned getNumOperands() const
Access to explicit operands of the instruction.
PrintReg - Helper class for printing registers on a raw_ostream.
void RemoveOperand(unsigned i)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
bool isDead() const
isDead - Returns true if this is a dead def kill slot.
iterator addSegment(Segment S)
Add the specified Segment to this range, merging segments as appropriate.
VNInfo * MergeValueNumberInto(VNInfo *V1, VNInfo *V2)
MergeValueNumberInto - This method is called when two value numbers are found to be equivalent...
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
mmo_iterator memoperands_end() const
bundle_iterator< MachineInstr, instr_iterator > iterator
initializer< Ty > init(const Ty &Val)
const MachineInstrBuilder & setMemRefs(MachineInstr::mmo_iterator b, MachineInstr::mmo_iterator e) const
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
const MachineOperand & getOperand(unsigned i) const
bool overlaps(const LiveRange &other) const
overlaps - Return true if the intersection of the two live ranges is not empty.
Represent the analysis usage information of a pass.
static cl::opt< unsigned > OptCoaLimit("expand-condsets-coa-limit", cl::init(~0U), cl::Hidden, cl::desc("Max number of segment coalescings"))
bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore...
FunctionPass class - This class is used to implement most global optimizations.
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
BuildMI - Builder interface.
PassInfo class - An instance of this class exists for every pass known by the system, and can be obtained from a live Pass by calling its getPassInfo() method.
iterator erase(iterator I)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
void removeSegment(SlotIndex Start, SlotIndex End, bool RemoveDeadValNo=false)
Remove the specified segment from this range.
bool readsRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr reads the specified register.
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
static cl::opt< unsigned > OptTfrLimit("expand-condsets-tfr-limit", cl::init(~0U), cl::Hidden, cl::desc("Max number of mux expansions"))
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
SlotIndex getNextIndex() const
Returns the next index.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
bool operator!=(uint64_t V1, const APInt &V2)
Representation of each machine instruction.
static bool isPhysicalRegister(unsigned Reg)
isPhysicalRegister - Return true if the specified register number is in the physical register namespa...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
void setSubReg(unsigned subReg)
void verify(const MachineRegisterInfo *MRI=nullptr) const
Walks the interval and assert if any invariants fail to hold.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def...
unsigned getReg() const
getReg - Returns the register number.
VNInfo * getNextValue(SlotIndex def, VNInfo::Allocator &VNInfoAllocator)
getNextValue - Create a new value number and return it.
virtual const TargetInstrInfo * getInstrInfo() const
#define CALL_ONCE_INITIALIZATION(function)
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
BasicBlockListType::iterator iterator
bool isIntReg(unsigned Reg)
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
iterator FindSegmentContaining(SlotIndex Idx)
Return an iterator to the segment that contains the specified index, or end() if there is none...
bool operator==(uint64_t V1, const APInt &V2)
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
addReg - Add a new virtual register operand...
SlotIndex - An opaque wrapper around machine indexes.
void initializeHexagonExpandCondsetsPass(PassRegistry &)
void registerPass(const PassInfo &PI, bool ShouldFree=false)
registerPass - Register a pass (by means of its PassInfo) with the registry.
MachineInstr::mmo_iterator allocateMemRefsArray(unsigned long Num)
allocateMemRefsArray - Allocate an array to hold MachineMemOperand pointers.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.