+void MachineInstr::bundleWithPred() {
+ assert(!isBundledWithPred() && "MI is already bundled with its predecessor");
+ setFlag(BundledPred);
+ MachineBasicBlock::instr_iterator Pred = this;
+ --Pred;
+ assert(!Pred->isBundledWithSucc() && "Inconsistent bundle flags");
+ Pred->setFlag(BundledSucc);
+}
+
+void MachineInstr::bundleWithSucc() {
+ assert(!isBundledWithSucc() && "MI is already bundled with its successor");
+ setFlag(BundledSucc);
+ MachineBasicBlock::instr_iterator Succ = this;
+ ++Succ;
+ assert(!Succ->isBundledWithPred() && "Inconsistent bundle flags");
+ Succ->setFlag(BundledPred);
+}
+
+void MachineInstr::unbundleFromPred() {
+ assert(isBundledWithPred() && "MI isn't bundled with its predecessor");
+ clearFlag(BundledPred);
+ MachineBasicBlock::instr_iterator Pred = this;
+ --Pred;
+ assert(Pred->isBundledWithSucc() && "Inconsistent bundle flags");
+ Pred->clearFlag(BundledSucc);
+}
+
+void MachineInstr::unbundleFromSucc() {
+ assert(isBundledWithSucc() && "MI isn't bundled with its successor");
+ clearFlag(BundledSucc);
+ MachineBasicBlock::instr_iterator Succ = this;
+ ++Succ;
+ assert(Succ->isBundledWithPred() && "Inconsistent bundle flags");
+ Succ->clearFlag(BundledPred);
+}
+
+bool MachineInstr::isStackAligningInlineAsm() const {
+ if (isInlineAsm()) {
+ unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
+ if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
+ return true;
+ }
+ return false;
+}
+
+InlineAsm::AsmDialect MachineInstr::getInlineAsmDialect() const {
+ assert(isInlineAsm() && "getInlineAsmDialect() only works for inline asms!");
+ unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
+ return InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect) != 0);
+}
+
+int MachineInstr::findInlineAsmFlagIdx(unsigned OpIdx,
+ unsigned *GroupNo) const {
+ assert(isInlineAsm() && "Expected an inline asm instruction");
+ assert(OpIdx < getNumOperands() && "OpIdx out of range");
+
+ // Ignore queries about the initial operands.
+ if (OpIdx < InlineAsm::MIOp_FirstOperand)
+ return -1;
+
+ unsigned Group = 0;
+ unsigned NumOps;
+ for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands(); i < e;
+ i += NumOps) {
+ const MachineOperand &FlagMO = getOperand(i);
+ // If we reach the implicit register operands, stop looking.
+ if (!FlagMO.isImm())
+ return -1;
+ NumOps = 1 + InlineAsm::getNumOperandRegisters(FlagMO.getImm());
+ if (i + NumOps > OpIdx) {
+ if (GroupNo)
+ *GroupNo = Group;
+ return i;
+ }
+ ++Group;
+ }
+ return -1;
+}
+
+const TargetRegisterClass*
+MachineInstr::getRegClassConstraint(unsigned OpIdx,
+ const TargetInstrInfo *TII,
+ const TargetRegisterInfo *TRI) const {
+ assert(getParent() && "Can't have an MBB reference here!");
+ assert(getParent()->getParent() && "Can't have an MF reference here!");
+ const MachineFunction &MF = *getParent()->getParent();
+
+ // Most opcodes have fixed constraints in their MCInstrDesc.
+ if (!isInlineAsm())
+ return TII->getRegClass(getDesc(), OpIdx, TRI, MF);
+
+ if (!getOperand(OpIdx).isReg())
+ return nullptr;
+
+ // For tied uses on inline asm, get the constraint from the def.
+ unsigned DefIdx;
+ if (getOperand(OpIdx).isUse() && isRegTiedToDefOperand(OpIdx, &DefIdx))
+ OpIdx = DefIdx;
+
+ // Inline asm stores register class constraints in the flag word.
+ int FlagIdx = findInlineAsmFlagIdx(OpIdx);
+ if (FlagIdx < 0)
+ return nullptr;
+
+ unsigned Flag = getOperand(FlagIdx).getImm();
+ unsigned RCID;
+ if (InlineAsm::hasRegClassConstraint(Flag, RCID))
+ return TRI->getRegClass(RCID);
+
+ // Assume that all registers in a memory operand are pointers.
+ if (InlineAsm::getKind(Flag) == InlineAsm::Kind_Mem)
+ return TRI->getPointerRegClass(MF);
+
+ return nullptr;
+}
+
+const TargetRegisterClass *MachineInstr::getRegClassConstraintEffectForVReg(
+ unsigned Reg, const TargetRegisterClass *CurRC, const TargetInstrInfo *TII,
+ const TargetRegisterInfo *TRI, bool ExploreBundle) const {
+ // Check every operands inside the bundle if we have
+ // been asked to.
+ if (ExploreBundle)
+ for (ConstMIBundleOperands OpndIt(this); OpndIt.isValid() && CurRC;
+ ++OpndIt)
+ CurRC = OpndIt->getParent()->getRegClassConstraintEffectForVRegImpl(
+ OpndIt.getOperandNo(), Reg, CurRC, TII, TRI);
+ else
+ // Otherwise, just check the current operands.
+ for (unsigned i = 0, e = NumOperands; i < e && CurRC; ++i)
+ CurRC = getRegClassConstraintEffectForVRegImpl(i, Reg, CurRC, TII, TRI);
+ return CurRC;
+}
+
+const TargetRegisterClass *MachineInstr::getRegClassConstraintEffectForVRegImpl(
+ unsigned OpIdx, unsigned Reg, const TargetRegisterClass *CurRC,
+ const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const {
+ assert(CurRC && "Invalid initial register class");
+ // Check if Reg is constrained by some of its use/def from MI.
+ const MachineOperand &MO = getOperand(OpIdx);
+ if (!MO.isReg() || MO.getReg() != Reg)
+ return CurRC;
+ // If yes, accumulate the constraints through the operand.
+ return getRegClassConstraintEffect(OpIdx, CurRC, TII, TRI);
+}
+
+const TargetRegisterClass *MachineInstr::getRegClassConstraintEffect(
+ unsigned OpIdx, const TargetRegisterClass *CurRC,
+ const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const {
+ const TargetRegisterClass *OpRC = getRegClassConstraint(OpIdx, TII, TRI);
+ const MachineOperand &MO = getOperand(OpIdx);
+ assert(MO.isReg() &&
+ "Cannot get register constraints for non-register operand");
+ assert(CurRC && "Invalid initial register class");
+ if (unsigned SubIdx = MO.getSubReg()) {
+ if (OpRC)
+ CurRC = TRI->getMatchingSuperRegClass(CurRC, OpRC, SubIdx);
+ else
+ CurRC = TRI->getSubClassWithSubReg(CurRC, SubIdx);
+ } else if (OpRC)
+ CurRC = TRI->getCommonSubClass(CurRC, OpRC);
+ return CurRC;
+}
+
+/// Return the number of instructions inside the MI bundle, not counting the
+/// header instruction.
+unsigned MachineInstr::getBundleSize() const {
+ MachineBasicBlock::const_instr_iterator I = this;
+ unsigned Size = 0;
+ while (I->isBundledWithSucc())
+ ++Size, ++I;
+ return Size;
+}