-/// Given the index of a tied register operand, find the operand it is tied to.
-/// Defs are tied to uses and vice versa. Returns the index of the tied operand
-/// which must exist.
-unsigned MachineInstr::findTiedOperandIdx(unsigned OpIdx) const {
- // It doesn't usually happen, but an instruction can have multiple pairs of
- // tied operands.
- SmallVector<unsigned, 4> Uses, Defs;
- unsigned PairNo = ~0u;
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
- const MachineOperand &MO = getOperand(i);
- if (!MO.isReg() || !MO.isTied())
- continue;
- if (MO.isUse()) {
- if (i == OpIdx)
- PairNo = Uses.size();
- Uses.push_back(i);
- } else {
- if (i == OpIdx)
- PairNo = Defs.size();
- Defs.push_back(i);
- }
+// MachineOperand::TiedTo is 4 bits wide.
+const unsigned TiedMax = 15;
+
+/// tieOperands - Mark operands at DefIdx and UseIdx as tied to each other.
+///
+/// Use and def operands can be tied together, indicated by a non-zero TiedTo
+/// field. TiedTo can have these values:
+///
+/// 0: Operand is not tied to anything.
+/// 1 to TiedMax-1: Tied to getOperand(TiedTo-1).
+/// TiedMax: Tied to an operand >= TiedMax-1.
+///
+/// The tied def must be one of the first TiedMax operands on a normal
+/// instruction. INLINEASM instructions allow more tied defs.
+///
+void MachineInstr::tieOperands(unsigned DefIdx, unsigned UseIdx) {
+ MachineOperand &DefMO = getOperand(DefIdx);
+ MachineOperand &UseMO = getOperand(UseIdx);
+ assert(DefMO.isDef() && "DefIdx must be a def operand");
+ assert(UseMO.isUse() && "UseIdx must be a use operand");
+ assert(!DefMO.isTied() && "Def is already tied to another use");
+ assert(!UseMO.isTied() && "Use is already tied to another def");
+
+ if (DefIdx < TiedMax)
+ UseMO.TiedTo = DefIdx + 1;
+ else {
+ // Inline asm can use the group descriptors to find tied operands, but on
+ // normal instruction, the tied def must be within the first TiedMax
+ // operands.
+ assert(isInlineAsm() && "DefIdx out of range");
+ UseMO.TiedTo = TiedMax;